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 <com/sun/star/accessibility/AccessibleRelationType.hpp>
21 #include <com/sun/star/awt/XWindow.hpp>
22 #include <o3tl/sorted_vector.hxx>
23 #include <officecfg/Office/Common.hxx>
24 #include <iconview.hxx>
25 #include <salframe.hxx>
26 #include <salinst.hxx>
27 #include <salvd.hxx>
28 #include <salprn.hxx>
29 #include <saltimer.hxx>
30 #include <salsession.hxx>
31 #include <salsys.hxx>
32 #include <salbmp.hxx>
33 #include <salobj.hxx>
34 #include <salmenu.hxx>
35 #include <strings.hrc>
36 #include <svdata.hxx>
37 #include <svimpbox.hxx>
38 #include <messagedialog.hxx>
39 #include <treeglue.hxx>
41 #include <unotools/configmgr.hxx>
42 #include <utility>
43 #include <tools/helpers.hxx>
44 #include <vcl/abstdlg.hxx>
45 #include <vcl/builder.hxx>
46 #include <vcl/calendar.hxx>
47 #include <vcl/combobox.hxx>
48 #include <vcl/lstbox.hxx>
49 #include <vcl/toolkit/dialog.hxx>
50 #include <vcl/fixed.hxx>
52 #include <vcl/fmtfield.hxx>
53 #include <vcl/headbar.hxx>
54 #include <vcl/ivctrl.hxx>
55 #include <vcl/layout.hxx>
56 #include <vcl/menubtn.hxx>
57 #include <vcl/toolkit/prgsbar.hxx>
58 #include <vcl/ptrstyle.hxx>
59 #include <slider.hxx>
60 #include <vcl/sysdata.hxx>
61 #include <vcl/svlbitm.hxx>
62 #include <vcl/toolkit/svtabbx.hxx>
63 #include <vcl/tabctrl.hxx>
64 #include <vcl/tabpage.hxx>
65 #include <vcl/treelistentry.hxx>
66 #include <vcl/toolkit/throbber.hxx>
67 #include <vcl/toolkit/unowrap.hxx>
68 #include <vcl/weld.hxx>
69 #include <vcl/vclmedit.hxx>
70 #include <vcl/viewdataentry.hxx>
71 #include <vcl/virdev.hxx>
72 #include <aboutdialog.hxx>
73 #include <bitmaps.hlst>
74 #include <wizdlg.hxx>
75 #include <salvtables.hxx>
76 
77 #include <boost/property_tree/ptree.hpp>
78 
80  : m_pWindow(nullptr)
81  , m_pProc(nullptr)
82 {
83 }
84 
85 // this file contains the virtual destructors of the sal interface
86 // compilers usually put their vtables where the destructor is
87 
89 
91 {
92  m_pWindow = pWindow;
93  m_pProc = pProc;
94 }
95 
96 // default to full-frame flushes
97 // on ports where partial-flushes are much cheaper this method should be overridden
99 
100 void SalFrame::SetRepresentedURL(const OUString&)
101 {
102  // currently this is Mac only functionality
103 }
104 
105 SalInstance::SalInstance(std::unique_ptr<comphelper::SolarMutex> pMutex)
106  : m_pYieldMutex(std::move(pMutex))
107 {
108 }
109 
111 
113 
114 sal_uInt32 SalInstance::ReleaseYieldMutexAll() { return m_pYieldMutex->release(true); }
115 
116 void SalInstance::AcquireYieldMutex(sal_uInt32 nCount) { m_pYieldMutex->acquire(nCount); }
117 
118 std::unique_ptr<SalSession> SalInstance::CreateSalSession() { return nullptr; }
119 
120 std::unique_ptr<SalMenu> SalInstance::CreateMenu(bool, Menu*)
121 {
122  // default: no native menus
123  return nullptr;
124 }
125 
126 std::unique_ptr<SalMenuItem> SalInstance::CreateMenuItem(const SalItemParams&) { return nullptr; }
127 
128 bool SalInstance::CallEventCallback(void const* pEvent, int nBytes)
129 {
130  return m_pEventInst.is() && m_pEventInst->dispatchEvent(pEvent, nBytes);
131 }
132 
133 SalTimer::~SalTimer() COVERITY_NOEXCEPT_FALSE {}
134 
136 {
137  if (ImplSVData* pSVData = ImplGetSVData())
138  {
139  auto& rCache = pSVData->maGDIData.maScaleCache;
140 
141  rCache.remove_if([this] (const lru_scale_cache::key_value_pair_t& rKeyValuePair)
142  { return rKeyValuePair.first.mpBitmap == this; });
143  }
144 }
145 
147 
149 
151 
152 bool SalPrinter::StartJob(const OUString*, const OUString&, const OUString&, ImplJobSetup*,
154 {
155  return false;
156 }
157 
159 
161 
163 
165 
167 {
168  return false;
169 }
170 
172 
173 bool SalMenu::AddMenuBarButton(const SalMenuButtonItem&) { return false; }
174 
175 void SalMenu::RemoveMenuBarButton(sal_uInt16) {}
176 
178 {
179  return tools::Rectangle();
180 }
181 
182 int SalMenu::GetMenuBarHeight() const { return 0; }
183 
185 
187 
189 {
190  if (!m_bEventListener)
191  {
192  m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, EventListener));
193  m_bEventListener = true;
194  }
195 }
196 
197 // we want the ability to mark key events as handled, so use this variant
198 // for those, we get all keystrokes in this case, so we will need to filter
199 // them later
201 {
202  if (!m_bKeyEventListener)
203  {
204  Application::AddKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
205  m_bKeyEventListener = true;
206  }
207 }
208 
209 // we want the ability to know about mouse events that happen in our children
210 // so use this variant, we will need to filter them later
212 {
214  {
215  Application::AddEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
216  m_bMouseEventListener = true;
217  }
218 }
219 
221 {
224  // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under"
225  // transparent children of the widget
227 }
228 
230  bool bTakeOwnership)
231  : m_xWidget(pWidget)
232  , m_pBuilder(pBuilder)
233  , m_bTakeOwnership(bTakeOwnership)
234  , m_bEventListener(false)
235  , m_bKeyEventListener(false)
236  , m_bMouseEventListener(false)
237  , m_nBlockNotify(0)
238 {
239 }
240 
241 void SalInstanceWidget::set_sensitive(bool sensitive) { m_xWidget->Enable(sensitive); }
242 
244 
246 
248 
250 {
251  auto nStyle = m_xWidget->GetStyle() & ~(WB_TABSTOP | WB_NOTABSTOP);
252  if (bCanFocus)
253  nStyle |= WB_TABSTOP;
254  else
255  nStyle |= WB_NOTABSTOP;
256  m_xWidget->SetStyle(nStyle);
257 }
258 
260 
262 
264 
266 {
267  m_xWidget->set_property("has-default", OUString::boolean(has_default));
268 }
269 
271 
273 
275 
276 void SalInstanceWidget::set_size_request(int nWidth, int nHeight)
277 {
278  m_xWidget->set_width_request(nWidth);
279  m_xWidget->set_height_request(nHeight);
280 }
281 
283 {
285 }
286 
288 
290 {
292 }
293 
295 
296 Size SalInstanceWidget::get_pixel_size(const OUString& rText) const
297 {
298  //TODO, or do I want GetTextBoundRect ?, just using width at the moment anyway
299  return Size(m_xWidget->GetTextWidth(rText), m_xWidget->GetTextHeight());
300 }
301 
303 
304 OString SalInstanceWidget::get_buildable_name() const { return m_xWidget->get_id().toUtf8(); }
305 
306 void SalInstanceWidget::set_help_id(const OString& rId) { return m_xWidget->SetHelpId(rId); }
307 
308 OString SalInstanceWidget::get_help_id() const { return m_xWidget->GetHelpId(); }
309 
311 {
313 }
314 
316 
318 
320 {
321  m_xWidget->set_grid_top_attach(nAttach);
322 }
323 
325 
326 void SalInstanceWidget::set_hexpand(bool bExpand) { m_xWidget->set_hexpand(bExpand); }
327 
329 
330 void SalInstanceWidget::set_vexpand(bool bExpand) { m_xWidget->set_vexpand(bExpand); }
331 
333 
334 void SalInstanceWidget::set_secondary(bool bSecondary) { m_xWidget->set_secondary(bSecondary); }
335 
337 
339 
341 
343 
345 
347 
349 
351 
352 void SalInstanceWidget::set_accessible_name(const OUString& rName)
353 {
355 }
356 
358 
360 {
362 }
363 
365 {
366  vcl::Window* pAtkLabel
367  = pLabel ? dynamic_cast<SalInstanceWidget&>(*pLabel).getWidget() : nullptr;
369 }
370 
372 {
373  vcl::Window* pAtkLabeled
374  = pLabeled ? dynamic_cast<SalInstanceWidget&>(*pLabeled).getWidget() : nullptr;
376 }
377 
379  const css::accessibility::AccessibleRelation& rRelation)
380 {
382 }
383 
385 {
387 }
388 
389 void SalInstanceWidget::set_tooltip_text(const OUString& rTip)
390 {
392 }
393 
395 
397 {
400 }
401 
403 {
404  m_xWidget->SetMnemonicActivateHdl(LINK(this, SalInstanceWidget, MnemonicActivateHdl));
406 }
407 
409 {
412 }
413 
415 {
418 }
419 
421 {
424 }
425 
427 {
430 }
431 
433 {
436 }
437 
439 {
442 }
443 
445 {
448 }
449 
450 bool SalInstanceWidget::get_extents_relative_to(Widget& rRelative, int& x, int& y, int& width,
451  int& height)
452 {
454  dynamic_cast<SalInstanceWidget&>(rRelative).getWidget()));
455  x = aRect.Left();
456  y = aRect.Top();
457  width = aRect.GetWidth();
458  height = aRect.GetHeight();
459  return true;
460 }
461 
463 
465 
467 
469 
471 
473 
475 
477 {
478  if (m_aMnemonicActivateHdl.IsSet())
481  Application::RemoveEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
483  Application::RemoveKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
484  if (m_bEventListener)
485  m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, EventListener));
486  if (m_bTakeOwnership)
488 }
489 
491 
493 
495 
497 
498 OUString SalInstanceWidget::strip_mnemonic(const OUString& rLabel) const
499 {
500  return rLabel.replaceFirst("~", "");
501 }
502 
504 {
505  // create with (annoying) separate alpha layer that LibreOffice itself uses
508 }
509 
510 css::uno::Reference<css::datatransfer::dnd::XDropTarget> SalInstanceWidget::get_drop_target()
511 {
512  return m_xWidget->GetDropTarget();
513 }
514 
517 {
519 }
520 
522 {
524 }
525 
527 {
530 }
531 
533 {
535 }
536 
538 
540 {
541  if (rEvent.GetId() == VclEventId::WindowGetFocus)
542  m_aFocusInHdl.Call(*this);
543  else if (rEvent.GetId() == VclEventId::WindowLoseFocus)
544  m_aFocusOutHdl.Call(*this);
545  else if (rEvent.GetId() == VclEventId::WindowResize)
547 }
548 
550 {
552  {
553  auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
554  if (m_xWidget->IsWindowOrChild(rWinEvent.GetWindow()))
555  {
556  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
557  m_aMousePressHdl.Call(*pMouseEvent);
558  }
559  }
560  else if (rEvent.GetId() == VclEventId::WindowMouseButtonUp)
561  {
562  auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
563  if (m_xWidget->IsWindowOrChild(rWinEvent.GetWindow()))
564  {
565  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
566  m_aMouseReleaseHdl.Call(*pMouseEvent);
567  }
568  }
569  else if (rEvent.GetId() == VclEventId::WindowMouseMove)
570  {
571  auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
572  if (m_xWidget->IsWindowOrChild(rWinEvent.GetWindow()))
573  {
574  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
575  m_aMouseMotionHdl.Call(*pMouseEvent);
576  }
577  }
578 }
579 
581 {
582  // we get all key events here, ignore them unless we have focus
583  if (!has_focus())
584  return false;
585  if (rEvent.GetId() == VclEventId::WindowKeyInput)
586  {
587  const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
588  return m_aKeyPressHdl.Call(*pKeyEvent);
589  }
590  else if (rEvent.GetId() == VclEventId::WindowKeyUp)
591  {
592  const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
593  return m_aKeyReleaseHdl.Call(*pKeyEvent);
594  }
595  return false;
596 }
597 
598 IMPL_LINK(SalInstanceWidget, EventListener, VclWindowEvent&, rEvent, void)
599 {
600  HandleEventListener(rEvent);
601 }
602 
603 IMPL_LINK(SalInstanceWidget, KeyEventListener, VclWindowEvent&, rEvent, bool)
604 {
605  return HandleKeyEventListener(rEvent);
606 }
607 
608 IMPL_LINK(SalInstanceWidget, MouseEventListener, VclSimpleEvent&, rEvent, void)
609 {
610  HandleMouseEventListener(rEvent);
611 }
612 
613 IMPL_LINK_NOARG(SalInstanceWidget, MnemonicActivateHdl, vcl::Window&, bool)
614 {
615  return m_aMnemonicActivateHdl.Call(*this);
616 }
617 
618 namespace
619 {
620 Image createImage(const OUString& rImage)
621 {
622  if (rImage.isEmpty())
623  return Image();
624  if (rImage.lastIndexOf('.') != rImage.getLength() - 4)
625  {
626  assert((rImage == "dialog-warning" || rImage == "dialog-error"
627  || rImage == "dialog-information")
628  && "unknown stock image");
629  if (rImage == "dialog-warning")
630  return Image(StockImage::Yes, IMG_WARN);
631  else if (rImage == "dialog-error")
632  return Image(StockImage::Yes, IMG_ERROR);
633  else if (rImage == "dialog-information")
634  return Image(StockImage::Yes, IMG_INFO);
635  }
636  return Image(StockImage::Yes, rImage);
637 }
638 
639 Image createImage(const VirtualDevice& rDevice)
640 {
641  return Image(rDevice.GetBitmapEx(Point(), rDevice.GetOutputSizePixel()));
642 }
643 
644 sal_uInt16 insert_to_menu(sal_uInt16 nLastId, PopupMenu* pMenu, int pos, const OUString& rId,
645  const OUString& rStr, const OUString* pIconName,
646  const VirtualDevice* pImageSurface, TriState eCheckRadioFalse)
647 {
648  const sal_uInt16 nNewid = nLastId + 1;
649 
650  MenuItemBits nBits;
651  if (eCheckRadioFalse == TRISTATE_TRUE)
652  nBits = MenuItemBits::CHECKABLE;
653  else if (eCheckRadioFalse == TRISTATE_FALSE)
655  else
656  nBits = MenuItemBits::NONE;
657 
658  pMenu->InsertItem(nNewid, rStr, nBits,
659  OUStringToOString(rId, RTL_TEXTENCODING_UTF8), pos == -1 ? MENU_APPEND : pos);
660  if (pIconName)
661  {
662  pMenu->SetItemImage(nNewid, createImage(*pIconName));
663  }
664  else if (pImageSurface)
665  {
666  pMenu->SetItemImage(nNewid, createImage(*pImageSurface));
667  }
668  return nNewid;
669 }
670 }
671 
672 namespace
673 {
674 class SalInstanceMenu : public weld::Menu
675 {
676 private:
677  VclPtr<PopupMenu> m_xMenu;
678 
679  bool m_bTakeOwnership;
680  sal_uInt16 m_nLastId;
681 
682  DECL_LINK(SelectMenuHdl, ::Menu*, bool);
683 
684 public:
685  SalInstanceMenu(PopupMenu* pMenu, bool bTakeOwnership)
686  : m_xMenu(pMenu)
687  , m_bTakeOwnership(bTakeOwnership)
688  {
689  const auto nCount = m_xMenu->GetItemCount();
690  m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
691  m_xMenu->SetSelectHdl(LINK(this, SalInstanceMenu, SelectMenuHdl));
692  }
693  virtual OString popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect) override
694  {
695  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent);
696  assert(pVclWidget);
697  m_xMenu->Execute(pVclWidget->getWidget(), rRect,
699  return m_xMenu->GetCurItemIdent();
700  }
701  virtual void set_sensitive(const OString& rIdent, bool bSensitive) override
702  {
703  m_xMenu->EnableItem(rIdent, bSensitive);
704  }
705  virtual void set_active(const OString& rIdent, bool bActive) override
706  {
707  m_xMenu->CheckItem(rIdent, bActive);
708  }
709  virtual bool get_active(const OString& rIdent) const override
710  {
711  return m_xMenu->IsItemChecked(m_xMenu->GetItemId(rIdent));
712  }
713  virtual void set_label(const OString& rIdent, const OUString& rLabel) override
714  {
715  m_xMenu->SetItemText(m_xMenu->GetItemId(rIdent), rLabel);
716  }
717  virtual OUString get_label(const OString& rIdent) const override
718  {
719  return m_xMenu->GetItemText(m_xMenu->GetItemId(rIdent));
720  }
721  virtual void set_visible(const OString& rIdent, bool bShow) override
722  {
723  m_xMenu->ShowItem(m_xMenu->GetItemId(rIdent), bShow);
724  }
725  virtual void clear() override { m_xMenu->Clear(); }
726  virtual void insert(int pos, const OUString& rId, const OUString& rStr,
727  const OUString* pIconName, VirtualDevice* pImageSurface,
728  TriState eCheckRadioFalse) override
729  {
730  m_nLastId
731  = insert_to_menu(m_nLastId, m_xMenu, pos, rId, rStr, pIconName, pImageSurface, eCheckRadioFalse);
732  }
733  virtual void insert_separator(int pos, const OUString& rId) override
734  {
735  auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
736  m_xMenu->InsertSeparator(rId.toUtf8(), nInsertPos);
737  }
738  virtual void remove(const OString& rId) override
739  {
740  m_xMenu->RemoveItem(m_xMenu->GetItemPos(m_xMenu->GetItemId(rId)));
741  }
742  virtual int n_children() const override { return m_xMenu->GetItemCount(); }
743  PopupMenu* getMenu() const { return m_xMenu.get(); }
744  virtual ~SalInstanceMenu() override
745  {
746  m_xMenu->SetSelectHdl(Link<::Menu*, bool>());
747  if (m_bTakeOwnership)
748  m_xMenu.disposeAndClear();
749  }
750 };
751 
752 }
753 
754 IMPL_LINK_NOARG(SalInstanceMenu, SelectMenuHdl, ::Menu*, bool)
755 {
756  signal_activate(m_xMenu->GetCurItemIdent());
757  return true;
758 }
759 
760 namespace
761 {
762 class SalInstanceToolbar : public SalInstanceWidget, public virtual weld::Toolbar
763 {
764 private:
765  VclPtr<ToolBox> m_xToolBox;
766  std::map<sal_uInt16, VclPtr<vcl::Window>> m_aFloats;
767  std::map<sal_uInt16, VclPtr<PopupMenu>> m_aMenus;
768 
769  OString m_sStartShowIdent;
770 
771  DECL_LINK(ClickHdl, ToolBox*, void);
772  DECL_LINK(DropdownClick, ToolBox*, void);
773  DECL_LINK(MenuToggleListener, VclWindowEvent&, void);
774 
775 public:
776  SalInstanceToolbar(ToolBox* pToolBox, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
777  : SalInstanceWidget(pToolBox, pBuilder, bTakeOwnership)
778  , m_xToolBox(pToolBox)
779  {
780  m_xToolBox->SetSelectHdl(LINK(this, SalInstanceToolbar, ClickHdl));
781  m_xToolBox->SetDropdownClickHdl(LINK(this, SalInstanceToolbar, DropdownClick));
782  }
783 
784  virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) override
785  {
786  m_xToolBox->EnableItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bSensitive);
787  }
788 
789  virtual bool get_item_sensitive(const OString& rIdent) const override
790  {
791  return m_xToolBox->IsItemEnabled(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
792  }
793 
794  virtual void set_item_visible(const OString& rIdent, bool bVisible) override
795  {
796  m_xToolBox->ShowItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bVisible);
797  }
798 
799  virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) override
800  {
801  m_xToolBox->SetHelpId(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rHelpId);
802  }
803 
804  virtual bool get_item_visible(const OString& rIdent) const override
805  {
806  return m_xToolBox->IsItemVisible(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
807  }
808 
809  virtual void set_item_active(const OString& rIdent, bool bActive) override
810  {
811  sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
812  m_xToolBox->CheckItem(nItemId, bActive);
813  }
814 
815  virtual bool get_item_active(const OString& rIdent) const override
816  {
817  return m_xToolBox->IsItemChecked(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
818  }
819 
820  void set_menu_item_active(const OString& rIdent, bool bActive) override
821  {
822  sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
823  assert(m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN);
824 
825  if (bActive)
826  {
827  m_sStartShowIdent = m_xToolBox->GetItemCommand(nItemId).toUtf8();
828  signal_toggle_menu(m_sStartShowIdent);
829  }
830 
831  auto pFloat = m_aFloats[nItemId];
832  if (pFloat)
833  {
834  if (bActive)
835  vcl::Window::GetDockingManager()->StartPopupMode(m_xToolBox, pFloat,
837  else
838  vcl::Window::GetDockingManager()->EndPopupMode(pFloat);
839  }
840  auto pPopup = m_aMenus[nItemId];
841  if (pPopup)
842  {
843  if (bActive)
844  {
845  tools::Rectangle aRect = m_xToolBox->GetItemRect(nItemId);
846  pPopup->Execute(m_xToolBox, aRect, PopupMenuFlags::ExecuteDown);
847  }
848  else
849  pPopup->EndExecute();
850  }
851 
852  m_sStartShowIdent.clear();
853  }
854 
855  bool get_menu_item_active(const OString& rIdent) const override
856  {
857  sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
858  assert(m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN);
859 
860  if (rIdent == m_sStartShowIdent)
861  return true;
862 
863  auto aFloat = m_aFloats.find(nItemId);
864  if (aFloat != m_aFloats.end())
865  {
866  return vcl::Window::GetDockingManager()->IsInPopupMode(aFloat->second);
867  }
868 
869  auto aPopup = m_aMenus.find(nItemId);
870  if (aPopup != m_aMenus.end())
871  {
872  return PopupMenu::GetActivePopupMenu() == aPopup->second;
873  }
874 
875  return false;
876  }
877 
878  virtual void set_item_popover(const OString& rIdent, weld::Widget* pPopover) override
879  {
880  SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
881 
882  vcl::Window* pFloat = pPopoverWidget ? pPopoverWidget->getWidget() : nullptr;
883  if (pFloat)
884  {
885  pFloat->AddEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
886  pFloat->EnableDocking();
887  }
888 
889  sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
890  auto xOldFloat = m_aFloats[nId];
891  if (xOldFloat)
892  {
893  xOldFloat->RemoveEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
894  }
895  m_aFloats[nId] = pFloat;
896  m_aMenus[nId] = nullptr;
897  }
898 
899  virtual void set_item_menu(const OString& rIdent, weld::Menu* pMenu) override
900  {
901  SalInstanceMenu* pInstanceMenu = dynamic_cast<SalInstanceMenu*>(pMenu);
902 
903  PopupMenu* pPopup = pInstanceMenu ? pInstanceMenu->getMenu() : nullptr;
904 
905  sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
906  m_aMenus[nId] = pPopup;
907  m_aFloats[nId] = nullptr;
908  }
909 
910  virtual void insert_separator(int pos, const OUString& /*rId*/) override
911  {
912  auto nInsertPos = pos == -1 ? ToolBox::APPEND : pos;
913  m_xToolBox->InsertSeparator(nInsertPos, 5);
914  }
915 
916  virtual int get_n_items() const override { return m_xToolBox->GetItemCount(); }
917 
918  virtual OString get_item_ident(int nIndex) const override
919  {
920  return m_xToolBox->GetItemCommand(m_xToolBox->GetItemId(nIndex)).toUtf8();
921  }
922 
923  virtual void set_item_ident(int nIndex, const OString& rIdent) override
924  {
925  return m_xToolBox->SetItemCommand(m_xToolBox->GetItemId(nIndex),
926  OUString::fromUtf8(rIdent));
927  }
928 
929  virtual void set_item_label(int nIndex, const OUString& rLabel) override
930  {
931  m_xToolBox->SetItemText(m_xToolBox->GetItemId(nIndex), rLabel);
932  }
933 
934  virtual OUString get_item_label(const OString& rIdent) const override
935  {
936  return m_xToolBox->GetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
937  }
938 
939  virtual void set_item_label(const OString& rIdent, const OUString& rLabel) override
940  {
941  m_xToolBox->SetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rLabel);
942  }
943 
944  virtual void set_item_icon_name(const OString& rIdent, const OUString& rIconName) override
945  {
946  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)),
947  Image(StockImage::Yes, rIconName));
948  }
949 
950  virtual void set_item_image(const OString& rIdent,
951  const css::uno::Reference<css::graphic::XGraphic>& rIcon) override
952  {
953  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image(rIcon));
954  }
955 
956  virtual void set_item_image(const OString& rIdent, VirtualDevice* pDevice) override
957  {
958  if (pDevice)
959  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)),
960  createImage(*pDevice));
961  else
962  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image());
963  }
964 
965  virtual void set_item_image(int nIndex,
966  const css::uno::Reference<css::graphic::XGraphic>& rIcon) override
967  {
968  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(nIndex), Image(rIcon));
969  }
970 
971  virtual void set_item_tooltip_text(int nIndex, const OUString& rTip) override
972  {
973  m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(nIndex), rTip);
974  }
975 
976  virtual void set_item_tooltip_text(const OString& rIdent, const OUString& rTip) override
977  {
978  m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rTip);
979  }
980 
981  virtual OUString get_item_tooltip_text(const OString& rIdent) const override
982  {
983  return m_xToolBox->GetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
984  }
985 
986  virtual vcl::ImageType get_icon_size() const override { return m_xToolBox->GetImageSize(); }
987 
988  virtual void set_icon_size(vcl::ImageType eType) override
989  {
991  switch (eType)
992  {
994  eButtonSize = ToolBoxButtonSize::Small;
995  break;
997  eButtonSize = ToolBoxButtonSize::Large;
998  break;
1000  eButtonSize = ToolBoxButtonSize::Size32;
1001  break;
1002  }
1003  if (m_xToolBox->GetToolboxButtonSize() != eButtonSize)
1004  {
1005  m_xToolBox->SetToolboxButtonSize(eButtonSize);
1006  m_xToolBox->queue_resize();
1007  }
1008  }
1009 
1010  virtual sal_uInt16 get_modifier_state() const override
1011  {
1012  return m_xToolBox->GetModifier();
1013  }
1014 
1015  virtual ~SalInstanceToolbar() override
1016  {
1018  m_xToolBox->SetSelectHdl(Link<ToolBox*, void>());
1019  }
1020 };
1021 
1022 }
1023 
1024 IMPL_LINK_NOARG(SalInstanceToolbar, ClickHdl, ToolBox*, void)
1025 {
1026  sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
1027  signal_clicked(m_xToolBox->GetItemCommand(nItemId).toUtf8());
1028 }
1029 
1030 IMPL_LINK_NOARG(SalInstanceToolbar, DropdownClick, ToolBox*, void)
1031 {
1032  sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
1033  set_menu_item_active(m_xToolBox->GetItemCommand(nItemId).toUtf8(), true);
1034 }
1035 
1036 IMPL_LINK(SalInstanceToolbar, MenuToggleListener, VclWindowEvent&, rEvent, void)
1037 {
1038  if (rEvent.GetId() == VclEventId::WindowEndPopupMode)
1039  {
1040  for (auto& rFloat : m_aFloats)
1041  {
1042  if (rEvent.GetWindow() == rFloat.second)
1043  {
1044  sal_uInt16 nItemId = rFloat.first;
1045  signal_toggle_menu(m_xToolBox->GetItemCommand(nItemId).toUtf8());
1046  break;
1047  }
1048  }
1049  }
1050 }
1051 
1052 namespace
1053 {
1054 class SalInstanceSizeGroup : public weld::SizeGroup
1055 {
1056 private:
1057  std::shared_ptr<VclSizeGroup> m_xGroup;
1058 
1059 public:
1060  SalInstanceSizeGroup()
1061  : m_xGroup(std::make_shared<VclSizeGroup>())
1062  {
1063  }
1064  virtual void add_widget(weld::Widget* pWidget) override
1065  {
1066  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1067  assert(pVclWidget && pVclWidget->getWidget());
1068  pVclWidget->getWidget()->add_to_size_group(m_xGroup);
1069  }
1070  virtual void set_mode(VclSizeGroupMode eMode) override { m_xGroup->set_mode(eMode); }
1071 };
1072 }
1073 
1075 {
1076  vcl::Window* pChildLoop = _pWindow->GetWindow(GetWindowType::FirstChild);
1077  while (pChildLoop)
1078  {
1079  // does the window participate in the tabbing order?
1080  if (pChildLoop->GetStyle() & WB_DIALOGCONTROL)
1081  implResetDefault(pChildLoop);
1082 
1083  // is it a button?
1084  WindowType eType = pChildLoop->GetType();
1085  if ((WindowType::PUSHBUTTON == eType) || (WindowType::OKBUTTON == eType)
1086  || (WindowType::CANCELBUTTON == eType) || (WindowType::HELPBUTTON == eType)
1087  || (WindowType::IMAGEBUTTON == eType) || (WindowType::MENUBUTTON == eType)
1088  || (WindowType::MOREBUTTON == eType))
1089  {
1090  pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON);
1091  }
1092 
1093  // the next one ...
1094  pChildLoop = pChildLoop->GetWindow(GetWindowType::Next);
1095  }
1096 }
1097 
1099  bool bTakeOwnership)
1100  : SalInstanceWidget(pContainer, pBuilder, bTakeOwnership)
1101  , m_xContainer(pContainer)
1102 {
1103 }
1104 
1106 {
1107  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1108  assert(pVclWidget);
1109  SalInstanceContainer* pNewVclParent = dynamic_cast<SalInstanceContainer*>(pNewParent);
1110  assert(!pNewParent || pNewVclParent);
1111  pVclWidget->getWidget()->SetParent(pNewVclParent ? pNewVclParent->getWidget() : nullptr);
1112 }
1113 
1115 {
1117 }
1118 
1119 css::uno::Reference<css::awt::XWindow> SalInstanceContainer::CreateChildFrame()
1120 {
1121  auto xPage = VclPtr<VclBin>::Create(m_xContainer.get());
1122  xPage->set_expand(true);
1123  xPage->Show();
1124  return css::uno::Reference<css::awt::XWindow>(xPage->GetComponentInterface(),
1125  css::uno::UNO_QUERY);
1126 }
1127 
1128 std::unique_ptr<weld::Container> SalInstanceWidget::weld_parent() const
1129 {
1130  vcl::Window* pParent = m_xWidget->GetParent();
1131  if (!pParent)
1132  return nullptr;
1133  return std::make_unique<SalInstanceContainer>(pParent, m_pBuilder, false);
1134 }
1135 
1136 namespace
1137 {
1138 class SalInstanceBox : public SalInstanceContainer, public virtual weld::Box
1139 {
1140 public:
1141  SalInstanceBox(vcl::Window* pContainer, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1142  : SalInstanceContainer(pContainer, pBuilder, bTakeOwnership)
1143  {
1144  }
1145  virtual void reorder_child(weld::Widget* pWidget, int nNewPosition) override
1146  {
1147  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1148  assert(pVclWidget);
1149  pVclWidget->getWidget()->reorderWithinParent(nNewPosition);
1150  }
1151 };
1152 
1153 void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& rTopLeft,
1154  weld::ScreenShotCollection& rControlDataCollection)
1155 {
1156  if (rCurrent.IsVisible())
1157  {
1158  const Point aCurrentPos(rCurrent.GetPosPixel());
1159  const Size aCurrentSize(rCurrent.GetSizePixel());
1160  const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + aCurrentPos.X(),
1161  rTopLeft.getY() + aCurrentPos.Y());
1162  const basegfx::B2IRange aCurrentRange(
1163  aCurrentTopLeft,
1164  aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), aCurrentSize.Height()));
1165 
1166  if (!aCurrentRange.isEmpty())
1167  {
1168  rControlDataCollection.emplace_back(rCurrent.GetHelpId(), aCurrentRange);
1169  }
1170 
1171  for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++)
1172  {
1173  vcl::Window* pChild = rCurrent.GetChild(a);
1174  if (nullptr != pChild)
1175  {
1176  CollectChildren(*pChild, aCurrentTopLeft, rControlDataCollection);
1177  }
1178  }
1179  }
1180 }
1181 
1182 }
1183 
1185 {
1186  for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1187  pChild = pChild->GetWindow(GetWindowType::Next))
1188  override_child_help(pChild);
1189  pParent->SetHelpHdl(LINK(this, SalInstanceWindow, HelpHdl));
1190 }
1191 
1193 {
1194  for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1195  pChild = pChild->GetWindow(GetWindowType::Next))
1196  clear_child_help(pChild);
1198 }
1199 
1201  bool bTakeOwnership)
1202  : SalInstanceContainer(pWindow, pBuilder, bTakeOwnership)
1203  , m_xWindow(pWindow)
1204 {
1206 }
1207 
1208 void SalInstanceWindow::set_title(const OUString& rTitle) { m_xWindow->SetText(rTitle); }
1209 
1210 OUString SalInstanceWindow::get_title() const { return m_xWindow->GetText(); }
1211 
1213 {
1214  if (bBusy)
1215  m_xWindow->EnterWait();
1216  else
1217  m_xWindow->LeaveWait();
1218 }
1219 
1220 css::uno::Reference<css::awt::XWindow> SalInstanceWindow::GetXWindow()
1221 {
1222  css::uno::Reference<css::awt::XWindow> xWindow(m_xWindow->GetComponentInterface(),
1223  css::uno::UNO_QUERY);
1224  return xWindow;
1225 }
1226 
1228 {
1229  if (SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get()))
1230  {
1231  pSysWin->setOptimalLayoutSize();
1232  return;
1233  }
1234  if (DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(m_xWindow.get()))
1235  {
1236  pDockWin->setOptimalLayoutSize();
1237  return;
1238  }
1239  assert(false && "must be system or docking window");
1240 }
1241 
1243 
1245 
1247 
1249 
1251 
1253 {
1254  return m_xWindow->GetDesktopRectPixel();
1255 }
1256 
1257 void SalInstanceWindow::set_centered_on_parent(bool /*bTrackGeometryRequests*/)
1258 {
1259  if (vcl::Window* pParent = m_xWidget->GetParent())
1260  {
1261  Size aParentGeometry(pParent->GetSizePixel());
1262  Size aGeometry(m_xWidget->get_preferred_size());
1263  auto nX = (aParentGeometry.Width() - aGeometry.Width()) / 2;
1264  auto nY = (aParentGeometry.Height() - aGeometry.Height()) / 2;
1265  m_xWidget->SetPosPixel(Point(nX, nY));
1266  }
1267 }
1268 
1270 
1272 
1274 {
1276 }
1277 
1278 void SalInstanceWindow::set_window_state(const OString& rStr)
1279 {
1280  SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1281  assert(pSysWin);
1282  pSysWin->SetWindowState(rStr);
1283 }
1284 
1286 {
1287  SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1288  assert(pSysWin);
1289  return pSysWin->GetWindowState(nMask);
1290 }
1291 
1293 
1295 {
1298 }
1299 
1301 {
1302  if (rEvent.GetId() == VclEventId::WindowActivate
1303  || rEvent.GetId() == VclEventId::WindowDeactivate)
1304  {
1306  return;
1307  }
1309 }
1310 
1312 {
1313  SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1314  assert(pSysWin);
1315  pSysWin->createScreenshot(rOutput);
1316 }
1317 
1319 {
1321 
1322  // collect all children. Choose start pos to be negative
1323  // of target dialog's position to get all positions relative to (0,0)
1324  const Point aParentPos(m_xWindow->GetPosPixel());
1325  const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y());
1326  CollectChildren(*m_xWindow, aTopLeft, aRet);
1327 
1328  return aRet;
1329 }
1330 
1332 
1334 {
1335  help();
1336  return false;
1337 }
1338 
1339 typedef std::set<VclPtr<vcl::Window>> winset;
1340 
1341 namespace
1342 {
1343 void hideUnless(const vcl::Window* pTop, const winset& rVisibleWidgets,
1344  std::vector<VclPtr<vcl::Window>>& rWasVisibleWidgets)
1345 {
1346  for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild;
1347  pChild = pChild->GetWindow(GetWindowType::Next))
1348  {
1349  if (!pChild->IsVisible())
1350  continue;
1351  if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
1352  {
1353  rWasVisibleWidgets.emplace_back(pChild);
1354  pChild->Hide();
1355  }
1356  else if (isContainerWindow(pChild))
1357  {
1358  hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
1359  }
1360  }
1361 }
1362 }
1363 
1365  bool bTakeOwnership)
1366  : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership)
1367  , m_xDialog(pDialog)
1368  , m_nOldEditWidthReq(0)
1369  , m_nOldBorderWidth(0)
1370 {
1371  const bool bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
1372  if (bScreenshotMode)
1373  {
1374  m_xDialog->SetPopupMenuHdl(LINK(this, SalInstanceDialog, PopupScreenShotMenuHdl));
1375  }
1376 }
1377 
1378 bool SalInstanceDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner,
1379  const std::function<void(sal_Int32)>& rEndDialogFn)
1380 {
1382  aCtx.mxOwnerDialogController = aOwner;
1383  aCtx.maEndDialogFn = rEndDialogFn;
1384  VclButtonBox* pActionArea = m_xDialog->get_action_area();
1385  if (pActionArea)
1386  pActionArea->sort_native_button_order();
1387  return m_xDialog->StartExecuteAsync(aCtx);
1388 }
1389 
1390 bool SalInstanceDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf,
1391  const std::function<void(sal_Int32)>& rEndDialogFn)
1392 {
1393  assert(rxSelf.get() == this);
1395  // In order to store a shared_ptr to ourself, we have to have been constructed by make_shared,
1396  // which is that rxSelf enforces.
1397  aCtx.mxOwnerSelf = rxSelf;
1398  aCtx.maEndDialogFn = rEndDialogFn;
1399  VclButtonBox* pActionArea = m_xDialog->get_action_area();
1400  if (pActionArea)
1401  pActionArea->sort_native_button_order();
1402  return m_xDialog->StartExecuteAsync(aCtx);
1403 }
1404 
1406 {
1407  SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit);
1408  assert(pVclEdit);
1409  SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton);
1410 
1411  vcl::Window* pRefEdit = pVclEdit->getWidget();
1412  vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr;
1413 
1414  auto nOldEditWidth = pRefEdit->GetSizePixel().Width();
1415  m_nOldEditWidthReq = pRefEdit->get_width_request();
1416 
1417  //We want just pRefBtn and pRefEdit to be shown
1418  //mark widgets we want to be visible, starting with pRefEdit
1419  //and all its direct parents.
1420  winset aVisibleWidgets;
1421  vcl::Window* pContentArea = m_xDialog->get_content_area();
1422  for (vcl::Window* pCandidate = pRefEdit;
1423  pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1424  pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1425  {
1426  aVisibleWidgets.insert(pCandidate);
1427  }
1428  //same again with pRefBtn, except stop if there's a
1429  //shared parent in the existing widgets
1430  for (vcl::Window* pCandidate = pRefBtn;
1431  pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1432  pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1433  {
1434  if (aVisibleWidgets.insert(pCandidate).second)
1435  break;
1436  }
1437 
1438  //hide everything except the aVisibleWidgets
1439  hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets);
1440 
1441  // the insert function case has an initially hidden edit widget, so it has
1442  // not start size, so take larger of actual size and size request
1443  pRefEdit->set_width_request(std::max(nOldEditWidth, m_nOldEditWidthReq));
1446  if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1447  pActionArea->Hide();
1449  m_xRefEdit = pRefEdit;
1450 }
1451 
1453 {
1454  // All others: Show();
1455  for (VclPtr<vcl::Window> const& pWindow : m_aHiddenWidgets)
1456  {
1457  pWindow->Show();
1458  }
1459  m_aHiddenWidgets.clear();
1460 
1462  m_xRefEdit.clear();
1464  if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1465  pActionArea->Show();
1467 }
1468 
1471 {
1473 }
1474 
1476 {
1477  VclButtonBox* pActionArea = m_xDialog->get_action_area();
1478  if (pActionArea)
1479  pActionArea->sort_native_button_order();
1480  return m_xDialog->Execute();
1481 }
1482 
1483 void SalInstanceDialog::response(int nResponse) { m_xDialog->EndDialog(nResponse); }
1484 
1485 void SalInstanceDialog::add_button(const OUString& rText, int nResponse, const OString& rHelpId)
1486 {
1488  VclPtr<PushButton> xButton(
1490  xButton->SetText(rText);
1491  xButton->SetHelpId(rHelpId);
1492 
1493  switch (nResponse)
1494  {
1495  case RET_OK:
1496  xButton->set_id("ok");
1497  break;
1498  case RET_CLOSE:
1499  xButton->set_id("close");
1500  break;
1501  case RET_CANCEL:
1502  xButton->set_id("cancel");
1503  break;
1504  case RET_YES:
1505  xButton->set_id("yes");
1506  break;
1507  case RET_NO:
1508  xButton->set_id("no");
1509  break;
1510  }
1511 
1512  xButton->Show();
1513  m_xDialog->add_button(xButton, nResponse, true);
1514 }
1515 
1517 {
1518  if (get_modal() == bModal)
1519  return;
1520  m_xDialog->SetModalInputMode(bModal);
1521 }
1522 
1524 
1526 {
1527  m_xDialog->set_default_response(nResponse);
1528 }
1529 
1531 {
1533 }
1534 
1535 IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, rCEvt, bool)
1536 {
1537  if (CommandEventId::ContextMenu == rCEvt.GetCommand())
1538  {
1539  const Point aMenuPos(rCEvt.GetMousePosPixel());
1541  sal_uInt16 nLocalID(1);
1542 
1543  aMenu->InsertItem(nLocalID, VclResId(SV_BUTTONTEXT_SCREENSHOT));
1544  aMenu->SetHelpText(nLocalID, VclResId(SV_HELPTEXT_SCREENSHOT));
1545  aMenu->SetHelpId(nLocalID, "InteractiveScreenshotMode");
1546  aMenu->EnableItem(nLocalID);
1547 
1548  const sal_uInt16 nId(aMenu->Execute(m_xDialog, aMenuPos));
1549 
1550  // 0 == no selection (so not usable as ID)
1551  if (0 != nId)
1552  {
1553  // open screenshot annotation dialog
1556  = pFact->CreateScreenshotAnnotationDlg(*this);
1558 
1559  if (pDialog)
1560  {
1561  // currently just execute the dialog, no need to do
1562  // different things for ok/cancel. This may change later,
1563  // for that case use 'if (pDlg->Execute() == RET_OK)'
1564  pDialog->Execute();
1565  }
1566  }
1567 
1568  // consume event when:
1569  // - CommandEventId::ContextMenu
1570  // - bScreenshotMode
1571  return true;
1572  }
1573 
1574  return false;
1575 }
1576 
1577 namespace
1578 {
1579 class SalInstanceMessageDialog : public SalInstanceDialog, public virtual weld::MessageDialog
1580 {
1581 private:
1582  VclPtr<::MessageDialog> m_xMessageDialog;
1583 
1584 public:
1585  SalInstanceMessageDialog(::MessageDialog* pDialog, SalInstanceBuilder* pBuilder,
1586  bool bTakeOwnership)
1587  : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1588  , m_xMessageDialog(pDialog)
1589  {
1590  }
1591 
1592  virtual void set_primary_text(const OUString& rText) override
1593  {
1594  m_xMessageDialog->set_primary_text(rText);
1595  }
1596 
1597  virtual OUString get_primary_text() const override
1598  {
1599  return m_xMessageDialog->get_primary_text();
1600  }
1601 
1602  virtual void set_secondary_text(const OUString& rText) override
1603  {
1604  m_xMessageDialog->set_secondary_text(rText);
1605  }
1606 
1607  virtual OUString get_secondary_text() const override
1608  {
1609  return m_xMessageDialog->get_secondary_text();
1610  }
1611 
1612  virtual Container* weld_message_area() override
1613  {
1614  return new SalInstanceContainer(m_xMessageDialog->get_message_area(), m_pBuilder, false);
1615  }
1616 };
1617 
1618 class SalInstanceAboutDialog : public SalInstanceDialog, public virtual weld::AboutDialog
1619 {
1620 private:
1621  VclPtr<vcl::AboutDialog> m_xAboutDialog;
1622 
1623 public:
1624  SalInstanceAboutDialog(vcl::AboutDialog* pDialog, SalInstanceBuilder* pBuilder,
1625  bool bTakeOwnership)
1626  : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1627  , m_xAboutDialog(pDialog)
1628  {
1629  }
1630  virtual void set_version(const OUString& rVersion) override
1631  {
1632  m_xAboutDialog->SetVersion(rVersion);
1633  }
1634  virtual void set_copyright(const OUString& rCopyright) override
1635  {
1636  m_xAboutDialog->SetCopyright(rCopyright);
1637  }
1638  virtual void set_website(const OUString& rURL) override
1639  {
1640  m_xAboutDialog->SetWebsiteLink(rURL);
1641  }
1642  virtual void set_website_label(const OUString& rLabel) override
1643  {
1644  m_xAboutDialog->SetWebsiteLabel(rLabel);
1645  }
1646  virtual OUString get_website_label() const override
1647  {
1648  return m_xAboutDialog->GetWebsiteLabel();
1649  }
1650  virtual void set_logo(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
1651  {
1652  m_xAboutDialog->SetLogo(Image(rImage));
1653  }
1654  virtual void set_background(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
1655  {
1656  m_xAboutDialog->SetBackground(Image(rImage));
1657  }
1658 };
1659 
1660 class SalInstanceAssistant : public SalInstanceDialog, public virtual weld::Assistant
1661 {
1662 private:
1663  VclPtr<vcl::RoadmapWizard> m_xWizard;
1664  std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
1665  std::vector<VclPtr<TabPage>> m_aAddedPages;
1666  std::vector<int> m_aIds;
1667  std::vector<VclPtr<VclGrid>> m_aAddedGrids;
1668  Idle m_aUpdateRoadmapIdle;
1669 
1670  int find_page(const OString& rIdent) const
1671  {
1672  for (size_t i = 0; i < m_aAddedPages.size(); ++i)
1673  {
1674  if (m_aAddedPages[i]->get_id().toUtf8() == rIdent)
1675  return i;
1676  }
1677  return -1;
1678  }
1679 
1680  int find_id(int nId) const
1681  {
1682  for (size_t i = 0; i < m_aIds.size(); ++i)
1683  {
1684  if (nId == m_aIds[i])
1685  return i;
1686  }
1687  return -1;
1688  }
1689 
1690  DECL_LINK(OnRoadmapItemSelected, LinkParamNone*, void);
1691  DECL_LINK(UpdateRoadmap_Hdl, Timer*, void);
1692 
1693 public:
1694  SalInstanceAssistant(vcl::RoadmapWizard* pDialog, SalInstanceBuilder* pBuilder,
1695  bool bTakeOwnership)
1696  : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1697  , m_xWizard(pDialog)
1698  {
1699  m_xWizard->SetItemSelectHdl(LINK(this, SalInstanceAssistant, OnRoadmapItemSelected));
1700 
1701  m_aUpdateRoadmapIdle.SetInvokeHandler(LINK(this, SalInstanceAssistant, UpdateRoadmap_Hdl));
1702  m_aUpdateRoadmapIdle.SetPriority(TaskPriority::HIGHEST);
1703  }
1704 
1705  virtual int get_current_page() const override { return find_id(m_xWizard->GetCurLevel()); }
1706 
1707  virtual int get_n_pages() const override { return m_aAddedPages.size(); }
1708 
1709  virtual OString get_page_ident(int nPage) const override
1710  {
1711  return m_aAddedPages[nPage]->get_id().toUtf8();
1712  }
1713 
1714  virtual OString get_current_page_ident() const override
1715  {
1716  return get_page_ident(get_current_page());
1717  }
1718 
1719  virtual void set_current_page(int nPage) override
1720  {
1722 
1723  // take the first shown page as the size for all pages
1724  if (m_xWizard->GetPageSizePixel().Width() == 0)
1725  {
1726  Size aFinalSize;
1727  for (int i = 0, nPages = get_n_pages(); i < nPages; ++i)
1728  {
1729  TabPage* pPage = m_xWizard->GetPage(m_aIds[i]);
1730  assert(pPage);
1731  Size aPageSize(pPage->get_preferred_size());
1732  if (aPageSize.Width() > aFinalSize.Width())
1733  aFinalSize.setWidth(aPageSize.Width());
1734  if (aPageSize.Height() > aFinalSize.Height())
1735  aFinalSize.setHeight(aPageSize.Height());
1736  }
1737  m_xWizard->SetPageSizePixel(aFinalSize);
1738  }
1739 
1740  (void)m_xWizard->ShowPage(m_aIds[nPage]);
1742  }
1743 
1744  virtual void set_current_page(const OString& rIdent) override
1745  {
1746  int nIndex = find_page(rIdent);
1747  if (nIndex == -1)
1748  return;
1749  set_current_page(nIndex);
1750  }
1751 
1752  virtual void set_page_index(const OString& rIdent, int nNewIndex) override
1753  {
1754  int nOldIndex = find_page(rIdent);
1755 
1756  if (nOldIndex == -1)
1757  return;
1758 
1759  if (nOldIndex == nNewIndex)
1760  return;
1761 
1763 
1764  auto entry = std::move(m_aAddedPages[nOldIndex]);
1765  m_aAddedPages.erase(m_aAddedPages.begin() + nOldIndex);
1766  m_aAddedPages.insert(m_aAddedPages.begin() + nNewIndex, std::move(entry));
1767 
1768  int nId = m_aIds[nOldIndex];
1769  m_aIds.erase(m_aIds.begin() + nOldIndex);
1770  m_aIds.insert(m_aIds.begin() + nNewIndex, nId);
1771 
1772  m_aUpdateRoadmapIdle.Start();
1773 
1775  }
1776 
1777  virtual weld::Container* append_page(const OString& rIdent) override
1778  {
1779  VclPtrInstance<TabPage> xPage(m_xWizard);
1780  VclPtrInstance<VclGrid> xGrid(xPage);
1781  xPage->set_id(OUString::fromUtf8(rIdent));
1782  xPage->Show();
1783  xGrid->set_hexpand(true);
1784  xGrid->set_vexpand(true);
1785  xGrid->Show();
1786  m_xWizard->AddPage(xPage);
1787  m_aIds.push_back(m_aAddedPages.size());
1788  m_xWizard->SetPage(m_aIds.back(), xPage);
1789  m_aAddedPages.push_back(xPage);
1790  m_aAddedGrids.push_back(xGrid);
1791 
1792  m_aUpdateRoadmapIdle.Start();
1793 
1794  m_aPages.emplace_back(new SalInstanceContainer(xGrid, m_pBuilder, false));
1795  return m_aPages.back().get();
1796  }
1797 
1798  virtual OUString get_page_title(const OString& rIdent) const override
1799  {
1800  int nIndex = find_page(rIdent);
1801  if (nIndex == -1)
1802  return OUString();
1803  return m_aAddedPages[nIndex]->GetText();
1804  }
1805 
1806  virtual void set_page_title(const OString& rIdent, const OUString& rTitle) override
1807  {
1808  int nIndex = find_page(rIdent);
1809  if (nIndex == -1)
1810  return;
1811  if (m_aAddedPages[nIndex]->GetText() != rTitle)
1812  {
1814  m_aAddedPages[nIndex]->SetText(rTitle);
1815  m_aUpdateRoadmapIdle.Start();
1817  }
1818  }
1819 
1820  virtual void set_page_sensitive(const OString& rIdent, bool bSensitive) override
1821  {
1822  int nIndex = find_page(rIdent);
1823  if (nIndex == -1)
1824  return;
1825  if (m_aAddedPages[nIndex]->IsEnabled() != bSensitive)
1826  {
1828  m_aAddedPages[nIndex]->Enable(bSensitive);
1829  m_aUpdateRoadmapIdle.Start();
1831  }
1832  }
1833 
1834  virtual void set_page_side_help_id(const OString& rHelpId) override
1835  {
1836  m_xWizard->SetRoadmapHelpId(rHelpId);
1837  }
1838 
1839  weld::Button* weld_widget_for_response(int nResponse) override;
1840 
1841  virtual ~SalInstanceAssistant() override
1842  {
1843  for (auto& rGrid : m_aAddedGrids)
1844  rGrid.disposeAndClear();
1845  for (auto& rPage : m_aAddedPages)
1846  rPage.disposeAndClear();
1847  }
1848 };
1849 
1850 }
1851 
1852 IMPL_LINK_NOARG(SalInstanceAssistant, OnRoadmapItemSelected, LinkParamNone*, void)
1853 {
1854  if (notify_events_disabled())
1855  return;
1856  int nPageIndex(find_id(m_xWizard->GetCurrentRoadmapItemID()));
1857  if (!signal_jump_page(get_page_ident(nPageIndex)))
1858  m_xWizard->SelectRoadmapItemByID(m_xWizard->GetCurLevel());
1859 }
1860 
1861 IMPL_LINK_NOARG(SalInstanceAssistant, UpdateRoadmap_Hdl, Timer*, void)
1862 {
1863  disable_notify_events();
1864 
1865  m_xWizard->DeleteRoadmapItems();
1866 
1867  int nPos = 0;
1868  for (size_t i = 0; i < m_aAddedPages.size(); ++i)
1869  {
1870  const OUString& rLabel = m_aAddedPages[i]->GetText();
1871  bool bSensitive = m_aAddedPages[i]->IsEnabled();
1872  if (rLabel.isEmpty())
1873  continue;
1874  m_xWizard->InsertRoadmapItem(nPos++, rLabel, m_aIds[i], bSensitive);
1875  }
1876 
1877  m_xWizard->SelectRoadmapItemByID(m_aIds[get_current_page()]);
1878 
1879  m_xWizard->ShowRoadmap(nPos != 0);
1880 
1881  enable_notify_events();
1882 }
1883 
1884 namespace
1885 {
1886 class SalInstanceFrame : public SalInstanceContainer, public virtual weld::Frame
1887 {
1888 private:
1890 
1891 public:
1892  SalInstanceFrame(VclFrame* pFrame, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1893  : SalInstanceContainer(pFrame, pBuilder, bTakeOwnership)
1894  , m_xFrame(pFrame)
1895  {
1896  }
1897 
1898  virtual void set_label(const OUString& rText) override { m_xFrame->set_label(rText); }
1899 
1900  virtual OUString get_label() const override { return m_xFrame->get_label(); }
1901 
1902  virtual std::unique_ptr<weld::Label> weld_label_widget() const override;
1903 };
1904 
1905 class SalInstanceScrolledWindow : public SalInstanceContainer, public virtual weld::ScrolledWindow
1906 {
1907 private:
1908  VclPtr<VclScrolledWindow> m_xScrolledWindow;
1909  Link<ScrollBar*, void> m_aOrigVScrollHdl;
1910  Link<ScrollBar*, void> m_aOrigHScrollHdl;
1911  bool m_bUserManagedScrolling;
1912 
1913  DECL_LINK(VscrollHdl, ScrollBar*, void);
1914  DECL_LINK(HscrollHdl, ScrollBar*, void);
1915 
1916 public:
1917  SalInstanceScrolledWindow(VclScrolledWindow* pScrolledWindow, SalInstanceBuilder* pBuilder,
1918  bool bTakeOwnership)
1919  : SalInstanceContainer(pScrolledWindow, pBuilder, bTakeOwnership)
1920  , m_xScrolledWindow(pScrolledWindow)
1921  , m_bUserManagedScrolling(false)
1922  {
1923  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
1924  m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl();
1925  rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, VscrollHdl));
1926  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1927  m_aOrigHScrollHdl = rHorzScrollBar.GetScrollHdl();
1928  rHorzScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, HscrollHdl));
1929  }
1930 
1931  virtual void hadjustment_configure(int value, int lower, int upper, int step_increment,
1932  int page_increment, int page_size) override
1933  {
1934  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1935  rHorzScrollBar.SetRangeMin(lower);
1936  rHorzScrollBar.SetRangeMax(upper);
1937  rHorzScrollBar.SetLineSize(step_increment);
1938  rHorzScrollBar.SetPageSize(page_increment);
1939  rHorzScrollBar.SetThumbPos(value);
1940  rHorzScrollBar.SetVisibleSize(page_size);
1941  }
1942 
1943  virtual int hadjustment_get_value() const override
1944  {
1945  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1946  return rHorzScrollBar.GetThumbPos();
1947  }
1948 
1949  virtual void hadjustment_set_value(int value) override
1950  {
1951  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1952  rHorzScrollBar.SetThumbPos(value);
1953  if (!m_bUserManagedScrolling)
1954  m_aOrigHScrollHdl.Call(&rHorzScrollBar);
1955  }
1956 
1957  virtual int hadjustment_get_upper() const override
1958  {
1959  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1960  return rHorzScrollBar.GetRangeMax();
1961  }
1962 
1963  virtual void hadjustment_set_upper(int upper) override
1964  {
1965  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1966  rHorzScrollBar.SetRangeMax(upper);
1967  }
1968 
1969  virtual int hadjustment_get_page_size() const override
1970  {
1971  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1972  return rHorzScrollBar.GetVisibleSize();
1973  }
1974 
1975  virtual void hadjustment_set_page_size(int size) override
1976  {
1977  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1978  return rHorzScrollBar.SetVisibleSize(size);
1979  }
1980 
1981  virtual void hadjustment_set_page_increment(int size) override
1982  {
1983  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1984  return rHorzScrollBar.SetPageSize(size);
1985  }
1986 
1987  virtual void hadjustment_set_step_increment(int size) override
1988  {
1989  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1990  return rHorzScrollBar.SetLineSize(size);
1991  }
1992 
1993  virtual void set_hpolicy(VclPolicyType eHPolicy) override
1994  {
1995  WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOHSCROLL | WB_HSCROLL);
1996  if (eHPolicy == VclPolicyType::ALWAYS)
1997  nWinBits |= WB_HSCROLL;
1998  else if (eHPolicy == VclPolicyType::AUTOMATIC)
1999  nWinBits |= WB_AUTOHSCROLL;
2000  m_xScrolledWindow->SetStyle(nWinBits);
2001  m_xScrolledWindow->queue_resize();
2002  }
2003 
2004  virtual VclPolicyType get_hpolicy() const override
2005  {
2006  WinBits nWinBits = m_xScrolledWindow->GetStyle();
2007  if (nWinBits & WB_AUTOHSCROLL)
2008  return VclPolicyType::AUTOMATIC;
2009  else if (nWinBits & WB_HSCROLL)
2010  return VclPolicyType::ALWAYS;
2011  return VclPolicyType::NEVER;
2012  }
2013 
2014  virtual int get_hscroll_height() const override
2015  {
2016  return m_xScrolledWindow->getHorzScrollBar().get_preferred_size().Height();
2017  }
2018 
2019  virtual void vadjustment_configure(int value, int lower, int upper, int step_increment,
2020  int page_increment, int page_size) override
2021  {
2022  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2023  rVertScrollBar.SetRangeMin(lower);
2024  rVertScrollBar.SetRangeMax(upper);
2025  rVertScrollBar.SetLineSize(step_increment);
2026  rVertScrollBar.SetPageSize(page_increment);
2027  rVertScrollBar.SetThumbPos(value);
2028  rVertScrollBar.SetVisibleSize(page_size);
2029  }
2030 
2031  virtual int vadjustment_get_value() const override
2032  {
2033  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2034  return rVertScrollBar.GetThumbPos();
2035  }
2036 
2037  virtual void vadjustment_set_value(int value) override
2038  {
2039  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2040  rVertScrollBar.SetThumbPos(value);
2041  if (!m_bUserManagedScrolling)
2042  m_aOrigVScrollHdl.Call(&rVertScrollBar);
2043  }
2044 
2045  virtual int vadjustment_get_upper() const override
2046  {
2047  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2048  return rVertScrollBar.GetRangeMax();
2049  }
2050 
2051  virtual void vadjustment_set_upper(int upper) override
2052  {
2053  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2054  rVertScrollBar.SetRangeMax(upper);
2055  }
2056 
2057  virtual int vadjustment_get_lower() const override
2058  {
2059  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2060  return rVertScrollBar.GetRangeMin();
2061  }
2062 
2063  virtual void vadjustment_set_lower(int lower) override
2064  {
2065  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2066  rVertScrollBar.SetRangeMin(lower);
2067  }
2068 
2069  virtual int vadjustment_get_page_size() const override
2070  {
2071  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2072  return rVertScrollBar.GetVisibleSize();
2073  }
2074 
2075  virtual void vadjustment_set_page_size(int size) override
2076  {
2077  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2078  return rVertScrollBar.SetVisibleSize(size);
2079  }
2080 
2081  virtual void vadjustment_set_page_increment(int size) override
2082  {
2083  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2084  return rVertScrollBar.SetPageSize(size);
2085  }
2086 
2087  virtual void vadjustment_set_step_increment(int size) override
2088  {
2089  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2090  return rVertScrollBar.SetLineSize(size);
2091  }
2092 
2093  virtual void set_vpolicy(VclPolicyType eVPolicy) override
2094  {
2095  WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOVSCROLL | WB_VSCROLL);
2096  if (eVPolicy == VclPolicyType::ALWAYS)
2097  nWinBits |= WB_VSCROLL;
2098  else if (eVPolicy == VclPolicyType::AUTOMATIC)
2099  nWinBits |= WB_AUTOVSCROLL;
2100  m_xScrolledWindow->SetStyle(nWinBits);
2101  m_xScrolledWindow->queue_resize();
2102  }
2103 
2104  virtual VclPolicyType get_vpolicy() const override
2105  {
2106  WinBits nWinBits = m_xScrolledWindow->GetStyle();
2107  if (nWinBits & WB_AUTOVSCROLL)
2108  return VclPolicyType::AUTOMATIC;
2109  else if (nWinBits & WB_VSCROLL)
2110  return VclPolicyType::ALWAYS;
2111  return VclPolicyType::NEVER;
2112  }
2113 
2114  virtual int get_vscroll_width() const override
2115  {
2116  return m_xScrolledWindow->getVertScrollBar().get_preferred_size().Width();
2117  }
2118 
2119  virtual void set_user_managed_scrolling() override
2120  {
2121  m_bUserManagedScrolling = true;
2122  m_xScrolledWindow->setUserManagedScrolling(true);
2123  }
2124 
2125  virtual ~SalInstanceScrolledWindow() override
2126  {
2127  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2128  rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl);
2129  }
2130 };
2131 
2132 }
2133 
2134 IMPL_LINK(SalInstanceScrolledWindow, VscrollHdl, ScrollBar*, pScrollBar, void)
2135 {
2136  signal_vadjustment_changed();
2137  if (!m_bUserManagedScrolling)
2138  m_aOrigVScrollHdl.Call(pScrollBar);
2139 }
2140 
2141 IMPL_LINK_NOARG(SalInstanceScrolledWindow, HscrollHdl, ScrollBar*, void)
2142 {
2143  signal_hadjustment_changed();
2144  if (!m_bUserManagedScrolling)
2145  m_aOrigHScrollHdl.Call(&m_xScrolledWindow->getHorzScrollBar());
2146 }
2147 
2148 namespace
2149 {
2150 class SalInstanceNotebook : public SalInstanceContainer, public virtual weld::Notebook
2151 {
2152 private:
2153  VclPtr<TabControl> m_xNotebook;
2154  mutable std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
2155  std::map<OString, std::pair<VclPtr<TabPage>, VclPtr<VclGrid>>> m_aAddedPages;
2156 
2157  DECL_LINK(DeactivatePageHdl, TabControl*, bool);
2158  DECL_LINK(ActivatePageHdl, TabControl*, void);
2159 
2160 public:
2161  SalInstanceNotebook(TabControl* pNotebook, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2162  : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership)
2163  , m_xNotebook(pNotebook)
2164  {
2165  m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceNotebook, ActivatePageHdl));
2166  m_xNotebook->SetDeactivatePageHdl(LINK(this, SalInstanceNotebook, DeactivatePageHdl));
2167  }
2168 
2169  virtual int get_current_page() const override
2170  {
2171  return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId());
2172  }
2173 
2174  virtual OString get_page_ident(int nPage) const override
2175  {
2176  return m_xNotebook->GetPageName(m_xNotebook->GetPageId(nPage));
2177  }
2178 
2179  virtual OString get_current_page_ident() const override
2180  {
2181  return m_xNotebook->GetPageName(m_xNotebook->GetCurPageId());
2182  }
2183 
2184  virtual weld::Container* get_page(const OString& rIdent) const override
2185  {
2186  sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2187  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2188  if (nPageIndex == TAB_PAGE_NOTFOUND)
2189  return nullptr;
2190  TabPage* pPage = m_xNotebook->GetTabPage(nPageId);
2191  vcl::Window* pChild = pPage->GetChild(0);
2192  if (m_aPages.size() < nPageIndex + 1U)
2193  m_aPages.resize(nPageIndex + 1U);
2194  if (!m_aPages[nPageIndex])
2195  m_aPages[nPageIndex].reset(new SalInstanceContainer(pChild, m_pBuilder, false));
2196  return m_aPages[nPageIndex].get();
2197  }
2198 
2199  virtual void set_current_page(int nPage) override
2200  {
2201  m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage));
2202  }
2203 
2204  virtual void set_current_page(const OString& rIdent) override
2205  {
2206  m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(rIdent));
2207  }
2208 
2209  virtual void remove_page(const OString& rIdent) override
2210  {
2211  sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2212  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2213  if (nPageIndex == TAB_PAGE_NOTFOUND)
2214  return;
2215 
2216  m_xNotebook->RemovePage(nPageId);
2217  if (nPageIndex < m_aPages.size())
2218  m_aPages.erase(m_aPages.begin() + nPageIndex);
2219 
2220  auto iter = m_aAddedPages.find(rIdent);
2221  if (iter != m_aAddedPages.end())
2222  {
2223  iter->second.second.disposeAndClear();
2224  iter->second.first.disposeAndClear();
2225  m_aAddedPages.erase(iter);
2226  }
2227  }
2228 
2229  virtual void insert_page(const OString& rIdent, const OUString& rLabel, int nPos) override
2230  {
2231  sal_uInt16 nPageCount = m_xNotebook->GetPageCount();
2232  sal_uInt16 nLastPageId = nPageCount ? m_xNotebook->GetPageId(nPageCount - 1) : 0;
2233  sal_uInt16 nNewPageId = nLastPageId + 1;
2234  m_xNotebook->InsertPage(nNewPageId, rLabel, nPos == -1 ? TAB_APPEND : nPos);
2235  VclPtrInstance<TabPage> xPage(m_xNotebook);
2236  VclPtrInstance<VclGrid> xGrid(xPage);
2237  xPage->Show();
2238  xGrid->set_hexpand(true);
2239  xGrid->set_vexpand(true);
2240  xGrid->Show();
2241  m_xNotebook->SetTabPage(nNewPageId, xPage);
2242  m_xNotebook->SetPageName(nNewPageId, rIdent);
2243  m_aAddedPages.try_emplace(rIdent, xPage, xGrid);
2244  }
2245 
2246  virtual int get_n_pages() const override { return m_xNotebook->GetPageCount(); }
2247 
2248  virtual OUString get_tab_label_text(const OString& rIdent) const override
2249  {
2250  return m_xNotebook->GetPageText(m_xNotebook->GetPageId(rIdent));
2251  }
2252 
2253  virtual void set_tab_label_text(const OString& rIdent, const OUString& rText) override
2254  {
2255  return m_xNotebook->SetPageText(m_xNotebook->GetPageId(rIdent), rText);
2256  }
2257 
2258  virtual ~SalInstanceNotebook() override
2259  {
2260  for (auto& rItem : m_aAddedPages)
2261  {
2262  rItem.second.second.disposeAndClear();
2263  rItem.second.first.disposeAndClear();
2264  }
2267  }
2268 };
2269 
2270 }
2271 
2272 IMPL_LINK_NOARG(SalInstanceNotebook, DeactivatePageHdl, TabControl*, bool)
2273 {
2274  return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2275 }
2276 
2277 IMPL_LINK_NOARG(SalInstanceNotebook, ActivatePageHdl, TabControl*, void)
2278 {
2279  m_aEnterPageHdl.Call(get_current_page_ident());
2280 }
2281 
2282 namespace
2283 {
2284 class SalInstanceVerticalNotebook : public SalInstanceContainer, public virtual weld::Notebook
2285 {
2286 private:
2287  VclPtr<VerticalTabControl> m_xNotebook;
2288  mutable std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
2289 
2290  DECL_LINK(DeactivatePageHdl, VerticalTabControl*, bool);
2291  DECL_LINK(ActivatePageHdl, VerticalTabControl*, void);
2292 
2293 public:
2294  SalInstanceVerticalNotebook(VerticalTabControl* pNotebook, SalInstanceBuilder* pBuilder,
2295  bool bTakeOwnership)
2296  : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership)
2297  , m_xNotebook(pNotebook)
2298  {
2299  m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceVerticalNotebook, ActivatePageHdl));
2300  m_xNotebook->SetDeactivatePageHdl(
2301  LINK(this, SalInstanceVerticalNotebook, DeactivatePageHdl));
2302  }
2303 
2304  virtual int get_current_page() const override
2305  {
2306  return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId());
2307  }
2308 
2309  virtual OString get_page_ident(int nPage) const override
2310  {
2311  return m_xNotebook->GetPageId(nPage);
2312  }
2313 
2314  virtual OString get_current_page_ident() const override { return m_xNotebook->GetCurPageId(); }
2315 
2316  virtual weld::Container* get_page(const OString& rIdent) const override
2317  {
2318  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2319  if (nPageIndex == TAB_PAGE_NOTFOUND)
2320  return nullptr;
2321  auto pChild = m_xNotebook->GetPage(rIdent);
2322  if (m_aPages.size() < nPageIndex + 1U)
2323  m_aPages.resize(nPageIndex + 1U);
2324  if (!m_aPages[nPageIndex])
2325  m_aPages[nPageIndex].reset(new SalInstanceContainer(pChild, m_pBuilder, false));
2326  return m_aPages[nPageIndex].get();
2327  }
2328 
2329  virtual void set_current_page(int nPage) override
2330  {
2331  m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage));
2332  }
2333 
2334  virtual void set_current_page(const OString& rIdent) override
2335  {
2336  m_xNotebook->SetCurPageId(rIdent);
2337  }
2338 
2339  virtual void remove_page(const OString& rIdent) override
2340  {
2341  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2342  if (nPageIndex == TAB_PAGE_NOTFOUND)
2343  return;
2344  m_xNotebook->RemovePage(rIdent);
2345  if (nPageIndex < m_aPages.size())
2346  m_aPages.erase(m_aPages.begin() + nPageIndex);
2347  }
2348 
2349  virtual void insert_page(const OString& rIdent, const OUString& rLabel, int nPos) override
2350  {
2351  VclPtrInstance<VclGrid> xGrid(m_xNotebook->GetPageParent());
2352  xGrid->set_hexpand(true);
2353  xGrid->set_vexpand(true);
2354  m_xNotebook->InsertPage(rIdent, rLabel, Image(), "", xGrid, nPos);
2355  }
2356 
2357  virtual int get_n_pages() const override { return m_xNotebook->GetPageCount(); }
2358 
2359  virtual void set_tab_label_text(const OString& rIdent, const OUString& rText) override
2360  {
2361  return m_xNotebook->SetPageText(rIdent, rText);
2362  }
2363 
2364  virtual OUString get_tab_label_text(const OString& rIdent) const override
2365  {
2366  return m_xNotebook->GetPageText(rIdent);
2367  }
2368 
2369  virtual ~SalInstanceVerticalNotebook() override
2370  {
2373  }
2374 };
2375 
2376 }
2377 
2378 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, DeactivatePageHdl, VerticalTabControl*, bool)
2379 {
2380  return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2381 }
2382 
2383 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, ActivatePageHdl, VerticalTabControl*, void)
2384 {
2385  m_aEnterPageHdl.Call(get_current_page_ident());
2386 }
2387 
2388 namespace
2389 {
2390 class SalInstanceButton : public SalInstanceContainer, public virtual weld::Button
2391 {
2392 private:
2393  VclPtr<::Button> m_xButton;
2394  Link<::Button*, void> const m_aOldClickHdl;
2395 
2396  DECL_LINK(ClickHdl, ::Button*, void);
2397 
2398 public:
2399  SalInstanceButton(::Button* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2400  : SalInstanceContainer(pButton, pBuilder, bTakeOwnership)
2401  , m_xButton(pButton)
2402  , m_aOldClickHdl(pButton->GetClickHdl())
2403  {
2404  m_xButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2405  }
2406 
2407  virtual void set_label(const OUString& rText) override { m_xButton->SetText(rText); }
2408 
2409  virtual void set_image(VirtualDevice* pDevice) override
2410  {
2411  m_xButton->SetImageAlign(ImageAlign::Left);
2412  if (pDevice)
2413  m_xButton->SetModeImage(createImage(*pDevice));
2414  else
2415  m_xButton->SetModeImage(Image());
2416  }
2417 
2418  virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2419  {
2420  m_xButton->SetImageAlign(ImageAlign::Left);
2421  m_xButton->SetModeImage(Image(rImage));
2422  }
2423 
2424  virtual void set_from_icon_name(const OUString& rIconName) override
2425  {
2426  m_xButton->SetModeImage(Image(StockImage::Yes, rIconName));
2427  }
2428 
2429  virtual void set_label_line_wrap(bool wrap) override
2430  {
2431  WinBits nBits = m_xButton->GetStyle();
2432  nBits &= ~WB_WORDBREAK;
2433  if (wrap)
2434  nBits |= WB_WORDBREAK;
2435  m_xButton->SetStyle(nBits);
2436  m_xButton->queue_resize();
2437  }
2438 
2439  virtual OUString get_label() const override { return m_xButton->GetText(); }
2440 
2441  virtual ~SalInstanceButton() override { m_xButton->SetClickHdl(Link<::Button*, void>()); }
2442 };
2443 
2444 }
2445 
2446 IMPL_LINK(SalInstanceButton, ClickHdl, ::Button*, pButton, void)
2447 {
2448  //if there's no handler set, disengage our intercept and
2449  //run the click again to get default behaviour for cancel/ok
2450  //etc buttons.
2451  if (!m_aClickHdl.IsSet())
2452  {
2453  pButton->SetClickHdl(m_aOldClickHdl);
2454  pButton->Click();
2455  pButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2456  return;
2457  }
2458  signal_clicked();
2459 }
2460 
2462 {
2463  PushButton* pButton = dynamic_cast<PushButton*>(m_xDialog->get_widget_for_response(nResponse));
2464  return pButton ? new SalInstanceButton(pButton, nullptr, false) : nullptr;
2465 }
2466 
2467 weld::Button* SalInstanceAssistant::weld_widget_for_response(int nResponse)
2468 {
2469  PushButton* pButton = nullptr;
2470  if (nResponse == RET_YES)
2471  pButton = m_xWizard->m_pNextPage;
2472  else if (nResponse == RET_NO)
2473  pButton = m_xWizard->m_pPrevPage;
2474  else if (nResponse == RET_OK)
2475  pButton = m_xWizard->m_pFinish;
2476  else if (nResponse == RET_CANCEL)
2477  pButton = m_xWizard->m_pCancel;
2478  else if (nResponse == RET_HELP)
2479  pButton = m_xWizard->m_pHelp;
2480  if (pButton)
2481  return new SalInstanceButton(pButton, nullptr, false);
2482  return nullptr;
2483 }
2484 
2485 namespace
2486 {
2487 class SalInstanceMenuButton : public SalInstanceButton, public virtual weld::MenuButton
2488 {
2489 private:
2490  VclPtr<::MenuButton> m_xMenuButton;
2491  sal_uInt16 m_nLastId;
2492 
2493  DECL_LINK(MenuSelectHdl, ::MenuButton*, void);
2494  DECL_LINK(ActivateHdl, ::MenuButton*, void);
2495 
2496 public:
2497  SalInstanceMenuButton(::MenuButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2498  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2499  , m_xMenuButton(pButton)
2500  , m_nLastId(0)
2501  {
2502  m_xMenuButton->SetActivateHdl(LINK(this, SalInstanceMenuButton, ActivateHdl));
2503  m_xMenuButton->SetSelectHdl(LINK(this, SalInstanceMenuButton, MenuSelectHdl));
2504  if (PopupMenu* pMenu = m_xMenuButton->GetPopupMenu())
2505  {
2506  pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
2507  const auto nCount = pMenu->GetItemCount();
2508  m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
2509  }
2510  }
2511 
2512  virtual void set_active(bool active) override
2513  {
2514  if (active == get_active())
2515  return;
2516  if (active)
2517  m_xMenuButton->ExecuteMenu();
2518  else
2519  m_xMenuButton->CancelMenu();
2520  }
2521 
2522  virtual bool get_active() const override { return m_xMenuButton->InPopupMode(); }
2523 
2524  virtual void set_inconsistent(bool /*inconsistent*/) override
2525  {
2526  //not available
2527  }
2528 
2529  virtual bool get_inconsistent() const override { return false; }
2530 
2531  virtual void insert_item(int pos, const OUString& rId, const OUString& rStr,
2532  const OUString* pIconName, VirtualDevice* pImageSurface,
2533  TriState eCheckRadioFalse) override
2534  {
2535  m_nLastId = insert_to_menu(m_nLastId, m_xMenuButton->GetPopupMenu(), pos, rId, rStr,
2536  pIconName, pImageSurface, eCheckRadioFalse);
2537  }
2538 
2539  virtual void insert_separator(int pos, const OUString& rId) override
2540  {
2541  auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
2542  m_xMenuButton->GetPopupMenu()->InsertSeparator(rId.toUtf8(), nInsertPos);
2543  }
2544 
2545  virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) override
2546  {
2547  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2548  pMenu->EnableItem(rIdent, bSensitive);
2549  }
2550 
2551  virtual void remove_item(const OString& rId) override
2552  {
2553  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2554  pMenu->RemoveItem(pMenu->GetItemPos(pMenu->GetItemId(rId)));
2555  }
2556 
2557  virtual void clear() override
2558  {
2559  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2560  pMenu->Clear();
2561  }
2562 
2563  virtual void set_item_active(const OString& rIdent, bool bActive) override
2564  {
2565  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2566  pMenu->CheckItem(rIdent, bActive);
2567  }
2568 
2569  virtual void set_item_label(const OString& rIdent, const OUString& rText) override
2570  {
2571  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2572  pMenu->SetItemText(pMenu->GetItemId(rIdent), rText);
2573  }
2574 
2575  virtual OUString get_item_label(const OString& rIdent) const override
2576  {
2577  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2578  return pMenu->GetItemText(pMenu->GetItemId(rIdent));
2579  }
2580 
2581  virtual void set_item_visible(const OString& rIdent, bool bShow) override
2582  {
2583  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2584  pMenu->ShowItem(pMenu->GetItemId(rIdent), bShow);
2585  }
2586 
2587  virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) override
2588  {
2589  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2590  pMenu->SetHelpId(pMenu->GetItemId(rIdent), rHelpId);
2591  }
2592 
2593  virtual OString get_item_help_id(const OString& rIdent) const override
2594  {
2595  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2596  return pMenu->GetHelpId(pMenu->GetItemId(rIdent));
2597  }
2598 
2599  virtual void set_popover(weld::Widget* pPopover) override
2600  {
2601  SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
2602  m_xMenuButton->SetPopover(pPopoverWidget ? pPopoverWidget->getWidget() : nullptr);
2603  }
2604 
2605  virtual ~SalInstanceMenuButton() override
2606  {
2607  m_xMenuButton->SetSelectHdl(Link<::MenuButton*, void>());
2608  m_xMenuButton->SetActivateHdl(Link<::MenuButton*, void>());
2609  }
2610 };
2611 
2612 }
2613 
2614 IMPL_LINK_NOARG(SalInstanceMenuButton, MenuSelectHdl, ::MenuButton*, void)
2615 {
2616  signal_selected(m_xMenuButton->GetCurItemIdent());
2617 }
2618 
2619 IMPL_LINK_NOARG(SalInstanceMenuButton, ActivateHdl, ::MenuButton*, void)
2620 {
2621  if (notify_events_disabled())
2622  return;
2623  signal_toggled();
2624 }
2625 
2626 namespace
2627 {
2628 class SalInstanceLinkButton : public SalInstanceContainer, public virtual weld::LinkButton
2629 {
2630 private:
2631  VclPtr<FixedHyperlink> m_xButton;
2632  Link<FixedHyperlink&, void> m_aOrigClickHdl;
2633 
2634  DECL_LINK(ClickHdl, FixedHyperlink&, void);
2635 
2636 public:
2637  SalInstanceLinkButton(FixedHyperlink* pButton, SalInstanceBuilder* pBuilder,
2638  bool bTakeOwnership)
2639  : SalInstanceContainer(pButton, pBuilder, bTakeOwnership)
2640  , m_xButton(pButton)
2641  {
2642  m_aOrigClickHdl = m_xButton->GetClickHdl();
2643  m_xButton->SetClickHdl(LINK(this, SalInstanceLinkButton, ClickHdl));
2644  }
2645 
2646  virtual void set_label(const OUString& rText) override { m_xButton->SetText(rText); }
2647 
2648  virtual OUString get_label() const override { return m_xButton->GetText(); }
2649 
2650  virtual void set_uri(const OUString& rUri) override { m_xButton->SetURL(rUri); }
2651 
2652  virtual OUString get_uri() const override { return m_xButton->GetURL(); }
2653 
2654  virtual ~SalInstanceLinkButton() override { m_xButton->SetClickHdl(m_aOrigClickHdl); }
2655 };
2656 
2657 }
2658 
2659 IMPL_LINK(SalInstanceLinkButton, ClickHdl, FixedHyperlink&, rButton, void)
2660 {
2661  bool bConsumed = signal_activate_link();
2662  if (!bConsumed)
2663  m_aOrigClickHdl.Call(rButton);
2664 }
2665 
2666 namespace
2667 {
2668 class SalInstanceRadioButton : public SalInstanceButton, public virtual weld::RadioButton
2669 {
2670 private:
2671  VclPtr<::RadioButton> m_xRadioButton;
2672 
2673  DECL_LINK(ToggleHdl, ::RadioButton&, void);
2674 
2675 public:
2676  SalInstanceRadioButton(::RadioButton* pButton, SalInstanceBuilder* pBuilder,
2677  bool bTakeOwnership)
2678  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2679  , m_xRadioButton(pButton)
2680  {
2681  m_xRadioButton->SetToggleHdl(LINK(this, SalInstanceRadioButton, ToggleHdl));
2682  }
2683 
2684  virtual void set_active(bool active) override
2685  {
2686  disable_notify_events();
2687  m_xRadioButton->Check(active);
2688  enable_notify_events();
2689  }
2690 
2691  virtual bool get_active() const override { return m_xRadioButton->IsChecked(); }
2692 
2693  virtual void set_image(VirtualDevice* pDevice) override
2694  {
2695  m_xRadioButton->SetImageAlign(ImageAlign::Center);
2696  if (pDevice)
2697  m_xRadioButton->SetModeImage(createImage(*pDevice));
2698  else
2699  m_xRadioButton->SetModeImage(Image());
2700  }
2701 
2702  virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2703  {
2704  m_xRadioButton->SetImageAlign(ImageAlign::Center);
2705  m_xRadioButton->SetModeImage(Image(rImage));
2706  }
2707 
2708  virtual void set_from_icon_name(const OUString& rIconName) override
2709  {
2710  m_xRadioButton->SetModeRadioImage(Image(StockImage::Yes, rIconName));
2711  }
2712 
2713  virtual void set_inconsistent(bool /*inconsistent*/) override
2714  {
2715  //not available
2716  }
2717 
2718  virtual bool get_inconsistent() const override { return false; }
2719 
2720  virtual ~SalInstanceRadioButton() override
2721  {
2722  m_xRadioButton->SetToggleHdl(Link<::RadioButton&, void>());
2723  }
2724 };
2725 
2726 }
2727 
2728 IMPL_LINK_NOARG(SalInstanceRadioButton, ToggleHdl, ::RadioButton&, void)
2729 {
2730  if (notify_events_disabled())
2731  return;
2732  signal_toggled();
2733 }
2734 
2735 namespace
2736 {
2737 class SalInstanceToggleButton : public SalInstanceButton, public virtual weld::ToggleButton
2738 {
2739 private:
2740  VclPtr<PushButton> m_xToggleButton;
2741 
2742  DECL_LINK(ToggleListener, VclWindowEvent&, void);
2743 
2744 public:
2745  SalInstanceToggleButton(PushButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2746  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2747  , m_xToggleButton(pButton)
2748  {
2749  }
2750 
2751  virtual void connect_toggled(const Link<ToggleButton&, void>& rLink) override
2752  {
2753  assert(!m_aToggleHdl.IsSet());
2754  m_xToggleButton->AddEventListener(LINK(this, SalInstanceToggleButton, ToggleListener));
2756  }
2757 
2758  virtual void set_active(bool active) override
2759  {
2760  disable_notify_events();
2761  m_xToggleButton->Check(active);
2762  enable_notify_events();
2763  }
2764 
2765  virtual bool get_active() const override { return m_xToggleButton->IsChecked(); }
2766 
2767  virtual void set_inconsistent(bool inconsistent) override
2768  {
2769  disable_notify_events();
2770  m_xToggleButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE);
2771  enable_notify_events();
2772  }
2773 
2774  virtual bool get_inconsistent() const override
2775  {
2776  return m_xToggleButton->GetState() == TRISTATE_INDET;
2777  }
2778 
2779  virtual ~SalInstanceToggleButton() override
2780  {
2781  if (m_aToggleHdl.IsSet())
2782  m_xToggleButton->RemoveEventListener(
2783  LINK(this, SalInstanceToggleButton, ToggleListener));
2784  }
2785 };
2786 
2787 }
2788 
2789 IMPL_LINK(SalInstanceToggleButton, ToggleListener, VclWindowEvent&, rEvent, void)
2790 {
2791  if (notify_events_disabled())
2792  return;
2793  if (rEvent.GetId() == VclEventId::PushbuttonToggle)
2794  signal_toggled();
2795 }
2796 
2797 namespace
2798 {
2799 class SalInstanceCheckButton : public SalInstanceButton, public virtual weld::CheckButton
2800 {
2801 private:
2802  VclPtr<CheckBox> m_xCheckButton;
2803 
2804  DECL_LINK(ToggleHdl, CheckBox&, void);
2805 
2806 public:
2807  SalInstanceCheckButton(CheckBox* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2808  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2809  , m_xCheckButton(pButton)
2810  {
2811  m_xCheckButton->SetToggleHdl(LINK(this, SalInstanceCheckButton, ToggleHdl));
2812  }
2813 
2814  virtual void set_active(bool active) override
2815  {
2816  disable_notify_events();
2817  m_xCheckButton->EnableTriState(false);
2818  m_xCheckButton->Check(active);
2819  enable_notify_events();
2820  }
2821 
2822  virtual bool get_active() const override { return m_xCheckButton->IsChecked(); }
2823 
2824  virtual void set_inconsistent(bool inconsistent) override
2825  {
2826  disable_notify_events();
2827  m_xCheckButton->EnableTriState(true);
2828  m_xCheckButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE);
2829  enable_notify_events();
2830  }
2831 
2832  virtual bool get_inconsistent() const override
2833  {
2834  return m_xCheckButton->GetState() == TRISTATE_INDET;
2835  }
2836 
2837  virtual ~SalInstanceCheckButton() override
2838  {
2839  m_xCheckButton->SetToggleHdl(Link<CheckBox&, void>());
2840  }
2841 };
2842 
2843 }
2844 
2845 IMPL_LINK_NOARG(SalInstanceCheckButton, ToggleHdl, CheckBox&, void)
2846 {
2847  if (notify_events_disabled())
2848  return;
2849  m_xCheckButton->EnableTriState(false);
2850  signal_toggled();
2851 }
2852 
2853 namespace
2854 {
2855 class SalInstanceScale : public SalInstanceWidget, public virtual weld::Scale
2856 {
2857 private:
2858  VclPtr<Slider> m_xScale;
2859 
2860  DECL_LINK(SlideHdl, Slider*, void);
2861 
2862 public:
2863  SalInstanceScale(Slider* pScale, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2864  : SalInstanceWidget(pScale, pBuilder, bTakeOwnership)
2865  , m_xScale(pScale)
2866  {
2867  m_xScale->SetSlideHdl(LINK(this, SalInstanceScale, SlideHdl));
2868  }
2869 
2870  virtual void set_value(int value) override { m_xScale->SetThumbPos(value); }
2871 
2872  virtual void set_range(int min, int max) override
2873  {
2874  m_xScale->SetRangeMin(min);
2875  m_xScale->SetRangeMax(max);
2876  }
2877 
2878  virtual int get_value() const override { return m_xScale->GetThumbPos(); }
2879 
2880  virtual void set_increments(int step, int page) override
2881  {
2882  m_xScale->SetLineSize(step);
2883  m_xScale->SetPageSize(page);
2884  }
2885 
2886  virtual void get_increments(int& step, int& page) const override
2887  {
2888  step = m_xScale->GetLineSize();
2889  page = m_xScale->GetPageSize();
2890  }
2891 
2892  virtual ~SalInstanceScale() override { m_xScale->SetSlideHdl(Link<Slider*, void>()); }
2893 };
2894 
2895 }
2896 
2897 IMPL_LINK_NOARG(SalInstanceScale, SlideHdl, Slider*, void) { signal_value_changed(); }
2898 
2899 namespace
2900 {
2901 class SalInstanceSpinner : public SalInstanceWidget, public virtual weld::Spinner
2902 {
2903 private:
2904  VclPtr<Throbber> m_xThrobber;
2905 
2906 public:
2907  SalInstanceSpinner(Throbber* pThrobber, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2908  : SalInstanceWidget(pThrobber, pBuilder, bTakeOwnership)
2909  , m_xThrobber(pThrobber)
2910  {
2911  }
2912 
2913  virtual void start() override { m_xThrobber->start(); }
2914 
2915  virtual void stop() override { m_xThrobber->stop(); }
2916 };
2917 
2918 class SalInstanceProgressBar : public SalInstanceWidget, public virtual weld::ProgressBar
2919 {
2920 private:
2921  VclPtr<::ProgressBar> m_xProgressBar;
2922 
2923 public:
2924  SalInstanceProgressBar(::ProgressBar* pProgressBar, SalInstanceBuilder* pBuilder,
2925  bool bTakeOwnership)
2926  : SalInstanceWidget(pProgressBar, pBuilder, bTakeOwnership)
2927  , m_xProgressBar(pProgressBar)
2928  {
2929  }
2930 
2931  virtual void set_percentage(int value) override { m_xProgressBar->SetValue(value); }
2932 
2933  virtual OUString get_text() const override { return m_xProgressBar->GetText(); }
2934 
2935  virtual void set_text(const OUString& rText) override { m_xProgressBar->SetText(rText); }
2936 };
2937 
2938 class SalInstanceImage : public SalInstanceWidget, public virtual weld::Image
2939 {
2940 private:
2941  VclPtr<FixedImage> m_xImage;
2942 
2943 public:
2944  SalInstanceImage(FixedImage* pImage, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2945  : SalInstanceWidget(pImage, pBuilder, bTakeOwnership)
2946  , m_xImage(pImage)
2947  {
2948  }
2949 
2950  virtual void set_from_icon_name(const OUString& rIconName) override
2951  {
2952  m_xImage->SetImage(::Image(StockImage::Yes, rIconName));
2953  }
2954 
2955  virtual void set_image(VirtualDevice* pDevice) override
2956  {
2957  if (pDevice)
2958  m_xImage->SetImage(createImage(*pDevice));
2959  else
2960  m_xImage->SetImage(::Image());
2961  }
2962 
2963  virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2964  {
2965  m_xImage->SetImage(::Image(rImage));
2966  }
2967 };
2968 
2969 class SalInstanceCalendar : public SalInstanceWidget, public virtual weld::Calendar
2970 {
2971 private:
2972  VclPtr<::Calendar> m_xCalendar;
2973 
2974  DECL_LINK(SelectHdl, ::Calendar*, void);
2975  DECL_LINK(ActivateHdl, ::Calendar*, void);
2976 
2977 public:
2978  SalInstanceCalendar(::Calendar* pCalendar, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2979  : SalInstanceWidget(pCalendar, pBuilder, bTakeOwnership)
2980  , m_xCalendar(pCalendar)
2981  {
2982  m_xCalendar->SetSelectHdl(LINK(this, SalInstanceCalendar, SelectHdl));
2983  m_xCalendar->SetActivateHdl(LINK(this, SalInstanceCalendar, ActivateHdl));
2984  }
2985 
2986  virtual void set_date(const Date& rDate) override { m_xCalendar->SetCurDate(rDate); }
2987 
2988  virtual Date get_date() const override { return m_xCalendar->GetFirstSelectedDate(); }
2989 
2990  virtual ~SalInstanceCalendar() override
2991  {
2992  m_xCalendar->SetSelectHdl(Link<::Calendar*, void>());
2993  m_xCalendar->SetActivateHdl(Link<::Calendar*, void>());
2994  }
2995 };
2996 
2997 }
2998 
2999 IMPL_LINK_NOARG(SalInstanceCalendar, SelectHdl, ::Calendar*, void)
3000 {
3001  if (notify_events_disabled())
3002  return;
3003  signal_selected();
3004 }
3005 
3006 IMPL_LINK_NOARG(SalInstanceCalendar, ActivateHdl, ::Calendar*, void)
3007 {
3008  if (notify_events_disabled())
3009  return;
3010  signal_activated();
3011 }
3012 
3014  : TextFilter(OUString())
3015  , m_rInsertTextHdl(rInsertTextHdl)
3016 {
3017 }
3018 
3019 OUString WeldTextFilter::filter(const OUString& rText)
3020 {
3021  if (!m_rInsertTextHdl.IsSet())
3022  return rText;
3023  OUString sText(rText);
3024  const bool bContinue = m_rInsertTextHdl.Call(sText);
3025  if (!bContinue)
3026  return OUString();
3027  return sText;
3028 }
3029 
3030 SalInstanceEntry::SalInstanceEntry(Edit* pEntry, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3031  : SalInstanceWidget(pEntry, pBuilder, bTakeOwnership)
3032  , m_xEntry(pEntry)
3033  , m_aTextFilter(m_aInsertTextHdl)
3034 {
3035  m_xEntry->SetModifyHdl(LINK(this, SalInstanceEntry, ChangeHdl));
3036  m_xEntry->SetActivateHdl(LINK(this, SalInstanceEntry, ActivateHdl));
3038 }
3039 
3040 void SalInstanceEntry::set_text(const OUString& rText)
3041 {
3043  m_xEntry->SetText(rText);
3045 }
3046 
3048 {
3049  return m_xEntry->GetText();
3050 }
3051 
3053 {
3054  m_xEntry->SetWidthInChars(nChars);
3055 }
3056 
3058 {
3059  return m_xEntry->GetWidthInChars();
3060 }
3061 
3063 {
3064  m_xEntry->SetMaxTextLen(nChars);
3065 }
3066 
3067 void SalInstanceEntry::select_region(int nStartPos, int nEndPos)
3068 {
3070  m_xEntry->SetSelection(Selection(nStartPos, nEndPos < 0 ? SELECTION_MAX : nEndPos));
3072 }
3073 
3074 bool SalInstanceEntry::get_selection_bounds(int& rStartPos, int& rEndPos)
3075 {
3076  const Selection& rSelection = m_xEntry->GetSelection();
3077  rStartPos = rSelection.Min();
3078  rEndPos = rSelection.Max();
3079  return rSelection.Len();
3080 }
3081 
3082 void SalInstanceEntry::replace_selection(const OUString& rText)
3083 {
3084  m_xEntry->ReplaceSelected(rText);
3085 }
3086 
3088 {
3090  if (nCursorPos < 0)
3092  else
3093  m_xEntry->SetSelection(Selection(nCursorPos, nCursorPos));
3095 }
3096 
3098 {
3099  return m_xEntry->GetSelection().Max();
3100 }
3101 
3103 {
3104  m_xEntry->SetReadOnly(!bEditable);
3105 }
3106 
3108 {
3109  return !m_xEntry->IsReadOnly();
3110 }
3111 
3113 {
3114  if (eType == weld::EntryMessageType::Error)
3115  {
3116  // tdf#114603: enable setting the background to a different color;
3117  // relevant for GTK; see also #i75179#
3120  m_xEntry->SetControlBackground(0xff6563);
3121  }
3122  else if (eType == weld::EntryMessageType::Warning)
3123  {
3124  // tdf#114603: enable setting the background to a different color;
3125  // relevant for GTK; see also #i75179#
3129  }
3130  else
3131  {
3135  }
3136 }
3137 
3139 {
3140  m_xEntry->SetPointFont(*m_xEntry, rFont);
3141  m_xEntry->Invalidate();
3142 }
3143 
3145 {
3146  assert(!m_aCursorPositionHdl.IsSet());
3147  m_xEntry->AddEventListener(LINK(this, SalInstanceEntry, CursorListener));
3149 }
3150 
3151 void SalInstanceEntry::set_placeholder_text(const OUString& rText)
3152 {
3153  m_xEntry->SetPlaceholderText(rText);
3154 }
3155 
3157 {
3158  return *m_xEntry;
3159 }
3160 
3162 {
3163  signal_changed();
3164 }
3165 
3167 {
3168  m_xEntry->Cut();
3169 }
3170 
3172 {
3173  m_xEntry->Copy();
3174 }
3175 
3177 {
3178  m_xEntry->Paste();
3179 }
3180 
3182 {
3183  if (m_aCursorPositionHdl.IsSet())
3184  m_xEntry->RemoveEventListener(LINK(this, SalInstanceEntry, CursorListener));
3185  m_xEntry->SetTextFilter(nullptr);
3188 }
3189 
3190 IMPL_LINK_NOARG(SalInstanceEntry, ChangeHdl, Edit&, void) { signal_changed(); }
3191 
3192 IMPL_LINK(SalInstanceEntry, CursorListener, VclWindowEvent&, rEvent, void)
3193 {
3194  if (notify_events_disabled())
3195  return;
3196  if (rEvent.GetId() == VclEventId::EditSelectionChanged
3197  || rEvent.GetId() == VclEventId::EditCaretChanged)
3198  signal_cursor_position();
3199 }
3200 
3201 IMPL_LINK_NOARG(SalInstanceEntry, ActivateHdl, Edit&, bool) { return m_aActivateHdl.Call(*this); }
3202 
3203 namespace
3204 {
3205 struct SalInstanceTreeIter : public weld::TreeIter
3206 {
3207  SalInstanceTreeIter(const SalInstanceTreeIter* pOrig)
3208  : iter(pOrig ? pOrig->iter : nullptr)
3209  {
3210  }
3211  SalInstanceTreeIter(SvTreeListEntry* pIter)
3212  : iter(pIter)
3213  {
3214  }
3215  virtual bool equal(const TreeIter& rOther) const override
3216  {
3217  return iter == static_cast<const SalInstanceTreeIter&>(rOther).iter;
3218  }
3219  SvTreeListEntry* iter;
3220 };
3221 
3222 TriState get_toggle(SvTreeListEntry* pEntry, int col)
3223 {
3224  ++col; //skip dummy/expander column
3225 
3226  if (static_cast<size_t>(col) == pEntry->ItemCount())
3227  return TRISTATE_FALSE;
3228 
3229  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3230  SvLBoxItem& rItem = pEntry->GetItem(col);
3231  assert(dynamic_cast<SvLBoxButton*>(&rItem));
3232  SvLBoxButton& rToggle = static_cast<SvLBoxButton&>(rItem);
3233  if (rToggle.IsStateTristate())
3234  return TRISTATE_INDET;
3235  else if (rToggle.IsStateChecked())
3236  return TRISTATE_TRUE;
3237  return TRISTATE_FALSE;
3238 }
3239 
3240 bool get_text_emphasis(SvTreeListEntry* pEntry, int col)
3241 {
3242  ++col; //skip dummy/expander column
3243 
3244  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3245  SvLBoxItem& rItem = pEntry->GetItem(col);
3246  assert(dynamic_cast<SvLBoxString*>(&rItem));
3247  return static_cast<SvLBoxString&>(rItem).IsEmphasized();
3248 }
3249 }
3250 
3252 
3254 
3256 {
3257 private:
3258  // owner for UserData
3259  std::vector<std::unique_ptr<OUString>> m_aUserData;
3263  // currently expanding parent that logically, but not currently physically,
3264  // contain placeholders
3268 
3269  DECL_LINK(SelectHdl, SvTreeListBox*, void);
3270  DECL_LINK(DeSelectHdl, SvTreeListBox*, void);
3271  DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
3272  DECL_LINK(ExpandingHdl, SvTreeListBox*, bool);
3273  DECL_LINK(EndDragHdl, HeaderBar*, void);
3274  DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
3275  DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
3276  DECL_LINK(ModelChangedHdl, SvTreeListBox*, void);
3277  DECL_LINK(StartDragHdl, SvTreeListBox*, bool);
3278  DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void);
3279  DECL_LINK(EditingEntryHdl, SvTreeListEntry*, bool);
3280  typedef std::pair<SvTreeListEntry*, OUString> IterString;
3281  DECL_LINK(EditedEntryHdl, IterString, bool);
3282  DECL_LINK(VisibleRangeChangedHdl, SvTreeListBox*, void);
3283  DECL_LINK(CompareHdl, const SvSortData&, sal_Int32);
3284  DECL_LINK(PopupMenuHdl, const CommandEvent&, bool);
3285  DECL_LINK(TooltipHdl, const HelpEvent&, bool);
3286 
3287  bool IsDummyEntry(SvTreeListEntry* pEntry) const
3288  {
3289  return m_xTreeView->GetEntryText(pEntry).trim() == "<dummy>";
3290  }
3291 
3293  {
3294  if (pEntry->HasChildren())
3295  {
3296  auto pChild = m_xTreeView->FirstChild(pEntry);
3297  assert(pChild);
3298  if (IsDummyEntry(pChild))
3299  return pChild;
3300  }
3301  return nullptr;
3302  }
3303 
3304  static void set_font_color(SvTreeListEntry* pEntry, const Color& rColor)
3305  {
3306  if (rColor == COL_AUTO)
3307  pEntry->SetTextColor(std::optional<Color>());
3308  else
3309  pEntry->SetTextColor(rColor);
3310  }
3311 
3312 public:
3313  SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3314  : SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
3315  , m_xTreeView(pTreeView)
3316  , m_aCheckButtonData(pTreeView, false)
3317  , m_aRadioButtonData(pTreeView, true)
3318  , m_bDisableCheckBoxAutoWidth(false)
3319  , m_nSortColumn(-1)
3320  {
3321  m_xTreeView->SetNodeDefaultImages();
3322  m_xTreeView->SetForceMakeVisible(true);
3323  m_xTreeView->SetSelectHdl(LINK(this, SalInstanceTreeView, SelectHdl));
3324  m_xTreeView->SetDeselectHdl(LINK(this, SalInstanceTreeView, DeSelectHdl));
3325  m_xTreeView->SetDoubleClickHdl(LINK(this, SalInstanceTreeView, DoubleClickHdl));
3326  m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl));
3327  m_xTreeView->SetPopupMenuHdl(LINK(this, SalInstanceTreeView, PopupMenuHdl));
3328  const long aTabPositions[] = { 0 };
3329  m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions);
3330  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3331 
3332  if (pHeaderBox)
3333  {
3334  if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
3335  {
3336  //make the last entry fill available space
3337  pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1),
3339  pHeaderBar->SetEndDragHdl(LINK(this, SalInstanceTreeView, EndDragHdl));
3340  pHeaderBar->SetSelectHdl(LINK(this, SalInstanceTreeView, HeaderBarClickedHdl));
3341  }
3342  pHeaderBox->SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3343  pHeaderBox->SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3344  }
3345  else
3346  {
3347  static_cast<LclTabListBox&>(*m_xTreeView)
3348  .SetModelChangedHdl(LINK(this, SalInstanceTreeView, ModelChangedHdl));
3349  static_cast<LclTabListBox&>(*m_xTreeView)
3350  .SetStartDragHdl(LINK(this, SalInstanceTreeView, StartDragHdl));
3351  static_cast<LclTabListBox&>(*m_xTreeView)
3352  .SetEndDragHdl(LINK(this, SalInstanceTreeView, FinishDragHdl));
3353  static_cast<LclTabListBox&>(*m_xTreeView)
3354  .SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3355  static_cast<LclTabListBox&>(*m_xTreeView)
3356  .SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3357  }
3358  m_aCheckButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3359  m_aRadioButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3360  }
3361 
3363  {
3365  m_xTreeView->SetTooltipHdl(LINK(this, SalInstanceTreeView, TooltipHdl));
3366  }
3367 
3368  virtual void columns_autosize() override
3369  {
3370  std::vector<long> aWidths;
3371  m_xTreeView->getPreferredDimensions(aWidths);
3372  if (aWidths.size() > 2)
3373  {
3374  std::vector<int> aColWidths;
3375  for (size_t i = 1; i < aWidths.size() - 1; ++i)
3376  aColWidths.push_back(aWidths[i] - aWidths[i - 1]);
3377  set_column_fixed_widths(aColWidths);
3378  }
3379  }
3380 
3381  virtual void freeze() override
3382  {
3384  m_xTreeView->SetUpdateMode(false);
3385  }
3386 
3387  virtual void thaw() override
3388  {
3389  m_xTreeView->SetUpdateMode(true);
3391  }
3392 
3393  virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override
3394  {
3395  m_bDisableCheckBoxAutoWidth = true;
3396  std::vector<long> aTabPositions;
3397  aTabPositions.push_back(0);
3398  for (size_t i = 0; i < rWidths.size(); ++i)
3399  aTabPositions.push_back(aTabPositions[i] + rWidths[i]);
3400  m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
3401  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3402  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3403  {
3404  for (size_t i = 0; i < rWidths.size(); ++i)
3405  pHeaderBar->SetItemSize(pHeaderBar->GetItemId(i), rWidths[i]);
3406  }
3407  // call Resize to recalculate based on the new tabs
3408  m_xTreeView->Resize();
3409  }
3410 
3411  virtual void set_column_editables(const std::vector<bool>& rEditables) override
3412  {
3413  size_t nTabCount = rEditables.size();
3414  for (size_t i = 0 ; i < nTabCount; ++i)
3415  m_xTreeView->SetTabEditable(i, rEditables[i]);
3416  }
3417 
3418  virtual void set_centered_column(int nCol) override
3419  {
3420  m_xTreeView->SetTabJustify(nCol, SvTabJustify::AdjustCenter);
3421  }
3422 
3423  virtual int get_column_width(int nColumn) const override
3424  {
3425  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3426  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3427  return pHeaderBar->GetItemSize(pHeaderBar->GetItemId(nColumn));
3428  // GetTab(0) gives the position of the bitmap which is automatically inserted by the TabListBox.
3429  // So the first text column's width is Tab(2)-Tab(1).
3430  auto nWidthPixel
3431  = m_xTreeView->GetLogicTab(nColumn + 2) - m_xTreeView->GetLogicTab(nColumn + 1);
3432  nWidthPixel -= SV_TAB_BORDER;
3433  return nWidthPixel;
3434  }
3435 
3436  virtual OUString get_column_title(int nColumn) const override
3437  {
3438  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3439  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3440  {
3441  return pHeaderBar->GetItemText(pHeaderBar->GetItemId(nColumn));
3442  }
3443  return OUString();
3444  }
3445 
3446  virtual void set_column_title(int nColumn, const OUString& rTitle) override
3447  {
3448  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3449  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3450  {
3451  return pHeaderBar->SetItemText(pHeaderBar->GetItemId(nColumn), rTitle);
3452  }
3453  }
3454 
3455  virtual void show() override
3456  {
3457  if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
3458  pHeaderBox->GetParent()->Show();
3460  }
3461 
3462  virtual void hide() override
3463  {
3464  if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
3465  pHeaderBox->GetParent()->Hide();
3467  }
3468 
3469  virtual void insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
3470  const OUString* pId, const OUString* pIconName,
3471  VirtualDevice* pImageSurface, const OUString* pExpanderName,
3472  bool bChildrenOnDemand, weld::TreeIter* pRet) override
3473  {
3475  const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
3476  SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
3477  auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
3478  void* pUserData;
3479  if (pId)
3480  {
3481  m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
3482  pUserData = m_aUserData.back().get();
3483  }
3484  else
3485  pUserData = nullptr;
3486 
3487  SvTreeListEntry* pEntry = new SvTreeListEntry;
3488  if (pIconName || pImageSurface)
3489  {
3490  Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface));
3491  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
3492  }
3493  else
3494  {
3495  Image aDummy;
3496  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3497  }
3498  if (pStr)
3499  pEntry->AddItem(std::make_unique<SvLBoxString>(*pStr));
3500  pEntry->SetUserData(pUserData);
3501  m_xTreeView->Insert(pEntry, iter, nInsertPos);
3502 
3503  if (pExpanderName)
3504  {
3505  Image aImage(createImage(*pExpanderName));
3506  m_xTreeView->SetExpandedEntryBmp(pEntry, aImage);
3507  m_xTreeView->SetCollapsedEntryBmp(pEntry, aImage);
3508  }
3509 
3510  if (pRet)
3511  {
3512  SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
3513  pVclRetIter->iter = pEntry;
3514  }
3515 
3516  if (bChildrenOnDemand)
3517  {
3518  m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
3519  }
3521  }
3522 
3523  virtual void
3524  bulk_insert_for_each(int nSourceCount,
3525  const std::function<void(weld::TreeIter&, int nSourceIndex)>& func,
3526  const std::vector<int>* pFixedWidths) override
3527  {
3528  freeze();
3529  clear();
3530  SalInstanceTreeIter aVclIter(static_cast<SvTreeListEntry*>(nullptr));
3531 
3532  m_xTreeView->nTreeFlags |= SvTreeFlags::MANINS;
3533 
3534  if (pFixedWidths)
3535  set_column_fixed_widths(*pFixedWidths);
3536 
3537  Image aDummy;
3538  for (int i = 0; i < nSourceCount; ++i)
3539  {
3540  aVclIter.iter = new SvTreeListEntry;
3541  aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3542  m_xTreeView->Insert(aVclIter.iter, nullptr, TREELIST_APPEND);
3543  func(aVclIter, i);
3544 
3545  if (!pFixedWidths)
3546  continue;
3547 
3548  size_t nFixedWidths = std::min(pFixedWidths->size(), aVclIter.iter->ItemCount());
3549  for (size_t j = 0; j < nFixedWidths; ++j)
3550  {
3551  SvLBoxItem& rItem = aVclIter.iter->GetItem(j);
3552  SvViewDataItem* pViewDataItem = m_xTreeView->GetViewDataItem(aVclIter.iter, &rItem);
3553  pViewDataItem->mnWidth = (*pFixedWidths)[j];
3554  }
3555  }
3556 
3557  m_xTreeView->nTreeFlags &= ~SvTreeFlags::MANINS;
3558 
3559  thaw();
3560  }
3561 
3562  virtual void set_font_color(int pos, const Color& rColor) override
3563  {
3564  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3565  set_font_color(pEntry, rColor);
3566  }
3567 
3568  virtual void set_font_color(const weld::TreeIter& rIter, const Color& rColor) override
3569  {
3570  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3571  set_font_color(rVclIter.iter, rColor);
3572  }
3573 
3574  virtual void remove(int pos) override
3575  {
3577  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3578  m_xTreeView->RemoveEntry(pEntry);
3580  }
3581 
3582  virtual int find_text(const OUString& rText) const override
3583  {
3584  for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry;
3585  pEntry = m_xTreeView->Next(pEntry))
3586  {
3587  if (SvTabListBox::GetEntryText(pEntry, 0) == rText)
3588  return SvTreeList::GetRelPos(pEntry);
3589  }
3590  return -1;
3591  }
3592 
3593  virtual int find_id(const OUString& rId) const override
3594  {
3595  for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry;
3596  pEntry = m_xTreeView->Next(pEntry))
3597  {
3598  const OUString* pId = static_cast<const OUString*>(pEntry->GetUserData());
3599  if (!pId)
3600  continue;
3601  if (rId == *pId)
3602  return SvTreeList::GetRelPos(pEntry);
3603  }
3604  return -1;
3605  }
3606 
3607  virtual void swap(int pos1, int pos2) override
3608  {
3609  int min = std::min(pos1, pos2);
3610  int max = std::max(pos1, pos2);
3611  SvTreeList* pModel = m_xTreeView->GetModel();
3612  SvTreeListEntry* pEntry1 = pModel->GetEntry(nullptr, min);
3613  SvTreeListEntry* pEntry2 = pModel->GetEntry(nullptr, max);
3614  pModel->Move(pEntry1, pEntry2);
3615  }
3616 
3617  virtual void clear() override
3618  {
3620  m_xTreeView->Clear();
3621  m_aUserData.clear();
3623  }
3624 
3625  virtual int n_children() const override
3626  {
3627  return m_xTreeView->GetModel()->GetChildList(nullptr).size();
3628  }
3629 
3630  virtual int iter_n_children(const weld::TreeIter& rIter) const override
3631  {
3632  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3633  return m_xTreeView->GetModel()->GetChildList(rVclIter.iter).size();
3634  }
3635 
3636  virtual void select(int pos) override
3637  {
3638  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3640  if (pos == -1 || (pos == 0 && n_children() == 0))
3641  m_xTreeView->SelectAll(false);
3642  else
3643  {
3644  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3645  m_xTreeView->Select(pEntry, true);
3646  m_xTreeView->MakeVisible(pEntry);
3647  }
3649  }
3650 
3651  virtual int get_cursor_index() const override
3652  {
3653  SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry();
3654  if (!pEntry)
3655  return -1;
3656  return SvTreeList::GetRelPos(pEntry);
3657  }
3658 
3659  virtual void set_cursor(int pos) override
3660  {
3662  if (pos == -1)
3663  m_xTreeView->SetCurEntry(nullptr);
3664  else
3665  {
3666  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3667  m_xTreeView->SetCurEntry(pEntry);
3668  }
3670  }
3671 
3672  virtual void scroll_to_row(int pos) override
3673  {
3674  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3676  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3677  m_xTreeView->MakeVisible(pEntry);
3679  }
3680 
3681  virtual bool is_selected(int pos) const override
3682  {
3683  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3684  return m_xTreeView->IsSelected(pEntry);
3685  }
3686 
3687  virtual void unselect(int pos) override
3688  {
3689  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3691  if (pos == -1)
3692  m_xTreeView->SelectAll(true);
3693  else
3694  {
3695  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3696  m_xTreeView->Select(pEntry, false);
3697  }
3699  }
3700 
3701  virtual std::vector<int> get_selected_rows() const override
3702  {
3703  std::vector<int> aRows;
3704 
3705  aRows.reserve(m_xTreeView->GetSelectionCount());
3706  for (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); pEntry;
3707  pEntry = m_xTreeView->NextSelected(pEntry))
3708  aRows.push_back(SvTreeList::GetRelPos(pEntry));
3709 
3710  return aRows;
3711  }
3712 
3713  static OUString get_text(SvTreeListEntry* pEntry, int col)
3714  {
3715  if (col == -1)
3716  return SvTabListBox::GetEntryText(pEntry, 0);
3717 
3718  ++col; //skip dummy/expander column
3719 
3720  if (static_cast<size_t>(col) == pEntry->ItemCount())
3721  return OUString();
3722 
3723  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3724  SvLBoxItem& rItem = pEntry->GetItem(col);
3725  assert(dynamic_cast<SvLBoxString*>(&rItem));
3726  return static_cast<SvLBoxString&>(rItem).GetText();
3727  }
3728 
3729  virtual OUString get_text(int pos, int col) const override
3730  {
3731  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3732  return get_text(pEntry, col);
3733  }
3734 
3735  void set_text(SvTreeListEntry* pEntry, const OUString& rText, int col)
3736  {
3737  if (col == -1)
3738  {
3739  m_xTreeView->SetEntryText(pEntry, rText);
3740  return;
3741  }
3742 
3743  ++col; //skip dummy/expander column
3744 
3745  // blank out missing entries
3746  for (int i = pEntry->ItemCount(); i < col; ++i)
3747  pEntry->AddItem(std::make_unique<SvLBoxString>(""));
3748 
3749  if (static_cast<size_t>(col) == pEntry->ItemCount())
3750  {
3751  pEntry->AddItem(std::make_unique<SvLBoxString>(rText));
3752  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3753  m_xTreeView->InitViewData(pViewData, pEntry);
3754  }
3755  else
3756  {
3757  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3758  SvLBoxItem& rItem = pEntry->GetItem(col);
3759  assert(dynamic_cast<SvLBoxString*>(&rItem));
3760  static_cast<SvLBoxString&>(rItem).SetText(rText);
3761  }
3762  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3763  }
3764 
3765  virtual void set_text(int pos, const OUString& rText, int col) override
3766  {
3767  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3768  set_text(pEntry, rText, col);
3769  }
3770 
3771  void set_sensitive(SvTreeListEntry* pEntry, bool bSensitive, int col)
3772  {
3773  if (col == -1)
3774  {
3775  auto nFlags = pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT;
3776  if (!bSensitive)
3777  nFlags = nFlags | SvTLEntryFlags::SEMITRANSPARENT;
3778  pEntry->SetFlags(nFlags);
3779  const sal_uInt16 nCount = pEntry->ItemCount();
3780  for (sal_uInt16 nCur = 0; nCur < nCount; ++nCur)
3781  {
3782  SvLBoxItem& rItem = pEntry->GetItem(nCur);
3783  if (rItem.GetType() == SvLBoxItemType::String)
3784  {
3785  rItem.Enable(bSensitive);
3786  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3787  break;
3788  }
3789  }
3790  return;
3791  }
3792 
3793  ++col; //skip dummy/expander column
3794 
3795  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3796  SvLBoxItem& rItem = pEntry->GetItem(col);
3797  rItem.Enable(bSensitive);
3798 
3799  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3800  }
3801 
3803 
3804  virtual void set_sensitive(int pos, bool bSensitive, int col) override
3805  {
3806  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3807  set_sensitive(pEntry, bSensitive, col);
3808  }
3809 
3810  virtual void set_sensitive(const weld::TreeIter& rIter, bool bSensitive, int col) override
3811  {
3812  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3813  set_sensitive(rVclIter.iter, bSensitive, col);
3814  }
3815 
3816  virtual TriState get_toggle(int pos, int col) const override
3817  {
3818  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3819  return ::get_toggle(pEntry, col);
3820  }
3821 
3822  virtual TriState get_toggle(const weld::TreeIter& rIter, int col) const override
3823  {
3824  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3825  return ::get_toggle(rVclIter.iter, col);
3826  }
3827 
3828  void set_toggle(SvTreeListEntry* pEntry, TriState eState, int col)
3829  {
3830  bool bRadio = std::find(m_aRadioIndexes.begin(), m_aRadioIndexes.end(), col)
3831  != m_aRadioIndexes.end();
3832  ++col; //skip dummy/expander column
3833 
3834  // blank out missing entries
3835  for (int i = pEntry->ItemCount(); i < col; ++i)
3836  pEntry->AddItem(std::make_unique<SvLBoxString>(""));
3837 
3838  if (static_cast<size_t>(col) == pEntry->ItemCount())
3839  {
3840  SvLBoxButtonData* pData = bRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
3841 
3842  // if we want to have the implicit auto-sizing of the checkbox
3843  // column we need to call EnableCheckButton and CheckBoxInserted to
3844  // let it figure out that width. But we don't want to override any
3845  // explicitly set column width, so disable this if we've set
3846  // explicit column widths
3847  if (!m_bDisableCheckBoxAutoWidth)
3848  {
3849  if (!(m_xTreeView->GetTreeFlags() & SvTreeFlags::CHKBTN))
3850  {
3851  m_xTreeView->EnableCheckButton(pData);
3852  // EnableCheckButton clobbered this, restore it
3853  pData->SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3854  }
3855  }
3856 
3857  pEntry->AddItem(std::make_unique<SvLBoxButton>(pData));
3858  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3859  m_xTreeView->InitViewData(pViewData, pEntry);
3860 
3861  if (!m_bDisableCheckBoxAutoWidth)
3862  m_xTreeView->CheckBoxInserted(pEntry);
3863  }
3864 
3865  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3866  SvLBoxItem& rItem = pEntry->GetItem(col);
3867  assert(dynamic_cast<SvLBoxButton*>(&rItem));
3868  switch (eState)
3869  {
3870  case TRISTATE_TRUE:
3871  static_cast<SvLBoxButton&>(rItem).SetStateChecked();
3872  break;
3873  case TRISTATE_FALSE:
3874  static_cast<SvLBoxButton&>(rItem).SetStateUnchecked();
3875  break;
3876  case TRISTATE_INDET:
3877  static_cast<SvLBoxButton&>(rItem).SetStateTristate();
3878  break;
3879  }
3880 
3881  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3882  }
3883 
3884  virtual void set_toggle(int pos, TriState eState, int col) override
3885  {
3886  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3887  set_toggle(pEntry, eState, col);
3888  }
3889 
3890  virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override
3891  {
3892  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3893  set_toggle(rVclIter.iter, eState, col);
3894  }
3895 
3896  virtual void set_extra_row_indent(const weld::TreeIter& rIter, int nIndentLevel) override
3897  {
3898  weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
3899  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
3900  rVclIter.iter->SetExtraIndent(nIndentLevel);
3901  }
3902 
3903  void set_text_emphasis(SvTreeListEntry* pEntry, bool bOn, int col)
3904  {
3905  ++col; //skip dummy/expander column
3906 
3907  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3908  SvLBoxItem& rItem = pEntry->GetItem(col);
3909  assert(dynamic_cast<SvLBoxString*>(&rItem));
3910  static_cast<SvLBoxString&>(rItem).Emphasize(bOn);
3911 
3912  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3913  }
3914 
3915  virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override
3916  {
3917  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3918  set_text_emphasis(rVclIter.iter, bOn, col);
3919  }
3920 
3921  virtual void set_text_emphasis(int pos, bool bOn, int col) override
3922  {
3923  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3924  set_text_emphasis(pEntry, bOn, col);
3925  }
3926 
3927  virtual bool get_text_emphasis(const weld::TreeIter& rIter, int col) const override
3928  {
3929  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3930  return ::get_text_emphasis(rVclIter.iter, col);
3931  }
3932 
3933  virtual bool get_text_emphasis(int pos, int col) const override
3934  {
3935  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3936  return ::get_text_emphasis(pEntry, col);
3937  }
3938 
3939  void set_text_align(SvTreeListEntry* pEntry, double fAlign, int col)
3940  {
3941  ++col; //skip dummy/expander column
3942 
3943  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3944  SvLBoxItem& rItem = pEntry->GetItem(col);
3945  assert(dynamic_cast<SvLBoxString*>(&rItem));
3946  static_cast<SvLBoxString&>(rItem).Align(fAlign);
3947 
3948  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3949  }
3950 
3951  virtual void set_text_align(const weld::TreeIter& rIter, double fAlign, int col) override
3952  {
3953  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3954  set_text_align(rVclIter.iter, fAlign, col);
3955  }
3956 
3957  virtual void set_text_align(int pos, double fAlign, int col) override
3958  {
3959  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3960  set_text_align(pEntry, fAlign, col);
3961  }
3962 
3963  virtual void connect_editing(
3964  const Link<const weld::TreeIter&, bool>& rStartLink,
3965  const Link<const std::pair<const weld::TreeIter&, OUString>&, bool>& rEndLink) override
3966  {
3967  m_xTreeView->EnableInplaceEditing(rStartLink.IsSet() || rEndLink.IsSet());
3968  weld::TreeView::connect_editing(rStartLink, rEndLink);
3969  }
3970 
3971  virtual void start_editing(const weld::TreeIter& rIter) override
3972  {
3973  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3974  m_xTreeView->EditEntry(rVclIter.iter);
3975  }
3976 
3977  virtual void end_editing() override { m_xTreeView->EndEditing(); }
3978 
3979  void set_image(SvTreeListEntry* pEntry, const Image& rImage, int col)
3980  {
3981  if (col == -1)
3982  {
3983  m_xTreeView->SetExpandedEntryBmp(pEntry, rImage);
3984  m_xTreeView->SetCollapsedEntryBmp(pEntry, rImage);
3985  return;
3986  }
3987 
3988  ++col; //skip dummy/expander column
3989 
3990  // blank out missing entries
3991  for (int i = pEntry->ItemCount(); i < col; ++i)
3992  pEntry->AddItem(std::make_unique<SvLBoxString>(""));
3993 
3994  if (static_cast<size_t>(col) == pEntry->ItemCount())
3995  {
3996  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(rImage, rImage, false));
3997  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3998  m_xTreeView->InitViewData(pViewData, pEntry);
3999  }
4000  else
4001  {
4002  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4003  SvLBoxItem& rItem = pEntry->GetItem(col);
4004  assert(dynamic_cast<SvLBoxContextBmp*>(&rItem));
4005  static_cast<SvLBoxContextBmp&>(rItem).SetBitmap1(rImage);
4006  static_cast<SvLBoxContextBmp&>(rItem).SetBitmap2(rImage);
4007  }
4008 
4009  m_xTreeView->SetEntryHeight(pEntry);
4010  m_xTreeView->ModelHasEntryInvalidated(pEntry);
4011  }
4012 
4013  virtual void set_image(int pos, const OUString& rImage, int col) override
4014  {
4015  set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col);
4016  }
4017 
4018  virtual void set_image(int pos, const css::uno::Reference<css::graphic::XGraphic>& rImage,
4019  int col) override
4020  {
4021  set_image(m_xTreeView->GetEntry(nullptr, pos), Image(rImage), col);
4022  }
4023 
4024  virtual void set_image(int pos, VirtualDevice& rImage, int col) override
4025  {
4026  set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col);
4027  }
4028 
4029  virtual void set_image(const weld::TreeIter& rIter, const OUString& rImage, int col) override
4030  {
4031  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4032  set_image(rVclIter.iter, createImage(rImage), col);
4033  }
4034 
4035  virtual void set_image(const weld::TreeIter& rIter,
4036  const css::uno::Reference<css::graphic::XGraphic>& rImage,
4037  int col) override
4038  {
4039  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4040  set_image(rVclIter.iter, Image(rImage), col);
4041  }
4042 
4043  virtual void set_image(const weld::TreeIter& rIter, VirtualDevice& rImage, int col) override
4044  {
4045  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4046  set_image(rVclIter.iter, createImage(rImage), col);
4047  }
4048 
4049  const OUString* getEntryData(int index) const
4050  {
4051  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, index);
4052  return pEntry ? static_cast<const OUString*>(pEntry->GetUserData()) : nullptr;
4053  }
4054 
4055  virtual OUString get_id(int pos) const override
4056  {
4057  const OUString* pRet = getEntryData(pos);
4058  if (!pRet)
4059  return OUString();
4060  return *pRet;
4061  }
4062 
4063  void set_id(SvTreeListEntry* pEntry, const OUString& rId)
4064  {
4065  m_aUserData.emplace_back(std::make_unique<OUString>(rId));
4066  pEntry->SetUserData(m_aUserData.back().get());
4067  }
4068 
4069  virtual void set_id(int pos, const OUString& rId) override
4070  {
4071  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4072  set_id(pEntry, rId);
4073  }
4074 
4075  virtual int get_selected_index() const override
4076  {
4077  assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4078  SvTreeListEntry* pEntry = m_xTreeView->FirstSelected();
4079  if (!pEntry)
4080  return -1;
4081  return SvTreeList::GetRelPos(pEntry);
4082  }
4083 
4084  virtual OUString get_selected_text() const override
4085  {
4086  assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4087  if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected())
4088  return m_xTreeView->GetEntryText(pEntry);
4089  return OUString();
4090  }
4091 
4092  virtual OUString get_selected_id() const override
4093  {
4094  assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4095  if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected())
4096  {
4097  if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData()))
4098  return *pStr;
4099  }
4100  return OUString();
4101  }
4102 
4103  virtual std::unique_ptr<weld::TreeIter>
4104  make_iterator(const weld::TreeIter* pOrig) const override
4105  {
4106  return std::unique_ptr<weld::TreeIter>(
4107  new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig)));
4108  }
4109 
4110  virtual void copy_iterator(const weld::TreeIter& rSource, weld::TreeIter& rDest) const override
4111  {
4112  const SalInstanceTreeIter& rVclSource(static_cast<const SalInstanceTreeIter&>(rSource));
4113  SalInstanceTreeIter& rVclDest(static_cast<SalInstanceTreeIter&>(rDest));
4114  rVclDest.iter = rVclSource.iter;
4115  }
4116 
4117  virtual bool get_selected(weld::TreeIter* pIter) const override
4118  {
4119  SvTreeListEntry* pEntry = m_xTreeView->FirstSelected();
4120  auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4121  if (pVclIter)
4122  pVclIter->iter = pEntry;
4123  return pEntry != nullptr;
4124  }
4125 
4126  virtual bool get_cursor(weld::TreeIter* pIter) const override
4127  {
4128  SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry();
4129  auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4130  if (pVclIter)
4131  pVclIter->iter = pEntry;
4132  return pEntry != nullptr;
4133  }
4134 
4135  virtual void set_cursor(const weld::TreeIter& rIter) override
4136  {
4137  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4139  m_xTreeView->SetCurEntry(rVclIter.iter);
4141  }
4142 
4143  virtual bool get_iter_first(weld::TreeIter& rIter) const override
4144  {
4145  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4146  rVclIter.iter = m_xTreeView->GetEntry(0);
4147  return rVclIter.iter != nullptr;
4148  }
4149 
4150  virtual bool iter_next_sibling(weld::TreeIter& rIter) const override
4151  {
4152  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4153  rVclIter.iter = rVclIter.iter->NextSibling();
4154  return rVclIter.iter != nullptr;
4155  }
4156 
4157  virtual bool iter_previous_sibling(weld::TreeIter& rIter) const override
4158  {
4159  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4160  rVclIter.iter = rVclIter.iter->PrevSibling();
4161  return rVclIter.iter != nullptr;
4162  }
4163 
4164  virtual bool iter_next(weld::TreeIter& rIter) const override
4165  {
4166  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4167  rVclIter.iter = m_xTreeView->Next(rVclIter.iter);
4168  if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4169  return iter_next(rVclIter);
4170  return rVclIter.iter != nullptr;
4171  }
4172 
4173  virtual bool iter_previous(weld::TreeIter& rIter) const override
4174  {
4175  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4176  rVclIter.iter = m_xTreeView->Prev(rVclIter.iter);
4177  if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4178  return iter_previous(rVclIter);
4179  return rVclIter.iter != nullptr;
4180  }
4181 
4182  virtual bool iter_next_visible(weld::TreeIter& rIter) const override
4183  {
4184  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4185  rVclIter.iter = m_xTreeView->NextVisible(rVclIter.iter);
4186  if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4187  return iter_next_visible(rVclIter);
4188  return rVclIter.iter != nullptr;
4189  }
4190 
4191  virtual bool iter_children(weld::TreeIter& rIter) const override
4192  {
4193  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4194  rVclIter.iter = m_xTreeView->FirstChild(rVclIter.iter);
4195  bool bRet = rVclIter.iter != nullptr;
4196  if (bRet)
4197  {
4198  //on-demand dummy entry doesn't count
4199  return !IsDummyEntry(rVclIter.iter);
4200  }
4201  return bRet;
4202  }
4203 
4204  virtual bool iter_parent(weld::TreeIter& rIter) const override
4205  {
4206  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4207  rVclIter.iter = m_xTreeView->GetParent(rVclIter.iter);
4208  return rVclIter.iter != nullptr;
4209  }
4210 
4211  virtual void remove(const weld::TreeIter& rIter) override
4212  {
4214  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4215  m_xTreeView->RemoveEntry(rVclIter.iter);
4217  }
4218 
4219  virtual void select(const weld::TreeIter& rIter) override
4220  {
4221  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4223  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4224  m_xTreeView->Select(rVclIter.iter, true);
4226  }
4227 
4228  virtual void scroll_to_row(const weld::TreeIter& rIter) override
4229  {
4230  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4232  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4233  m_xTreeView->MakeVisible(rVclIter.iter);
4235  }
4236 
4237  virtual void unselect(const weld::TreeIter& rIter) override
4238  {
4239  assert(m_xTreeView->IsUpdateMode() && "don't unselect when frozen");
4241  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4242  m_xTreeView->Select(rVclIter.iter, false);
4244  }
4245 
4246  virtual int get_iter_depth(const weld::TreeIter& rIter) const override
4247  {
4248  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4249  return m_xTreeView->GetModel()->GetDepth(rVclIter.iter);
4250  }
4251 
4252  virtual bool iter_has_child(const weld::TreeIter& rIter) const override
4253  {
4254  weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
4255  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
4256  SvTreeListEntry* restore(rVclIter.iter);
4257  bool ret = iter_children(rNonConstIter);
4258  rVclIter.iter = restore;
4259  return ret;
4260  }
4261 
4262  virtual bool get_row_expanded(const weld::TreeIter& rIter) const override
4263  {
4264  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4265  return m_xTreeView->IsExpanded(rVclIter.iter);
4266  }
4267 
4268  virtual bool get_children_on_demand(const weld::TreeIter& rIter) const override
4269  {
4270  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4271  if (m_aExpandingPlaceHolderParents.count(rVclIter.iter))
4272  return true;
4273  return GetPlaceHolderChild(rVclIter.iter) != nullptr;
4274  }
4275 
4276  virtual void set_children_on_demand(const weld::TreeIter& rIter, bool bChildrenOnDemand) override
4277  {
4279 
4280  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4281 
4282  SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(rVclIter.iter);
4283 
4284  if (bChildrenOnDemand && !pPlaceHolder)
4285  m_xTreeView->InsertEntry("<dummy>", rVclIter.iter, false, 0, nullptr);
4286  else if (!bChildrenOnDemand && pPlaceHolder)
4287  m_xTreeView->RemoveEntry(pPlaceHolder);
4288 
4290  }
4291 
4292  virtual void expand_row(const weld::TreeIter& rIter) override
4293  {
4294  assert(m_xTreeView->IsUpdateMode() && "don't expand when frozen");
4295  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4296  if (!m_xTreeView->IsExpanded(rVclIter.iter) && signal_expanding(rIter))
4297  m_xTreeView->Expand(rVclIter.iter);
4298  }
4299 
4300  virtual void collapse_row(const weld::TreeIter& rIter) override
4301  {
4302  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4303  if (m_xTreeView->IsExpanded(rVclIter.iter) && signal_collapsing(rIter))
4304  m_xTreeView->Collapse(rVclIter.iter);
4305  }
4306 
4307  virtual OUString get_text(const weld::TreeIter& rIter, int col) const override
4308  {
4309  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4310  return get_text(rVclIter.iter, col);
4311  }
4312 
4313  virtual void set_text(const weld::TreeIter& rIter, const OUString& rText, int col) override
4314  {
4315  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4316  set_text(rVclIter.iter, rText, col);
4317  }
4318 
4319  virtual OUString get_id(const weld::TreeIter& rIter) const override
4320  {
4321  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4322  const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData());
4323  if (pStr)
4324  return *pStr;
4325  return OUString();
4326  }
4327 
4328  virtual void set_id(const weld::TreeIter& rIter, const OUString& rId) override
4329  {
4330  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4331  set_id(rVclIter.iter, rId);
4332  }
4333 
4335  sal_uInt8 eDNDConstants) override
4336  {
4337  m_xTreeView->SetDragHelper(rHelper, eDNDConstants);
4338  }
4339 
4340  virtual void set_selection_mode(SelectionMode eMode) override
4341  {
4342  m_xTreeView->SetSelectionMode(eMode);
4343  }
4344 
4345  virtual void all_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4346  {
4347  SalInstanceTreeIter aVclIter(m_xTreeView->First());
4348  while (aVclIter.iter)
4349  {
4350  if (func(aVclIter))
4351  return;
4352  iter_next(aVclIter);
4353  }
4354  }
4355 
4356  virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4357  {
4358  SalInstanceTreeIter aVclIter(m_xTreeView->FirstSelected());
4359  while (aVclIter.iter)
4360  {
4361  if (func(aVclIter))
4362  return;
4363  aVclIter.iter = m_xTreeView->NextSelected(aVclIter.iter);
4364  }
4365  }
4366 
4367  virtual void visible_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4368  {
4369  SalInstanceTreeIter aVclIter(m_xTreeView->GetFirstEntryInView());
4370  while (aVclIter.iter)
4371  {
4372  if (func(aVclIter))
4373  return;
4374  aVclIter.iter = m_xTreeView->GetNextEntryInView(aVclIter.iter);
4375  }
4376  }
4377 
4379  {
4381  m_xTreeView->SetScrolledHdl(LINK(this, SalInstanceTreeView, VisibleRangeChangedHdl));
4382  }
4383 
4384  virtual void remove_selection() override
4385  {
4387  SvTreeListEntry* pSelected = m_xTreeView->FirstSelected();
4388  while (pSelected)
4389  {
4390  SvTreeListEntry* pNextSelected = m_xTreeView->NextSelected(pSelected);
4391  m_xTreeView->RemoveEntry(pSelected);
4392  pSelected = pNextSelected;
4393  }
4395  }
4396 
4397  virtual bool is_selected(const weld::TreeIter& rIter) const override
4398  {
4399  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4400  return m_xTreeView->IsSelected(rVclIter.iter);
4401  }
4402 
4403  virtual int get_iter_index_in_parent(const weld::TreeIter& rIter) const override
4404  {
4405  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4406  return SvTreeList::GetRelPos(rVclIter.iter);
4407  }
4408 
4409  virtual int iter_compare(const weld::TreeIter& a, const weld::TreeIter& b) const override
4410  {
4411  const SalInstanceTreeIter& rVclIterA = static_cast<const SalInstanceTreeIter&>(a);
4412  const SalInstanceTreeIter& rVclIterB = static_cast<const SalInstanceTreeIter&>(b);
4413  const SvTreeList* pModel = m_xTreeView->GetModel();
4414  auto nAbsPosA = pModel->GetAbsPos(rVclIterA.iter);
4415  auto nAbsPosB = pModel->GetAbsPos(rVclIterB.iter);
4416  if (nAbsPosA < nAbsPosB)
4417  return -1;
4418  if (nAbsPosA > nAbsPosB)
4419  return 1;
4420  return 0;
4421  }
4422 
4423  virtual void move_subtree(weld::TreeIter& rNode, const weld::TreeIter* pNewParent,
4424  int nIndexInNewParent) override
4425  {
4426  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNode);
4427  const SalInstanceTreeIter* pVclParentIter
4428  = static_cast<const SalInstanceTreeIter*>(pNewParent);
4429  m_xTreeView->GetModel()->Move(
4430  rVclIter.iter, pVclParentIter ? pVclParentIter->iter : nullptr, nIndexInNewParent);
4431  }
4432 
4433  virtual int count_selected_rows() const override { return m_xTreeView->GetSelectionCount(); }
4434 
4435  virtual int get_height_rows(int nRows) const override
4436  {
4437  return m_xTreeView->GetEntryHeight() * nRows;
4438  }
4439 
4440  virtual void make_sorted() override
4441  {
4442  assert(m_xTreeView->IsUpdateMode() && "don't sort when frozen");
4443  m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT);
4444  m_xTreeView->GetModel()->SetCompareHdl(LINK(this, SalInstanceTreeView, CompareHdl));
4445  set_sort_order(true);
4446  }
4447 
4448  virtual void set_sort_func(
4449  const std::function<int(const weld::TreeIter&, const weld::TreeIter&)>& func) override
4450  {
4452  SvTreeList* pListModel = m_xTreeView->GetModel();
4453  pListModel->Resort();
4454  }
4455 
4456  virtual void make_unsorted() override
4457  {
4458  m_xTreeView->SetStyle(m_xTreeView->GetStyle() & ~WB_SORT);
4459  }
4460 
4461  virtual void set_sort_order(bool bAscending) override
4462  {
4463  SvTreeList* pListModel = m_xTreeView->GetModel();
4464  pListModel->SetSortMode(bAscending ? SortAscending : SortDescending);
4465  pListModel->Resort();
4466  }
4467 
4468  virtual bool get_sort_order() const override
4469  {
4470  return m_xTreeView->GetModel()->GetSortMode() == SortAscending;
4471  }
4472 
4473  virtual void set_sort_indicator(TriState eState, int col) override
4474  {
4475  if (col == -1)
4476  col = 0;
4477 
4478  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4479  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
4480  {
4481  sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
4482  HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
4483  nBits &= ~HeaderBarItemBits::UPARROW;
4484  nBits &= ~HeaderBarItemBits::DOWNARROW;
4485  if (eState != TRISTATE_INDET)
4486  {
4487  if (eState == TRISTATE_TRUE)
4489  else
4490  nBits |= HeaderBarItemBits::UPARROW;
4491  }
4492  pHeaderBar->SetItemBits(nTextId, nBits);
4493  }
4494  }
4495 
4496  virtual TriState get_sort_indicator(int col) const override
4497  {
4498  if (col == -1)
4499  col = 0;
4500 
4501  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4502  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
4503  {
4504  sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
4505  HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
4506  if (nBits & HeaderBarItemBits::DOWNARROW)
4507  return TRISTATE_TRUE;
4508  if (nBits & HeaderBarItemBits::UPARROW)
4509  return TRISTATE_FALSE;
4510  }
4511 
4512  return TRISTATE_INDET;
4513  }
4514 
4515  virtual int get_sort_column() const override { return m_nSortColumn; }
4516 
4517  virtual void set_sort_column(int nColumn) override
4518  {
4519  if (nColumn == -1)
4520  {
4521  make_unsorted();
4522  m_nSortColumn = -1;
4523  return;
4524  }
4525 
4526  if (nColumn != m_nSortColumn)
4527  {
4528  m_nSortColumn = nColumn;
4529  m_xTreeView->GetModel()->Resort();
4530  }
4531  }
4532 
4534 
4535  virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult) override
4536  {
4537  SvTreeListEntry* pTarget = m_xTreeView->GetDropTarget(rPos);
4538 
4539  if (pTarget && pResult)
4540  {
4541  SalInstanceTreeIter& rSalIter = static_cast<SalInstanceTreeIter&>(*pResult);
4542  rSalIter.iter = pTarget;
4543  }
4544 
4545  return pTarget != nullptr;
4546  }
4547 
4548  virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const override
4549  {
4550  return m_xTreeView->GetBoundingRect(static_cast<const SalInstanceTreeIter&>(rIter).iter);
4551  }
4552 
4553  virtual TreeView* get_drag_source() const override { return g_DragSource; }
4554 
4555  virtual int vadjustment_get_value() const override
4556  {
4557  ScrollBar* pVertScrollBar = m_xTreeView->GetVScroll();
4558  return pVertScrollBar->GetThumbPos();
4559  }
4560 
4561  virtual void vadjustment_set_value(int nValue) override
4562  {
4563  m_xTreeView->ScrollToAbsPos(nValue);
4564  }
4565 
4566  virtual ~SalInstanceTreeView() override
4567  {
4568  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4569  if (pHeaderBox)
4570  {
4571  if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
4572  {
4573  pHeaderBar->SetSelectHdl(Link<HeaderBar*, void>());
4574  pHeaderBar->SetEndDragHdl(Link<HeaderBar*, void>());
4575  }
4576  }
4577  else
4578  {
4579  static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>());
4580  static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, bool>());
4581  static_cast<LclTabListBox&>(*m_xTreeView)
4583  }
4587  m_xTreeView->SetSelectHdl(Link<SvTreeListBox*, void>());
4591  }
4592 };
4593 
4594 IMPL_LINK(SalInstanceTreeView, TooltipHdl, const HelpEvent&, rHEvt, bool)
4595 {
4596  if (notify_events_disabled())
4597  return false;
4598  Point aPos(m_xTreeView->ScreenToOutputPixel(rHEvt.GetMousePosPixel()));
4599  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(aPos);
4600  if (pEntry)
4601  {
4602  SalInstanceTreeIter aIter(pEntry);
4603  OUString aTooltip = signal_query_tooltip(aIter);
4604  if (aTooltip.isEmpty())
4605  return false;
4606  Size aSize(m_xTreeView->GetOutputSizePixel().Width(), m_xTreeView->GetEntryHeight());
4607  tools::Rectangle aScreenRect(
4608  m_xTreeView->OutputToScreenPixel(m_xTreeView->GetEntryPosition(pEntry)), aSize);
4609  Help::ShowQuickHelp(m_xTreeView, aScreenRect, aTooltip);
4610  }
4611  return true;
4612 }
4613 
4614 IMPL_LINK(SalInstanceTreeView, CompareHdl, const SvSortData&, rSortData, sal_Int32)
4615 {
4616  const SvTreeListEntry* pLHS = rSortData.pLeft;
4617  const SvTreeListEntry* pRHS = rSortData.pRight;
4618  assert(pLHS && pRHS);
4619 
4620  if (m_aCustomSort)
4621  return m_aCustomSort(SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pLHS)),
4622  SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pRHS)));
4623 
4624  const SvLBoxString* pLeftTextItem;
4625  const SvLBoxString* pRightTextItem;
4626 
4627  if (m_nSortColumn != -1)
4628  {
4629  size_t col = m_nSortColumn;
4630 
4631  ++col; //skip dummy/expander column
4632 
4633  if (col < pLHS->ItemCount())
4634  {
4635  const SvLBoxString& rLeftTextItem
4636  = static_cast<const SvLBoxString&>(pLHS->GetItem(col));
4637  pLeftTextItem = &rLeftTextItem;
4638  }
4639  else
4640  pLeftTextItem = nullptr;
4641  if (col < pRHS->ItemCount())
4642  {
4643  const SvLBoxString& rRightTextItem
4644  = static_cast<const SvLBoxString&>(pRHS->GetItem(col));
4645  pRightTextItem = &rRightTextItem;
4646  }
4647  else
4648  pRightTextItem = nullptr;
4649  }
4650  else
4651  {
4652  pLeftTextItem
4653  = static_cast<const SvLBoxString*>(pLHS->GetFirstItem(SvLBoxItemType::String));
4654  pRightTextItem
4655  = static_cast<const SvLBoxString*>(pRHS->GetFirstItem(SvLBoxItemType::String));
4656  }
4657 
4658  return m_xTreeView->DefaultCompare(pLeftTextItem, pRightTextItem);
4659 }
4660 
4661 IMPL_LINK_NOARG(SalInstanceTreeView, VisibleRangeChangedHdl, SvTreeListBox*, void)
4662 {
4663  if (notify_events_disabled())
4664  return;
4665  signal_visible_range_changed();
4666 }
4667 
4669 {
4670  if (notify_events_disabled())
4671  return;
4672  signal_model_changed();
4673 }
4674 
4676 {
4677  bool bUnsetDragIcon(false); // ignored for vcl
4678  if (m_aDragBeginHdl.Call(bUnsetDragIcon))
4679  return true;
4680  g_DragSource = this;
4681  return false;
4682 }
4683 
4685 {
4686  g_DragSource = nullptr;
4687 }
4688 
4690 {
4691  SvTreeListEntry* pEntry = pData->GetActEntry();
4692  SvLBoxButton* pBox = pData->GetActBox();
4693 
4694  // tdf#122874 Select the row, calling SelectHdl, before handling
4695  // the toggle
4696  if (!m_xTreeView->IsSelected(pEntry))
4697  {
4698  m_xTreeView->SelectAll(false);
4699  m_xTreeView->Select(pEntry, true);
4700  }
4701 
4702  // toggled signal handlers can query get_cursor to get which
4703  // node was clicked
4704  m_xTreeView->pImpl->m_pCursor = pEntry;
4705 
4706  for (int i = 1, nCount = pEntry->ItemCount(); i < nCount; ++i)
4707  {
4708  SvLBoxItem& rItem = pEntry->GetItem(i);
4709  if (&rItem == pBox)
4710  {
4711  int nRow = SvTreeList::GetRelPos(pEntry);
4712  int nCol = i - 1; // less dummy/expander column
4713  signal_toggled(std::make_pair(nRow, nCol));
4714  break;
4715  }
4716  }
4717 }
4718 
4720 {
4721  if (notify_events_disabled())
4722  return;
4723  signal_changed();
4724 }
4725 
4727 {
4728  if (notify_events_disabled())
4729  return;
4730  if (m_xTreeView->GetSelectionMode() == SelectionMode::Single)
4731  return;
4732  signal_changed();
4733 }
4734 
4736 {
4737  if (notify_events_disabled())
4738  return false;
4739  return !signal_row_activated();
4740 }
4741 
4742 IMPL_LINK(SalInstanceTreeView, EndDragHdl, HeaderBar*, pHeaderBar, void)
4743 {
4744  std::vector<long> aTabPositions;
4745  aTabPositions.push_back(0);
4746  for (int i = 0; i < pHeaderBar->GetItemCount() - 1; ++i)
4747  aTabPositions.push_back(aTabPositions[i]
4748  + pHeaderBar->GetItemSize(pHeaderBar->GetItemId(i)));
4749  m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
4750 }
4751 
4752 IMPL_LINK(SalInstanceTreeView, HeaderBarClickedHdl, HeaderBar*, pHeaderBar, void)
4753 {
4754  sal_uInt16 nId = pHeaderBar->GetCurItemId();
4755  if (!(pHeaderBar->GetItemBits(nId) & HeaderBarItemBits::CLICKABLE))
4756  return;
4757  signal_column_clicked(pHeaderBar->GetItemPos(nId));
4758 }
4759 
4761 {
4762  SvTreeListEntry* pEntry = m_xTreeView->GetHdlEntry();
4763  SalInstanceTreeIter aIter(pEntry);
4764 
4765  if (m_xTreeView->IsExpanded(pEntry))
4766  {
4767  //collapsing;
4768  return signal_collapsing(aIter);
4769  }
4770 
4771  // expanding
4772 
4773  // if there's a preexisting placeholder child, required to make this
4774  // potentially expandable in the first place, now we remove it
4775  SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(pEntry);
4776  if (pPlaceHolder)
4777  {
4778  m_aExpandingPlaceHolderParents.insert(pEntry);
4779  m_xTreeView->RemoveEntry(pPlaceHolder);
4780  }
4781 
4782  bool bRet = signal_expanding(aIter);
4783 
4784  if (pPlaceHolder)
4785  {
4786  //expand disallowed, restore placeholder
4787  if (!bRet)
4788  {
4789  m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
4790  }
4791  m_aExpandingPlaceHolderParents.erase(pEntry);
4792  }
4793 
4794  return bRet;
4795 }
4796 
4797 IMPL_LINK(SalInstanceTreeView, PopupMenuHdl, const CommandEvent&, rEvent, bool)
4798 {
4799  return m_aPopupMenuHdl.Call(rEvent);
4800 }
4801 
4802 IMPL_LINK(SalInstanceTreeView, EditingEntryHdl, SvTreeListEntry*, pEntry, bool)
4803 {
4804  return signal_editing_started(SalInstanceTreeIter(pEntry));
4805 }
4806 
4807 IMPL_LINK(SalInstanceTreeView, EditedEntryHdl, IterString, rIterString, bool)
4808 {
4809  return signal_editing_done(std::pair<const weld::TreeIter&, OUString>(
4810  SalInstanceTreeIter(rIterString.first), rIterString.second));
4811 }
4812 
4814 {
4815 private:
4816  // owner for UserData
4817  std::vector<std::unique_ptr<OUString>> m_aUserData;
4819 
4820  DECL_LINK(SelectHdl, SvTreeListBox*, void);
4821  DECL_LINK(DeSelectHdl, SvTreeListBox*, void);
4822  DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
4823 
4824 public:
4825  SalInstanceIconView(::IconView* pIconView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
4826  : SalInstanceContainer(pIconView, pBuilder, bTakeOwnership)
4827  , m_xIconView(pIconView)
4828  {
4829  m_xIconView->SetSelectHdl(LINK(this, SalInstanceIconView, SelectHdl));
4830  m_xIconView->SetDeselectHdl(LINK(this, SalInstanceIconView, DeSelectHdl));
4831  m_xIconView->SetDoubleClickHdl(LINK(this, SalInstanceIconView, DoubleClickHdl));
4832  }
4833 
4834  virtual void freeze() override
4835  {
4837  m_xIconView->SetUpdateMode(false);
4838  }
4839 
4840  virtual void thaw() override
4841  {
4842  m_xIconView->SetUpdateMode(true);
4844  }
4845 
4846  virtual void insert(int pos, const OUString* pStr, const OUString* pId,
4847  const OUString* pIconName, weld::TreeIter* pRet) override
4848  {
4850  auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
4851  void* pUserData;
4852  if (pId)
4853  {
4854  m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
4855  pUserData = m_aUserData.back().get();
4856  }
4857  else
4858  pUserData = nullptr;
4859 
4860  SvTreeListEntry* pEntry = new SvTreeListEntry;
4861  if (pIconName)
4862  {
4863  Image aImage(createImage(*pIconName));
4864  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
4865  }
4866  else
4867  {
4868  Image aDummy;
4869  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
4870  }
4871  if (pStr)
4872  pEntry->AddItem(std::make_unique<SvLBoxString>(*pStr));
4873  pEntry->SetUserData(pUserData);
4874  m_xIconView->Insert(pEntry, nullptr, nInsertPos);
4875 
4876  if (pRet)
4877  {
4878  SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
4879  pVclRetIter->iter = pEntry;
4880  }
4881 
4883  }
4884 
4885  virtual OUString get_selected_id() const override
4886  {
4887  assert(m_xIconView->IsUpdateMode() && "don't request selection when frozen");
4888  if (SvTreeListEntry* pEntry = m_xIconView->FirstSelected())
4889  {
4890  if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData()))
4891  return *pStr;
4892  }
4893  return OUString();
4894  }
4895 
4896  virtual OUString get_selected_text() const override
4897  {
4898  assert(m_xIconView->IsUpdateMode() && "don't request selection when frozen");
4899  if (SvTreeListEntry* pEntry = m_xIconView->FirstSelected())
4900  return m_xIconView->GetEntryText(pEntry);
4901  return OUString();
4902  }
4903 
4904  virtual int count_selected_items() const override { return m_xIconView->GetSelectionCount(); }
4905 
4906  virtual void select(int pos) override
4907  {
4908  assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4910  if (pos == -1 || (pos == 0 && n_children() == 0))
4911  m_xIconView->SelectAll(false);
4912  else
4913  {
4914  SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos);
4915  m_xIconView->Select(pEntry, true);
4916  m_xIconView->MakeVisible(pEntry);
4917  }
4919  }
4920 
4921  virtual void unselect(int pos) override
4922  {
4923  assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4925  if (pos == -1)
4926  m_xIconView->SelectAll(true);
4927  else
4928  {
4929  SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos);
4930  m_xIconView->Select(pEntry, false);
4931  }
4933  }
4934 
4935  virtual int n_children() const override
4936  {
4937  return m_xIconView->GetModel()->GetChildList(nullptr).size();
4938  }
4939 
4940  virtual std::unique_ptr<weld::TreeIter>
4941  make_iterator(const weld::TreeIter* pOrig) const override
4942  {
4943  return std::unique_ptr<weld::TreeIter>(
4944  new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig)));
4945  }
4946 
4947  virtual bool get_selected(weld::TreeIter* pIter) const override
4948  {
4949  SvTreeListEntry* pEntry = m_xIconView->FirstSelected();
4950  auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4951  if (pVclIter)
4952  pVclIter->iter = pEntry;
4953  return pEntry != nullptr;
4954  }
4955 
4956  virtual bool get_cursor(weld::TreeIter* pIter) const override
4957  {
4958  SvTreeListEntry* pEntry = m_xIconView->GetCurEntry();
4959  auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4960  if (pVclIter)
4961  pVclIter->iter = pEntry;
4962  return pEntry != nullptr;
4963  }
4964 
4965  virtual void set_cursor(const weld::TreeIter& rIter) override
4966  {
4967  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4969  m_xIconView->SetCurEntry(rVclIter.iter);
4971  }
4972 
4973  virtual bool get_iter_first(weld::TreeIter& rIter) const override
4974  {
4975  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4976  rVclIter.iter = m_xIconView->GetEntry(0);
4977  return rVclIter.iter != nullptr;
4978  }
4979 
4980  virtual void scroll_to_item(const weld::TreeIter& rIter) override
4981  {
4982  assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4984  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4985  m_xIconView->MakeVisible(rVclIter.iter);
4987  }
4988 
4989  virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4990  {
4991  SalInstanceTreeIter aVclIter(m_xIconView->FirstSelected());
4992  while (aVclIter.iter)
4993  {
4994  if (func(aVclIter))
4995  return;
4996  aVclIter.iter = m_xIconView->NextSelected(aVclIter.iter);
4997  }
4998  }
4999 
5000  virtual OUString get_id(const weld::TreeIter& rIter) const override
5001  {
5002  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
5003  const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData());
5004  if (pStr)
5005  return *pStr;
5006  return OUString();
5007  }
5008 
5009  virtual void clear() override
5010  {
5012  m_xIconView->Clear();
5013  m_aUserData.clear();
5015  }
5016 
5017  virtual ~SalInstanceIconView() override
5018  {
5020  m_xIconView->SetSelectHdl(Link<SvTreeListBox*, void>());
5022  }
5023 };
5024 
5026 {
5027  if (notify_events_disabled())
5028  return;
5029  signal_selection_changed();
5030 }
5031 
5033 {
5034  if (notify_events_disabled())
5035  return;
5036  if (m_xIconView->GetSelectionMode() == SelectionMode::Single)
5037  return;
5038  signal_selection_changed();
5039 }
5040 
5042 {
5043  if (notify_events_disabled())
5044  return false;
5045  return !signal_item_activated();
5046 }
5047 
5048 double SalInstanceSpinButton::toField(int nValue) const
5049 {
5050  return static_cast<double>(nValue) / Power10(get_digits());
5051  }
5052 
5053 int SalInstanceSpinButton::fromField(double fValue) const
5054 {
5055  return FRound(fValue * Power10(get_digits()));
5056 }
5057 
5059  bool bTakeOwnership)
5060  : SalInstanceEntry(pButton, pBuilder, bTakeOwnership)
5061  , m_xButton(pButton)
5062 {
5063  m_xButton->SetThousandsSep(false); //off by default, MetricSpinButton enables it
5064  m_xButton->SetUpHdl(LINK(this, SalInstanceSpinButton, UpDownHdl));
5065  m_xButton->SetDownHdl(LINK(this, SalInstanceSpinButton, UpDownHdl));
5066  m_xButton->SetLoseFocusHdl(LINK(this, SalInstanceSpinButton, LoseFocusHdl));
5067  m_xButton->SetOutputHdl(LINK(this, SalInstanceSpinButton, OutputHdl));
5068  m_xButton->SetInputHdl(LINK(this, SalInstanceSpinButton, InputHdl));
5069  if (Edit* pEdit = m_xButton->GetSubEdit())
5070  pEdit->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl));
5071  else
5072  m_xButton->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl));
5073 }
5074 
5076 {
5077  return fromField(m_xButton->GetValue());
5078  }
5079 
5081 {
5082  m_xButton->SetValue(toField(value));
5083  }
5084 
5085 void SalInstanceSpinButton::set_range(int min, int max)
5086 {
5087  m_xButton->SetMinValue(toField(min));
5088  m_xButton->SetMaxValue(toField(max));
5089 }
5090 
5091 void SalInstanceSpinButton::get_range(int& min, int& max) const
5092 {
5093  min = fromField(m_xButton->GetMinValue());
5094  max = fromField(m_xButton->GetMaxValue());
5095 }
5096 
5097 void SalInstanceSpinButton::set_increments(int step, int /*page*/)
5098 {
5099  m_xButton->SetSpinSize(toField(step));
5100 }
5101 
5102 void SalInstanceSpinButton::get_increments(int& step, int& page) const
5103 {
5104  step = fromField(m_xButton->GetSpinSize());
5105  page = fromField(m_xButton->GetSpinSize());
5106 }
5107 
5108 void SalInstanceSpinButton::set_digits(unsigned int digits)
5109 {
5110  m_xButton->SetDecimalDigits(digits);
5111 }
5112 
5113 // SpinButton may be comprised of multiple subwidgets, consider the lot as
5114 // one thing for focus