xref: /core/vcl/source/app/salvtables.cxx (revision 45649f44)
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 <com/sun/star/awt/XWindowPeer.hpp>
23 #include <o3tl/sorted_vector.hxx>
24 #include <officecfg/Office/Common.hxx>
25 #include <iconview.hxx>
26 #include <salframe.hxx>
27 #include <salinst.hxx>
28 #include <salvd.hxx>
29 #include <salprn.hxx>
30 #include <saltimer.hxx>
31 #include <salsession.hxx>
32 #include <salsys.hxx>
33 #include <salbmp.hxx>
34 #include <salobj.hxx>
35 #include <salmenu.hxx>
36 #include <strings.hrc>
37 #include <svdata.hxx>
38 #include <svimpbox.hxx>
39 #include <messagedialog.hxx>
40 #include <treeglue.hxx>
41 #include <unotools/accessiblerelationsethelper.hxx>
42 #include <unotools/configmgr.hxx>
43 #include <utility>
44 #include <tools/helpers.hxx>
45 #include <vcl/abstdlg.hxx>
46 #include <vcl/builder.hxx>
47 #include <vcl/toolkit/combobox.hxx>
48 #include <vcl/toolkit/dialog.hxx>
49 #include <vcl/toolkit/fixed.hxx>
50 #include <vcl/toolkit/fixedhyper.hxx>
51 #include <vcl/toolkit/fmtfield.hxx>
52 #include <vcl/headbar.hxx>
53 #include <vcl/toolkit/ivctrl.hxx>
54 #include <vcl/layout.hxx>
55 #include <vcl/menubtn.hxx>
56 #include <vcl/toolkit/prgsbar.hxx>
57 #include <vcl/ptrstyle.hxx>
58 #include <slider.hxx>
59 #include <vcl/sysdata.hxx>
60 #include <vcl/toolkit/svlbitm.hxx>
61 #include <vcl/toolkit/svtabbx.hxx>
62 #include <vcl/tabctrl.hxx>
63 #include <vcl/tabpage.hxx>
64 #include <vcl/toolkit/treelistentry.hxx>
65 #include <vcl/toolkit/throbber.hxx>
66 #include <vcl/toolkit/unowrap.hxx>
67 #include <vcl/weld.hxx>
68 #include <vcl/weldutils.hxx>
69 #include <vcl/toolkit/vclmedit.hxx>
70 #include <vcl/toolkit/viewdataentry.hxx>
71 #include <vcl/virdev.hxx>
72 #include <bitmaps.hlst>
73 #include <calendar.hxx>
74 #include <verticaltabctrl.hxx>
75 #include <window.h>
76 #include <wizdlg.hxx>
77 #include <salvtables.hxx>
78 
79 #include <boost/property_tree/ptree.hpp>
80 
81 SalFrame::SalFrame()
82     : m_pWindow(nullptr)
83     , m_pProc(nullptr)
84 {
85 }
86 
87 // this file contains the virtual destructors of the sal interface
88 // compilers usually put their vtables where the destructor is
89 
90 SalFrame::~SalFrame() {}
91 
92 void SalFrame::SetCallback(vcl::Window* pWindow, SALFRAMEPROC pProc)
93 {
94     m_pWindow = pWindow;
95     m_pProc = pProc;
96 }
97 
98 // default to full-frame flushes
99 // on ports where partial-flushes are much cheaper this method should be overridden
100 void SalFrame::Flush(const tools::Rectangle&) { Flush(); }
101 
102 void SalFrame::SetRepresentedURL(const OUString&)
103 {
104     // currently this is Mac only functionality
105 }
106 
107 SalInstance::SalInstance(std::unique_ptr<comphelper::SolarMutex> pMutex)
108     : m_pYieldMutex(std::move(pMutex))
109 {
110 }
111 
112 SalInstance::~SalInstance() {}
113 
114 comphelper::SolarMutex* SalInstance::GetYieldMutex() { return m_pYieldMutex.get(); }
115 
116 sal_uInt32 SalInstance::ReleaseYieldMutexAll() { return m_pYieldMutex->release(true); }
117 
118 void SalInstance::AcquireYieldMutex(sal_uInt32 nCount) { m_pYieldMutex->acquire(nCount); }
119 
120 std::unique_ptr<SalSession> SalInstance::CreateSalSession() { return nullptr; }
121 
122 std::unique_ptr<SalMenu> SalInstance::CreateMenu(bool, Menu*)
123 {
124     // default: no native menus
125     return nullptr;
126 }
127 
128 std::unique_ptr<SalMenuItem> SalInstance::CreateMenuItem(const SalItemParams&) { return nullptr; }
129 
130 bool SalInstance::CallEventCallback(void const* pEvent, int nBytes)
131 {
132     return m_pEventInst.is() && m_pEventInst->dispatchEvent(pEvent, nBytes);
133 }
134 
135 SalTimer::~SalTimer() COVERITY_NOEXCEPT_FALSE {}
136 
137 void SalBitmap::DropScaledCache()
138 {
139     if (ImplSVData* pSVData = ImplGetSVData())
140     {
141         auto& rCache = pSVData->maGDIData.maScaleCache;
142 
143         rCache.remove_if([this] (const lru_scale_cache::key_value_pair_t& rKeyValuePair)
144                          { return rKeyValuePair.first.mpBitmap == this; });
145     }
146 }
147 
148 SalBitmap::~SalBitmap() { DropScaledCache(); }
149 
150 SalSystem::~SalSystem() {}
151 
152 SalPrinter::~SalPrinter() {}
153 
154 bool SalPrinter::StartJob(const OUString*, const OUString&, const OUString&, ImplJobSetup*,
155                           vcl::PrinterController&)
156 {
157     return false;
158 }
159 
160 SalInfoPrinter::~SalInfoPrinter() {}
161 
162 SalVirtualDevice::~SalVirtualDevice() {}
163 
164 SalObject::~SalObject() {}
165 
166 SalMenu::~SalMenu() {}
167 
168 bool SalMenu::ShowNativePopupMenu(FloatingWindow*, const tools::Rectangle&, FloatWinPopupFlags)
169 {
170     return false;
171 }
172 
173 void SalMenu::ShowCloseButton(bool) {}
174 
175 bool SalMenu::AddMenuBarButton(const SalMenuButtonItem&) { return false; }
176 
177 void SalMenu::RemoveMenuBarButton(sal_uInt16) {}
178 
179 tools::Rectangle SalMenu::GetMenuBarButtonRectPixel(sal_uInt16, SalFrame*)
180 {
181     return tools::Rectangle();
182 }
183 
184 int SalMenu::GetMenuBarHeight() const { return 0; }
185 
186 void SalMenu::ApplyPersona() {}
187 
188 SalMenuItem::~SalMenuItem() {}
189 
190 void SalInstanceWidget::ensure_event_listener()
191 {
192     if (!m_bEventListener)
193     {
194         m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, EventListener));
195         m_bEventListener = true;
196     }
197 }
198 
199 // we want the ability to mark key events as handled, so use this variant
200 // for those, we get all keystrokes in this case, so we will need to filter
201 // them later
202 void SalInstanceWidget::ensure_key_listener()
203 {
204     if (!m_bKeyEventListener)
205     {
206         Application::AddKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
207         m_bKeyEventListener = true;
208     }
209 }
210 
211 // we want the ability to know about mouse events that happen in our children
212 // so use this variant, we will need to filter them later
213 void SalInstanceWidget::ensure_mouse_listener()
214 {
215     if (!m_bMouseEventListener)
216     {
217         Application::AddEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
218         m_bMouseEventListener = true;
219     }
220 }
221 
222 void SalInstanceWidget::set_background(const Color& rColor)
223 {
224     m_xWidget->SetControlBackground(rColor);
225     m_xWidget->SetBackground(m_xWidget->GetControlBackground());
226     // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under"
227     // transparent children of the widget
228     m_xWidget->SetStyle(m_xWidget->GetStyle() & ~WB_CLIPCHILDREN);
229 }
230 
231 SalInstanceWidget::SalInstanceWidget(vcl::Window* pWidget, SalInstanceBuilder* pBuilder,
232                                      bool bTakeOwnership)
233     : m_xWidget(pWidget)
234     , m_pBuilder(pBuilder)
235     , m_bTakeOwnership(bTakeOwnership)
236     , m_bEventListener(false)
237     , m_bKeyEventListener(false)
238     , m_bMouseEventListener(false)
239     , m_nBlockNotify(0)
240 {
241 }
242 
243 void SalInstanceWidget::set_sensitive(bool sensitive) { m_xWidget->Enable(sensitive); }
244 
245 bool SalInstanceWidget::get_sensitive() const { return m_xWidget->IsEnabled(); }
246 
247 bool SalInstanceWidget::get_visible() const { return m_xWidget->IsVisible(); }
248 
249 bool SalInstanceWidget::is_visible() const { return m_xWidget->IsReallyVisible(); }
250 
251 void SalInstanceWidget::set_can_focus(bool bCanFocus)
252 {
253     auto nStyle = m_xWidget->GetStyle() & ~(WB_TABSTOP | WB_NOTABSTOP);
254     if (bCanFocus)
255         nStyle |= WB_TABSTOP;
256     else
257         nStyle |= WB_NOTABSTOP;
258     m_xWidget->SetStyle(nStyle);
259 }
260 
261 void SalInstanceWidget::grab_focus()
262 {
263     disable_notify_events();
264     m_xWidget->GrabFocus();
265     enable_notify_events();
266 }
267 
268 bool SalInstanceWidget::has_focus() const { return m_xWidget->HasFocus(); }
269 
270 bool SalInstanceWidget::is_active() const { return m_xWidget->IsActive(); }
271 
272 void SalInstanceWidget::set_has_default(bool has_default)
273 {
274     m_xWidget->set_property("has-default", OUString::boolean(has_default));
275 }
276 
277 bool SalInstanceWidget::get_has_default() const { return m_xWidget->GetStyle() & WB_DEFBUTTON; }
278 
279 void SalInstanceWidget::show() { m_xWidget->Show(); }
280 
281 void SalInstanceWidget::hide() { m_xWidget->Hide(); }
282 
283 void SalInstanceWidget::set_size_request(int nWidth, int nHeight)
284 {
285     m_xWidget->set_width_request(nWidth);
286     m_xWidget->set_height_request(nHeight);
287 }
288 
289 Size SalInstanceWidget::get_size_request() const
290 {
291     return Size(m_xWidget->get_width_request(), m_xWidget->get_height_request());
292 }
293 
294 Size SalInstanceWidget::get_preferred_size() const { return m_xWidget->get_preferred_size(); }
295 
296 float SalInstanceWidget::get_approximate_digit_width() const
297 {
298     return m_xWidget->approximate_digit_width();
299 }
300 
301 int SalInstanceWidget::get_text_height() const { return m_xWidget->GetTextHeight(); }
302 
303 Size SalInstanceWidget::get_pixel_size(const OUString& rText) const
304 {
305     //TODO, or do I want GetTextBoundRect ?, just using width at the moment anyway
306     return Size(m_xWidget->GetTextWidth(rText), m_xWidget->GetTextHeight());
307 }
308 
309 vcl::Font SalInstanceWidget::get_font() { return m_xWidget->GetPointFont(*m_xWidget); }
310 
311 OString SalInstanceWidget::get_buildable_name() const { return m_xWidget->get_id().toUtf8(); }
312 
313 void SalInstanceWidget::set_help_id(const OString& rId) { return m_xWidget->SetHelpId(rId); }
314 
315 OString SalInstanceWidget::get_help_id() const { return m_xWidget->GetHelpId(); }
316 
317 void SalInstanceWidget::set_grid_left_attach(int nAttach)
318 {
319     m_xWidget->set_grid_left_attach(nAttach);
320 }
321 
322 int SalInstanceWidget::get_grid_left_attach() const { return m_xWidget->get_grid_left_attach(); }
323 
324 void SalInstanceWidget::set_grid_width(int nCols) { m_xWidget->set_grid_width(nCols); }
325 
326 void SalInstanceWidget::set_grid_top_attach(int nAttach)
327 {
328     m_xWidget->set_grid_top_attach(nAttach);
329 }
330 
331 int SalInstanceWidget::get_grid_top_attach() const { return m_xWidget->get_grid_top_attach(); }
332 
333 void SalInstanceWidget::set_hexpand(bool bExpand) { m_xWidget->set_hexpand(bExpand); }
334 
335 bool SalInstanceWidget::get_hexpand() const { return m_xWidget->get_hexpand(); }
336 
337 void SalInstanceWidget::set_vexpand(bool bExpand) { m_xWidget->set_vexpand(bExpand); }
338 
339 bool SalInstanceWidget::get_vexpand() const { return m_xWidget->get_vexpand(); }
340 
341 void SalInstanceWidget::set_secondary(bool bSecondary) { m_xWidget->set_secondary(bSecondary); }
342 
343 void SalInstanceWidget::set_margin_top(int nMargin) { m_xWidget->set_margin_top(nMargin); }
344 
345 void SalInstanceWidget::set_margin_bottom(int nMargin) { m_xWidget->set_margin_bottom(nMargin); }
346 
347 void SalInstanceWidget::set_margin_left(int nMargin) { m_xWidget->set_margin_left(nMargin); }
348 
349 void SalInstanceWidget::set_margin_right(int nMargin) { m_xWidget->set_margin_bottom(nMargin); }
350 
351 int SalInstanceWidget::get_margin_top() const { return m_xWidget->get_margin_top(); }
352 
353 int SalInstanceWidget::get_margin_bottom() const { return m_xWidget->get_margin_bottom(); }
354 
355 int SalInstanceWidget::get_margin_left() const { return m_xWidget->get_margin_left(); }
356 
357 int SalInstanceWidget::get_margin_right() const { return m_xWidget->get_margin_bottom(); }
358 
359 void SalInstanceWidget::set_accessible_name(const OUString& rName)
360 {
361     m_xWidget->SetAccessibleName(rName);
362 }
363 
364 OUString SalInstanceWidget::get_accessible_name() const { return m_xWidget->GetAccessibleName(); }
365 
366 OUString SalInstanceWidget::get_accessible_description() const
367 {
368     return m_xWidget->GetAccessibleDescription();
369 }
370 
371 void SalInstanceWidget::set_accessible_relation_labeled_by(weld::Widget* pLabel)
372 {
373     vcl::Window* pAtkLabel
374         = pLabel ? dynamic_cast<SalInstanceWidget&>(*pLabel).getWidget() : nullptr;
375     m_xWidget->SetAccessibleRelationLabeledBy(pAtkLabel);
376 }
377 
378 void SalInstanceWidget::set_accessible_relation_label_for(weld::Widget* pLabeled)
379 {
380     vcl::Window* pAtkLabeled
381         = pLabeled ? dynamic_cast<SalInstanceWidget&>(*pLabeled).getWidget() : nullptr;
382     m_xWidget->SetAccessibleRelationLabelFor(pAtkLabeled);
383 }
384 
385 void SalInstanceWidget::set_tooltip_text(const OUString& rTip)
386 {
387     m_xWidget->SetQuickHelpText(rTip);
388 }
389 
390 OUString SalInstanceWidget::get_tooltip_text() const { return m_xWidget->GetQuickHelpText(); }
391 
392 void SalInstanceWidget::connect_focus_in(const Link<Widget&, void>& rLink)
393 {
394     ensure_event_listener();
395     weld::Widget::connect_focus_in(rLink);
396 }
397 
398 void SalInstanceWidget::connect_mnemonic_activate(const Link<Widget&, bool>& rLink)
399 {
400     m_xWidget->SetMnemonicActivateHdl(LINK(this, SalInstanceWidget, MnemonicActivateHdl));
401     weld::Widget::connect_mnemonic_activate(rLink);
402 }
403 
404 void SalInstanceWidget::connect_focus_out(const Link<Widget&, void>& rLink)
405 {
406     ensure_event_listener();
407     weld::Widget::connect_focus_out(rLink);
408 }
409 
410 void SalInstanceWidget::connect_size_allocate(const Link<const Size&, void>& rLink)
411 {
412     ensure_event_listener();
413     weld::Widget::connect_size_allocate(rLink);
414 }
415 
416 void SalInstanceWidget::connect_mouse_press(const Link<const MouseEvent&, bool>& rLink)
417 {
418     ensure_mouse_listener();
419     weld::Widget::connect_mouse_press(rLink);
420 }
421 
422 void SalInstanceWidget::connect_mouse_move(const Link<const MouseEvent&, bool>& rLink)
423 {
424     ensure_mouse_listener();
425     weld::Widget::connect_mouse_move(rLink);
426 }
427 
428 void SalInstanceWidget::connect_mouse_release(const Link<const MouseEvent&, bool>& rLink)
429 {
430     ensure_mouse_listener();
431     weld::Widget::connect_mouse_release(rLink);
432 }
433 
434 void SalInstanceWidget::connect_key_press(const Link<const KeyEvent&, bool>& rLink)
435 {
436     ensure_key_listener();
437     weld::Widget::connect_key_press(rLink);
438 }
439 
440 void SalInstanceWidget::connect_key_release(const Link<const KeyEvent&, bool>& rLink)
441 {
442     ensure_key_listener();
443     weld::Widget::connect_key_release(rLink);
444 }
445 
446 bool SalInstanceWidget::get_extents_relative_to(const Widget& rRelative, int& x, int& y, int& width,
447                                                 int& height) const
448 {
449     tools::Rectangle aRect(m_xWidget->GetWindowExtentsRelative(
450         dynamic_cast<const SalInstanceWidget&>(rRelative).getWidget()));
451     x = aRect.Left();
452     y = aRect.Top();
453     width = aRect.GetWidth();
454     height = aRect.GetHeight();
455     return true;
456 }
457 
458 void SalInstanceWidget::grab_add() { m_xWidget->CaptureMouse(); }
459 
460 bool SalInstanceWidget::has_grab() const { return m_xWidget->IsMouseCaptured(); }
461 
462 void SalInstanceWidget::grab_remove() { m_xWidget->ReleaseMouse(); }
463 
464 bool SalInstanceWidget::get_direction() const { return m_xWidget->IsRTLEnabled(); }
465 
466 void SalInstanceWidget::set_direction(bool bRTL) { m_xWidget->EnableRTL(bRTL); }
467 
468 void SalInstanceWidget::freeze() { m_xWidget->SetUpdateMode(false); }
469 
470 void SalInstanceWidget::thaw() { m_xWidget->SetUpdateMode(true); }
471 
472 SalInstanceWidget::~SalInstanceWidget()
473 {
474     if (m_aMnemonicActivateHdl.IsSet())
475         m_xWidget->SetMnemonicActivateHdl(Link<vcl::Window&, bool>());
476     if (m_bMouseEventListener)
477         Application::RemoveEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
478     if (m_bKeyEventListener)
479         Application::RemoveKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
480     if (m_bEventListener)
481         m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, EventListener));
482     if (m_bTakeOwnership)
483         m_xWidget.disposeAndClear();
484 }
485 
486 vcl::Window* SalInstanceWidget::getWidget() const { return m_xWidget; }
487 
488 void SalInstanceWidget::disable_notify_events() { ++m_nBlockNotify; }
489 
490 bool SalInstanceWidget::notify_events_disabled() { return m_nBlockNotify != 0; }
491 
492 void SalInstanceWidget::enable_notify_events() { --m_nBlockNotify; }
493 
494 OUString SalInstanceWidget::strip_mnemonic(const OUString& rLabel) const
495 {
496     return rLabel.replaceFirst("~", "");
497 }
498 
499 VclPtr<VirtualDevice> SalInstanceWidget::create_virtual_device() const
500 {
501     // create with (annoying) separate alpha layer that LibreOffice itself uses
502     return VclPtr<VirtualDevice>::Create(*Application::GetDefaultDevice(), DeviceFormat::DEFAULT,
503                                          DeviceFormat::DEFAULT);
504 }
505 
506 css::uno::Reference<css::datatransfer::dnd::XDropTarget> SalInstanceWidget::get_drop_target()
507 {
508     return m_xWidget->GetDropTarget();
509 }
510 
511 void SalInstanceWidget::connect_get_property_tree(
512     const Link<tools::JsonWriter&, void>& rLink)
513 {
514     m_xWidget->SetDumpAsPropertyTreeHdl(rLink);
515 }
516 
517 void SalInstanceWidget::set_stack_background()
518 {
519     set_background(m_xWidget->GetSettings().GetStyleSettings().GetWindowColor());
520 }
521 
522 void SalInstanceWidget::set_title_background()
523 {
524     set_background(m_xWidget->GetSettings().GetStyleSettings().GetShadowColor());
525 }
526 
527 void SalInstanceWidget::set_toolbar_background()
528 {
529     m_xWidget->SetBackground();
530     m_xWidget->SetPaintTransparent(true);
531 }
532 
533 void SalInstanceWidget::set_highlight_background()
534 {
535     set_background(m_xWidget->GetSettings().GetStyleSettings().GetHighlightColor());
536 }
537 
538 SystemWindow* SalInstanceWidget::getSystemWindow() { return m_xWidget->GetSystemWindow(); }
539 
540 void SalInstanceWidget::HandleEventListener(VclWindowEvent& rEvent)
541 {
542     if (notify_events_disabled())
543         return;
544     if (rEvent.GetId() == VclEventId::WindowGetFocus)
545         m_aFocusInHdl.Call(*this);
546     else if (rEvent.GetId() == VclEventId::WindowLoseFocus)
547         m_aFocusOutHdl.Call(*this);
548     else if (rEvent.GetId() == VclEventId::WindowResize)
549         m_aSizeAllocateHdl.Call(m_xWidget->GetSizePixel());
550 }
551 
552 namespace
553 {
554     MouseEvent TransformEvent(const MouseEvent& rEvent, const vcl::Window* pParent, const vcl::Window* pChild)
555     {
556         return MouseEvent(pParent->ScreenToOutputPixel(pChild->OutputToScreenPixel(rEvent.GetPosPixel())),
557                           rEvent.GetClicks(), rEvent.GetMode(), rEvent.GetButtons(), rEvent.GetModifier());
558     }
559 }
560 
561 void SalInstanceWidget::HandleMouseEventListener(VclSimpleEvent& rEvent)
562 {
563     if (rEvent.GetId() == VclEventId::WindowMouseButtonDown)
564     {
565         auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
566         if (m_xWidget == rWinEvent.GetWindow())
567         {
568             const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
569             m_aMousePressHdl.Call(*pMouseEvent);
570         }
571         else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
572         {
573             const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
574             const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
575             m_aMousePressHdl.Call(aTransformedEvent);
576         }
577     }
578     else if (rEvent.GetId() == VclEventId::WindowMouseButtonUp)
579     {
580         auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
581         if (m_xWidget == rWinEvent.GetWindow())
582         {
583             const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
584             m_aMouseReleaseHdl.Call(*pMouseEvent);
585         }
586         else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
587         {
588             const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
589             const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
590             m_aMouseReleaseHdl.Call(aTransformedEvent);
591         }
592     }
593     else if (rEvent.GetId() == VclEventId::WindowMouseMove)
594     {
595         auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
596         if (m_xWidget == rWinEvent.GetWindow())
597         {
598             const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
599             m_aMouseMotionHdl.Call(*pMouseEvent);
600         }
601         else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
602         {
603             const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
604             const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
605             m_aMouseMotionHdl.Call(aTransformedEvent);
606         }
607     }
608 }
609 
610 bool SalInstanceWidget::HandleKeyEventListener(VclWindowEvent& rEvent)
611 {
612     // we get all key events here, ignore them unless we have focus
613     if (!m_xWidget->HasChildPathFocus())
614         return false;
615     if (rEvent.GetId() == VclEventId::WindowKeyInput)
616     {
617         const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
618         return m_aKeyPressHdl.Call(*pKeyEvent);
619     }
620     else if (rEvent.GetId() == VclEventId::WindowKeyUp)
621     {
622         const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
623         return m_aKeyReleaseHdl.Call(*pKeyEvent);
624     }
625     return false;
626 }
627 
628 IMPL_LINK(SalInstanceWidget, EventListener, VclWindowEvent&, rEvent, void)
629 {
630     HandleEventListener(rEvent);
631 }
632 
633 IMPL_LINK(SalInstanceWidget, KeyEventListener, VclWindowEvent&, rEvent, bool)
634 {
635     return HandleKeyEventListener(rEvent);
636 }
637 
638 IMPL_LINK(SalInstanceWidget, MouseEventListener, VclSimpleEvent&, rEvent, void)
639 {
640     HandleMouseEventListener(rEvent);
641 }
642 
643 IMPL_LINK_NOARG(SalInstanceWidget, MnemonicActivateHdl, vcl::Window&, bool)
644 {
645     return m_aMnemonicActivateHdl.Call(*this);
646 }
647 
648 namespace
649 {
650 Image createImage(const OUString& rImage)
651 {
652     if (rImage.isEmpty())
653         return Image();
654     if (rImage.lastIndexOf('.') != rImage.getLength() - 4)
655     {
656         assert((rImage == "dialog-warning" || rImage == "dialog-error"
657                 || rImage == "dialog-information")
658                && "unknown stock image");
659         if (rImage == "dialog-warning")
660             return Image(StockImage::Yes, IMG_WARN);
661         else if (rImage == "dialog-error")
662             return Image(StockImage::Yes, IMG_ERROR);
663         else if (rImage == "dialog-information")
664             return Image(StockImage::Yes, IMG_INFO);
665     }
666     return Image(StockImage::Yes, rImage);
667 }
668 
669 Image createImage(const VirtualDevice& rDevice)
670 {
671     return Image(rDevice.GetBitmapEx(Point(), rDevice.GetOutputSizePixel()));
672 }
673 
674 sal_uInt16 insert_to_menu(sal_uInt16 nLastId, PopupMenu* pMenu, int pos, const OUString& rId,
675                           const OUString& rStr, const OUString* pIconName,
676                           const VirtualDevice* pImageSurface, TriState eCheckRadioFalse)
677 {
678     const sal_uInt16 nNewid = nLastId + 1;
679 
680     MenuItemBits nBits;
681     if (eCheckRadioFalse == TRISTATE_TRUE)
682         nBits = MenuItemBits::CHECKABLE;
683     else if (eCheckRadioFalse == TRISTATE_FALSE)
684         nBits = MenuItemBits::CHECKABLE | MenuItemBits::RADIOCHECK;
685     else
686         nBits = MenuItemBits::NONE;
687 
688     pMenu->InsertItem(nNewid, rStr, nBits,
689                       OUStringToOString(rId, RTL_TEXTENCODING_UTF8), pos == -1 ? MENU_APPEND : pos);
690     if (pIconName)
691     {
692         pMenu->SetItemImage(nNewid, createImage(*pIconName));
693     }
694     else if (pImageSurface)
695     {
696         pMenu->SetItemImage(nNewid, createImage(*pImageSurface));
697     }
698     return nNewid;
699 }
700 }
701 
702 SalInstanceMenu::SalInstanceMenu(PopupMenu* pMenu, bool bTakeOwnership)
703     : m_xMenu(pMenu)
704     , m_bTakeOwnership(bTakeOwnership)
705 {
706     const auto nCount = m_xMenu->GetItemCount();
707     m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
708     m_xMenu->SetSelectHdl(LINK(this, SalInstanceMenu, SelectMenuHdl));
709 }
710 OString SalInstanceMenu::popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect)
711 {
712     SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent);
713     assert(pVclWidget);
714     m_xMenu->Execute(pVclWidget->getWidget(), rRect,
715                         PopupMenuFlags::ExecuteDown | PopupMenuFlags::NoMouseUpClose);
716     return m_xMenu->GetCurItemIdent();
717 }
718 void SalInstanceMenu::set_sensitive(const OString& rIdent, bool bSensitive)
719 {
720     m_xMenu->EnableItem(rIdent, bSensitive);
721 }
722 void SalInstanceMenu::set_active(const OString& rIdent, bool bActive)
723 {
724     m_xMenu->CheckItem(rIdent, bActive);
725 }
726 bool SalInstanceMenu::get_active(const OString& rIdent) const
727 {
728     return m_xMenu->IsItemChecked(m_xMenu->GetItemId(rIdent));
729 }
730 void SalInstanceMenu::set_label(const OString& rIdent, const OUString& rLabel)
731 {
732     m_xMenu->SetItemText(m_xMenu->GetItemId(rIdent), rLabel);
733 }
734 OUString SalInstanceMenu::get_label(const OString& rIdent) const
735 {
736     return m_xMenu->GetItemText(m_xMenu->GetItemId(rIdent));
737 }
738 void SalInstanceMenu::set_visible(const OString& rIdent, bool bShow)
739 {
740     m_xMenu->ShowItem(m_xMenu->GetItemId(rIdent), bShow);
741 }
742 void SalInstanceMenu::clear() { m_xMenu->Clear(); }
743 void SalInstanceMenu::insert(int pos, const OUString& rId, const OUString& rStr,
744                     const OUString* pIconName, VirtualDevice* pImageSurface,
745                     TriState eCheckRadioFalse)
746 {
747     m_nLastId
748         = insert_to_menu(m_nLastId, m_xMenu, pos, rId, rStr, pIconName, pImageSurface, eCheckRadioFalse);
749 }
750 void SalInstanceMenu::insert_separator(int pos, const OUString& rId)
751 {
752     auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
753     m_xMenu->InsertSeparator(rId.toUtf8(), nInsertPos);
754 }
755 void SalInstanceMenu::remove(const OString& rId)
756 {
757     m_xMenu->RemoveItem(m_xMenu->GetItemPos(m_xMenu->GetItemId(rId)));
758 }
759 int SalInstanceMenu::n_children() const { return m_xMenu->GetItemCount(); }
760 PopupMenu* SalInstanceMenu::getMenu() const { return m_xMenu.get(); }
761 SalInstanceMenu::~SalInstanceMenu()
762 {
763     m_xMenu->SetSelectHdl(Link<::Menu*, bool>());
764     if (m_bTakeOwnership)
765         m_xMenu.disposeAndClear();
766 }
767 
768 IMPL_LINK_NOARG(SalInstanceMenu, SelectMenuHdl, ::Menu*, bool)
769 {
770     signal_activate(m_xMenu->GetCurItemIdent());
771     /* tdf#131333 Menu::Select depends on a false here to allow
772        propagating a submens's selected id to its parent menu to become its
773        selected id.
774 
775        without this, while gen menus already have propagated this to its parent
776        in MenuFloatingWindow::EndExecute, SalMenus as used under kf5/macOS
777        won't propagate the selected id
778     */
779     return false;
780 }
781 
782 SalInstanceToolbar::SalInstanceToolbar(ToolBox* pToolBox, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
783     : SalInstanceWidget(pToolBox, pBuilder, bTakeOwnership)
784     , m_xToolBox(pToolBox)
785 {
786     m_xToolBox->SetSelectHdl(LINK(this, SalInstanceToolbar, ClickHdl));
787     m_xToolBox->SetDropdownClickHdl(LINK(this, SalInstanceToolbar, DropdownClick));
788 }
789 
790 void SalInstanceToolbar::set_item_sensitive(const OString& rIdent, bool bSensitive)
791 {
792     m_xToolBox->EnableItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bSensitive);
793 }
794 
795 bool SalInstanceToolbar::get_item_sensitive(const OString& rIdent) const
796 {
797     return m_xToolBox->IsItemEnabled(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
798 }
799 
800 void SalInstanceToolbar::set_item_visible(const OString& rIdent, bool bVisible)
801 {
802     m_xToolBox->ShowItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bVisible);
803 }
804 
805 void SalInstanceToolbar::set_item_help_id(const OString& rIdent, const OString& rHelpId)
806 {
807     m_xToolBox->SetHelpId(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rHelpId);
808 }
809 
810 bool SalInstanceToolbar::get_item_visible(const OString& rIdent) const
811 {
812     return m_xToolBox->IsItemVisible(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
813 }
814 
815 void SalInstanceToolbar::set_item_active(const OString& rIdent, bool bActive)
816 {
817     sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
818     m_xToolBox->CheckItem(nItemId, bActive);
819 }
820 
821 bool SalInstanceToolbar::get_item_active(const OString& rIdent) const
822 {
823     return m_xToolBox->IsItemChecked(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
824 }
825 
826 void SalInstanceToolbar::set_menu_item_active(const OString& rIdent, bool bActive)
827 {
828     sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
829     assert(m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN);
830 
831     if (bActive)
832     {
833         m_sStartShowIdent = m_xToolBox->GetItemCommand(nItemId).toUtf8();
834         signal_toggle_menu(m_sStartShowIdent);
835     }
836 
837     auto pFloat = m_aFloats[nItemId];
838     if (pFloat)
839     {
840         if (bActive)
841             vcl::Window::GetDockingManager()->StartPopupMode(m_xToolBox, pFloat,
842                                                                 FloatWinPopupFlags::GrabFocus);
843         else
844             vcl::Window::GetDockingManager()->EndPopupMode(pFloat);
845     }
846     auto pPopup = m_aMenus[nItemId];
847     if (pPopup)
848     {
849         if (bActive)
850         {
851             tools::Rectangle aRect = m_xToolBox->GetItemRect(nItemId);
852             pPopup->Execute(m_xToolBox, aRect, PopupMenuFlags::ExecuteDown);
853         }
854         else
855             pPopup->EndExecute();
856     }
857 
858     m_sStartShowIdent.clear();
859 }
860 
861 bool SalInstanceToolbar::get_menu_item_active(const OString& rIdent) const
862 {
863     sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
864     assert(m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN);
865 
866     if (rIdent == m_sStartShowIdent)
867         return true;
868 
869     auto aFloat = m_aFloats.find(nItemId);
870     if (aFloat != m_aFloats.end())
871     {
872         return vcl::Window::GetDockingManager()->IsInPopupMode(aFloat->second);
873     }
874 
875     auto aPopup = m_aMenus.find(nItemId);
876     if (aPopup != m_aMenus.end())
877     {
878         return PopupMenu::GetActivePopupMenu() == aPopup->second;
879     }
880 
881     return false;
882 }
883 
884 void SalInstanceToolbar::set_item_popover(const OString& rIdent, weld::Widget* pPopover)
885 {
886     SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
887 
888     vcl::Window* pFloat = pPopoverWidget ? pPopoverWidget->getWidget() : nullptr;
889     if (pFloat)
890     {
891         pFloat->AddEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
892         pFloat->EnableDocking();
893     }
894 
895     sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
896     auto xOldFloat = m_aFloats[nId];
897     if (xOldFloat)
898     {
899         xOldFloat->RemoveEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
900     }
901     m_aFloats[nId] = pFloat;
902     m_aMenus[nId] = nullptr;
903 }
904 
905 void SalInstanceToolbar::set_item_menu(const OString& rIdent, weld::Menu* pMenu)
906 {
907     SalInstanceMenu* pInstanceMenu = dynamic_cast<SalInstanceMenu*>(pMenu);
908 
909     PopupMenu* pPopup = pInstanceMenu ? pInstanceMenu->getMenu() : nullptr;
910 
911     sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
912     m_aMenus[nId] = pPopup;
913     m_aFloats[nId] = nullptr;
914 }
915 
916 void SalInstanceToolbar::insert_separator(int pos, const OUString& /*rId*/)
917 {
918     auto nInsertPos = pos == -1 ? ToolBox::APPEND : pos;
919     m_xToolBox->InsertSeparator(nInsertPos, 5);
920 }
921 
922 int SalInstanceToolbar::get_n_items() const { return m_xToolBox->GetItemCount(); }
923 
924 OString SalInstanceToolbar::get_item_ident(int nIndex) const
925 {
926     return m_xToolBox->GetItemCommand(m_xToolBox->GetItemId(nIndex)).toUtf8();
927 }
928 
929 void SalInstanceToolbar::set_item_ident(int nIndex, const OString& rIdent)
930 {
931     return m_xToolBox->SetItemCommand(m_xToolBox->GetItemId(nIndex),
932                                         OUString::fromUtf8(rIdent));
933 }
934 
935 void SalInstanceToolbar::set_item_label(int nIndex, const OUString& rLabel)
936 {
937     m_xToolBox->SetItemText(m_xToolBox->GetItemId(nIndex), rLabel);
938 }
939 
940 OUString SalInstanceToolbar::get_item_label(const OString& rIdent) const
941 {
942     return m_xToolBox->GetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
943 }
944 
945 void SalInstanceToolbar::set_item_label(const OString& rIdent, const OUString& rLabel)
946 {
947     m_xToolBox->SetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rLabel);
948 }
949 
950 void SalInstanceToolbar::set_item_icon_name(const OString& rIdent, const OUString& rIconName)
951 {
952     m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)),
953                                 Image(StockImage::Yes, rIconName));
954 }
955 
956 void SalInstanceToolbar::set_item_image(const OString& rIdent,
957                             const css::uno::Reference<css::graphic::XGraphic>& rIcon)
958 {
959     m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image(rIcon));
960 }
961 
962 void SalInstanceToolbar::set_item_image(const OString& rIdent, VirtualDevice* pDevice)
963 {
964     if (pDevice)
965         m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)),
966                                     createImage(*pDevice));
967     else
968         m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image());
969 }
970 
971 void SalInstanceToolbar::set_item_image(int nIndex,
972                             const css::uno::Reference<css::graphic::XGraphic>& rIcon)
973 {
974     m_xToolBox->SetItemImage(m_xToolBox->GetItemId(nIndex), Image(rIcon));
975 }
976 
977 void SalInstanceToolbar::set_item_tooltip_text(int nIndex, const OUString& rTip)
978 {
979     m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(nIndex), rTip);
980 }
981 
982 void SalInstanceToolbar::set_item_tooltip_text(const OString& rIdent, const OUString& rTip)
983 {
984     m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rTip);
985 }
986 
987 OUString SalInstanceToolbar::get_item_tooltip_text(const OString& rIdent) const
988 {
989     return m_xToolBox->GetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
990 }
991 
992 vcl::ImageType SalInstanceToolbar::get_icon_size() const { return m_xToolBox->GetImageSize(); }
993 
994 void SalInstanceToolbar::set_icon_size(vcl::ImageType eType)
995 {
996     ToolBoxButtonSize eButtonSize = ToolBoxButtonSize::DontCare;
997     switch (eType)
998     {
999         case vcl::ImageType::Size16:
1000             eButtonSize = ToolBoxButtonSize::Small;
1001             break;
1002         case vcl::ImageType::Size26:
1003             eButtonSize = ToolBoxButtonSize::Large;
1004             break;
1005         case vcl::ImageType::Size32:
1006             eButtonSize = ToolBoxButtonSize::Size32;
1007             break;
1008     }
1009     if (m_xToolBox->GetToolboxButtonSize() != eButtonSize)
1010     {
1011         m_xToolBox->SetToolboxButtonSize(eButtonSize);
1012         m_xToolBox->queue_resize();
1013     }
1014 }
1015 
1016 sal_uInt16 SalInstanceToolbar::get_modifier_state() const
1017 {
1018     return m_xToolBox->GetModifier();
1019 }
1020 
1021 int SalInstanceToolbar::get_drop_index(const Point& rPoint) const
1022 {
1023     auto nRet = m_xToolBox->GetItemPos(rPoint);
1024     if (nRet == ToolBox::ITEM_NOTFOUND)
1025         return 0;
1026     return nRet;
1027 }
1028 
1029 SalInstanceToolbar::~SalInstanceToolbar()
1030 {
1031     m_xToolBox->SetDropdownClickHdl(Link<ToolBox*, void>());
1032     m_xToolBox->SetSelectHdl(Link<ToolBox*, void>());
1033 }
1034 
1035 IMPL_LINK_NOARG(SalInstanceToolbar, ClickHdl, ToolBox*, void)
1036 {
1037     sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
1038     signal_clicked(m_xToolBox->GetItemCommand(nItemId).toUtf8());
1039 }
1040 
1041 IMPL_LINK_NOARG(SalInstanceToolbar, DropdownClick, ToolBox*, void)
1042 {
1043     sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
1044     set_menu_item_active(m_xToolBox->GetItemCommand(nItemId).toUtf8(), true);
1045 }
1046 
1047 IMPL_LINK(SalInstanceToolbar, MenuToggleListener, VclWindowEvent&, rEvent, void)
1048 {
1049     if (rEvent.GetId() == VclEventId::WindowEndPopupMode)
1050     {
1051         for (auto& rFloat : m_aFloats)
1052         {
1053             if (rEvent.GetWindow() == rFloat.second)
1054             {
1055                 sal_uInt16 nItemId = rFloat.first;
1056                 signal_toggle_menu(m_xToolBox->GetItemCommand(nItemId).toUtf8());
1057                 break;
1058             }
1059         }
1060     }
1061 }
1062 
1063 namespace
1064 {
1065 class SalInstanceSizeGroup : public weld::SizeGroup
1066 {
1067 private:
1068     std::shared_ptr<VclSizeGroup> m_xGroup;
1069 
1070 public:
1071     SalInstanceSizeGroup()
1072         : m_xGroup(std::make_shared<VclSizeGroup>())
1073     {
1074     }
1075     virtual void add_widget(weld::Widget* pWidget) override
1076     {
1077         SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1078         assert(pVclWidget && pVclWidget->getWidget());
1079         pVclWidget->getWidget()->add_to_size_group(m_xGroup);
1080     }
1081     virtual void set_mode(VclSizeGroupMode eMode) override { m_xGroup->set_mode(eMode); }
1082 };
1083 }
1084 
1085 void SalInstanceContainer::implResetDefault(const vcl::Window* _pWindow)
1086 {
1087     vcl::Window* pChildLoop = _pWindow->GetWindow(GetWindowType::FirstChild);
1088     while (pChildLoop)
1089     {
1090         // does the window participate in the tabbing order?
1091         if (pChildLoop->GetStyle() & WB_DIALOGCONTROL)
1092             implResetDefault(pChildLoop);
1093 
1094         // is it a button?
1095         WindowType eType = pChildLoop->GetType();
1096         if ((WindowType::PUSHBUTTON == eType) || (WindowType::OKBUTTON == eType)
1097             || (WindowType::CANCELBUTTON == eType) || (WindowType::HELPBUTTON == eType)
1098             || (WindowType::IMAGEBUTTON == eType) || (WindowType::MENUBUTTON == eType)
1099             || (WindowType::MOREBUTTON == eType))
1100         {
1101             pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON);
1102         }
1103 
1104         // the next one ...
1105         pChildLoop = pChildLoop->GetWindow(GetWindowType::Next);
1106     }
1107 }
1108 
1109 SalInstanceContainer::SalInstanceContainer(vcl::Window* pContainer, SalInstanceBuilder* pBuilder,
1110                                            bool bTakeOwnership)
1111     : SalInstanceWidget(pContainer, pBuilder, bTakeOwnership)
1112     , m_xContainer(pContainer)
1113 {
1114 }
1115 
1116 void SalInstanceContainer::move(weld::Widget* pWidget, weld::Container* pNewParent)
1117 {
1118     SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1119     assert(pVclWidget);
1120     SalInstanceContainer* pNewVclParent = dynamic_cast<SalInstanceContainer*>(pNewParent);
1121     assert(!pNewParent || pNewVclParent);
1122     if (pNewVclParent)
1123         pVclWidget->getWidget()->SetParent(pNewVclParent->getWidget());
1124     else
1125         pVclWidget->getWidget()->SetParentToDefaultWindow();
1126 }
1127 
1128 void SalInstanceContainer::recursively_unset_default_buttons()
1129 {
1130     implResetDefault(m_xContainer.get());
1131 }
1132 
1133 css::uno::Reference<css::awt::XWindow> SalInstanceContainer::CreateChildFrame()
1134 {
1135     auto xPage = VclPtr<VclBin>::Create(m_xContainer.get());
1136     xPage->set_expand(true);
1137     xPage->Show();
1138     return css::uno::Reference<css::awt::XWindow>(xPage->GetComponentInterface(),
1139                                                   css::uno::UNO_QUERY);
1140 }
1141 
1142 std::unique_ptr<weld::Container> SalInstanceWidget::weld_parent() const
1143 {
1144     vcl::Window* pParent = m_xWidget->GetParent();
1145     if (!pParent)
1146         return nullptr;
1147     return std::make_unique<SalInstanceContainer>(pParent, m_pBuilder, false);
1148 }
1149 
1150 namespace
1151 {
1152     void DoRecursivePaint(vcl::Window* pWindow, const Point& rPos, OutputDevice& rOutput)
1153     {
1154         Size aSize = pWindow->GetSizePixel();
1155 
1156         VclPtr<VirtualDevice> xOutput(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT));
1157         xOutput->SetOutputSizePixel(aSize);
1158         xOutput->DrawOutDev(Point(), aSize, rPos, aSize, rOutput);
1159 
1160         //set ReallyVisible to match Visible, we restore the original
1161         //state after Paint
1162         WindowImpl* pImpl = pWindow->ImplGetWindowImpl();
1163         bool bRVisible = pImpl->mbReallyVisible;
1164         pImpl->mbReallyVisible = pWindow->IsVisible();
1165 
1166         pWindow->Paint(*xOutput, tools::Rectangle(Point(), aSize));
1167 
1168         pImpl->mbReallyVisible = bRVisible;
1169 
1170         rOutput.DrawOutDev(rPos, aSize, Point(), aSize, *xOutput);
1171 
1172         xOutput.disposeAndClear();
1173 
1174         for (vcl::Window *pChild = pWindow->GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next))
1175         {
1176             if (!pChild->IsVisible())
1177                 continue;
1178             DoRecursivePaint(pChild, rPos + pChild->GetPosPixel(), rOutput);
1179         }
1180     }
1181 }
1182 
1183 void SalInstanceWidget::draw(OutputDevice& rOutput, const tools::Rectangle& rRect)
1184 {
1185     Size aOrigSize(m_xWidget->GetSizePixel());
1186 
1187     m_xWidget->SetSizePixel(rRect.GetSize());
1188     DoRecursivePaint(m_xWidget, rRect.TopLeft(), rOutput);
1189 
1190     m_xWidget->SetSizePixel(aOrigSize);
1191 }
1192 
1193 namespace
1194 {
1195 class SalInstanceBox : public SalInstanceContainer, public virtual weld::Box
1196 {
1197 private:
1198     VclPtr<VclBox> m_xBox;
1199 public:
1200     SalInstanceBox(VclBox* pContainer, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1201         : SalInstanceContainer(pContainer, pBuilder, bTakeOwnership)
1202         , m_xBox(pContainer)
1203     {
1204     }
1205     virtual void reorder_child(weld::Widget* pWidget, int nNewPosition) override
1206     {
1207         SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1208         assert(pVclWidget);
1209         pVclWidget->getWidget()->reorderWithinParent(nNewPosition);
1210     }
1211     virtual void sort_native_button_order() override
1212     {
1213         ::sort_native_button_order(*m_xBox);
1214     }
1215 };
1216 
1217 void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& rTopLeft,
1218                      weld::ScreenShotCollection& rControlDataCollection)
1219 {
1220     if (!rCurrent.IsVisible())
1221         return;
1222 
1223     const Point aCurrentPos(rCurrent.GetPosPixel());
1224     const Size aCurrentSize(rCurrent.GetSizePixel());
1225     const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + aCurrentPos.X(),
1226                                             rTopLeft.getY() + aCurrentPos.Y());
1227     const basegfx::B2IRange aCurrentRange(
1228         aCurrentTopLeft,
1229         aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), aCurrentSize.Height()));
1230 
1231     if (!aCurrentRange.isEmpty())
1232     {
1233         rControlDataCollection.emplace_back(rCurrent.GetHelpId(), aCurrentRange);
1234     }
1235 
1236     for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++)
1237     {
1238         vcl::Window* pChild = rCurrent.GetChild(a);
1239         if (nullptr != pChild)
1240         {
1241             CollectChildren(*pChild, aCurrentTopLeft, rControlDataCollection);
1242         }
1243     }
1244 }
1245 
1246 }
1247 
1248 void SalInstanceWindow::override_child_help(vcl::Window* pParent)
1249 {
1250     for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1251          pChild = pChild->GetWindow(GetWindowType::Next))
1252         override_child_help(pChild);
1253     pParent->SetHelpHdl(LINK(this, SalInstanceWindow, HelpHdl));
1254 }
1255 
1256 void SalInstanceWindow::clear_child_help(vcl::Window* pParent)
1257 {
1258     for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1259          pChild = pChild->GetWindow(GetWindowType::Next))
1260         clear_child_help(pChild);
1261     pParent->SetHelpHdl(Link<vcl::Window&, bool>());
1262 }
1263 
1264 SalInstanceWindow::SalInstanceWindow(vcl::Window* pWindow, SalInstanceBuilder* pBuilder,
1265                                      bool bTakeOwnership)
1266     : SalInstanceContainer(pWindow, pBuilder, bTakeOwnership)
1267     , m_xWindow(pWindow)
1268 {
1269     override_child_help(m_xWindow);
1270 }
1271 
1272 void SalInstanceWindow::set_title(const OUString& rTitle) { m_xWindow->SetText(rTitle); }
1273 
1274 OUString SalInstanceWindow::get_title() const { return m_xWindow->GetText(); }
1275 
1276 void SalInstanceWindow::set_busy_cursor(bool bBusy)
1277 {
1278     if (bBusy)
1279         m_xWindow->EnterWait();
1280     else
1281         m_xWindow->LeaveWait();
1282 }
1283 
1284 css::uno::Reference<css::awt::XWindow> SalInstanceWindow::GetXWindow()
1285 {
1286     css::uno::Reference<css::awt::XWindow> xWindow(m_xWindow->GetComponentInterface(),
1287                                                    css::uno::UNO_QUERY);
1288     return xWindow;
1289 }
1290 
1291 void SalInstanceWindow::resize_to_request()
1292 {
1293     if (SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get()))
1294     {
1295         pSysWin->setOptimalLayoutSize();
1296         return;
1297     }
1298     if (DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(m_xWindow.get()))
1299     {
1300         pDockWin->setOptimalLayoutSize();
1301         return;
1302     }
1303     assert(false && "must be system or docking window");
1304 }
1305 
1306 void SalInstanceWindow::set_modal(bool bModal) { m_xWindow->ImplGetFrame()->SetModal(bModal); }
1307 
1308 bool SalInstanceWindow::get_modal() const { return m_xWindow->ImplGetFrame()->GetModal(); }
1309 
1310 void SalInstanceWindow::window_move(int x, int y) { m_xWindow->SetPosPixel(Point(x, y)); }
1311 
1312 Size SalInstanceWindow::get_size() const { return m_xWindow->GetSizePixel(); }
1313 
1314 Point SalInstanceWindow::get_position() const { return m_xWindow->GetPosPixel(); }
1315 
1316 tools::Rectangle SalInstanceWindow::get_monitor_workarea() const
1317 {
1318     return m_xWindow->GetDesktopRectPixel();
1319 }
1320 
1321 void SalInstanceWindow::set_centered_on_parent(bool /*bTrackGeometryRequests*/)
1322 {
1323     if (vcl::Window* pParent = m_xWidget->GetParent())
1324     {
1325         Size aParentGeometry(pParent->GetSizePixel());
1326         Size aGeometry(m_xWidget->get_preferred_size());
1327         auto nX = (aParentGeometry.Width() - aGeometry.Width()) / 2;
1328         auto nY = (aParentGeometry.Height() - aGeometry.Height()) / 2;
1329         m_xWidget->SetPosPixel(Point(nX, nY));
1330     }
1331 }
1332 
1333 bool SalInstanceWindow::get_resizable() const { return m_xWindow->GetStyle() & WB_SIZEABLE; }
1334 
1335 bool SalInstanceWindow::has_toplevel_focus() const { return m_xWindow->HasChildPathFocus(); }
1336 
1337 void SalInstanceWindow::present()
1338 {
1339     m_xWindow->ToTop(ToTopFlags::RestoreWhenMin | ToTopFlags::ForegroundTask);
1340 }
1341 
1342 void SalInstanceWindow::set_window_state(const OString& rStr)
1343 {
1344     SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1345     assert(pSysWin);
1346     pSysWin->SetWindowState(rStr);
1347 }
1348 
1349 OString SalInstanceWindow::get_window_state(WindowStateMask nMask) const
1350 {
1351     SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1352     assert(pSysWin);
1353     return pSysWin->GetWindowState(nMask);
1354 }
1355 
1356 SystemEnvData SalInstanceWindow::get_system_data() const { return *m_xWindow->GetSystemData(); }
1357 
1358 void SalInstanceWindow::connect_toplevel_focus_changed(const Link<weld::Widget&, void>& rLink)
1359 {
1360     ensure_event_listener();
1361     weld::Window::connect_toplevel_focus_changed(rLink);
1362 }
1363 
1364 void SalInstanceWindow::HandleEventListener(VclWindowEvent& rEvent)
1365 {
1366     if (rEvent.GetId() == VclEventId::WindowActivate
1367         || rEvent.GetId() == VclEventId::WindowDeactivate)
1368     {
1369         signal_toplevel_focus_changed();
1370         return;
1371     }
1372     SalInstanceContainer::HandleEventListener(rEvent);
1373 }
1374 
1375 VclPtr<VirtualDevice> SalInstanceWindow::screenshot()
1376 {
1377     SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1378     assert(pSysWin);
1379     return pSysWin->createScreenshot();
1380 }
1381 
1382 weld::ScreenShotCollection SalInstanceWindow::collect_screenshot_data()
1383 {
1384     weld::ScreenShotCollection aRet;
1385 
1386     // collect all children. Choose start pos to be negative
1387     // of target dialog's position to get all positions relative to (0,0)
1388     const Point aParentPos(m_xWindow->GetPosPixel());
1389     const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y());
1390     CollectChildren(*m_xWindow, aTopLeft, aRet);
1391 
1392     return aRet;
1393 }
1394 
1395 SalInstanceWindow::~SalInstanceWindow() { clear_child_help(m_xWindow); }
1396 
1397 IMPL_LINK_NOARG(SalInstanceWindow, HelpHdl, vcl::Window&, bool)
1398 {
1399     help();
1400     return false;
1401 }
1402 
1403 typedef std::set<VclPtr<vcl::Window>> winset;
1404 
1405 namespace
1406 {
1407 void hideUnless(const vcl::Window* pTop, const winset& rVisibleWidgets,
1408                 std::vector<VclPtr<vcl::Window>>& rWasVisibleWidgets)
1409 {
1410     for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild;
1411          pChild = pChild->GetWindow(GetWindowType::Next))
1412     {
1413         if (!pChild->IsVisible())
1414             continue;
1415         if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
1416         {
1417             rWasVisibleWidgets.emplace_back(pChild);
1418             pChild->Hide();
1419         }
1420         else if (isContainerWindow(pChild))
1421         {
1422             hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
1423         }
1424     }
1425 }
1426 }
1427 
1428 SalInstanceDialog::SalInstanceDialog(::Dialog* pDialog, SalInstanceBuilder* pBuilder,
1429                                      bool bTakeOwnership)
1430     : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership)
1431     , m_xDialog(pDialog)
1432     , m_nOldEditWidthReq(0)
1433     , m_nOldBorderWidth(0)
1434 {
1435     const bool bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
1436     if (bScreenshotMode)
1437     {
1438         m_xDialog->SetPopupMenuHdl(LINK(this, SalInstanceDialog, PopupScreenShotMenuHdl));
1439     }
1440 }
1441 
1442 bool SalInstanceDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner,
1443                                  const std::function<void(sal_Int32)>& rEndDialogFn)
1444 {
1445     VclAbstractDialog::AsyncContext aCtx;
1446     aCtx.mxOwnerDialogController = aOwner;
1447     aCtx.maEndDialogFn = rEndDialogFn;
1448     VclButtonBox* pActionArea = m_xDialog->get_action_area();
1449     if (pActionArea)
1450         sort_native_button_order(*pActionArea);
1451     return m_xDialog->StartExecuteAsync(aCtx);
1452 }
1453 
1454 bool SalInstanceDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf,
1455                                  const std::function<void(sal_Int32)>& rEndDialogFn)
1456 {
1457     assert(rxSelf.get() == this);
1458     VclAbstractDialog::AsyncContext aCtx;
1459     // In order to store a shared_ptr to ourself, we have to have been constructed by make_shared,
1460     // which is that rxSelf enforces.
1461     aCtx.mxOwnerSelf = rxSelf;
1462     aCtx.maEndDialogFn = rEndDialogFn;
1463     VclButtonBox* pActionArea = m_xDialog->get_action_area();
1464     if (pActionArea)
1465         sort_native_button_order(*pActionArea);
1466     return m_xDialog->StartExecuteAsync(aCtx);
1467 }
1468 
1469 void SalInstanceDialog::collapse(weld::Widget* pEdit, weld::Widget* pButton)
1470 {
1471     SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit);
1472     assert(pVclEdit);
1473     SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton);
1474 
1475     vcl::Window* pRefEdit = pVclEdit->getWidget();
1476     vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr;
1477 
1478     auto nOldEditWidth = pRefEdit->GetSizePixel().Width();
1479     m_nOldEditWidthReq = pRefEdit->get_width_request();
1480 
1481     //We want just pRefBtn and pRefEdit to be shown
1482     //mark widgets we want to be visible, starting with pRefEdit
1483     //and all its direct parents.
1484     winset aVisibleWidgets;
1485     vcl::Window* pContentArea = m_xDialog->get_content_area();
1486     for (vcl::Window* pCandidate = pRefEdit;
1487          pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1488          pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1489     {
1490         aVisibleWidgets.insert(pCandidate);
1491     }
1492     //same again with pRefBtn, except stop if there's a
1493     //shared parent in the existing widgets
1494     for (vcl::Window* pCandidate = pRefBtn;
1495          pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1496          pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1497     {
1498         if (aVisibleWidgets.insert(pCandidate).second)
1499             break;
1500     }
1501 
1502     //hide everything except the aVisibleWidgets
1503     hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets);
1504 
1505     // the insert function case has an initially hidden edit widget, so it has
1506     // not start size, so take larger of actual size and size request
1507     pRefEdit->set_width_request(std::max(nOldEditWidth, m_nOldEditWidthReq));
1508     m_nOldBorderWidth = m_xDialog->get_border_width();
1509     m_xDialog->set_border_width(0);
1510     if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1511         pActionArea->Hide();
1512     m_xDialog->setOptimalLayoutSize();
1513     m_xRefEdit = pRefEdit;
1514 }
1515 
1516 void SalInstanceDialog::undo_collapse()
1517 {
1518     // All others: Show();
1519     for (VclPtr<vcl::Window> const& pWindow : m_aHiddenWidgets)
1520     {
1521         pWindow->Show();
1522     }
1523     m_aHiddenWidgets.clear();
1524 
1525     m_xRefEdit->set_width_request(m_nOldEditWidthReq);
1526     m_xRefEdit.clear();
1527     m_xDialog->set_border_width(m_nOldBorderWidth);
1528     if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1529         pActionArea->Show();
1530     m_xDialog->setOptimalLayoutSize();
1531 }
1532 
1533 void SalInstanceDialog::SetInstallLOKNotifierHdl(
1534     const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink)
1535 {
1536     m_xDialog->SetInstallLOKNotifierHdl(rLink);
1537 }
1538 
1539 int SalInstanceDialog::run()
1540 {
1541     VclButtonBox* pActionArea = m_xDialog->get_action_area();
1542     if (pActionArea)
1543         sort_native_button_order(*pActionArea);
1544     return m_xDialog->Execute();
1545 }
1546 
1547 void SalInstanceDialog::response(int nResponse) { m_xDialog->EndDialog(nResponse); }
1548 
1549 void SalInstanceDialog::add_button(const OUString& rText, int nResponse, const OString& rHelpId)
1550 {
1551     VclButtonBox* pBox = m_xDialog->get_action_area();
1552     VclPtr<PushButton> xButton(
1553         VclPtr<PushButton>::Create(pBox, WB_CLIPCHILDREN | WB_CENTER | WB_VCENTER));
1554     xButton->SetText(rText);
1555     xButton->SetHelpId(rHelpId);
1556 
1557     switch (nResponse)
1558     {
1559         case RET_OK:
1560             xButton->set_id("ok");
1561             break;
1562         case RET_CLOSE:
1563             xButton->set_id("close");
1564             break;
1565         case RET_CANCEL:
1566             xButton->set_id("cancel");
1567             break;
1568         case RET_YES:
1569             xButton->set_id("yes");
1570             break;
1571         case RET_NO:
1572             xButton->set_id("no");
1573             break;
1574     }
1575 
1576     xButton->Show();
1577     m_xDialog->add_button(xButton, nResponse, true);
1578 }
1579 
1580 void SalInstanceDialog::set_modal(bool bModal)
1581 {
1582     if (get_modal() == bModal)
1583         return;
1584     m_xDialog->SetModalInputMode(bModal);
1585 }
1586 
1587 bool SalInstanceDialog::get_modal() const { return m_xDialog->IsModalInputMode(); }
1588 
1589 void SalInstanceDialog::set_default_response(int nResponse)
1590 {
1591     m_xDialog->set_default_response(nResponse);
1592 }
1593 
1594 weld::Container* SalInstanceDialog::weld_content_area()
1595 {
1596     return new SalInstanceContainer(m_xDialog->get_content_area(), m_pBuilder, false);
1597 }
1598 
1599 IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, rCEvt, bool)
1600 {
1601     if (CommandEventId::ContextMenu == rCEvt.GetCommand())
1602     {
1603         const Point aMenuPos(rCEvt.GetMousePosPixel());
1604         ScopedVclPtrInstance<PopupMenu> aMenu;
1605         sal_uInt16 nLocalID(1);
1606 
1607         aMenu->InsertItem(nLocalID, VclResId(SV_BUTTONTEXT_SCREENSHOT));
1608         aMenu->SetHelpText(nLocalID, VclResId(SV_HELPTEXT_SCREENSHOT));
1609         aMenu->SetHelpId(nLocalID, "InteractiveScreenshotMode");
1610         aMenu->EnableItem(nLocalID);
1611 
1612         const sal_uInt16 nId(aMenu->Execute(m_xDialog, aMenuPos));
1613 
1614         // 0 == no selection (so not usable as ID)
1615         if (0 != nId)
1616         {
1617             // open screenshot annotation dialog
1618             VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
1619             VclPtr<AbstractScreenshotAnnotationDlg> pTmp
1620                 = pFact->CreateScreenshotAnnotationDlg(*this);
1621             ScopedVclPtr<AbstractScreenshotAnnotationDlg> pDialog(pTmp);
1622 
1623             if (pDialog)
1624             {
1625                 // currently just execute the dialog, no need to do
1626                 // different things for ok/cancel. This may change later,
1627                 // for that case use 'if (pDlg->Execute() == RET_OK)'
1628                 pDialog->Execute();
1629             }
1630         }
1631 
1632         // consume event when:
1633         // - CommandEventId::ContextMenu
1634         // - bScreenshotMode
1635         return true;
1636     }
1637 
1638     return false;
1639 }
1640 
1641 SalInstanceMessageDialog::SalInstanceMessageDialog(::MessageDialog* pDialog, SalInstanceBuilder* pBuilder,
1642                             bool bTakeOwnership)
1643     : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1644     , m_xMessageDialog(pDialog)
1645 {
1646 }
1647 
1648 void SalInstanceMessageDialog::set_primary_text(const OUString& rText)
1649 {
1650     m_xMessageDialog->set_primary_text(rText);
1651 }
1652 
1653 OUString SalInstanceMessageDialog::get_primary_text() const
1654 {
1655     return m_xMessageDialog->get_primary_text();
1656 }
1657 
1658 void SalInstanceMessageDialog::set_secondary_text(const OUString& rText)
1659 {
1660     m_xMessageDialog->set_secondary_text(rText);
1661 }
1662 
1663 OUString SalInstanceMessageDialog::get_secondary_text() const
1664 {
1665     return m_xMessageDialog->get_secondary_text();
1666 }
1667 
1668 weld::Container* SalInstanceMessageDialog::weld_message_area()
1669 {
1670     return new SalInstanceContainer(m_xMessageDialog->get_message_area(), m_pBuilder, false);
1671 }
1672 
1673 namespace
1674 {
1675 
1676 class SalInstanceAssistant : public SalInstanceDialog, public virtual weld::Assistant
1677 {
1678 private:
1679     VclPtr<vcl::RoadmapWizard> m_xWizard;
1680     std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
1681     std::vector<VclPtr<TabPage>> m_aAddedPages;
1682     std::vector<int> m_aIds;
1683     std::vector<VclPtr<VclGrid>> m_aAddedGrids;
1684     Idle m_aUpdateRoadmapIdle;
1685 
1686     int find_page(const OString& rIdent) const
1687     {
1688         for (size_t i = 0; i < m_aAddedPages.size(); ++i)
1689         {
1690             if (m_aAddedPages[i]->get_id().toUtf8() == rIdent)
1691                 return i;
1692         }
1693         return -1;
1694     }
1695 
1696     int find_id(int nId) const
1697     {
1698         for (size_t i = 0; i < m_aIds.size(); ++i)
1699         {
1700             if (nId == m_aIds[i])
1701                 return i;
1702         }
1703         return -1;
1704     }
1705 
1706     DECL_LINK(OnRoadmapItemSelected, LinkParamNone*, void);
1707     DECL_LINK(UpdateRoadmap_Hdl, Timer*, void);
1708 
1709 public:
1710     SalInstanceAssistant(vcl::RoadmapWizard* pDialog, SalInstanceBuilder* pBuilder,
1711                          bool bTakeOwnership)
1712         : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1713         , m_xWizard(pDialog)
1714     {
1715         m_xWizard->SetItemSelectHdl(LINK(this, SalInstanceAssistant, OnRoadmapItemSelected));
1716 
1717         m_aUpdateRoadmapIdle.SetInvokeHandler(LINK(this, SalInstanceAssistant, UpdateRoadmap_Hdl));
1718         m_aUpdateRoadmapIdle.SetPriority(TaskPriority::HIGHEST);
1719     }
1720 
1721     virtual int get_current_page() const override { return find_id(m_xWizard->GetCurLevel()); }
1722 
1723     virtual int get_n_pages() const override { return m_aAddedPages.size(); }
1724 
1725     virtual OString get_page_ident(int nPage) const override
1726     {
1727         return m_aAddedPages[nPage]->get_id().toUtf8();
1728     }
1729 
1730     virtual OString get_current_page_ident() const override
1731     {
1732         return get_page_ident(get_current_page());
1733     }
1734 
1735     virtual void set_current_page(int nPage) override
1736     {
1737         disable_notify_events();
1738 
1739         // take the first shown page as the size for all pages
1740         if (m_xWizard->GetPageSizePixel().Width() == 0)
1741         {
1742             Size aFinalSize;
1743             for (int i = 0, nPages = get_n_pages(); i < nPages; ++i)
1744             {
1745                 TabPage* pPage = m_xWizard->GetPage(m_aIds[i]);
1746                 assert(pPage);
1747                 Size aPageSize(pPage->get_preferred_size());
1748                 if (aPageSize.Width() > aFinalSize.Width())
1749                     aFinalSize.setWidth(aPageSize.Width());
1750                 if (aPageSize.Height() > aFinalSize.Height())
1751                     aFinalSize.setHeight(aPageSize.Height());
1752             }
1753             m_xWizard->SetPageSizePixel(aFinalSize);
1754         }
1755 
1756         (void)m_xWizard->ShowPage(m_aIds[nPage]);
1757         enable_notify_events();
1758     }
1759 
1760     virtual void set_current_page(const OString& rIdent) override
1761     {
1762         int nIndex = find_page(rIdent);
1763         if (nIndex == -1)
1764             return;
1765         set_current_page(nIndex);
1766     }
1767 
1768     virtual void set_page_index(const OString& rIdent, int nNewIndex) override
1769     {
1770         int nOldIndex = find_page(rIdent);
1771 
1772         if (nOldIndex == -1)
1773             return;
1774 
1775         if (nOldIndex == nNewIndex)
1776             return;
1777 
1778         disable_notify_events();
1779 
1780         auto entry = std::move(m_aAddedPages[nOldIndex]);
1781         m_aAddedPages.erase(m_aAddedPages.begin() + nOldIndex);
1782         m_aAddedPages.insert(m_aAddedPages.begin() + nNewIndex, std::move(entry));
1783 
1784         int nId = m_aIds[nOldIndex];
1785         m_aIds.erase(m_aIds.begin() + nOldIndex);
1786         m_aIds.insert(m_aIds.begin() + nNewIndex, nId);
1787 
1788         m_aUpdateRoadmapIdle.Start();
1789 
1790         enable_notify_events();
1791     }
1792 
1793     virtual weld::Container* append_page(const OString& rIdent) override
1794     {
1795         VclPtrInstance<TabPage> xPage(m_xWizard);
1796         VclPtrInstance<VclGrid> xGrid(xPage);
1797         xPage->set_id(OUString::fromUtf8(rIdent));
1798         xPage->Show();
1799         xGrid->set_hexpand(true);
1800         xGrid->set_vexpand(true);
1801         xGrid->Show();
1802         m_xWizard->AddPage(xPage);
1803         m_aIds.push_back(m_aAddedPages.size());
1804         m_xWizard->SetPage(m_aIds.back(), xPage);
1805         m_aAddedPages.push_back(xPage);
1806         m_aAddedGrids.push_back(xGrid);
1807 
1808         m_aUpdateRoadmapIdle.Start();
1809 
1810         m_aPages.emplace_back(new SalInstanceContainer(xGrid, m_pBuilder, false));
1811         return m_aPages.back().get();
1812     }
1813 
1814     virtual OUString get_page_title(const OString& rIdent) const override
1815     {
1816         int nIndex = find_page(rIdent);
1817         if (nIndex == -1)
1818             return OUString();
1819         return m_aAddedPages[nIndex]->GetText();
1820     }
1821 
1822     virtual void set_page_title(const OString& rIdent, const OUString& rTitle) override
1823     {
1824         int nIndex = find_page(rIdent);
1825         if (nIndex == -1)
1826             return;
1827         if (m_aAddedPages[nIndex]->GetText() != rTitle)
1828         {
1829             disable_notify_events();
1830             m_aAddedPages[nIndex]->SetText(rTitle);
1831             m_aUpdateRoadmapIdle.Start();
1832             enable_notify_events();
1833         }
1834     }
1835 
1836     virtual void set_page_sensitive(const OString& rIdent, bool bSensitive) override
1837     {
1838         int nIndex = find_page(rIdent);
1839         if (nIndex == -1)
1840             return;
1841         if (m_aAddedPages[nIndex]->IsEnabled() != bSensitive)
1842         {
1843             disable_notify_events();
1844             m_aAddedPages[nIndex]->Enable(bSensitive);
1845             m_aUpdateRoadmapIdle.Start();
1846             enable_notify_events();
1847         }
1848     }
1849 
1850     virtual void set_page_side_help_id(const OString& rHelpId) override
1851     {
1852         m_xWizard->SetRoadmapHelpId(rHelpId);
1853     }
1854 
1855     weld::Button* weld_widget_for_response(int nResponse) override;
1856 
1857     virtual ~SalInstanceAssistant() override
1858     {
1859         for (auto& rGrid : m_aAddedGrids)
1860             rGrid.disposeAndClear();
1861         for (auto& rPage : m_aAddedPages)
1862             rPage.disposeAndClear();
1863     }
1864 };
1865 
1866 }
1867 
1868 IMPL_LINK_NOARG(SalInstanceAssistant, OnRoadmapItemSelected, LinkParamNone*, void)
1869 {
1870     if (notify_events_disabled())
1871         return;
1872     auto nCurItemId = m_xWizard->GetCurrentRoadmapItemID();
1873     int nPageIndex(find_id(nCurItemId));
1874     if (!signal_jump_page(get_page_ident(nPageIndex)) && nCurItemId != m_xWizard->GetCurLevel())
1875         m_xWizard->SelectRoadmapItemByID(m_xWizard->GetCurLevel());
1876 }
1877 
1878 IMPL_LINK_NOARG(SalInstanceAssistant, UpdateRoadmap_Hdl, Timer*, void)
1879 {
1880     disable_notify_events();
1881 
1882     m_xWizard->DeleteRoadmapItems();
1883 
1884     int nPos = 0;
1885     for (size_t i = 0; i < m_aAddedPages.size(); ++i)
1886     {
1887         const OUString& rLabel = m_aAddedPages[i]->GetText();
1888         bool bSensitive = m_aAddedPages[i]->IsEnabled();
1889         if (rLabel.isEmpty())
1890             continue;
1891         m_xWizard->InsertRoadmapItem(nPos++, rLabel, m_aIds[i], bSensitive);
1892     }
1893 
1894     m_xWizard->SelectRoadmapItemByID(m_aIds[get_current_page()]);
1895 
1896     m_xWizard->ShowRoadmap(nPos != 0);
1897 
1898     enable_notify_events();
1899 }
1900 
1901 namespace
1902 {
1903 class SalInstanceFrame : public SalInstanceContainer, public virtual weld::Frame
1904 {
1905 private:
1906     VclPtr<VclFrame> m_xFrame;
1907 
1908 public:
1909     SalInstanceFrame(VclFrame* pFrame, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1910         : SalInstanceContainer(pFrame, pBuilder, bTakeOwnership)
1911         , m_xFrame(pFrame)
1912     {
1913     }
1914 
1915     virtual void set_label(const OUString& rText) override { m_xFrame->set_label(rText); }
1916 
1917     virtual OUString get_label() const override { return m_xFrame->get_label(); }
1918 
1919     virtual std::unique_ptr<weld::Label> weld_label_widget() const override;
1920 };
1921 
1922 class SalInstancePaned : public SalInstanceContainer, public virtual weld::Paned
1923 {
1924 private:
1925     VclPtr<VclPaned> m_xPaned;
1926 
1927 public:
1928     SalInstancePaned(VclPaned* pPaned, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1929         : SalInstanceContainer(pPaned, pBuilder, bTakeOwnership)
1930         , m_xPaned(pPaned)
1931     {
1932     }
1933 
1934     virtual void set_position(int nPos) override
1935     {
1936         m_xPaned->set_position(nPos);
1937     }
1938 
1939     virtual int get_position() const override
1940     {
1941         return m_xPaned->get_position();
1942     }
1943 };
1944 
1945 class SalInstanceScrolledWindow : public SalInstanceContainer, public virtual weld::ScrolledWindow
1946 {
1947 private:
1948     VclPtr<VclScrolledWindow> m_xScrolledWindow;
1949     Link<ScrollBar*, void> m_aOrigVScrollHdl;
1950     Link<ScrollBar*, void> m_aOrigHScrollHdl;
1951     bool m_bUserManagedScrolling;
1952 
1953     DECL_LINK(VscrollHdl, ScrollBar*, void);
1954     DECL_LINK(HscrollHdl, ScrollBar*, void);
1955 
1956 public:
1957     SalInstanceScrolledWindow(VclScrolledWindow* pScrolledWindow, SalInstanceBuilder* pBuilder,
1958                               bool bTakeOwnership)
1959         : SalInstanceContainer(pScrolledWindow, pBuilder, bTakeOwnership)
1960         , m_xScrolledWindow(pScrolledWindow)
1961         , m_bUserManagedScrolling(false)
1962     {
1963         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
1964         m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl();
1965         rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, VscrollHdl));
1966         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1967         m_aOrigHScrollHdl = rHorzScrollBar.GetScrollHdl();
1968         rHorzScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, HscrollHdl));
1969     }
1970 
1971     virtual void hadjustment_configure(int value, int lower, int upper, int step_increment,
1972                                        int page_increment, int page_size) override
1973     {
1974         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1975         rHorzScrollBar.SetRangeMin(lower);
1976         rHorzScrollBar.SetRangeMax(upper);
1977         rHorzScrollBar.SetLineSize(step_increment);
1978         rHorzScrollBar.SetPageSize(page_increment);
1979         rHorzScrollBar.SetThumbPos(value);
1980         rHorzScrollBar.SetVisibleSize(page_size);
1981     }
1982 
1983     virtual int hadjustment_get_value() const override
1984     {
1985         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1986         return rHorzScrollBar.GetThumbPos();
1987     }
1988 
1989     virtual void hadjustment_set_value(int value) override
1990     {
1991         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1992         rHorzScrollBar.SetThumbPos(value);
1993         if (!m_bUserManagedScrolling)
1994             m_aOrigHScrollHdl.Call(&rHorzScrollBar);
1995     }
1996 
1997     virtual int hadjustment_get_upper() const override
1998     {
1999         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2000         return rHorzScrollBar.GetRangeMax();
2001     }
2002 
2003     virtual void hadjustment_set_upper(int upper) override
2004     {
2005         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2006         rHorzScrollBar.SetRangeMax(upper);
2007     }
2008 
2009     virtual int hadjustment_get_page_size() const override
2010     {
2011         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2012         return rHorzScrollBar.GetVisibleSize();
2013     }
2014 
2015     virtual void hadjustment_set_page_size(int size) override
2016     {
2017         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2018         return rHorzScrollBar.SetVisibleSize(size);
2019     }
2020 
2021     virtual void hadjustment_set_page_increment(int size) override
2022     {
2023         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2024         return rHorzScrollBar.SetPageSize(size);
2025     }
2026 
2027     virtual void hadjustment_set_step_increment(int size) override
2028     {
2029         ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2030         return rHorzScrollBar.SetLineSize(size);
2031     }
2032 
2033     virtual void set_hpolicy(VclPolicyType eHPolicy) override
2034     {
2035         WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOHSCROLL | WB_HSCROLL);
2036         if (eHPolicy == VclPolicyType::ALWAYS)
2037             nWinBits |= WB_HSCROLL;
2038         else if (eHPolicy == VclPolicyType::AUTOMATIC)
2039             nWinBits |= WB_AUTOHSCROLL;
2040         m_xScrolledWindow->SetStyle(nWinBits);
2041         m_xScrolledWindow->queue_resize();
2042     }
2043 
2044     virtual VclPolicyType get_hpolicy() const override
2045     {
2046         WinBits nWinBits = m_xScrolledWindow->GetStyle();
2047         if (nWinBits & WB_AUTOHSCROLL)
2048             return VclPolicyType::AUTOMATIC;
2049         else if (nWinBits & WB_HSCROLL)
2050             return VclPolicyType::ALWAYS;
2051         return VclPolicyType::NEVER;
2052     }
2053 
2054     virtual int get_hscroll_height() const override
2055     {
2056         return m_xScrolledWindow->getHorzScrollBar().get_preferred_size().Height();
2057     }
2058 
2059     virtual void vadjustment_configure(int value, int lower, int upper, int step_increment,
2060                                        int page_increment, int page_size) override
2061     {
2062         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2063         rVertScrollBar.SetRangeMin(lower);
2064         rVertScrollBar.SetRangeMax(upper);
2065         rVertScrollBar.SetLineSize(step_increment);
2066         rVertScrollBar.SetPageSize(page_increment);
2067         rVertScrollBar.SetThumbPos(value);
2068         rVertScrollBar.SetVisibleSize(page_size);
2069     }
2070 
2071     virtual int vadjustment_get_value() const override
2072     {
2073         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2074         return rVertScrollBar.GetThumbPos();
2075     }
2076 
2077     virtual void vadjustment_set_value(int value) override
2078     {
2079         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2080         rVertScrollBar.SetThumbPos(value);
2081         if (!m_bUserManagedScrolling)
2082             m_aOrigVScrollHdl.Call(&rVertScrollBar);
2083     }
2084 
2085     virtual int vadjustment_get_upper() const override
2086     {
2087         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2088         return rVertScrollBar.GetRangeMax();
2089     }
2090 
2091     virtual void vadjustment_set_upper(int upper) override
2092     {
2093         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2094         rVertScrollBar.SetRangeMax(upper);
2095     }
2096 
2097     virtual int vadjustment_get_lower() const override
2098     {
2099         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2100         return rVertScrollBar.GetRangeMin();
2101     }
2102 
2103     virtual void vadjustment_set_lower(int lower) override
2104     {
2105         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2106         rVertScrollBar.SetRangeMin(lower);
2107     }
2108 
2109     virtual int vadjustment_get_page_size() const override
2110     {
2111         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2112         return rVertScrollBar.GetVisibleSize();
2113     }
2114 
2115     virtual void vadjustment_set_page_size(int size) override
2116     {
2117         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2118         return rVertScrollBar.SetVisibleSize(size);
2119     }
2120 
2121     virtual void vadjustment_set_page_increment(int size) override
2122     {
2123         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2124         return rVertScrollBar.SetPageSize(size);
2125     }
2126 
2127     virtual void vadjustment_set_step_increment(int size) override
2128     {
2129         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2130         return rVertScrollBar.SetLineSize(size);
2131     }
2132 
2133     virtual void set_vpolicy(VclPolicyType eVPolicy) override
2134     {
2135         WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOVSCROLL | WB_VSCROLL);
2136         if (eVPolicy == VclPolicyType::ALWAYS)
2137             nWinBits |= WB_VSCROLL;
2138         else if (eVPolicy == VclPolicyType::AUTOMATIC)
2139             nWinBits |= WB_AUTOVSCROLL;
2140         m_xScrolledWindow->SetStyle(nWinBits);
2141         m_xScrolledWindow->queue_resize();
2142     }
2143 
2144     virtual VclPolicyType get_vpolicy() const override
2145     {
2146         WinBits nWinBits = m_xScrolledWindow->GetStyle();
2147         if (nWinBits & WB_AUTOVSCROLL)
2148             return VclPolicyType::AUTOMATIC;
2149         else if (nWinBits & WB_VSCROLL)
2150             return VclPolicyType::ALWAYS;
2151         return VclPolicyType::NEVER;
2152     }
2153 
2154     virtual int get_vscroll_width() const override
2155     {
2156         return m_xScrolledWindow->getVertScrollBar().get_preferred_size().Width();
2157     }
2158 
2159     virtual void set_user_managed_scrolling() override
2160     {
2161         m_bUserManagedScrolling = true;
2162         m_xScrolledWindow->setUserManagedScrolling(true);
2163     }
2164 
2165     virtual ~SalInstanceScrolledWindow() override
2166     {
2167         ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2168         rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl);
2169     }
2170 };
2171 
2172 }
2173 
2174 IMPL_LINK(SalInstanceScrolledWindow, VscrollHdl, ScrollBar*, pScrollBar, void)
2175 {
2176     signal_vadjustment_changed();
2177     if (!m_bUserManagedScrolling)
2178         m_aOrigVScrollHdl.Call(pScrollBar);
2179 }
2180 
2181 IMPL_LINK_NOARG(SalInstanceScrolledWindow, HscrollHdl, ScrollBar*, void)
2182 {
2183     signal_hadjustment_changed();
2184     if (!m_bUserManagedScrolling)
2185         m_aOrigHScrollHdl.Call(&m_xScrolledWindow->getHorzScrollBar());
2186 }
2187 
2188 SalInstanceNotebook::SalInstanceNotebook(TabControl* pNotebook, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2189     : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership)
2190     , m_xNotebook(pNotebook)
2191 {
2192     m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceNotebook, ActivatePageHdl));
2193     m_xNotebook->SetDeactivatePageHdl(LINK(this, SalInstanceNotebook, DeactivatePageHdl));
2194 }
2195 
2196 int SalInstanceNotebook::get_current_page() const
2197 {
2198     return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId());
2199 }
2200 
2201 OString SalInstanceNotebook::get_page_ident(int nPage) const
2202 {
2203     return m_xNotebook->GetPageName(m_xNotebook->GetPageId(nPage));
2204 }
2205 
2206 OString SalInstanceNotebook::get_current_page_ident() const
2207 {
2208     return m_xNotebook->GetPageName(m_xNotebook->GetCurPageId());
2209 }
2210 
2211 int SalInstanceNotebook::get_page_index(const OString& rIdent) const
2212 {
2213     sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2214     sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2215     if (nPageIndex == TAB_PAGE_NOTFOUND)
2216         return -1;
2217     return nPageIndex;
2218 }
2219 
2220 weld::Container* SalInstanceNotebook::get_page(const OString& rIdent) const
2221 {
2222     int nPageIndex = get_page_index(rIdent);
2223     if (nPageIndex == -1)
2224         return nullptr;
2225     sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2226     TabPage* pPage = m_xNotebook->GetTabPage(nPageId);
2227     vcl::Window* pChild = pPage->GetChild(0);
2228     if (m_aPages.size() < nPageIndex + 1U)
2229         m_aPages.resize(nPageIndex + 1U);
2230     if (!m_aPages[nPageIndex])
2231         m_aPages[nPageIndex] = std::make_shared<SalInstanceContainer>(pChild, m_pBuilder, false);
2232     return m_aPages[nPageIndex].get();
2233 }
2234 
2235 void SalInstanceNotebook::set_current_page(int nPage)
2236 {
2237     m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage));
2238 }
2239 
2240 void SalInstanceNotebook::set_current_page(const OString& rIdent)
2241 {
2242     m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(rIdent));
2243 }
2244 
2245 void SalInstanceNotebook::remove_page(const OString& rIdent)
2246 {
2247     sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2248     sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2249     if (nPageIndex == TAB_PAGE_NOTFOUND)
2250         return;
2251 
2252     m_xNotebook->RemovePage(nPageId);
2253     if (nPageIndex < m_aPages.size())
2254         m_aPages.erase(m_aPages.begin() + nPageIndex);
2255 
2256     auto iter = m_aAddedPages.find(rIdent);
2257     if (iter != m_aAddedPages.end())
2258     {
2259         iter->second.second.disposeAndClear();
2260         iter->second.first.disposeAndClear();
2261         m_aAddedPages.erase(iter);
2262     }
2263 }
2264 
2265 void SalInstanceNotebook::insert_page(const OString& rIdent, const OUString& rLabel, int nPos)
2266 {
2267     sal_uInt16 nPageCount = m_xNotebook->GetPageCount();
2268     sal_uInt16 nLastPageId = nPageCount ? m_xNotebook->GetPageId(nPageCount - 1) : 0;
2269     sal_uInt16 nNewPageId = nLastPageId + 1;
2270     while (m_xNotebook->GetPagePos(nNewPageId) != TAB_PAGE_NOTFOUND)
2271         ++nNewPageId;
2272     m_xNotebook->InsertPage(nNewPageId, rLabel, nPos == -1 ? TAB_APPEND : nPos);
2273     VclPtrInstance<TabPage> xPage(m_xNotebook);
2274     VclPtrInstance<VclGrid> xGrid(xPage);
2275     xPage->Show();
2276     xGrid->set_hexpand(true);
2277     xGrid->set_vexpand(true);
2278     xGrid->Show();
2279     m_xNotebook->SetTabPage(nNewPageId, xPage);
2280     m_xNotebook->SetPageName(nNewPageId, rIdent);
2281     m_aAddedPages.try_emplace(rIdent, xPage, xGrid);
2282 
2283     if (nPos != -1)
2284     {
2285         unsigned int nPageIndex = static_cast<unsigned int>(nPos);
2286         if (nPageIndex < m_aPages.size())
2287             m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr);
2288     }
2289 }
2290 
2291 int SalInstanceNotebook::get_n_pages() const { return m_xNotebook->GetPageCount(); }
2292 
2293 OUString SalInstanceNotebook::get_tab_label_text(const OString& rIdent) const
2294 {
2295     return m_xNotebook->GetPageText(m_xNotebook->GetPageId(rIdent));
2296 }
2297 
2298 void SalInstanceNotebook::set_tab_label_text(const OString& rIdent, const OUString& rText)
2299 {
2300     return m_xNotebook->SetPageText(m_xNotebook->GetPageId(rIdent), rText);
2301 }
2302 
2303 SalInstanceNotebook::~SalInstanceNotebook()
2304 {
2305     for (auto& rItem : m_aAddedPages)
2306     {
2307         rItem.second.second.disposeAndClear();
2308         rItem.second.first.disposeAndClear();
2309     }
2310     m_xNotebook->SetActivatePageHdl(Link<TabControl*, void>());
2311     m_xNotebook->SetDeactivatePageHdl(Link<TabControl*, bool>());
2312 }
2313 
2314 IMPL_LINK_NOARG(SalInstanceNotebook, DeactivatePageHdl, TabControl*, bool)
2315 {
2316     return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2317 }
2318 
2319 IMPL_LINK_NOARG(SalInstanceNotebook, ActivatePageHdl, TabControl*, void)
2320 {
2321     m_aEnterPageHdl.Call(get_current_page_ident());
2322 }
2323 
2324 namespace
2325 {
2326 class SalInstanceVerticalNotebook : public SalInstanceContainer, public virtual weld::Notebook
2327 {
2328 private:
2329     VclPtr<VerticalTabControl> m_xNotebook;
2330     mutable std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
2331 
2332     DECL_LINK(DeactivatePageHdl, VerticalTabControl*, bool);
2333     DECL_LINK(ActivatePageHdl, VerticalTabControl*, void);
2334 
2335 public:
2336     SalInstanceVerticalNotebook(VerticalTabControl* pNotebook, SalInstanceBuilder* pBuilder,
2337                                 bool bTakeOwnership)
2338         : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership)
2339         , m_xNotebook(pNotebook)
2340     {
2341         m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceVerticalNotebook, ActivatePageHdl));
2342         m_xNotebook->SetDeactivatePageHdl(
2343             LINK(this, SalInstanceVerticalNotebook, DeactivatePageHdl));
2344     }
2345 
2346     virtual int get_current_page() const override
2347     {
2348         return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId());
2349     }
2350 
2351     virtual OString get_page_ident(int nPage) const override
2352     {
2353         return m_xNotebook->GetPageId(nPage);
2354     }
2355 
2356     virtual OString get_current_page_ident() const override { return m_xNotebook->GetCurPageId(); }
2357 
2358     virtual int get_page_index(const OString& rIdent) const override
2359     {
2360         sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2361         if (nPageIndex == TAB_PAGE_NOTFOUND)
2362             return -1;
2363         return nPageIndex;
2364     }
2365 
2366     virtual weld::Container* get_page(const OString& rIdent) const override
2367     {
2368         int nPageIndex = get_page_index(rIdent);
2369         if (nPageIndex == -1)
2370             return nullptr;
2371         auto pChild = m_xNotebook->GetPage(rIdent);
2372         if (m_aPages.size() < nPageIndex + 1U)
2373             m_aPages.resize(nPageIndex + 1U);
2374         if (!m_aPages[nPageIndex])
2375             m_aPages[nPageIndex].reset(new SalInstanceContainer(pChild, m_pBuilder, false));
2376         return m_aPages[nPageIndex].get();
2377     }
2378 
2379     virtual void set_current_page(int nPage) override
2380     {
2381         m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage));
2382     }
2383 
2384     virtual void set_current_page(const OString& rIdent) override
2385     {
2386         m_xNotebook->SetCurPageId(rIdent);
2387     }
2388 
2389     virtual void remove_page(const OString& rIdent) override
2390     {
2391         sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2392         if (nPageIndex == TAB_PAGE_NOTFOUND)
2393             return;
2394         m_xNotebook->RemovePage(rIdent);
2395         if (nPageIndex < m_aPages.size())
2396             m_aPages.erase(m_aPages.begin() + nPageIndex);
2397     }
2398 
2399     virtual void insert_page(const OString& rIdent, const OUString& rLabel, int nPos) override
2400     {
2401         VclPtrInstance<VclGrid> xGrid(m_xNotebook->GetPageParent());
2402         xGrid->set_hexpand(true);
2403         xGrid->set_vexpand(true);
2404         m_xNotebook->InsertPage(rIdent, rLabel, Image(), "", xGrid, nPos);
2405 
2406         if (nPos != -1)
2407         {
2408             unsigned int nPageIndex = static_cast<unsigned int>(nPos);
2409             if (nPageIndex < m_aPages.size())
2410                 m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr);
2411         }
2412     }
2413 
2414     virtual int get_n_pages() const override { return m_xNotebook->GetPageCount(); }
2415 
2416     virtual void set_tab_label_text(const OString& rIdent, const OUString& rText) override
2417     {
2418         return m_xNotebook->SetPageText(rIdent, rText);
2419     }
2420 
2421     virtual OUString get_tab_label_text(const OString& rIdent) const override
2422     {
2423         return m_xNotebook->GetPageText(rIdent);
2424     }
2425 
2426     virtual ~SalInstanceVerticalNotebook() override
2427     {
2428         m_xNotebook->SetActivatePageHdl(Link<VerticalTabControl*, void>());
2429         m_xNotebook->SetDeactivatePageHdl(Link<VerticalTabControl*, bool>());
2430     }
2431 };
2432 
2433 }
2434 
2435 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, DeactivatePageHdl, VerticalTabControl*, bool)
2436 {
2437     return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2438 }
2439 
2440 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, ActivatePageHdl, VerticalTabControl*, void)
2441 {
2442     m_aEnterPageHdl.Call(get_current_page_ident());
2443 }
2444 
2445 SalInstanceButton::SalInstanceButton(::Button* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2446     : SalInstanceContainer(pButton, pBuilder, bTakeOwnership)
2447     , m_xButton(pButton)
2448     , m_aOldClickHdl(pButton->GetClickHdl())
2449 {
2450     m_xButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2451 }
2452 
2453 void SalInstanceButton::set_label(const OUString& rText) { m_xButton->SetText(rText); }
2454 
2455 void SalInstanceButton::set_image(VirtualDevice* pDevice)
2456 {
2457     m_xButton->SetImageAlign(ImageAlign::Left);
2458     if (pDevice)
2459         m_xButton->SetModeImage(createImage(*pDevice));
2460     else
2461         m_xButton->SetModeImage(Image());
2462 }
2463 
2464 void SalInstanceButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage)
2465 {
2466     m_xButton->SetImageAlign(ImageAlign::Left);
2467     m_xButton->SetModeImage(Image(rImage));
2468 }
2469 
2470 void SalInstanceButton::set_from_icon_name(const OUString& rIconName)
2471 {
2472     m_xButton->SetModeImage(Image(StockImage::Yes, rIconName));
2473 }
2474 
2475 void SalInstanceButton::set_label_line_wrap(bool wrap)
2476 {
2477     WinBits nBits = m_xButton->GetStyle();
2478     nBits &= ~WB_WORDBREAK;
2479     if (wrap)
2480         nBits |= WB_WORDBREAK;
2481     m_xButton->SetStyle(nBits);
2482     m_xButton->queue_resize();
2483 }
2484 
2485 OUString SalInstanceButton::get_label() const { return m_xButton->GetText(); }
2486 
2487 SalInstanceButton::~SalInstanceButton() { m_xButton->SetClickHdl(Link<::Button*, void>()); }
2488 
2489 IMPL_LINK(SalInstanceButton, ClickHdl, ::Button*, pButton, void)
2490 {
2491     //if there's no handler set, disengage our intercept and
2492     //run the click again to get default behaviour for cancel/ok
2493     //etc buttons.
2494     if (!m_aClickHdl.IsSet())
2495     {
2496         pButton->SetClickHdl(m_aOldClickHdl);
2497         pButton->Click();
2498         pButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2499         return;
2500     }
2501     signal_clicked();
2502 }
2503 
2504 weld::Button* SalInstanceDialog::weld_widget_for_response(int nResponse)
2505 {
2506     PushButton* pButton = dynamic_cast<PushButton*>(m_xDialog->get_widget_for_response(nResponse));
2507     return pButton ? new SalInstanceButton(pButton, nullptr, false) : nullptr;
2508 }
2509 
2510 weld::Button* SalInstanceAssistant::weld_widget_for_response(int nResponse)
2511 {
2512     PushButton* pButton = nullptr;
2513     if (nResponse == RET_YES)
2514         pButton = m_xWizard->m_pNextPage;
2515     else if (nResponse == RET_NO)
2516         pButton = m_xWizard->m_pPrevPage;
2517     else if (nResponse == RET_OK)
2518         pButton = m_xWizard->m_pFinish;
2519     else if (nResponse == RET_CANCEL)
2520         pButton = m_xWizard->m_pCancel;
2521     else if (nResponse == RET_HELP)
2522         pButton = m_xWizard->m_pHelp;
2523     if (pButton)
2524         return new SalInstanceButton(pButton, nullptr, false);
2525     return nullptr;
2526 }
2527 
2528 namespace
2529 {
2530 class SalInstanceMenuButton : public SalInstanceButton, public virtual weld::MenuButton
2531 {
2532 private:
2533     VclPtr<::MenuButton> m_xMenuButton;
2534     sal_uInt16 m_nLastId;
2535 
2536     DECL_LINK(MenuSelectHdl, ::MenuButton*, void);
2537     DECL_LINK(ActivateHdl, ::MenuButton*, void);
2538 
2539 public:
2540     SalInstanceMenuButton(::MenuButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2541         : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2542         , m_xMenuButton(pButton)
2543         , m_nLastId(0)
2544     {
2545         m_xMenuButton->SetActivateHdl(LINK(this, SalInstanceMenuButton, ActivateHdl));
2546         m_xMenuButton->SetSelectHdl(LINK(this, SalInstanceMenuButton, MenuSelectHdl));
2547         if (PopupMenu* pMenu = m_xMenuButton->GetPopupMenu())
2548         {
2549             pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
2550             const auto nCount = pMenu->GetItemCount();
2551             m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
2552         }
2553     }
2554 
2555     virtual void set_active(bool active) override
2556     {
2557         if (active == get_active())
2558             return;
2559         if (active)
2560             m_xMenuButton->ExecuteMenu();
2561         else
2562             m_xMenuButton->CancelMenu();
2563     }
2564 
2565     virtual bool get_active() const override { return m_xMenuButton->InPopupMode(); }
2566 
2567     virtual void set_inconsistent(bool /*inconsistent*/) override
2568     {
2569         //not available
2570     }
2571 
2572     virtual bool get_inconsistent() const override { return false; }
2573 
2574     virtual void insert_item(int pos, const OUString& rId, const OUString& rStr,
2575                              const OUString* pIconName, VirtualDevice* pImageSurface,
2576                              TriState eCheckRadioFalse) override
2577     {
2578         m_nLastId = insert_to_menu(m_nLastId, m_xMenuButton->GetPopupMenu(), pos, rId, rStr,
2579                                    pIconName, pImageSurface, eCheckRadioFalse);
2580     }
2581 
2582     virtual void insert_separator(int pos, const OUString& rId) override
2583     {
2584         auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
2585         m_xMenuButton->GetPopupMenu()->InsertSeparator(rId.toUtf8(), nInsertPos);
2586     }
2587 
2588     virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) override
2589     {
2590         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2591         pMenu->EnableItem(rIdent, bSensitive);
2592     }
2593 
2594     virtual void remove_item(const OString& rId) override
2595     {
2596         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2597         pMenu->RemoveItem(pMenu->GetItemPos(pMenu->GetItemId(rId)));
2598     }
2599 
2600     virtual void clear() override
2601     {
2602         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2603         pMenu->Clear();
2604     }
2605 
2606     virtual void set_item_active(const OString& rIdent, bool bActive) override
2607     {
2608         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2609         pMenu->CheckItem(rIdent, bActive);
2610     }
2611 
2612     virtual void set_item_label(const OString& rIdent, const OUString& rText) override
2613     {
2614         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2615         pMenu->SetItemText(pMenu->GetItemId(rIdent), rText);
2616     }
2617 
2618     virtual OUString get_item_label(const OString& rIdent) const override
2619     {
2620         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2621         return pMenu->GetItemText(pMenu->GetItemId(rIdent));
2622     }
2623 
2624     virtual void set_item_visible(const OString& rIdent, bool bShow) override
2625     {
2626         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2627         pMenu->ShowItem(pMenu->GetItemId(rIdent), bShow);
2628     }
2629 
2630     virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) override
2631     {
2632         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2633         pMenu->SetHelpId(pMenu->GetItemId(rIdent), rHelpId);
2634     }
2635 
2636     virtual OString get_item_help_id(const OString& rIdent) const override
2637     {
2638         PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2639         return pMenu->GetHelpId(pMenu->GetItemId(rIdent));
2640     }
2641 
2642     virtual void set_popover(weld::Widget* pPopover) override
2643     {
2644         SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
2645         m_xMenuButton->SetPopover(pPopoverWidget ? pPopoverWidget->getWidget() : nullptr);
2646     }
2647 
2648     virtual ~SalInstanceMenuButton() override
2649     {
2650         m_xMenuButton->SetSelectHdl(Link<::MenuButton*, void>());
2651         m_xMenuButton->SetActivateHdl(Link<::MenuButton*, void>());
2652     }
2653 };
2654 
2655 }
2656 
2657 IMPL_LINK_NOARG(SalInstanceMenuButton, MenuSelectHdl, ::MenuButton*, void)
2658 {
2659     signal_selected(m_xMenuButton->GetCurItemIdent());
2660 }
2661 
2662 IMPL_LINK_NOARG(SalInstanceMenuButton, ActivateHdl, ::MenuButton*, void)
2663 {
2664     if (notify_events_disabled())
2665         return;
2666     signal_toggled();
2667 }
2668 
2669 namespace
2670 {
2671 class SalInstanceLinkButton : public SalInstanceContainer, public virtual weld::LinkButton
2672 {
2673 private:
2674     VclPtr<FixedHyperlink> m_xButton;
2675     Link<FixedHyperlink&, void> m_aOrigClickHdl;
2676 
2677     DECL_LINK(ClickHdl, FixedHyperlink&, void);
2678 
2679 public:
2680     SalInstanceLinkButton(FixedHyperlink* pButton, SalInstanceBuilder* pBuilder,
2681                           bool bTakeOwnership)
2682         : SalInstanceContainer(pButton, pBuilder, bTakeOwnership)
2683         , m_xButton(pButton)
2684     {
2685         m_aOrigClickHdl = m_xButton->GetClickHdl();
2686         m_xButton->SetClickHdl(LINK(this, SalInstanceLinkButton, ClickHdl));
2687     }
2688 
2689     virtual void set_label(const OUString& rText) override { m_xButton->SetText(rText); }
2690 
2691     virtual OUString get_label() const override { return m_xButton->GetText(); }
2692 
2693     virtual void set_uri(const OUString& rUri) override { m_xButton->SetURL(rUri); }
2694 
2695     virtual OUString get_uri() const override { return m_xButton->GetURL(); }
2696 
2697     virtual ~SalInstanceLinkButton() override { m_xButton->SetClickHdl(m_aOrigClickHdl); }
2698 };
2699 
2700 }
2701 
2702 IMPL_LINK(SalInstanceLinkButton, ClickHdl, FixedHyperlink&, rButton, void)
2703 {
2704     bool bConsumed = signal_activate_link();
2705     if (!bConsumed)
2706         m_aOrigClickHdl.Call(rButton);
2707 }
2708 
2709 namespace
2710 {
2711 class SalInstanceRadioButton : public SalInstanceButton, public virtual weld::RadioButton
2712 {
2713 private:
2714     VclPtr<::RadioButton> m_xRadioButton;
2715 
2716     DECL_LINK(ToggleHdl, ::RadioButton&, void);
2717 
2718 public:
2719     SalInstanceRadioButton(::RadioButton* pButton, SalInstanceBuilder* pBuilder,
2720                            bool bTakeOwnership)
2721         : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2722         , m_xRadioButton(pButton)
2723     {
2724         m_xRadioButton->SetToggleHdl(LINK(this, SalInstanceRadioButton, ToggleHdl));
2725     }
2726 
2727     virtual void set_active(bool active) override
2728     {
2729         disable_notify_events();
2730         m_xRadioButton->Check(active);
2731         enable_notify_events();
2732     }
2733 
2734     virtual bool get_active() const override { return m_xRadioButton->IsChecked(); }
2735 
2736     virtual void set_image(VirtualDevice* pDevice) override
2737     {
2738         m_xRadioButton->SetImageAlign(ImageAlign::Center);
2739         if (pDevice)
2740             m_xRadioButton->SetModeImage(createImage(*pDevice));
2741         else
2742             m_xRadioButton->SetModeImage(Image());
2743     }
2744 
2745     virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2746     {
2747         m_xRadioButton->SetImageAlign(ImageAlign::Center);
2748         m_xRadioButton->SetModeImage(Image(rImage));
2749     }
2750 
2751     virtual void set_from_icon_name(const OUString& rIconName) override
2752     {
2753         m_xRadioButton->SetModeRadioImage(Image(StockImage::Yes, rIconName));
2754     }
2755 
2756     virtual void set_inconsistent(bool /*inconsistent*/) override
2757     {
2758         //not available
2759     }
2760 
2761     virtual bool get_inconsistent() const override { return false; }
2762 
2763     virtual ~SalInstanceRadioButton() override
2764     {
2765         m_xRadioButton->SetToggleHdl(Link<::RadioButton&, void>());
2766     }
2767 };
2768 
2769 }
2770 
2771 IMPL_LINK_NOARG(SalInstanceRadioButton, ToggleHdl, ::RadioButton&, void)
2772 {
2773     if (notify_events_disabled())
2774         return;
2775     signal_toggled();
2776 }
2777 
2778 namespace
2779 {
2780 class SalInstanceToggleButton : public SalInstanceButton, public virtual weld::ToggleButton
2781 {
2782 private:
2783     VclPtr<PushButton> m_xToggleButton;
2784 
2785     DECL_LINK(ToggleListener, VclWindowEvent&, void);
2786 
2787 public:
2788     SalInstanceToggleButton(PushButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2789         : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2790         , m_xToggleButton(pButton)
2791     {
2792     }
2793 
2794     virtual void connect_toggled(const Link<ToggleButton&, void>& rLink) override
2795     {
2796         assert(!m_aToggleHdl.IsSet());
2797         m_xToggleButton->AddEventListener(LINK(this, SalInstanceToggleButton, ToggleListener));
2798         weld::ToggleButton::connect_toggled(rLink);
2799     }
2800 
2801     virtual void set_active(bool active) override
2802     {
2803         disable_notify_events();
2804         m_xToggleButton->Check(active);
2805         enable_notify_events();
2806     }
2807 
2808     virtual bool get_active() const override { return m_xToggleButton->IsChecked(); }
2809 
2810     virtual void set_inconsistent(bool inconsistent) override
2811     {
2812         disable_notify_events();
2813         m_xToggleButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE);
2814         enable_notify_events();
2815     }
2816 
2817     virtual bool get_inconsistent() const override
2818     {
2819         return m_xToggleButton->GetState() == TRISTATE_INDET;
2820     }
2821 
2822     virtual ~SalInstanceToggleButton() override
2823     {
2824         if (m_aToggleHdl.IsSet())
2825             m_xToggleButton->RemoveEventListener(
2826                 LINK(this, SalInstanceToggleButton, ToggleListener));
2827     }
2828 };
2829 
2830 }
2831 
2832 IMPL_LINK(SalInstanceToggleButton, ToggleListener, VclWindowEvent&, rEvent, void)
2833 {
2834     if (notify_events_disabled())
2835         return;
2836     if (rEvent.GetId() == VclEventId::PushbuttonToggle)
2837         signal_toggled();
2838 }
2839 
2840 SalInstanceCheckButton::SalInstanceCheckButton(CheckBox* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2841     : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2842     , m_xCheckButton(pButton)
2843 {
2844     m_xCheckButton->SetToggleHdl(LINK(this, SalInstanceCheckButton, ToggleHdl));
2845 }
2846 
2847 void SalInstanceCheckButton::set_active(bool active)
2848 {
2849     disable_notify_events();
2850     m_xCheckButton->EnableTriState(false);
2851     m_xCheckButton->Check(active);
2852     enable_notify_events();
2853 }
2854 
2855 bool SalInstanceCheckButton::get_active() const { return m_xCheckButton->IsChecked(); }
2856 
2857 void SalInstanceCheckButton::set_inconsistent(bool inconsistent)
2858 {
2859     disable_notify_events();
2860     m_xCheckButton->EnableTriState(true);
2861     m_xCheckButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE);
2862     enable_notify_events();
2863 }
2864 
2865 bool SalInstanceCheckButton::get_inconsistent() const
2866 {
2867     return m_xCheckButton->GetState() == TRISTATE_INDET;
2868 }
2869 
2870 SalInstanceCheckButton::~SalInstanceCheckButton()
2871 {
2872     m_xCheckButton->SetToggleHdl(Link<CheckBox&, void>());
2873 }
2874 
2875 IMPL_LINK_NOARG(SalInstanceCheckButton, ToggleHdl, CheckBox&, void)
2876 {
2877     if (notify_events_disabled())
2878         return;
2879     m_xCheckButton->EnableTriState(false);
2880     signal_toggled();
2881 }
2882 
2883 namespace
2884 {
2885 class SalInstanceScale : public SalInstanceWidget, public virtual weld::Scale
2886 {
2887 private:
2888     VclPtr<Slider> m_xScale;
2889 
2890     DECL_LINK(SlideHdl, Slider*, void);
2891 
2892 public:
2893     SalInstanceScale(Slider* pScale, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2894         : SalInstanceWidget(pScale, pBuilder, bTakeOwnership)
2895         , m_xScale(pScale)
2896     {
2897         m_xScale->SetSlideHdl(LINK(this, SalInstanceScale, SlideHdl));
2898     }
2899 
2900     virtual void set_value(int value) override { m_xScale->SetThumbPos(value); }
2901 
2902     virtual void set_range(int min, int max) override
2903     {
2904         m_xScale->SetRangeMin(min);
2905         m_xScale->SetRangeMax(max);
2906     }
2907 
2908     virtual int get_value() const override { return m_xScale->GetThumbPos(); }
2909 
2910     virtual void set_increments(int step, int page) override
2911     {
2912         m_xScale->SetLineSize(step);
2913         m_xScale->SetPageSize(page);
2914     }
2915 
2916     virtual void get_increments(int& step, int& page) const override
2917     {
2918         step = m_xScale->GetLineSize();
2919         page = m_xScale->GetPageSize();
2920     }
2921 
2922     virtual ~SalInstanceScale() override { m_xScale->SetSlideHdl(Link<Slider*, void>()); }
2923 };
2924 
2925 }
2926 
2927 IMPL_LINK_NOARG(SalInstanceScale, SlideHdl, Slider*, void) { signal_value_changed(); }
2928 
2929 namespace
2930 {
2931 class SalInstanceSpinner : public SalInstanceWidget, public virtual weld::Spinner
2932 {
2933 private:
2934     VclPtr<Throbber> m_xThrobber;
2935 
2936 public:
2937     SalInstanceSpinner(Throbber* pThrobber, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2938         : SalInstanceWidget(pThrobber, pBuilder, bTakeOwnership)
2939         , m_xThrobber(pThrobber)
2940     {
2941     }
2942 
2943     virtual void start() override { m_xThrobber->start(); }
2944 
2945     virtual void stop() override { m_xThrobber->stop(); }
2946 };
2947 
2948 class SalInstanceProgressBar : public SalInstanceWidget, public virtual weld::ProgressBar
2949 {
2950 private:
2951     VclPtr<::ProgressBar> m_xProgressBar;
2952 
2953 public:
2954     SalInstanceProgressBar(::ProgressBar* pProgressBar, SalInstanceBuilder* pBuilder,
2955                            bool bTakeOwnership)
2956         : SalInstanceWidget(pProgressBar, pBuilder, bTakeOwnership)
2957         , m_xProgressBar(pProgressBar)
2958     {
2959     }
2960 
2961     virtual void set_percentage(int value) override { m_xProgressBar->SetValue(value); }
2962 
2963     virtual OUString get_text() const override { return m_xProgressBar->GetText(); }
2964 
2965     virtual void set_text(const OUString& rText) override { m_xProgressBar->SetText(rText); }
2966 };
2967 
2968 class SalInstanceImage : public SalInstanceWidget, public virtual weld::Image
2969 {
2970 private:
2971     VclPtr<FixedImage> m_xImage;
2972 
2973 public:
2974     SalInstanceImage(FixedImage* pImage, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2975         : SalInstanceWidget(pImage, pBuilder, bTakeOwnership)
2976         , m_xImage(pImage)
2977     {
2978     }
2979 
2980     virtual void set_from_icon_name(const OUString& rIconName) override
2981     {
2982         m_xImage->SetImage(::Image(StockImage::Yes, rIconName));
2983     }
2984 
2985     virtual void set_image(VirtualDevice* pDevice) override
2986     {
2987         if (pDevice)
2988             m_xImage->SetImage(createImage(*pDevice));
2989         else
2990             m_xImage->SetImage(::Image());
2991     }
2992 
2993     virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2994     {
2995         m_xImage->SetImage(::Image(rImage));
2996     }
2997 };
2998 
2999 class SalInstanceCalendar : public SalInstanceWidget, public virtual weld::Calendar
3000 {
3001 private:
3002     VclPtr<::Calendar> m_xCalendar;
3003 
3004     DECL_LINK(SelectHdl, ::Calendar*, void);
3005     DECL_LINK(ActivateHdl, ::Calendar*, void);
3006 
3007 public:
3008     SalInstanceCalendar(::Calendar* pCalendar, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3009         : SalInstanceWidget(pCalendar, pBuilder, bTakeOwnership)
3010         , m_xCalendar(pCalendar)
3011     {
3012         m_xCalendar->SetSelectHdl(LINK(this, SalInstanceCalendar, SelectHdl));
3013         m_xCalendar->SetActivateHdl(LINK(this, SalInstanceCalendar, ActivateHdl));
3014     }
3015 
3016     virtual void set_date(const Date& rDate) override { m_xCalendar->SetCurDate(rDate); }
3017 
3018     virtual Date get_date() const override { return m_xCalendar->GetFirstSelectedDate(); }
3019 
3020     virtual ~SalInstanceCalendar() override
3021     {
3022         m_xCalendar->SetSelectHdl(Link<::Calendar*, void>());
3023         m_xCalendar->SetActivateHdl(Link<::Calendar*, void>());
3024     }
3025 };
3026 
3027 }
3028 
3029 IMPL_LINK_NOARG(SalInstanceCalendar, SelectHdl, ::Calendar*, void)
3030 {
3031     if (notify_events_disabled())
3032         return;
3033     signal_selected();
3034 }
3035 
3036 IMPL_LINK_NOARG(SalInstanceCalendar, ActivateHdl, ::Calendar*, void)
3037 {
3038     if (notify_events_disabled())
3039         return;
3040     signal_activated();
3041 }
3042 
3043 WeldTextFilter::WeldTextFilter(Link<OUString&, bool>& rInsertTextHdl)
3044     : TextFilter(OUString())
3045     , m_rInsertTextHdl(rInsertTextHdl)
3046 {
3047 }
3048 
3049 OUString WeldTextFilter::filter(const OUString& rText)
3050 {
3051     if (!m_rInsertTextHdl.IsSet())
3052         return rText;
3053     OUString sText(rText);
3054     const bool bContinue = m_rInsertTextHdl.Call(sText);
3055     if (!bContinue)
3056         return OUString();
3057     return sText;
3058 }
3059 
3060 SalInstanceEntry::SalInstanceEntry(Edit* pEntry, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3061     : SalInstanceWidget(pEntry, pBuilder, bTakeOwnership)
3062     , m_xEntry(pEntry)
3063     , m_aTextFilter(m_aInsertTextHdl)
3064 {
3065     m_xEntry->SetModifyHdl(LINK(this, SalInstanceEntry, ChangeHdl));
3066     m_xEntry->SetActivateHdl(LINK(this, SalInstanceEntry, ActivateHdl));
3067     m_xEntry->SetTextFilter(&m_aTextFilter);
3068 }
3069 
3070 void SalInstanceEntry::set_text(const OUString& rText)
3071 {
3072     disable_notify_events();
3073     m_xEntry->SetText(rText);
3074     enable_notify_events();
3075 }
3076 
3077 OUString SalInstanceEntry::get_text() const
3078 {
3079     return m_xEntry->GetText();
3080 }
3081 
3082 void SalInstanceEntry::set_width_chars(int nChars)
3083 {
3084     m_xEntry->SetWidthInChars(nChars);
3085 }
3086 
3087 int SalInstanceEntry::get_width_chars() const
3088 {
3089     return m_xEntry->GetWidthInChars();
3090 }
3091 
3092 void SalInstanceEntry::set_max_length(int nChars)
3093 {
3094     m_xEntry->SetMaxTextLen(nChars);
3095 }
3096 
3097 void SalInstanceEntry::select_region(int nStartPos, int nEndPos)
3098 {
3099     disable_notify_events();
3100     long nStart = nStartPos < 0 ? SELECTION_MAX : nStartPos;
3101     long nEnd = nEndPos < 0 ? SELECTION_MAX : nEndPos;
3102     m_xEntry->SetSelection(Selection(nStart, nEnd));
3103     enable_notify_events();
3104 }
3105 
3106 bool SalInstanceEntry::get_selection_bounds(int& rStartPos, int& rEndPos)
3107 {
3108     const Selection& rSelection = m_xEntry->GetSelection();
3109     rStartPos = rSelection.Min();
3110     rEndPos = rSelection.Max();
3111     return rSelection.Len();
3112 }
3113 
3114 void SalInstanceEntry::replace_selection(const OUString& rText)
3115 {
3116     m_xEntry->ReplaceSelected(rText);
3117 }
3118 
3119 void SalInstanceEntry::set_position(int nCursorPos)
3120 {
3121     disable_notify_events();
3122     if (nCursorPos < 0)
3123         m_xEntry->SetCursorAtLast();
3124     else
3125         m_xEntry->SetSelection(Selection(nCursorPos, nCursorPos));
3126     enable_notify_events();
3127 }
3128 
3129 int SalInstanceEntry::get_position() const
3130 {
3131     return m_xEntry->GetSelection().Max();
3132 }
3133 
3134 void SalInstanceEntry::set_editable(bool bEditable)
3135 {
3136     m_xEntry->SetReadOnly(!bEditable);
3137 }
3138 
3139 bool SalInstanceEntry::get_editable() const
3140 {
3141     return !m_xEntry->IsReadOnly();
3142 }
3143 
3144 void SalInstanceEntry::set_overwrite_mode(bool bOn)
3145 {
3146     m_xEntry->SetInsertMode(!bOn);
3147 }
3148 
3149 bool SalInstanceEntry::get_overwrite_mode() const
3150 {
3151     return !m_xEntry->IsInsertMode();
3152 }
3153 
3154 void SalInstanceEntry::set_message_type(weld::EntryMessageType eType)
3155 {
3156     switch (eType)
3157     {
3158         case weld::EntryMessageType::Normal:
3159             m_xEntry->SetForceControlBackground(false);
3160             m_xEntry->SetControlForeground();
3161             m_xEntry->SetControlBackground();
3162             break;
3163         case weld::EntryMessageType::Warning:
3164             // tdf#114603: enable setting the background to a different color;
3165             // relevant for GTK; see also #i75179#
3166             m_xEntry->SetForceControlBackground(true);
3167             m_xEntry->SetControlForeground();
3168             m_xEntry->SetControlBackground(COL_YELLOW);
3169             break;
3170         case weld::EntryMessageType::Error:
3171             // tdf#114603: enable setting the background to a different color;
3172             // relevant for GTK; see also #i75179#
3173             m_xEntry->SetForceControlBackground(true);
3174             m_xEntry->SetControlForeground(COL_WHITE);
3175             m_xEntry->SetControlBackground(0xff6563);
3176             break;
3177     }
3178 }
3179 
3180 void SalInstanceEntry::set_font(const vcl::Font& rFont)
3181 {
3182     m_xEntry->SetPointFont(*m_xEntry, rFont);
3183     m_xEntry->Invalidate();
3184 }
3185 
3186 void SalInstanceEntry::set_font_color(const Color& rColor)
3187 {
3188     if (rColor == COL_AUTO)
3189         m_xEntry->SetControlForeground();
3190     else
3191         m_xEntry->SetControlForeground(rColor);
3192 }
3193 
3194 void SalInstanceEntry::connect_cursor_position(const Link<Entry&, void>& rLink)
3195 {
3196     assert(!m_aCursorPositionHdl.IsSet());
3197     m_xEntry->AddEventListener(LINK(this, SalInstanceEntry, CursorListener));
3198     weld::Entry::connect_cursor_position(rLink);
3199 }
3200 
3201 void SalInstanceEntry::set_placeholder_text(const OUString& rText)
3202 {
3203     m_xEntry->SetPlaceholderText(rText);
3204 }
3205 
3206 Edit& SalInstanceEntry::getEntry()
3207 {
3208     return *m_xEntry;
3209 }
3210 
3211 void SalInstanceEntry::fire_signal_changed()
3212 {
3213     signal_changed();
3214 }
3215 
3216 void SalInstanceEntry::cut_clipboard()
3217 {
3218     m_xEntry->Cut();
3219 }
3220 
3221 void SalInstanceEntry::copy_clipboard()
3222 {
3223     m_xEntry->Copy();
3224 }
3225 
3226 void SalInstanceEntry::paste_clipboard()
3227 {
3228     m_xEntry->Paste();
3229 }
3230 
3231 namespace
3232 {
3233     void set_alignment(Edit& rEntry, TxtAlign eXAlign)
3234     {
3235         WinBits nAlign(0);
3236         switch (eXAlign)
3237         {
3238             case TxtAlign::Left:
3239                 nAlign = WB_LEFT;
3240                 break;
3241             case TxtAlign::Center:
3242                 nAlign = WB_CENTER;
3243                 break;
3244             case TxtAlign::Right:
3245                 nAlign = WB_RIGHT;
3246                 break;
3247         }
3248         WinBits nBits = rEntry.GetStyle();
3249         nBits &= ~(WB_LEFT | WB_CENTER | WB_RIGHT);
3250         rEntry.SetStyle(nBits | nAlign);
3251     }
3252 }
3253 
3254 void SalInstanceEntry::set_alignment(TxtAlign eXAlign)
3255 {
3256     ::set_alignment(*m_xEntry, eXAlign);
3257 }
3258 
3259 SalInstanceEntry::~SalInstanceEntry()
3260 {
3261     if (m_aCursorPositionHdl.IsSet())
3262         m_xEntry->RemoveEventListener(LINK(this, SalInstanceEntry, CursorListener));
3263     m_xEntry->SetTextFilter(nullptr);
3264     m_xEntry->SetActivateHdl(Link<Edit&, bool>());
3265     m_xEntry->SetModifyHdl(Link<Edit&, void>());
3266 }
3267 
3268 IMPL_LINK_NOARG(SalInstanceEntry, ChangeHdl, Edit&, void) { signal_changed(); }
3269 
3270 IMPL_LINK(SalInstanceEntry, CursorListener, VclWindowEvent&, rEvent, void)
3271 {
3272     if (notify_events_disabled())
3273         return;
3274     if (rEvent.GetId() == VclEventId::EditSelectionChanged
3275         || rEvent.GetId() == VclEventId::EditCaretChanged)
3276         signal_cursor_position();
3277 }
3278 
3279 IMPL_LINK_NOARG(SalInstanceEntry, ActivateHdl, Edit&, bool) { return m_aActivateHdl.Call(*this); }
3280 
3281 namespace
3282 {
3283 struct SalInstanceTreeIter : public weld::TreeIter
3284 {
3285     SalInstanceTreeIter(const SalInstanceTreeIter* pOrig)
3286         : iter(pOrig ? pOrig->iter : nullptr)
3287     {
3288     }
3289     SalInstanceTreeIter(SvTreeListEntry* pIter)
3290         : iter(pIter)
3291     {
3292     }
3293     virtual bool equal(const TreeIter& rOther) const override
3294     {
3295         return iter == static_cast<const SalInstanceTreeIter&>(rOther).iter;
3296     }
3297     SvTreeListEntry* iter;
3298 };
3299 
3300 }
3301 
3302 class SalInstanceTreeView;
3303 
3304 static SalInstanceTreeView* g_DragSource;
3305 
3306 class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView
3307 {
3308 private:
3309     // owner for UserData
3310     std::vector<std::unique_ptr<OUString>> m_aUserData;
3311     VclPtr<SvTabListBox> m_xTreeView;
3312     SvLBoxButtonData m_aCheckButtonData;
3313     SvLBoxButtonData m_aRadioButtonData;
3314     // currently expanding parent that logically, but not currently physically,
3315     // contain placeholders
3316     o3tl::sorted_vector<SvTreeListEntry*> m_aExpandingPlaceHolderParents;
3317     // which columns should be custom rendered
3318     o3tl::sorted_vector<int> m_aCustomRenders;
3319     bool m_bTogglesAsRadio;
3320     int m_nSortColumn;
3321 
3322     DECL_LINK(SelectHdl, SvTreeListBox*, void);
3323     DECL_LINK(DeSelectHdl, SvTreeListBox*, void);
3324     DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
3325     DECL_LINK(ExpandingHdl, SvTreeListBox*, bool);
3326     DECL_LINK(EndDragHdl, HeaderBar*, void);
3327     DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
3328     DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
3329     DECL_LINK(ModelChangedHdl, SvTreeListBox*, void);
3330     DECL_LINK(StartDragHdl, SvTreeListBox*, bool);
3331     DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void);
3332     DECL_LINK(EditingEntryHdl, SvTreeListEntry*, bool);
3333     typedef std::pair<SvTreeListEntry*, OUString> IterString;
3334     DECL_LINK(EditedEntryHdl, IterString, bool);
3335     DECL_LINK(VisibleRangeChangedHdl, SvTreeListBox*, void);
3336     DECL_LINK(CompareHdl, const SvSortData&, sal_Int32);
3337     DECL_LINK(PopupMenuHdl, const CommandEvent&, bool);
3338     DECL_LINK(TooltipHdl, const HelpEvent&, bool);
3339     DECL_LINK(CustomRenderHdl, svtree_render_args, void);
3340     DECL_LINK(CustomMeasureHdl, svtree_measure_args, Size);
3341 
3342     // Each row has a cell for the expander image, (and an optional cell for a
3343     // checkbutton if enable_toggle_buttons has been called) which precede
3344     // index 0
3345     int to_internal_model(int col) const
3346     {
3347         if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
3348             ++col; // skip checkbutton column
3349         ++col; //skip expander column
3350         return col;
3351     }
3352 
3353     int to_external_model(int col) const
3354     {
3355         if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
3356             --col; // skip checkbutton column
3357         --col; //skip expander column
3358         return col;
3359     }
3360 
3361     bool IsDummyEntry(SvTreeListEntry* pEntry) const
3362     {
3363         return m_xTreeView->GetEntryText(pEntry).trim() == "<dummy>";
3364     }
3365 
3366     SvTreeListEntry* GetPlaceHolderChild(SvTreeListEntry* pEntry) const
3367     {
3368         if (pEntry->HasChildren())
3369         {
3370             auto pChild = m_xTreeView->FirstChild(pEntry);
3371             assert(pChild);
3372             if (IsDummyEntry(pChild))
3373                 return pChild;
3374         }
3375         return nullptr;
3376     }
3377 
3378     static void set_font_color(SvTreeListEntry* pEntry, const Color& rColor)
3379     {
3380         if (rColor == COL_AUTO)
3381             pEntry->SetTextColor(std::optional<Color>());
3382         else
3383             pEntry->SetTextColor(rColor);
3384     }
3385 
3386     void AddStringItem(SvTreeListEntry* pEntry, const OUString& rStr, int nCol)
3387     {
3388         auto xCell = std::make_unique<SvLBoxString>(rStr);
3389         if (m_aCustomRenders.count(nCol))
3390             xCell->SetCustomRender();
3391         pEntry->AddItem(std::move(xCell));
3392     }
3393 
3394     void do_insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
3395                    const OUString* pId, const OUString* pIconName,
3396                    VirtualDevice* pImageSurface, bool bChildrenOnDemand,
3397                    weld::TreeIter* pRet, bool bIsSeparator)
3398     {
3399         disable_notify_events();
3400         const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
3401         SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
3402         auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
3403         void* pUserData;
3404         if (pId)
3405         {
3406             m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
3407             pUserData = m_aUserData.back().get();
3408         }
3409         else
3410             pUserData = nullptr;
3411 
3412         SvTreeListEntry* pEntry = new SvTreeListEntry;
3413         if (bIsSeparator)
3414             pEntry->SetFlags(pEntry->GetFlags() | SvTLEntryFlags::IS_SEPARATOR);
3415 
3416         if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
3417             AddStringItem(pEntry, "", -1);
3418 
3419         if (pIconName || pImageSurface)
3420         {
3421             Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface));
3422             pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
3423         }
3424         else
3425         {
3426             Image aDummy;
3427             pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3428         }
3429         if (pStr)
3430             AddStringItem(pEntry, *pStr, 0);
3431         pEntry->SetUserData(pUserData);
3432         m_xTreeView->Insert(pEntry, iter, nInsertPos);
3433 
3434         if (pRet)
3435         {
3436             SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
3437             pVclRetIter->iter = pEntry;
3438         }
3439 
3440         if (bChildrenOnDemand)
3441         {
3442             SvTreeListEntry* pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
3443             SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
3444             pViewData->SetSelectable(false);
3445         }
3446 
3447         if (bIsSeparator)
3448         {
3449             SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3450             pViewData->SetSelectable(false);
3451         }
3452 
3453         enable_notify_events();
3454     }
3455 
3456     void update_checkbutton_column_width(SvTreeListEntry* pEntry)
3457     {
3458         SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3459         m_xTreeView->InitViewData(pViewData, pEntry);
3460         m_xTreeView->CheckBoxInserted(pEntry);
3461     }
3462 
3463     void do_set_toggle(SvTreeListEntry* pEntry, TriState eState, int col)
3464     {
3465         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3466         // if its the placeholder to allow a blank column, replace it now
3467         if (pEntry->GetItem(col).GetType() != SvLBoxItemType::Button)
3468         {
3469             SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
3470             pEntry->ReplaceItem(std::make_unique<SvLBoxButton>(pData), 0);
3471             update_checkbutton_column_width(pEntry);
3472 
3473         }
3474         SvLBoxItem& rItem = pEntry->GetItem(col);
3475         assert(dynamic_cast<SvLBoxButton*>(&rItem));
3476         switch (eState)
3477         {
3478             case TRISTATE_TRUE:
3479                 static_cast<SvLBoxButton&>(rItem).SetStateChecked();
3480                 break;
3481             case TRISTATE_FALSE:
3482                 static_cast<SvLBoxButton&>(rItem).SetStateUnchecked();
3483                 break;
3484             case TRISTATE_INDET:
3485                 static_cast<SvLBoxButton&>(rItem).SetStateTristate();
3486                 break;
3487         }
3488 
3489         m_xTreeView->ModelHasEntryInvalidated(pEntry);
3490     }
3491 
3492     static TriState do_get_toggle(SvTreeListEntry* pEntry, int col)
3493     {
3494         if (static_cast<size_t>(col) == pEntry->ItemCount())
3495             return TRISTATE_FALSE;
3496 
3497         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3498         SvLBoxItem& rItem = pEntry->GetItem(col);
3499         assert(dynamic_cast<SvLBoxButton*>(&rItem));
3500         SvLBoxButton& rToggle = static_cast<SvLBoxButton&>(rItem);
3501         if (rToggle.IsStateTristate())
3502             return TRISTATE_INDET;
3503         else if (rToggle.IsStateChecked())
3504             return TRISTATE_TRUE;
3505         return TRISTATE_FALSE;
3506     }
3507 
3508     TriState get_toggle(SvTreeListEntry* pEntry, int col) const
3509     {
3510         if (col == -1)
3511         {
3512             assert(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
3513             return do_get_toggle(pEntry, 0);
3514         }
3515         col = to_internal_model(col);
3516         return do_get_toggle(pEntry, col);
3517     }
3518 
3519     void set_toggle(SvTreeListEntry* pEntry, TriState eState, int col)
3520     {
3521         if (col == -1)
3522         {
3523             assert(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
3524             do_set_toggle(pEntry, eState, 0);
3525             return;
3526         }
3527 
3528         col = to_internal_model(col);
3529 
3530         // blank out missing entries
3531         for (int i = pEntry->ItemCount(); i < col; ++i)
3532             AddStringItem(pEntry, "", i - 1);
3533 
3534         if (static_cast<size_t>(col) == pEntry->ItemCount())
3535         {
3536             SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
3537             pEntry->AddItem(std::make_unique<SvLBoxButton>(pData));
3538             update_checkbutton_column_width(pEntry);
3539         }
3540 
3541         do_set_toggle(pEntry, eState, col);
3542     }
3543 
3544     bool get_text_emphasis(SvTreeListEntry* pEntry, int col) const
3545     {
3546         col = to_internal_model(col);
3547 
3548         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3549         SvLBoxItem& rItem = pEntry->GetItem(col);
3550         assert(dynamic_cast<SvLBoxString*>(&rItem));
3551         return static_cast<SvLBoxString&>(rItem).IsEmphasized();
3552     }
3553 
3554 public:
3555     SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3556         : SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
3557         , m_xTreeView(pTreeView)
3558         , m_aCheckButtonData(pTreeView, false)
3559         , m_aRadioButtonData(pTreeView, true)
3560         , m_bTogglesAsRadio(false)
3561         , m_nSortColumn(-1)
3562     {
3563         m_xTreeView->SetNodeDefaultImages();
3564         m_xTreeView->SetForceMakeVisible(true);
3565         m_xTreeView->SetSelectHdl(LINK(this, SalInstanceTreeView, SelectHdl));
3566         m_xTreeView->SetDeselectHdl(LINK(this, SalInstanceTreeView, DeSelectHdl));
3567         m_xTreeView->SetDoubleClickHdl(LINK(this, SalInstanceTreeView, DoubleClickHdl));
3568         m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl));
3569         m_xTreeView->SetPopupMenuHdl(LINK(this, SalInstanceTreeView, PopupMenuHdl));
3570         m_xTreeView->SetCustomRenderHdl(LINK(this, SalInstanceTreeView, CustomRenderHdl));
3571         m_xTreeView->SetCustomMeasureHdl(LINK(this, SalInstanceTreeView, CustomMeasureHdl));
3572         const long aTabPositions[] = { 0 };
3573         m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions);
3574         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3575 
3576         if (pHeaderBox)
3577         {
3578             if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
3579             {
3580                 //make the last entry fill available space
3581                 pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1),
3582                                         HEADERBAR_FULLSIZE);
3583                 pHeaderBar->SetEndDragHdl(LINK(this, SalInstanceTreeView, EndDragHdl));
3584                 pHeaderBar->SetSelectHdl(LINK(this, SalInstanceTreeView, HeaderBarClickedHdl));
3585             }
3586             pHeaderBox->SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3587             pHeaderBox->SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3588         }
3589         else
3590         {
3591             static_cast<LclTabListBox&>(*m_xTreeView)
3592                 .SetModelChangedHdl(LINK(this, SalInstanceTreeView, ModelChangedHdl));
3593             static_cast<LclTabListBox&>(*m_xTreeView)
3594                 .SetStartDragHdl(LINK(this, SalInstanceTreeView, StartDragHdl));
3595             static_cast<LclTabListBox&>(*m_xTreeView)
3596                 .SetEndDragHdl(LINK(this, SalInstanceTreeView, FinishDragHdl));
3597             static_cast<LclTabListBox&>(*m_xTreeView)
3598                 .SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3599             static_cast<LclTabListBox&>(*m_xTreeView)
3600                 .SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3601         }
3602         m_aCheckButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3603         m_aRadioButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3604     }
3605 
3606     virtual void connect_query_tooltip(const Link<const weld::TreeIter&, OUString>& rLink) override
3607     {
3608         weld::TreeView::connect_query_tooltip(rLink);
3609         m_xTreeView->SetTooltipHdl(LINK(this, SalInstanceTreeView, TooltipHdl));
3610     }
3611 
3612     virtual void columns_autosize() override
3613     {
3614         std::vector<long> aWidths;
3615         m_xTreeView->getPreferredDimensions(aWidths);
3616         if (aWidths.size() > 2)
3617         {
3618             std::vector<int> aColWidths;
3619             for (size_t i = 1; i < aWidths.size() - 1; ++i)
3620                 aColWidths.push_back(aWidths[i] - aWidths[i - 1]);
3621             set_column_fixed_widths(aColWidths);
3622         }
3623     }
3624 
3625     virtual void freeze() override
3626     {
3627         SalInstanceWidget::freeze();
3628         m_xTreeView->SetUpdateMode(false);
3629         m_xTreeView->GetModel()->EnableInvalidate(false);
3630     }
3631 
3632     virtual void thaw() override
3633     {
3634         m_xTreeView->GetModel()->EnableInvalidate(true);
3635         m_xTreeView->SetUpdateMode(true);
3636         SalInstanceWidget::thaw();
3637     }
3638 
3639     virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override
3640     {
3641         std::vector<long> aTabPositions;
3642         aTabPositions.push_back(0);
3643         for (size_t i = 0; i < rWidths.size(); ++i)
3644             aTabPositions.push_back(aTabPositions[i] + rWidths[i]);
3645         m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
3646         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3647         if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3648         {
3649             for (size_t i = 0; i < rWidths.size(); ++i)
3650                 pHeaderBar->SetItemSize(pHeaderBar->GetItemId(i), rWidths[i]);
3651         }
3652         // call Resize to recalculate based on the new tabs
3653         m_xTreeView->Resize();
3654     }
3655 
3656     virtual void set_column_editables(const std::vector<bool>& rEditables) override
3657     {
3658         size_t nTabCount = rEditables.size();
3659         for (size_t i = 0 ; i < nTabCount; ++i)
3660             m_xTreeView->SetTabEditable(i, rEditables[i]);
3661     }
3662 
3663     virtual void set_centered_column(int nCol) override
3664     {
3665         m_xTreeView->SetTabJustify(nCol, SvTabJustify::AdjustCenter);
3666     }
3667 
3668     virtual int get_column_width(int nColumn) const override
3669     {
3670         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3671         if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3672             return pHeaderBar->GetItemSize(pHeaderBar->GetItemId(nColumn));
3673         // GetTab(0) gives the position of the bitmap which is automatically inserted by the TabListBox.
3674         // So the first text column's width is Tab(2)-Tab(1).
3675         auto nWidthPixel
3676             = m_xTreeView->GetLogicTab(nColumn + 2) - m_xTreeView->GetLogicTab(nColumn + 1);
3677         nWidthPixel -= SV_TAB_BORDER;
3678         return nWidthPixel;
3679     }
3680 
3681     virtual OUString get_column_title(int nColumn) const override
3682     {
3683         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3684         if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3685         {
3686             return pHeaderBar->GetItemText(pHeaderBar->GetItemId(nColumn));
3687         }
3688         return OUString();
3689     }
3690 
3691     virtual void set_column_title(int nColumn, const OUString& rTitle) override
3692     {
3693         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3694         if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3695         {
3696             return pHeaderBar->SetItemText(pHeaderBar->GetItemId(nColumn), rTitle);
3697         }
3698     }
3699 
3700     virtual void set_column_custom_renderer(int nColumn, bool bEnable) override
3701     {
3702         assert(n_children() == 0 && "tree must be empty");
3703         if (bEnable)
3704             m_aCustomRenders.insert(nColumn);
3705         else
3706             m_aCustomRenders.erase(nColumn);
3707     }
3708 
3709     virtual void queue_draw() override
3710     {
3711         // invalidate the entries
3712         SvTreeList* pModel = m_xTreeView->GetModel();
3713         for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; pEntry = m_xTreeView->Next(pEntry))
3714             pModel->InvalidateEntry(pEntry);
3715     }
3716 
3717     virtual void show() override
3718     {
3719         if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
3720             pHeaderBox->GetParent()->Show();
3721         SalInstanceContainer::show();
3722     }
3723 
3724     virtual void hide() override
3725     {
3726         if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
3727             pHeaderBox->GetParent()->Hide();
3728         SalInstanceContainer::hide();
3729     }
3730 
3731     virtual void insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
3732                         const OUString* pId, const OUString* pIconName,
3733                         VirtualDevice* pImageSurface, bool bChildrenOnDemand,
3734                         weld::TreeIter* pRet) override
3735     {
3736         do_insert(pParent, pos, pStr, pId, pIconName, pImageSurface,
3737                   bChildrenOnDemand, pRet, false);
3738     }
3739 
3740     virtual void insert_separator(int pos, const OUString& /*rId*/) override
3741     {
3742         OUString sSep(VclResId(STR_SEPARATOR));
3743         do_insert(nullptr, pos, &sSep, nullptr, nullptr, nullptr,
3744                   false, nullptr, true);
3745     }
3746 
3747     virtual void
3748     bulk_insert_for_each(int nSourceCount,
3749                          const std::function<void(weld::TreeIter&, int nSourceIndex)>& func,
3750                          const std::vector<int>* pFixedWidths) override
3751     {
3752         freeze();
3753         clear();
3754         SalInstanceTreeIter aVclIter(static_cast<SvTreeListEntry*>(nullptr));
3755 
3756         m_xTreeView->nTreeFlags |= SvTreeFlags::MANINS;
3757 
3758         if (pFixedWidths)
3759             set_column_fixed_widths(*pFixedWidths);
3760 
3761         bool bHasAutoCheckButton(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
3762         size_t nExtraCols = bHasAutoCheckButton ? 2 : 1;
3763 
3764         Image aDummy;
3765         for (int i = 0; i < nSourceCount; ++i)
3766         {
3767             aVclIter.iter = new SvTreeListEntry;
3768             if (bHasAutoCheckButton)
3769                 AddStringItem(aVclIter.iter, "", -1);
3770             aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3771             m_xTreeView->Insert(aVclIter.iter, nullptr, TREELIST_APPEND);
3772             func(aVclIter, i);
3773 
3774             if (!pFixedWidths)
3775                 continue;
3776 
3777             size_t nFixedWidths = std::min(pFixedWidths->size(), aVclIter.iter->ItemCount());
3778             for (size_t j = 0; j < nFixedWidths; ++j)
3779             {
3780                 SvLBoxItem& rItem = aVclIter.iter->GetItem(j + nExtraCols);
3781                 SvViewDataItem* pViewDataItem = m_xTreeView->GetViewDataItem(aVclIter.iter, &rItem);
3782                 pViewDataItem->mnWidth = (*pFixedWidths)[j];
3783             }
3784         }
3785 
3786         m_xTreeView->nTreeFlags &= ~SvTreeFlags::MANINS;
3787 
3788         thaw();
3789     }
3790 
3791     virtual void set_font_color(int pos, const Color& rColor) override
3792     {
3793         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3794         set_font_color(pEntry, rColor);
3795     }
3796 
3797     virtual void set_font_color(const weld::TreeIter& rIter, const Color& rColor) override
3798     {
3799         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3800         set_font_color(rVclIter.iter, rColor);
3801     }
3802 
3803     virtual void remove(int pos) override
3804     {
3805         disable_notify_events();
3806         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3807         m_xTreeView->RemoveEntry(pEntry);
3808         enable_notify_events();
3809     }
3810 
3811     virtual int find_text(const OUString& rText) const override
3812     {
3813         for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry;
3814              pEntry = m_xTreeView->Next(pEntry))
3815         {
3816             if (SvTabListBox::GetEntryText(pEntry, 0) == rText)
3817                 return SvTreeList::GetRelPos(pEntry);
3818         }
3819         return -1;
3820     }
3821 
3822     virtual int find_id(const OUString& rId) const override
3823     {
3824         for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry;
3825              pEntry = m_xTreeView->Next(pEntry))
3826         {
3827             const OUString* pId = static_cast<const OUString*>(pEntry->GetUserData());
3828             if (!pId)
3829                 continue;
3830             if (rId == *pId)
3831                 return SvTreeList::GetRelPos(pEntry);
3832         }
3833         return -1;
3834     }
3835 
3836     virtual void swap(int pos1, int pos2) override
3837     {
3838         int min = std::min(pos1, pos2);
3839         int max = std::max(pos1, pos2);
3840         SvTreeList* pModel = m_xTreeView->GetModel();
3841         SvTreeListEntry* pEntry1 = pModel->GetEntry(nullptr, min);
3842         SvTreeListEntry* pEntry2 = pModel->GetEntry(nullptr, max);
3843         pModel->Move(pEntry1, pEntry2);
3844     }
3845 
3846     virtual void clear() override
3847     {
3848         disable_notify_events();
3849         m_xTreeView->Clear();
3850         m_aUserData.clear();
3851         enable_notify_events();
3852     }
3853 
3854     virtual int n_children() const override
3855     {
3856         return m_xTreeView->GetModel()->GetChildList(nullptr).size();
3857     }
3858 
3859     virtual int iter_n_children(const weld::TreeIter& rIter) const override
3860     {
3861         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3862         return m_xTreeView->GetModel()->GetChildList(rVclIter.iter).size();
3863     }
3864 
3865     virtual void select(int pos) override
3866     {
3867         assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3868         disable_notify_events();
3869         if (pos == -1 || (pos == 0 && n_children() == 0))
3870             m_xTreeView->SelectAll(false);
3871         else
3872         {
3873             SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3874             m_xTreeView->Select(pEntry, true);
3875             m_xTreeView->MakeVisible(pEntry);
3876         }
3877         enable_notify_events();
3878     }
3879 
3880     virtual int get_cursor_index() const override
3881     {
3882         SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry();
3883         if (!pEntry)
3884             return -1;
3885         return SvTreeList::GetRelPos(pEntry);
3886     }
3887 
3888     virtual void set_cursor(int pos) override
3889     {
3890         disable_notify_events();
3891         if (pos == -1)
3892             m_xTreeView->SetCurEntry(nullptr);
3893         else
3894         {
3895             SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3896             m_xTreeView->SetCurEntry(pEntry);
3897         }
3898         enable_notify_events();
3899     }
3900 
3901     virtual void scroll_to_row(int pos) override
3902     {
3903         assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3904         disable_notify_events();
3905         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3906         m_xTreeView->MakeVisible(pEntry);
3907         enable_notify_events();
3908     }
3909 
3910     virtual bool is_selected(int pos) const override
3911     {
3912         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3913         return m_xTreeView->IsSelected(pEntry);
3914     }
3915 
3916     virtual void unselect(int pos) override
3917     {
3918         assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3919         disable_notify_events();
3920         if (pos == -1)
3921             m_xTreeView->SelectAll(true);
3922         else
3923         {
3924             SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3925             m_xTreeView->Select(pEntry, false);
3926         }
3927         enable_notify_events();
3928     }
3929 
3930     virtual std::vector<int> get_selected_rows() const override
3931     {
3932         std::vector<int> aRows;
3933 
3934         aRows.reserve(m_xTreeView->GetSelectionCount());
3935         for (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); pEntry;
3936              pEntry = m_xTreeView->NextSelected(pEntry))
3937             aRows.push_back(SvTreeList::GetRelPos(pEntry));
3938 
3939         return aRows;
3940     }
3941 
3942     OUString get_text(SvTreeListEntry* pEntry, int col) const
3943     {
3944         if (col == -1)
3945             return SvTabListBox::GetEntryText(pEntry, 0);
3946 
3947         col = to_internal_model(col);
3948 
3949         if (static_cast<size_t>(col) == pEntry->ItemCount())
3950             return OUString();
3951 
3952         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3953         SvLBoxItem& rItem = pEntry->GetItem(col);
3954         assert(dynamic_cast<SvLBoxString*>(&rItem));
3955         return static_cast<SvLBoxString&>(rItem).GetText();
3956     }
3957 
3958     virtual OUString get_text(int pos, int col) const override
3959     {
3960         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3961         return get_text(pEntry, col);
3962     }
3963 
3964     void set_text(SvTreeListEntry* pEntry, const OUString& rText, int col)
3965     {
3966         if (col == -1)
3967         {
3968             m_xTreeView->SetEntryText(pEntry, rText);
3969             return;
3970         }
3971 
3972         col = to_internal_model(col);
3973 
3974         // blank out missing entries
3975         for (int i = pEntry->ItemCount(); i < col; ++i)
3976             AddStringItem(pEntry, "", i - 1);
3977 
3978         if (static_cast<size_t>(col) == pEntry->ItemCount())
3979         {
3980             AddStringItem(pEntry, rText, col - 1);
3981             SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3982             m_xTreeView->InitViewData(pViewData, pEntry);
3983         }
3984         else
3985         {
3986             assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3987             SvLBoxItem& rItem = pEntry->GetItem(col);
3988             assert(dynamic_cast<SvLBoxString*>(&rItem));
3989             static_cast<SvLBoxString&>(rItem).SetText(rText);
3990         }
3991         m_xTreeView->ModelHasEntryInvalidated(pEntry);
3992     }
3993 
3994     virtual void set_text(int pos, const OUString& rText, int col) override
3995     {
3996         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3997         set_text(pEntry, rText, col);
3998     }
3999 
4000     void set_sensitive(SvTreeListEntry* pEntry, bool bSensitive, int col)
4001     {
4002         if (col == -1)
4003         {
4004             auto nFlags = pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT;
4005             if (!bSensitive)
4006                 nFlags = nFlags | SvTLEntryFlags::SEMITRANSPARENT;
4007             pEntry->SetFlags(nFlags);
4008             const sal_uInt16 nCount = pEntry->ItemCount();
4009             for (sal_uInt16 nCur = 0; nCur < nCount; ++nCur)
4010             {
4011                 SvLBoxItem& rItem = pEntry->GetItem(nCur);
4012                 if (rItem.GetType() == SvLBoxItemType::String)
4013                 {
4014                     rItem.Enable(bSensitive);
4015                     m_xTreeView->ModelHasEntryInvalidated(pEntry);
4016                     break;
4017                 }
4018             }
4019             return;
4020         }
4021 
4022         col = to_internal_model(col);
4023 
4024         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4025         SvLBoxItem& rItem = pEntry->GetItem(col);
4026         rItem.Enable(bSensitive);
4027 
4028         m_xTreeView->ModelHasEntryInvalidated(pEntry);
4029     }
4030 
4031     using SalInstanceWidget::set_sensitive;
4032 
4033     virtual void set_sensitive(int pos, bool bSensitive, int col) override
4034     {
4035         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4036         set_sensitive(pEntry, bSensitive, col);
4037     }
4038 
4039     virtual void set_sensitive(const weld::TreeIter& rIter, bool bSensitive, int col) override
4040     {
4041         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4042         set_sensitive(rVclIter.iter, bSensitive, col);
4043     }
4044 
4045     virtual TriState get_toggle(int pos, int col) const override
4046     {
4047         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4048         return get_toggle(pEntry, col);
4049     }
4050 
4051     virtual TriState get_toggle(const weld::TreeIter& rIter, int col) const override
4052     {
4053         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4054         return get_toggle(rVclIter.iter, col);
4055     }
4056 
4057     virtual void enable_toggle_buttons(weld::ColumnToggleType eType) override
4058     {
4059         assert(n_children() == 0 && "tree must be empty");
4060         m_bTogglesAsRadio = eType == weld::ColumnToggleType::Radio;
4061 
4062         SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
4063         m_xTreeView->EnableCheckButton(pData);
4064         // EnableCheckButton clobbered this, restore it
4065         pData->SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
4066     }
4067 
4068     virtual void set_toggle(int pos, TriState eState, int col) override
4069     {
4070         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4071         set_toggle(pEntry, eState, col);
4072     }
4073 
4074     virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override
4075     {
4076         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4077         set_toggle(rVclIter.iter, eState, col);
4078     }
4079 
4080     virtual void set_extra_row_indent(const weld::TreeIter& rIter, int nIndentLevel) override
4081     {
4082         weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
4083         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
4084         rVclIter.iter->SetExtraIndent(nIndentLevel);
4085     }
4086 
4087     void set_text_emphasis(SvTreeListEntry* pEntry, bool bOn, int col)
4088     {
4089         col = to_internal_model(col);
4090 
4091         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4092         SvLBoxItem& rItem = pEntry->GetItem(col);
4093         assert(dynamic_cast<SvLBoxString*>(&rItem));
4094         static_cast<SvLBoxString&>(rItem).Emphasize(bOn);
4095 
4096         m_xTreeView->ModelHasEntryInvalidated(pEntry);
4097     }
4098 
4099     virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override
4100     {
4101         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4102         set_text_emphasis(rVclIter.iter, bOn, col);
4103     }
4104 
4105     virtual void set_text_emphasis(int pos, bool bOn, int col) override
4106     {
4107         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4108         set_text_emphasis(pEntry, bOn, col);
4109     }
4110 
4111     virtual bool get_text_emphasis(const weld::TreeIter& rIter, int col) const override
4112     {
4113         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4114         return get_text_emphasis(rVclIter.iter, col);
4115     }
4116 
4117     virtual bool get_text_emphasis(int pos, int col) const override
4118     {
4119         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4120         return get_text_emphasis(pEntry, col);
4121     }
4122 
4123     void set_text_align(SvTreeListEntry* pEntry, double fAlign, int col)
4124     {
4125         col = to_internal_model(col);
4126 
4127         assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4128         SvLBoxItem& rItem = pEntry->GetItem(col);
4129         assert(dynamic_cast<SvLBoxString*>(&rItem));
4130         static_cast<SvLBoxString&>(rItem).Align(fAlign);
4131 
4132         m_xTreeView->ModelHasEntryInvalidated(pEntry);
4133     }
4134 
4135     virtual void set_text_align(const weld::TreeIter& rIter, double fAlign, int col) override
4136     {
4137         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4138         set_text_align(rVclIter.iter, fAlign, col);
4139     }
4140 
4141     virtual void set_text_align(int pos, double fAlign, int col) override
4142     {
4143         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4144         set_text_align(pEntry, fAlign, col);
4145     }
4146 
4147     virtual void connect_editing(
4148         const Link<const weld::TreeIter&, bool>& rStartLink,
4149         const Link<const iter_string&, bool>& rEndLink) override
4150     {
4151         m_xTreeView->EnableInplaceEditing(rStartLink.IsSet() || rEndLink.IsSet());
4152         weld::TreeView::connect_editing(rStartLink, rEndLink);
4153     }
4154 
4155     virtual void start_editing(const weld::TreeIter& rIter) override
4156     {
4157         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4158         m_xTreeView->EditEntry(rVclIter.iter);
4159     }
4160 
4161     virtual void end_editing() override { m_xTreeView->EndEditing(); }
4162 
4163     void set_image(SvTreeListEntry* pEntry, const Image& rImage, int col)
4164     {
4165         if (col == -1)
4166         {
4167             m_xTreeView->SetExpandedEntryBmp(pEntry, rImage);
4168             m_xTreeView->SetCollapsedEntryBmp(pEntry, rImage);
4169             return;
4170         }
4171 
4172         col = to_internal_model(col);
4173 
4174         // blank out missing entries
4175         for (int i = pEntry->ItemCount(); i < col; ++i)
4176             AddStringItem(pEntry, "", i - 1);
4177 
4178         if (static_cast<size_t>(col) == pEntry->ItemCount())
4179         {
4180             pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(rImage, rImage, false));
4181             SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
4182             m_xTreeView->InitViewData(pViewData, pEntry);
4183         }
4184         else
4185         {
4186             assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4187             SvLBoxItem& rItem = pEntry->GetItem(col);
4188             assert(dynamic_cast<SvLBoxContextBmp*>(&rItem));
4189             static_cast<SvLBoxContextBmp&>(rItem).SetBitmap1(rImage);
4190             static_cast<SvLBoxContextBmp&>(rItem).SetBitmap2(rImage);
4191         }
4192 
4193         m_xTreeView->SetEntryHeight(pEntry);
4194         m_xTreeView->ModelHasEntryInvalidated(pEntry);
4195     }
4196 
4197     virtual void set_image(int pos, const OUString& rImage, int col) override
4198     {
4199         set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col);
4200     }
4201 
4202     virtual void set_image(int pos, const css::uno::Reference<css::graphic::XGraphic>& rImage,
4203                            int col) override
4204     {
4205         set_image(m_xTreeView->GetEntry(nullptr, pos), Image(rImage), col);
4206     }
4207 
4208     virtual void set_image(int pos, VirtualDevice& rImage, int col) override
4209     {
4210         set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col);
4211     }
4212 
4213     virtual void set_image(const weld::TreeIter& rIter, const OUString& rImage, int col) override
4214     {
4215         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4216         set_image(rVclIter.iter, createImage(rImage), col);
4217     }
4218 
4219     virtual void set_image(const weld::TreeIter& rIter,
4220                            const css::uno::Reference<css::graphic::XGraphic>& rImage,
4221                            int col) override
4222     {
4223         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4224         set_image(rVclIter.iter, Image(rImage), col);
4225     }
4226 
4227     virtual void set_image(const weld::TreeIter& rIter, VirtualDevice& rImage, int col) override
4228     {
4229         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4230         set_image(rVclIter.iter, createImage(rImage), col);
4231     }
4232 
4233     const OUString* getEntryData(int index) const
4234     {
4235         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, index);
4236         return pEntry ? static_cast<const OUString*>(pEntry->GetUserData()) : nullptr;
4237     }
4238 
4239     virtual OUString get_id(int pos) const override
4240     {
4241         const OUString* pRet = getEntryData(pos);
4242         if (!pRet)
4243             return OUString();
4244         return *pRet;
4245     }
4246 
4247     void set_id(SvTreeListEntry* pEntry, const OUString& rId)
4248     {
4249         m_aUserData.emplace_back(std::make_unique<OUString>(rId));
4250         pEntry->SetUserData(m_aUserData.back().get());
4251     }
4252 
4253     virtual void set_id(int pos, const OUString& rId) override
4254     {
4255         SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4256         set_id(pEntry, rId);
4257     }
4258 
4259     virtual int get_selected_index() const override
4260     {
4261         assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4262         SvTreeListEntry* pEntry = m_xTreeView->FirstSelected();
4263         if (!pEntry)
4264             return -1;
4265         return SvTreeList::GetRelPos(pEntry);
4266     }
4267 
4268     virtual OUString get_selected_text() const override
4269     {
4270         assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4271         if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected())
4272             return m_xTreeView->GetEntryText(pEntry);
4273         return OUString();
4274     }
4275 
4276     virtual OUString get_selected_id() const override
4277     {
4278         assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4279         if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected())
4280         {
4281             if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData()))
4282                 return *pStr;
4283         }
4284         return OUString();
4285     }
4286 
4287     virtual std::unique_ptr<weld::TreeIter>
4288     make_iterator(const weld::TreeIter* pOrig) const override
4289     {
4290         return std::unique_ptr<weld::TreeIter>(
4291             new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig)));
4292     }
4293 
4294     virtual void copy_iterator(const weld::TreeIter& rSource, weld::TreeIter& rDest) const override
4295     {
4296         const SalInstanceTreeIter& rVclSource(static_cast<const SalInstanceTreeIter&>(rSource));
4297         SalInstanceTreeIter& rVclDest(static_cast<SalInstanceTreeIter&>(rDest));
4298         rVclDest.iter = rVclSource.iter;
4299     }
4300 
4301     virtual bool get_selected(weld::TreeIter* pIter) const override
4302     {
4303         SvTreeListEntry* pEntry = m_xTreeView->FirstSelected();
4304         auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4305         if (pVclIter)
4306             pVclIter->iter = pEntry;
4307         return pEntry != nullptr;
4308     }
4309 
4310     virtual bool get_cursor(weld::TreeIter* pIter) const override
4311     {
4312         SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry();
4313         auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4314         if (pVclIter)
4315             pVclIter->iter = pEntry;
4316         return pEntry != nullptr;
4317     }
4318 
4319     virtual void set_cursor(const weld::TreeIter& rIter) override
4320     {
4321         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4322         disable_notify_events();
4323         m_xTreeView->SetCurEntry(rVclIter.iter);
4324         enable_notify_events();
4325     }
4326 
4327     virtual bool get_iter_first(weld::TreeIter& rIter) const override
4328     {
4329         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4330         rVclIter.iter = m_xTreeView->GetEntry(0);
4331         return rVclIter.iter != nullptr;
4332     }
4333 
4334     virtual bool iter_next_sibling(weld::TreeIter& rIter) const override
4335     {
4336         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4337         rVclIter.iter = rVclIter.iter->NextSibling();
4338         return rVclIter.iter != nullptr;
4339     }
4340 
4341     virtual bool iter_previous_sibling(weld::TreeIter& rIter) const override
4342     {
4343         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4344         rVclIter.iter = rVclIter.iter->PrevSibling();
4345         return rVclIter.iter != nullptr;
4346     }
4347 
4348     virtual bool iter_next(weld::TreeIter& rIter) const override
4349     {
4350         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4351         rVclIter.iter = m_xTreeView->Next(rVclIter.iter);
4352         if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4353             return iter_next(rVclIter);
4354         return rVclIter.iter != nullptr;
4355     }
4356 
4357     virtual bool iter_previous(weld::TreeIter& rIter) const override
4358     {
4359         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4360         rVclIter.iter = m_xTreeView->Prev(rVclIter.iter);
4361         if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4362             return iter_previous(rVclIter);
4363         return rVclIter.iter != nullptr;
4364     }
4365 
4366     virtual bool iter_next_visible(weld::TreeIter& rIter) const override
4367     {
4368         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4369         rVclIter.iter = m_xTreeView->NextVisible(rVclIter.iter);
4370         if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4371             return iter_next_visible(rVclIter);
4372         return rVclIter.iter != nullptr;
4373     }
4374 
4375     virtual bool iter_children(weld::TreeIter& rIter) const override
4376     {
4377         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4378         rVclIter.iter = m_xTreeView->FirstChild(rVclIter.iter);
4379         bool bRet = rVclIter.iter != nullptr;
4380         if (bRet)
4381         {
4382             //on-demand dummy entry doesn't count
4383             return !IsDummyEntry(rVclIter.iter);
4384         }
4385         return bRet;
4386     }
4387 
4388     virtual bool iter_parent(weld::TreeIter& rIter) const override
4389     {
4390         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4391         rVclIter.iter = m_xTreeView->GetParent(rVclIter.iter);
4392         return rVclIter.iter != nullptr;
4393     }
4394 
4395     virtual void remove(const weld::TreeIter& rIter) override
4396     {
4397         disable_notify_events();
4398         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4399         m_xTreeView->RemoveEntry(rVclIter.iter);
4400         enable_notify_events();
4401     }
4402 
4403     virtual void select(const weld::TreeIter& rIter) override
4404     {
4405         assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4406         disable_notify_events();
4407         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4408         m_xTreeView->Select(rVclIter.iter, true);
4409         enable_notify_events();
4410     }
4411 
4412     virtual void scroll_to_row(const weld::TreeIter& rIter) override
4413     {
4414         assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4415         disable_notify_events();
4416         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4417         m_xTreeView->MakeVisible(rVclIter.iter);
4418         enable_notify_events();
4419     }
4420 
4421     virtual void unselect(const weld::TreeIter& rIter) override
4422     {
4423         assert(m_xTreeView->IsUpdateMode() && "don't unselect when frozen");
4424         disable_notify_events();
4425         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4426         m_xTreeView->Select(rVclIter.iter, false);
4427         enable_notify_events();
4428     }
4429 
4430     virtual int get_iter_depth(const weld::TreeIter& rIter) const override
4431     {
4432         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4433         return m_xTreeView->GetModel()->GetDepth(rVclIter.iter);
4434     }
4435 
4436     virtual bool iter_has_child(const weld::TreeIter& rIter) const override
4437     {
4438         weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
4439         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
4440         SvTreeListEntry* restore(rVclIter.iter);
4441         bool ret = iter_children(rNonConstIter);
4442         rVclIter.iter = restore;
4443         return ret;
4444     }
4445 
4446     virtual bool get_row_expanded(const weld::TreeIter& rIter) const override
4447     {
4448         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4449         return m_xTreeView->IsExpanded(rVclIter.iter);
4450     }
4451 
4452     virtual bool get_children_on_demand(const weld::TreeIter& rIter) const override
4453     {
4454         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4455         if (m_aExpandingPlaceHolderParents.count(rVclIter.iter))
4456             return true;
4457         return GetPlaceHolderChild(rVclIter.iter) != nullptr;
4458     }
4459 
4460     virtual void set_children_on_demand(const weld::TreeIter& rIter, bool bChildrenOnDemand) override
4461     {
4462         disable_notify_events();
4463 
4464         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4465 
4466         SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(rVclIter.iter);
4467 
4468         if (bChildrenOnDemand && !pPlaceHolder)
4469         {
4470             pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", rVclIter.iter, false, 0, nullptr);
4471             SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
4472             pViewData->SetSelectable(false);
4473         }
4474         else if (!bChildrenOnDemand && pPlaceHolder)
4475             m_xTreeView->RemoveEntry(pPlaceHolder);
4476 
4477         enable_notify_events();
4478     }
4479 
4480     virtual void expand_row(const weld::TreeIter& rIter) override
4481     {
4482         assert(m_xTreeView->IsUpdateMode() && "don't expand when frozen");
4483         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4484         if (!m_xTreeView->IsExpanded(rVclIter.iter) && signal_expanding(rIter))
4485             m_xTreeView->Expand(rVclIter.iter);
4486     }
4487 
4488     virtual void collapse_row(const weld::TreeIter& rIter) override
4489     {
4490         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4491         if (m_xTreeView->IsExpanded(rVclIter.iter) && signal_collapsing(rIter))
4492             m_xTreeView->Collapse(rVclIter.iter);
4493     }
4494 
4495     virtual OUString get_text(const weld::TreeIter& rIter, int col) const override
4496     {
4497         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4498         return get_text(rVclIter.iter, col);
4499     }
4500 
4501     virtual void set_text(const weld::TreeIter& rIter, const OUString& rText, int col) override
4502     {
4503         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4504         set_text(rVclIter.iter, rText, col);
4505     }
4506 
4507     virtual OUString get_id(const weld::TreeIter& rIter) const override
4508     {
4509         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4510         const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData());
4511         if (pStr)
4512             return *pStr;
4513         return OUString();
4514     }
4515 
4516     virtual void set_id(const weld::TreeIter& rIter, const OUString& rId) override
4517     {
4518         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4519         set_id(rVclIter.iter, rId);
4520     }
4521 
4522     virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper,
4523                                     sal_uInt8 eDNDConstants) override
4524     {
4525         m_xTreeView->SetDragHelper(rHelper, eDNDConstants);
4526     }
4527 
4528     virtual void set_selection_mode(SelectionMode eMode) override
4529     {
4530         m_xTreeView->SetSelectionMode(eMode);
4531     }
4532 
4533     virtual void all_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4534     {
4535         SalInstanceTreeIter aVclIter(m_xTreeView->First());
4536         while (aVclIter.iter)
4537         {
4538             if (func(aVclIter))
4539                 return;
4540             iter_next(aVclIter);
4541         }
4542     }
4543 
4544     virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4545     {
4546         SalInstanceTreeIter aVclIter(m_xTreeView->FirstSelected());
4547         while (aVclIter.iter)
4548         {
4549             if (func(aVclIter))
4550                 return;
4551             aVclIter.iter = m_xTreeView->NextSelected(aVclIter.iter);
4552         }
4553     }
4554 
4555     virtual void visible_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4556     {
4557         SalInstanceTreeIter aVclIter(m_xTreeView->GetFirstEntryInView());
4558         while (aVclIter.iter)
4559         {
4560             if (func(aVclIter))
4561                 return;
4562             aVclIter.iter = m_xTreeView->GetNextEntryInView(aVclIter.iter);
4563         }
4564     }
4565 
4566     virtual void connect_visible_range_changed(const Link<weld::TreeView&, void>& rLink) override
4567     {
4568         weld::TreeView::connect_visible_range_changed(rLink);
4569         m_xTreeView->SetScrolledHdl(LINK(this, SalInstanceTreeView, VisibleRangeChangedHdl));
4570     }
4571 
4572     virtual void remove_selection() override
4573     {
4574         disable_notify_events();
4575         SvTreeListEntry* pSelected = m_xTreeView->FirstSelected();
4576         while (pSelected)
4577         {
4578             SvTreeListEntry* pNextSelected = m_xTreeView->NextSelected(pSelected);
4579             m_xTreeView->RemoveEntry(pSelected);
4580             pSelected = pNextSelected;
4581         }
4582         enable_notify_events();
4583     }
4584 
4585     virtual bool is_selected(const weld::TreeIter& rIter) const override
4586     {
4587         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4588         return m_xTreeView->IsSelected(rVclIter.iter);
4589     }
4590 
4591     virtual int get_iter_index_in_parent(const weld::TreeIter& rIter) const override
4592     {
4593         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4594         return SvTreeList::GetRelPos(rVclIter.iter);
4595     }
4596 
4597     virtual int iter_compare(const weld::TreeIter& a, const weld::TreeIter& b) const override
4598     {
4599         const SalInstanceTreeIter& rVclIterA = static_cast<const SalInstanceTreeIter&>(a);
4600         const SalInstanceTreeIter& rVclIterB = static_cast<const SalInstanceTreeIter&>(b);
4601         const SvTreeList* pModel = m_xTreeView->GetModel();
4602         auto nAbsPosA = pModel->GetAbsPos(rVclIterA.iter);
4603         auto nAbsPosB = pModel->GetAbsPos(rVclIterB.iter);
4604         if (nAbsPosA < nAbsPosB)
4605             return -1;
4606         if (nAbsPosA > nAbsPosB)
4607             return 1;
4608         return 0;
4609     }
4610 
4611     virtual void move_subtree(weld::TreeIter& rNode, const weld::TreeIter* pNewParent,
4612                               int nIndexInNewParent) override
4613     {
4614         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNode);
4615         const SalInstanceTreeIter* pVclParentIter
4616             = static_cast<const SalInstanceTreeIter*>(pNewParent);
4617         m_xTreeView->GetModel()->Move(
4618             rVclIter.iter, pVclParentIter ? pVclParentIter->iter : nullptr, nIndexInNewParent);
4619     }
4620 
4621     virtual int count_selected_rows() const override { return m_xTreeView->GetSelectionCount(); }
4622 
4623     virtual int get_height_rows(int nRows) const override
4624     {
4625         return m_xTreeView->GetEntryHeight() * nRows;
4626     }
4627 
4628     virtual void make_sorted() override
4629     {
4630         assert(m_xTreeView->IsUpdateMode() && "don't sort when frozen");
4631         m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT);
4632         m_xTreeView->GetModel()->SetCompareHdl(LINK(this, SalInstanceTreeView, CompareHdl));
4633         set_sort_order(true);
4634     }
4635 
4636     virtual void set_sort_func(
4637         const std::function<int(const weld::TreeIter&, const weld::TreeIter&)>& func) override
4638     {
4639         weld::TreeView::set_sort_func(func);
4640         SvTreeList* pListModel = m_xTreeView->GetModel();
4641         pListModel->Resort();
4642     }
4643 
4644     virtual void make_unsorted() override
4645     {
4646         m_xTreeView->SetStyle(m_xTreeView->GetStyle() & ~WB_SORT);
4647     }
4648 
4649     virtual void set_sort_order(bool bAscending) override
4650     {
4651         SvTreeList* pListModel = m_xTreeView->GetModel();
4652         pListModel->SetSortMode(bAscending ? SortAscending : SortDescending);
4653         pListModel->Resort();
4654     }
4655 
4656     virtual bool get_sort_order() const override
4657     {
4658         return m_xTreeView->GetModel()->GetSortMode() == SortAscending;
4659     }
4660 
4661     virtual void set_sort_indicator(TriState eState, int col) override
4662     {
4663         assert(col >= 0 && "cannot sort on expander column");
4664 
4665         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4666         HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr;
4667         if (!pHeaderBar)
4668             return;
4669 
4670         sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
4671         HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
4672         nBits &= ~HeaderBarItemBits::UPARROW;
4673         nBits &= ~HeaderBarItemBits::DOWNARROW;
4674         if (eState != TRISTATE_INDET)
4675         {
4676             if (eState == TRISTATE_TRUE)
4677                 nBits |= HeaderBarItemBits::DOWNARROW;
4678             else
4679                 nBits |= HeaderBarItemBits::UPARROW;
4680         }
4681         pHeaderBar->SetItemBits(nTextId, nBits);
4682     }
4683 
4684     virtual TriState get_sort_indicator(int col) const override
4685     {
4686         assert(col >= 0 && "cannot sort on expander column");
4687 
4688         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4689         if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
4690         {
4691             sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
4692             HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
4693             if (nBits & HeaderBarItemBits::DOWNARROW)
4694                 return TRISTATE_TRUE;
4695             if (nBits & HeaderBarItemBits::UPARROW)
4696                 return TRISTATE_FALSE;
4697         }
4698 
4699         return TRISTATE_INDET;
4700     }
4701 
4702     virtual int get_sort_column() const override { return m_nSortColumn; }
4703 
4704     virtual void set_sort_column(int nColumn) override
4705     {
4706         if (nColumn == -1)
4707         {
4708             make_unsorted();
4709             m_nSortColumn = -1;
4710             return;
4711         }
4712 
4713         if (nColumn != m_nSortColumn)
4714         {
4715             m_nSortColumn = nColumn;
4716             m_xTreeView->GetModel()->Resort();
4717         }
4718     }
4719 
4720     SvTabListBox& getTreeView() { return *m_xTreeView; }
4721 
4722     virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode) override
4723     {
4724         LclTabListBox* pTreeView = !bDnDMode ? dynamic_cast<LclTabListBox*>(m_xTreeView.get()) : nullptr;
4725         SvTreeListEntry* pTarget = pTreeView ? pTreeView->GetTargetAtPoint(rPos, false) : m_xTreeView->GetDropTarget(rPos);
4726 
4727         if (pTarget && pResult)
4728         {
4729             SalInstanceTreeIter& rSalIter = static_cast<SalInstanceTreeIter&>(*pResult);
4730             rSalIter.iter = pTarget;
4731         }
4732 
4733         return pTarget != nullptr;
4734     }
4735 
4736     virtual void unset_drag_dest_row() override
4737     {
4738         m_xTreeView->UnsetDropTarget();
4739     }
4740 
4741     virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const override
4742     {
4743         return m_xTreeView->GetBoundingRect(static_cast<const SalInstanceTreeIter&>(rIter).iter);
4744     }
4745 
4746     virtual TreeView* get_drag_source() const override { return g_DragSource; }
4747 
4748     virtual int vadjustment_get_value() const override
4749     {
4750         int nValue = -1;
4751         const SvTreeListEntry* pEntry = m_xTreeView->GetFirstEntryInView();
4752         if (pEntry)
4753             nValue = m_xTreeView->GetAbsPos(pEntry);
4754         return nValue;
4755     }
4756 
4757     virtual void vadjustment_set_value(int nValue) override
4758     {
4759         if (nValue == -1)
4760             return;
4761         bool bUpdate = m_xTreeView->IsUpdateMode();
4762         if (bUpdate)
4763             m_xTreeView->SetUpdateMode(false);
4764         m_xTreeView->ScrollToAbsPos(nValue);
4765         if (bUpdate)
4766             m_xTreeView->SetUpdateMode(true);
4767     }
4768 
4769     void set_show_expanders(bool bShow) override
4770     {
4771         m_xTreeView->set_property("show-expanders", OUString::boolean(bShow));
4772     }
4773 
4774     virtual ~SalInstanceTreeView() override
4775     {
4776         LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4777         if (pHeaderBox)
4778         {
4779             if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
4780             {
4781                 pHeaderBar->SetSelectHdl(Link<HeaderBar*, void>());
4782                 pHeaderBar->SetEndDragHdl(Link<HeaderBar*, void>());
4783             }
4784         }
4785         else
4786         {
4787             static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>());
4788             static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, bool>());
4789             static_cast<LclTabListBox&>(*m_xTreeView)
4790                 .SetModelChangedHdl(Link<SvTreeListBox*, void>());
4791         }
4792         m_xTreeView->SetPopupMenuHdl(Link<const CommandEvent&, bool>());
4793         m_xTreeView->SetExpandingHdl(Link<SvTreeListBox*, bool>());
4794         m_xTreeView->SetDoubleClickHdl(Link<SvTreeListBox*, bool>());
4795         m_xTreeView->SetSelectHdl(Link<SvTreeListBox*, void>());
4796         m_xTreeView->SetDeselectHdl(Link<SvTreeListBox*, void>());
4797         m_xTreeView->SetScrolledHdl(Link<SvTreeListBox*, void>());
4798         m_xTreeView->SetTooltipHdl(Link<const HelpEvent&, bool>());
4799         m_xTreeView->SetCustomRenderHdl(Link<svtree_render_args, void>());
4800         m_xTreeView->SetCustomMeasureHdl(Link<svtree_measure_args, Size>());
4801     }
4802 };
4803 
4804 IMPL_LINK(SalInstanceTreeView, TooltipHdl, const HelpEvent&, rHEvt, bool)
4805 {
4806     if (notify_events_disabled())
4807         return false;
4808     Point aPos(m_xTreeView->ScreenToOutputPixel(rHEvt.GetMousePosPixel()));
4809     SvTreeListEntry* pEntry = m_xTreeView->GetEntry(aPos);
4810     if (pEntry)
4811     {
4812         SalInstanceTreeIter aIter(pEntry);
4813         OUString aTooltip = signal_query_tooltip(aIter);
4814         if (aTooltip.isEmpty())
4815             return false;
4816         Size aSize(m_xTreeView->GetOutputSizePixel().Width(), m_xTreeView->GetEntryHeight());
4817         tools::Rectangle aScreenRect(
4818             m_xTreeView->OutputToScreenPixel(m_xTreeView->GetEntryPosition(pEntry)), aSize);
4819         Help::ShowQuickHelp(m_xTreeView, aScreenRect, aTooltip);
4820     }
4821     return true;
4822 }
4823 
4824 IMPL_LINK(SalInstanceTreeView, CustomRenderHdl, svtree_render_args, payload, void)
4825 {
4826     vcl::RenderContext& rRenderDevice = std::get<0>(payload);
4827     const tools::Rectangle& rRect = std::get<1>(payload);
4828     const SvTreeListEntry& rEntry = std::get<2>(payload);
4829     const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData());
4830     if (!pId)
4831         return;
4832     signal_custom_render(rRenderDevice, rRect, m_xTreeView->IsSelected(&rEntry), *pId);
4833 }
4834 
4835 IMPL_LINK(SalInstanceTreeView, CustomMeasureHdl, svtree_measure_args, payload, Size)
4836 {
4837     vcl::RenderContext& rRenderDevice = payload.first;
4838     const SvTreeListEntry& rEntry = payload.second;
4839     const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData());
4840     if (!pId)
4841         return Size();
4842     return signal_custom_get_size(rRenderDevice, *pId);
4843 }
4844 
4845 IMPL_LINK(SalInstanceTreeView, CompareHdl, const SvSortData&, rSortData, sal_Int32)
4846 {
4847     const SvTreeListEntry* pLHS = rSortData.pLeft;
4848     const SvTreeListEntry* pRHS = rSortData.pRight;
4849     assert(pLHS && pRHS);
4850 
4851     if (m_aCustomSort)
4852         return m_aCustomSort(SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pLHS)),
4853                              SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pRHS)));
4854 
4855     const SvLBoxString* pLeftTextItem;
4856     const SvLBoxString* pRightTextItem;
4857 
4858     if (m_nSortColumn != -1)
4859     {
4860         size_t col = to_internal_model(m_nSortColumn);
4861 
4862         if (col < pLHS->ItemCount())
4863         {
4864             const SvLBoxString& rLeftTextItem
4865                 = static_cast<const SvLBoxString&>(pLHS->GetItem(col));
4866             pLeftTextItem = &rLeftTextItem;
4867         }
4868         else
4869             pLeftTextItem = nullptr;
4870         if (col < pRHS->ItemCount())
4871         {
4872             const SvLBoxString& rRightTextItem
4873                 = static_cast<const SvLBoxString&>(pRHS->GetItem(col));
4874             pRightTextItem = &rRightTextItem;
4875         }
4876         else
4877             pRightTextItem = nullptr;
4878     }
4879     else
4880     {
4881         pLeftTextItem
4882             = static_cast<const SvLBoxString*>(pLHS->GetFirstItem(SvLBoxItemType::String));
4883         pRightTextItem
4884             = static_cast<const SvLBoxString*>(pRHS->GetFirstItem(SvLBoxItemType::String));
4885     }
4886 
4887     return m_xTreeView->DefaultCompare(pLeftTextItem, pRightTextItem);
4888 }
4889 
4890 IMPL_LINK_NOARG(SalInstanceTreeView, VisibleRangeChangedHdl, SvTreeListBox*, void)
4891 {
4892     if (notify_events_disabled())
4893         return;
4894     signal_visible_range_changed();
4895 }
4896 
4897 IMPL_LINK_NOARG(SalInstanceTreeView, ModelChangedHdl, SvTreeListBox*, void)
4898 {
4899     if (notify_events_disabled())
4900         return;
4901     signal_model_changed();
4902 }
4903 
4904 IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, bool)
4905 {
4906     bool bUnsetDragIcon(false); // ignored for vcl
4907     if (m_aDragBeginHdl.Call(bUnsetDragIcon))
4908         return true;
4909     g_DragSource = this;
4910     return false;
4911 }
4912 
4913 IMPL_STATIC_LINK_NOARG(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void)
4914 {
4915     g_DragSource = nullptr;
4916 }
4917 
4918 IMPL_LINK(SalInstanceTreeView, ToggleHdl, SvLBoxButtonData*, pData, void)
4919 {
4920     SvTreeListEntry* pEntry = pData->GetActEntry();
4921     SvLBoxButton* pBox = pData->GetActBox();
4922 
4923     // tdf#122874 Select the row, calling SelectHdl, before handling
4924     // the toggle
4925     if (!m_xTreeView->IsSelected(pEntry))
4926     {
4927         m_xTreeView->SelectAll(false);
4928         m_xTreeView->Select(pEntry, true);
4929     }
4930 
4931     // additionally set the cursor into the row the toggled element is in
4932     m_xTreeView->pImpl->m_pCursor = pEntry;
4933 
4934     for (int i = 0, nCount = pEntry->ItemCount(); i < nCount; ++i)
4935     {
4936         SvLBoxItem& rItem = pEntry->GetItem(i);
4937         if (&rItem == pBox)
4938         {
4939             int nCol = to_external_model(i);
4940             signal_toggled(iter_col(SalInstanceTreeIter(pEntry), nCol));
4941             break;
4942         }
4943     }
4944 }
4945 
4946 IMPL_LINK_NOARG(SalInstanceTreeView, SelectHdl, SvTreeListBox*, void)
4947 {
4948     if (notify_events_disabled())
4949         return;
4950     signal_changed();
4951 }
4952 
4953 IMPL_LINK_NOARG(SalInstanceTreeView, DeSelectHdl, SvTreeListBox*, void)
4954 {
4955     if (notify_events_disabled())
4956         return;
4957     if (m_xTreeView->GetSelectionMode() == SelectionMode::Single && !m_xTreeView->GetHoverSelection())
4958         return;
4959     signal_changed();
4960 }
4961 
4962 IMPL_LINK_NOARG(SalInstanceTreeView, DoubleClickHdl, SvTreeListBox*, bool)
4963 {
4964     if (notify_events_disabled())
4965         return false;
4966     return !signal_row_activated();
4967 }
4968 
4969 IMPL_LINK(SalInstanceTreeView, EndDragHdl, HeaderBar*, pHeaderBar, void)
4970 {
4971     std::vector<long> aTabPositions;
4972     aTabPositions.push_back(0);
4973     for (int i = 0; i < pHeaderBar->GetItemCount() - 1; ++i)
4974         aTabPositions.push_back(aTabPositions[i]
4975                                 + pHeaderBar->GetItemSize(pHeaderBar->GetItemId(i)));
4976     m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
4977 }
4978 
4979 IMPL_LINK(SalInstanceTreeView, HeaderBarClickedHdl, HeaderBar*, pHeaderBar, void)
4980 {
4981     sal_uInt16 nId = pHeaderBar->GetCurItemId();
4982     if (!(pHeaderBar->GetItemBits(nId) & HeaderBarItemBits::CLICKABLE))
4983         return;
4984     signal_column_clicked(pHeaderBar->GetItemPos(nId));
4985 }
4986 
4987 IMPL_LINK_NOARG(SalInstanceTreeView, ExpandingHdl, SvTreeListBox*, bool)
4988 {
4989     SvTreeListEntry* pEntry = m_xTreeView->GetHdlEntry();
4990     SalInstanceTreeIter aIter(pEntry);
4991 
4992     if (m_xTreeView->IsExpanded(pEntry))
4993     {
4994         //collapsing;
4995         return signal_collapsing(aIter);
4996     }
4997 
4998     // expanding
4999 
5000     // if there's a preexisting placeholder child, required to make this
5001     // potentially expandable in the first place, now we remove it
5002     SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(pEntry);
5003     if (pPlaceHolder)
5004     {
5005         m_aExpandingPlaceHolderParents.insert(pEntry);
5006         m_xTreeView->RemoveEntry(pPlaceHolder);
5007     }
5008 
5009     bool bRet = signal_expanding(aIter);
5010 
5011     if (pPlaceHolder)
5012     {
5013         //expand disallowed, restore placeholder
5014         if (!bRet)
5015         {
5016             pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
5017             SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
5018             pViewData->SetSelectable(false);
5019         }
5020         m_aExpandingPlaceHolderParents.erase(pEntry);
5021     }
5022 
5023     return bRet;
5024 }
5025 
5026 IMPL_LINK(SalInstanceTreeView, PopupMenuHdl, const CommandEvent&, rEvent, bool)
5027 {
5028     return m_aPopupMenuHdl.Call(rEvent);
5029 }
5030 
5031 IMPL_LINK(SalInstanceTreeView, EditingEntryHdl, SvTreeListEntry*, pEntry, bool)
5032 {
5033     return signal_editing_started(SalInstanceTreeIter(pEntry));
5034 }
5035 
5036 IMPL_LINK(SalInstanceTreeView, EditedEntryHdl, IterString, rIterString, bool)
5037 {
5038     return signal_editing_done(iter_string(
5039         SalInstanceTreeIter(rIterString.first), rIterString.second));
5040 }
5041 
5042 class SalInstanceIconView : public SalInstanceContainer, public virtual weld::IconView
5043 {
5044 private:
5045     // owner for UserData
5046     std::vector<std::unique_ptr<OUString>> m_aUserData;
5047     VclPtr<::IconView> m_xIconView;
5048 
5049     DECL_LINK(SelectHdl, SvTreeListBox*, void);
5050     DECL_LINK(DeSelectHdl, SvTreeListBox*, void);
5051     DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
5052 
5053 public:
5054     SalInstanceIconView(::IconView* pIconView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
5055         : SalInstanceContainer(pIconView, pBuilder, bTakeOwnership)
5056         , m_xIconView(pIconView)
5057     {
5058         m_xIconView->SetSelectHdl(LINK(this, SalInstanceIconView, SelectHdl));
5059         m_xIconView->SetDeselectHdl(LINK(this, SalInstanceIconView, DeSelectHdl));
5060         m_xIconView->SetDoubleClickHdl(LINK(this, SalInstanceIconView, DoubleClickHdl));
5061     }
5062 
5063     virtual void freeze() override
5064     {
5065         SalInstanceWidget::freeze();
5066         m_xIconView->SetUpdateMode(false);
5067     }
5068 
5069     virtual void thaw() override
5070     {
5071         m_xIconView->SetUpdateMode(true);
5072         SalInstanceWidget::thaw();
5073     }
5074 
5075     virtual void insert(int pos, const OUString* pStr, const OUString* pId,
5076                         const OUString* pIconName, weld::TreeIter* pRet) override
5077     {
5078         disable_notify_events();
5079         auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
5080         void* pUserData;
5081         if (pId)
5082         {
5083             m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
5084             pUserData = m_aUserData.back().get();
5085         }
5086         else
5087             pUserData = nullptr;
5088 
5089         SvTreeListEntry* pEntry = new SvTreeListEntry;
5090         if (pIconName)
5091         {
5092             Image aImage(createImage(*pIconName));
5093             pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
5094         }
5095         else
5096         {
5097             Image aDummy;
5098             pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
5099         }
5100         if (pStr)
5101             pEntry->AddItem(std::make_unique<SvLBoxString>(*pStr));
5102         pEntry->SetUserData(pUserData);
5103         m_xIconView->Insert(pEntry, nullptr, nInsertPos);
5104 
5105         if (pRet)
5106         {
5107             SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
5108             pVclRetIter->iter = pEntry;
5109         }
5110 
5111         enable_notify_events();
5112     }
5113 
5114     virtual OUString get_selected_id() const override
5115     {
5116         assert(m_xIconView->IsUpdateMode() && "don't request selection when frozen");
5117         if (SvTreeListEntry* pEntry = m_xIconView->FirstSelected())
5118         {
5119             if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData()))
5120                 return *pStr;
5121         }
5122         return OUString();
5123     }
5124 
5125     virtual OUString get_selected_text() const override
5126     {
5127         assert(m_xIconView->IsUpdateMode() && "don't request selection when frozen");
5128         if (SvTreeListEntry* pEntry = m_xIconView->FirstSelected())
5129             return m_xIconView->GetEntryText(pEntry);
5130         return OUString();
5131     }
5132 
5133     virtual int count_selected_items() const override { return m_xIconView->GetSelectionCount(); }
5134 
5135     virtual void select(int pos) override
5136     {
5137         assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
5138         disable_notify_events();
5139         if (pos == -1 || (pos == 0 && n_children() == 0))
5140             m_xIconView->SelectAll(false);
5141         else
5142         {
5143             SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos);
5144             m_xIconView->Select(pEntry, true);
5145             m_xIconView->MakeVisible(pEntry);
5146         }
5147         enable_notify_events();
5148     }
5149 
5150     virtual void unselect(int pos) override
5151     {
5152         assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
5153         disable_notify_events();
5154         if (pos == -1)
5155             m_xIconView->SelectAll(true);
5156         else
5157         {
5158             SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos);
5159             m_xIconView->Select(pEntry, false);
5160         }
5161         enable_notify_events();
5162     }
5163 
5164     virtual int n_children() const override
5165     {
5166         return m_xIconView->GetModel()->GetChildList(nullptr).size();
5167     }
5168 
5169     virtual std::unique_ptr<weld::TreeIter>
5170     make_iterator(const weld::TreeIter* pOrig) const override
5171     {
5172         return std::unique_ptr<weld::TreeIter>(
5173             new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig)));
5174     }
5175 
5176     virtual bool get_selected(weld::TreeIter* pIter) const override
5177     {
5178         SvTreeListEntry* pEntry = m_xIconView->FirstSelected();
5179         auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
5180         if (pVclIter)
5181             pVclIter->iter = pEntry;
5182         return pEntry != nullptr;
5183     }
5184 
5185     virtual bool get_cursor(weld::TreeIter* pIter) const override
5186     {
5187         SvTreeListEntry* pEntry = m_xIconView->GetCurEntry();
5188         auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
5189         if (pVclIter)
5190             pVclIter->iter = pEntry;
5191         return pEntry != nullptr;
5192     }
5193 
5194     virtual void set_cursor(const weld::TreeIter& rIter) override
5195     {
5196         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
5197         disable_notify_events();
5198         m_xIconView->SetCurEntry(rVclIter.iter);
5199         enable_notify_events();
5200     }
5201 
5202     virtual bool get_iter_first(weld::TreeIter& rIter) const override
5203     {
5204         SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
5205         rVclIter.iter = m_xIconView->GetEntry(0);
5206         return rVclIter.iter != nullptr;
5207     }
5208 
5209     virtual void scroll_to_item(const weld::TreeIter& rIter) override
5210     {
5211         assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
5212         disable_notify_events();
5213         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
5214         m_xIconView->MakeVisible(rVclIter.iter);
5215         enable_notify_events();
5216     }
5217 
5218     virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override
5219     {
5220         SalInstanceTreeIter aVclIter(m_xIconView->FirstSelected());
5221         while (aVclIter.iter)
5222         {
5223             if (func(aVclIter))
5224                 return;
5225             aVclIter.iter = m_xIconView->NextSelected(aVclIter.iter);
5226         }
5227     }
5228 
5229     virtual OUString get_id(const weld::TreeIter& rIter) const override
5230     {
5231         const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
5232         const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData());
5233         if (pStr)
5234             return *pStr;
5235         return OUString();
5236     }
5237 
5238     virtual void clear() override
5239     {
5240         disable_notify_events();
5241         m_xIconView->Clear();
5242         m_aUserData.clear();
5243         enable_notify_events();
5244     }
5245 
5246     virtual ~SalInstanceIconView() override
5247     {
5248         m_xIconView->SetDoubleClickHdl(Link<SvTreeListBox*, bool>());
5249         m_xIconView->SetSelectHdl(Link<SvTreeListBox*, void>());
5250         m_xIconView->SetDeselectHdl(Link<SvTreeListBox*, void>());
5251     }
5252 };
5253 
5254 IMPL_LINK_NOARG(SalInstanceIconView, SelectHdl, SvTreeListBox*, void)
5255 {
5256     if (notify_events_disabled())
5257         return;
5258     signal_selection_changed();
5259 }
5260 
5261 IMPL_LINK_NOARG(SalInstanceIconView, DeSelectHdl, SvTreeListBox*, void)
5262 {
5263     if (notify_events_disabled())
5264         return;
5265     if (m_xIconView->GetSelectionMode() == SelectionMode::Single)
5266         return;
5267     signal_selection_changed();
5268 }
5269 
5270 IMPL_LINK_NOARG(SalInstanceIconView, DoubleClickHdl, SvTreeListBox*, bool)
5271 {
5272     if (notify_events_disabled())
5273         return false;
5274     return !signal_item_activated();
5275 }
5276 
5277 double SalInstanceSpinButton::toField(int nValue) const
5278 {
5279     return static_cast<double>(nValue) / Power10(get_digits());
5280     }
5281 
5282 int SalInstanceSpinButton::fromField(double fValue) const
5283 {
5284     return FRound(fValue * Power10(get_digits()));
5285 }
5286 
5287 SalInstanceSpinButton::SalInstanceSpinButton(FormattedField* pButton, SalInstanceBuilder* pBuilder,
5288                         bool bTakeOwnership)
5289     : SalInstanceEntry(pButton, pBuilder, bTakeOwnership)
5290     , m_xButton(pButton)
5291     , m_rFormatter(m_xButton->GetFormatter())
5292 {
5293     m_rFormatter.SetThousandsSep(false); //off by default, MetricSpinButton enables it
5294     m_xButton->SetUpHdl(LINK(this, SalInstanceSpinButton, UpDownHdl));
5295     m_xButton->SetDownHdl(LINK(this, SalInstanceSpinButton, UpDownHdl));
5296     m_xButton->SetLoseFocusHdl(LINK(this, SalInstanceSpinButton, LoseFocusHdl));
5297     m_rFormatter.SetOutputHdl(LINK(this, SalInstanceSpinButton, OutputHdl));
5298     m_rFormatter.SetInputHdl(LINK(this, SalInstanceSpinButton, InputHdl));
5299     if (Edit* pEdit = m_xButton->GetSubEdit())
5300         pEdit->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl));
5301     else
5302         m_xButton->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl));
5303 }
5304 
5305 int SalInstanceSpinButton::get_value() const
5306 {
5307     return fromField(m_rFormatter.GetValue());
5308 }
5309 
5310 void SalInstanceSpinButton::set_value(int value)
5311 {
5312     m_rFormatter.SetValue(toField(value));
5313 }
5314 
5315 void SalInstanceSpinButton::set_range(int min, int max)
5316 {
5317     m_rFormatter.SetMinValue(toField(min));
5318     m_rFormatter.SetMaxValue(toField(max));
5319 }
5320 
5321 void SalInstanceSpinButton::get_range(int& min, int& max) const
5322 {
5323     min = fromField(m_rFormatter.GetMinValue());
5324     max = fromField(m_rFormatter.GetMaxValue());
5325 }
5326 
5327 void SalInstanceSpinButton::set_increments(int step, int /*page*/)
5328 {
5329     m_rFormatter.SetSpinSize(toField(step));
5330 }
5331 
5332 void SalInstanceSpinButton::get_increments(int& step, int& page) const
5333 {
5334     step = fromField(m_rFormatter.GetSpinSize());
5335     page = fromField(m_rFormatter.GetSpinSize());
5336 }
5337 
5338 void SalInstanceSpinButton::set_digits(unsigned int digits)
5339 {
5340     m_rFormatter.SetDecimalDigits(digits);
5341 }
5342 
5343 // SpinButton may be comprised of multiple subwidgets, consider the lot as
5344 // one thing for focus
5345 bool SalInstanceSpinButton::has_focus() const
5346 {
5347     return m_xWidget->HasChildPathFocus();
5348 }
5349 
5350 //off by default for direct SpinButtons, MetricSpinButton enables it
5351 void SalInstanceSpinButton::SetUseThousandSep()
5352 {
5353     m_rFormatter.SetThousandsSep(true);
5354 }
5355 
5356 unsigned int SalInstanceSpinButton::get_digits() const
5357 {
5358     return m_rFormatter.GetDecimalDigits();
5359 }
5360 
5361 SalInstanceSpinButton::~SalInstanceSpinButton()
5362 {
5363     if (Edit* pEdit = m_xButton->GetSubEdit())
5364         pEdit->SetActivateHdl(Link<Edit&, bool>());
5365     else
5366         m_xButton->SetActivateHdl(Link<Edit&, bool>());
5367     m_rFormatter.SetInputHdl(Link<sal_Int64*, TriState>());
5368     m_rFormatter.SetOutputHdl(Link<LinkParamNone*, bool>());
5369     m_xButton->SetLoseFocusHdl(Link<Control&, void>());
5370     m_xButton->SetDownHdl(Link<SpinField&, void>());
5371     m_xButton->SetUpHdl(Link<SpinField&, void>());
5372 }
5373 
5374 IMPL_LINK_NOARG(SalInstanceSpinButton, ActivateHdl, Edit&, bool)
5375 {
5376     // tdf#122348 return pressed to end dialog
5377     signal_value_changed();
5378     return m_aActivateHdl.Call(*this);
5379 }
5380 
5381 IMPL_LINK_NOARG(SalInstanceSpinButton, UpDownHdl, SpinField&, void) { signal_value_changed(); }
5382 
5383 IMPL_LINK_NOARG(SalInstanceSpinButton, LoseFocusHdl, Control&, void) { signal_value_changed(); }
5384 
5385 IMPL_LINK_NOARG(SalInstanceSpinButton, OutputHdl, LinkParamNone*, bool) { return signal_output(); }
5386 
5387 IMPL_LINK(SalInstanceSpinButton, InputHdl, sal_Int64*, pResult, TriState)
5388 {
5389     int nResult;
5390     TriState eRet = signal_input(&nResult);
5391     if (eRet == TRISTATE_TRUE)
5392         *pResult = nResult;
5393     return eRet;
5394 }
5395 
5396 namespace
5397 {
5398 class SalInstanceFormattedSpinButton : public SalInstanceEntry,
5399                                        public virtual weld::FormattedSpinButton
5400 {
5401 private:
5402     VclPtr<FormattedField> m_xButton;
5403     weld::EntryFormatter* m_pFormatter;
5404 
5405 public:
5406     SalInstanceFormattedSpinButton(FormattedField* pButton, SalInstanceBuilder* pBuilder,
5407                                    bool bTakeOwnership)
5408         : SalInstanceEntry(pButton, pBuilder, bTakeOwnership)
5409         , m_xButton(pButton)
5410         , m_pFormatter(nullptr)
5411     {
5412     }
5413 
5414     virtual void set_text(const OUString& rText) override
5415     {
5416         disable_notify_events();
5417         m_xButton->SpinField::SetText(rText);
5418         enable_notify_events();
5419     }
5420 
5421     virtual void connect_changed(const Link<weld::Entry&, void>& rLink) override
5422     {
5423         if (!m_pFormatter) // once a formatter is set, it takes over "changed"
5424         {
5425             SalInstanceEntry::connect_changed(rLink);
5426             return;
5427         }
5428         m_pFormatter->connect_changed(rLink);
5429     }
5430 
5431     virtual void connect_focus_out(const Link<weld::Widget&, void>& rLink) override
5432     {
5433         if (!m_pFormatter) // once a formatter is set, it takes over "focus-out"
5434         {
5435             SalInstanceEntry::connect_focus_out(rLink);
5436             return;
5437         }
5438         m_pFormatter->connect_focus_out(rLink);
5439     }
5440 
5441     virtual void SetFormatter(weld::EntryFormatter* pFormatter) override
5442     {
5443         m_pFormatter = pFormatter;
5444         m_xButton->SetFormatter(pFormatter);
5445     }
5446 
5447     virtual void sync_value_from_formatter() override
5448     {
5449         // no-op for gen
5450     }
5451 
5452     virtual void sync_range_from_formatter() override
5453     {
5454         // no-op for gen
5455     }
5456 
5457     virtual void sync_increments_from_formatter() override
5458     {
5459         // no-op for gen
5460     }
5461 
5462     virtual Formatter& GetFormatter() override
5463     {
5464         return m_xButton->GetFormatter();
5465     }
5466 };
5467 
5468 }
5469 
5470 SalInstanceLabel::SalInstanceLabel(Control* pLabel, SalInstanceBuilder* pBuilder,
5471                                    bool bTakeOwnership)
5472     : SalInstanceWidget(pLabel, pBuilder, bTakeOwnership)
5473     , m_xLabel(pLabel)
5474 {
5475 }
5476 
5477 void SalInstanceLabel::set_label(const OUString& rText) { m_xLabel->SetText(rText); }
5478 
5479 OUString SalInstanceLabel::get_label() const { return m_xLabel->GetText(); }
5480 
5481 void SalInstanceLabel::set_mnemonic_widget(Widget* pTarget)
5482 {
5483     FixedText* pLabel = dynamic_cast<FixedText*>(m_xLabel.get());
5484     assert(pLabel && "can't use set_mnemonic_widget on SelectableFixedText");
5485     SalInstanceWidget* pTargetWidget = dynamic_cast<SalInstanceWidget*>(pTarget);
5486     pLabel->set_mnemonic_widget(pTargetWidget ? pTargetWidget->getWidget() : nullptr);
5487 }
5488 
5489 void SalInstanceLabel::set_label_type(weld::LabelType eType)
5490 {
5491     switch (eType)
5492     {
5493         case weld::LabelType::Normal:
5494             m_xLabel->SetControlForeground();
5495             m_xLabel->SetControlBackground();
5496             break;
5497         case weld::LabelType::Warning:
5498             m_xLabel->SetControlForeground();
5499             m_xLabel->SetControlBackground(COL_YELLOW);
5500             break;
5501         case weld::LabelType::Error:
5502             m_xLabel->SetControlForeground();
5503             m_xLabel->SetControlBackground(
5504                 m_xLabel->GetSettings().GetStyleSettings().GetHighlightColor());
5505             break;
5506         case weld::LabelType::Title:
5507             m_xLabel->SetControlForeground(
5508                 m_xLabel->GetSettings().GetStyleSettings().GetLightColor());
5509             m_xLabel->SetControlBackground();
5510             break;
5511     }
5512 }
5513 
5514 void SalInstanceLabel::set_font(const vcl::Font& rFont)
5515 {
5516     m_xLabel->SetPointFont(*m_xLabel, rFont);
5517     m_xLabel->Invalidate();
5518 }
5519 
5520 std::unique_ptr<weld::Label> SalInstanceFrame::weld_label_widget() const
5521 {
5522     FixedText* pLabel = dynamic_cast<FixedText*>(m_xFrame->get_label_widget());
5523     if (!pLabel)
5524         return nullptr;
5525     return std::make_unique<SalInstanceLabel>(pLabel, m_pBuilder, false);
5526 }
5527 
5528 SalInstanceTextView::SalInstanceTextView(VclMultiLineEdit* pTextView, SalInstanceBuilder* pBuilder,
5529                     bool bTakeOwnership)
5530     : SalInstanceContainer(pTextView, pBuilder, bTakeOwnership)
5531     , m_xTextView(pTextView)
5532 {
5533     m_xTextView->SetModifyHdl(LINK(this, SalInstanceTextView, ChangeHdl));
5534     ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5535     m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl();
5536     rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceTextView, VscrollHdl));
5537 }
5538 
5539 void SalInstanceTextView::set_text(const OUString& rText)
5540 {
5541     disable_notify_events();
5542     m_xTextView->SetText(rText);
5543     enable_notify_events();
5544 }
5545 
5546 void SalInstanceTextView::replace_selection(const OUString& rText)
5547 {
5548     disable_notify_events();
5549     m_xTextView->ReplaceSelected(rText);
5550     enable_notify_events();
5551 }
5552 
5553 OUString SalInstanceTextView::get_text() const { return m_xTextView->GetText(); }
5554 
5555 bool SalInstanceTextView::get_selection_bounds(int& rStartPos, int& rEndPos)
5556 {
5557     const Selection& rSelection = m_xTextView->GetSelection();
5558     rStartPos = rSelection.Min();
5559     rEndPos = rSelection.Max();
5560     return rSelection.Len();
5561 }
5562 
5563 void SalInstanceTextView::select_region(int nStartPos, int nEndPos)
5564 {
5565     disable_notify_events();
5566     long nStart = nStartPos < 0 ? SELECTION_MAX : nStartPos;
5567     long nEnd = nEndPos < 0 ? SELECTION_MAX : nEndPos;
5568     m_xTextView->SetSelection(Selection(nStart, nEnd));
5569     enable_notify_events();
5570 }
5571 
5572 void SalInstanceTextView::set_editable(bool bEditable) { m_xTextView->SetReadOnly(!bEditable); }
5573 bool SalInstanceTextView::get_editable() const { return !m_xTextView->IsReadOnly(); }
5574 void SalInstanceTextView::set_max_length(int nChars) { m_xTextView->SetMaxTextLen(nChars); }
5575 
5576 void SalInstanceTextView::set_monospace(bool bMonospace)
5577 {
5578     vcl::Font aOrigFont = m_xTextView->GetControlFont();
5579     vcl::Font aFont;
5580     if (bMonospace)
5581         aFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_FIXED, LANGUAGE_DONTKNOW,
5582                                                 GetDefaultFontFlags::OnlyOne, m_xTextView);
5583     else
5584         aFont = Application::GetSettings().GetStyleSettings().GetFieldFont();
5585     aFont.SetFontHeight(aOrigFont.GetFontHeight());
5586     m_xTextView->SetFont(aFont);
5587     m_xTextView->SetControlFont(aFont);
5588 }
5589 
5590 void SalInstanceTextView::connect_cursor_position(const Link<TextView&, void>& rLink)
5591 {
5592     assert(!m_aCursorPositionHdl.IsSet());
5593     m_xTextView->AddEventListener(LINK(this, SalInstanceTextView, CursorListener));
5594     weld::TextView::connect_cursor_position(rLink);
5595 }
5596 
5597 bool SalInstanceTextView::can_move_cursor_with_up() const
5598 {
5599     bool bNoSelection = !m_xTextView->GetSelection();
5600     return !bNoSelection || m_xTextView->CanUp();
5601 }
5602 
5603 bool SalInstanceTextView::can_move_cursor_with_down() const
5604 {
5605     bool bNoSelection = !m_xTextView->GetSelection();
5606     return !bNoSelection || m_xTextView->CanDown();
5607 }
5608 
5609 void SalInstanceTextView::cut_clipboard()
5610 {
5611     m_xTextView->Cut();
5612 }
5613 
5614 void SalInstanceTextView::copy_clipboard()
5615 {
5616     m_xTextView->Copy();
5617 }
5618 
5619 void SalInstanceTextView::paste_clipboard()
5620 {
5621     m_xTextView->Paste();
5622 }
5623 
5624 void SalInstanceTextView::set_alignment(TxtAlign eXAlign)
5625 {
5626     ::set_alignment(*m_xTextView, eXAlign);
5627 }
5628 
5629 int SalInstanceTextView::vadjustment_get_value() const
5630 {
5631     ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5632     return rVertScrollBar.GetThumbPos();
5633 }
5634 
5635 void SalInstanceTextView::vadjustment_set_value(int value)
5636 {
5637     ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5638     rVertScrollBar.SetThumbPos(value);
5639     m_aOrigVScrollHdl.Call(&rVertScrollBar);
5640 }
5641 
5642 int SalInstanceTextView::vadjustment_get_upper() const
5643 {
5644     ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5645     return rVertScrollBar.GetRangeMax();
5646 }
5647 
5648 int SalInstanceTextView::vadjustment_get_lower() const
5649 {
5650     ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5651     return rVertScrollBar.GetRangeMin();
5652 }
5653 
5654 int SalInstanceTextView::vadjustment_get_page_size() const
5655 {
5656     ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5657     return rVertScrollBar.GetVisibleSize();
5658 }
5659 
5660 bool SalInstanceTextView::has_focus() const
5661 {
5662     return m_xTextView->HasChildPathFocus();
5663 }
5664 
5665 SalInstanceTextView::~SalInstanceTextView()
5666 {
5667     if (!m_xTextView->IsDisposed())
5668     {
5669         if (m_aCursorPositionHdl.IsSet())
5670             m_xTextView->RemoveEventListener(LINK(this, SalInstanceTextView, CursorListener));
5671         m_xTextView->SetModifyHdl(Link<Edit&, void>());
5672         ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar();
5673         rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl);
5674     }
5675 }
5676 
5677 IMPL_LINK(SalInstanceTextView, VscrollHdl, ScrollBar*, pScrollBar, void)
5678 {
5679     signal_vadjustment_changed();
5680     m_aOrigVScrollHdl.Call(pScrollBar);
5681 }
5682 
5683 IMPL_LINK_NOARG(SalInstanceTextView, ChangeHdl, Edit&, void) { signal_changed(); }
5684 
5685 IMPL_LINK(SalInstanceTextView, CursorListener, VclWindowEvent&, rEvent, void)
5686 {
5687     if (notify_events_disabled())
5688         return;
5689     if (rEvent.GetId() == VclEventId::EditSelectionChanged
5690         || rEvent.GetId() == VclEventId::EditCaretChanged)
5691         signal_cursor_position();
5692 }
5693 
5694 namespace
5695 {
5696 class SalInstanceExpander : public SalInstanceContainer, public virtual weld::Expander
5697 {
5698 private:
5699     VclPtr<VclExpander> m_xExpander;
5700 
5701     DECL_LINK(ExpandedHdl, VclExpander&, void);
5702 
5703 public:
5704     SalInstanceExpander(VclExpander* pExpander, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
5705         : SalInstanceContainer(pExpander, pBuilder, bTakeOwnership)
5706         , m_xExpander(pExpander)
5707     {
5708         m_xExpander->SetExpandedHdl(LINK(this, SalInstanceExpander, ExpandedHdl));
5709     }
5710 
5711     virtual bool get_expanded() const override { return m_xExpander->get_expanded(); }
5712 
5713     virtual void set_expanded(bool bExpand) override { m_xExpander->set_expanded(bExpand); }
5714 
5715     virtual ~SalInstanceExpander() override
5716     {
5717         m_xExpander->SetExpandedHdl(Link<VclExpander&, void>());
5718     }
5719 };
5720 
5721 }
5722 
5723 IMPL_LINK_NOARG(SalInstanceExpander, ExpandedHdl, VclExpander&, void) { signal_expanded(); }
5724 
5725 // SalInstanceWidget has a generic listener for all these
5726 // events, ignore the ones we have specializations for
5727 // in VclDrawingArea
5728 void SalInstanceDrawingArea::HandleEventListener(VclWindowEvent& rEvent)
5729 {
5730     if (rEvent.GetId() == VclEventId::WindowResize)
5731         return;
5732     SalInstanceWidget::HandleEventListener(rEvent);
5733 }
5734 
5735 void SalInstanceDrawingArea::HandleMouseEventListener(VclSimpleEvent& rEvent)
5736 {
5737     if (rEvent.GetId() == VclEventId::WindowMouseButtonDown
5738         || rEvent.GetId() == VclEventId::WindowMouseButtonUp
5739         || rEvent.GetId() == VclEventId::WindowMouseMove)
5740     {
5741         return;
5742     }
5743     SalInstanceWidget::HandleMouseEventListener(rEvent);
5744 }
5745 
5746 bool SalInstanceDrawingArea::HandleKeyEventListener(VclWindowEvent& /*rEvent*/) { return false; }
5747 
5748 SalInstanceDrawingArea::SalInstanceDrawingArea(VclDrawingArea* pDrawingArea, SalInstanceBuilder* pBuilder,
5749                         const a11yref& rAlly, FactoryFunction pUITestFactoryFunction,
5750                         void* pUserData, bool bTakeOwnership)
5751     : SalInstanceWidget(pDrawingArea, pBuilder, bTakeOwnership)
5752     , m_xDrawingArea(pDrawingArea)
5753 {
5754     m_xDrawingArea->SetAccessible(rAlly);
5755     m_xDrawingArea->SetUITestFactory(std::move(pUITestFactoryFunction), pUserData);
5756     m_xDrawingArea->SetPaintHdl(LINK(this, SalInstanceDrawingArea, PaintHdl));
5757     m_xDrawingArea->SetResizeHdl(LINK(this, SalInstanceDrawingArea, ResizeHdl));
5758     m_xDrawingArea->SetMousePressHdl(LINK(this, SalInstanceDrawingArea, MousePressHdl));
5759     m_xDrawingArea->SetMouseMoveHdl(LINK(this, SalInstanceDrawingArea, MouseMoveHdl));
5760     m_xDrawingArea->SetMouseReleaseHdl(LINK(this, SalInstanceDrawingArea, MouseReleaseHdl));
5761     m_xDrawingArea->SetKeyPressHdl(LINK(this, SalInstanceDrawingArea, KeyPressHdl));
5762     m_xDrawingArea->SetKeyReleaseHdl(LINK(this, SalInstanceDrawingArea, KeyReleaseHdl));
5763     m_xDrawingArea->SetStyleUpdatedHdl(LINK(this, SalInstanceDrawingArea, StyleUpdatedHdl));
5764     m_xDrawingArea->SetCommandHdl(LINK(this, SalInstanceDrawingArea, CommandHdl));
5765     m_xDrawingArea->SetQueryTooltipHdl(LINK(this, SalInstanceDrawingArea, QueryTooltipHdl));
5766     m_xDrawingArea->SetStartDragHdl(LINK(this, SalInstanceDrawingArea, StartDragHdl));
5767 }
5768 
5769 void SalInstanceDrawingArea::queue_draw() { m_xDrawingArea->Invalidate(); }
5770 
5771 void SalInstanceDrawingArea::queue_draw_area(int x, int y, int width, int height)
5772 {
5773     m_xDrawingArea->Invalidate(tools::Rectangle(Point(x, y), Size(width, height)));
5774 }
5775 
5776 void SalInstanceDrawingArea::queue_resize() { m_xDrawingArea->queue_resize(); }
5777 
5778 void SalInstanceDrawingArea::connect_size_allocate(const Link<const Size&, void>& rLink)
5779 {
5780     weld::Widget::connect_size_allocate(rLink);
5781 }
5782 
5783 void SalInstanceDrawingArea::connect_key_press(const Link<const KeyEvent&, bool>& rLink)
5784 {
5785     weld::Widget::connect_key_press(rLink);
5786 }
5787 
5788 void SalInstanceDrawingArea::connect_key_release(const Link<const KeyEvent&, bool>& rLink)
5789 {
5790     weld::Widget::connect_key_release(rLink);
5791 }
5792 
5793 void SalInstanceDrawingArea::set_cursor(PointerStyle ePointerStyle)
5794 {
5795     m_xDrawingArea->SetPointer(ePointerStyle);
5796 }
5797 
5798 a11yref SalInstanceDrawingArea::get_accessible_parent()
5799 {
5800     vcl::Window* pParent = m_xDrawingArea->GetParent();
5801     if (pParent)
5802         return pParent->GetAccessible();
5803     return css::uno::Reference<css::accessibility::XAccessible>();
5804 }
5805 
5806 a11yrelationset SalInstanceDrawingArea::get_accessible_relation_set()
5807 {
5808     utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
5809     css::uno::Reference<css::accessibility::XAccessibleRelationSet> xSet = pRelationSetHelper;
5810     vcl::Window* pWindow = m_xDrawingArea.get();
5811     if (pWindow)
5812     {
5813         vcl::Window* pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
5814         if (pLabeledBy && pLabeledBy != pWindow)
5815         {
5816             css::uno::Sequence<css::uno::Reference<css::uno::XInterface>> aSequence{
5817                 pLabeledBy->GetAccessible()
5818             };
5819             pRelationSetHelper->AddRelation(css::accessibility::AccessibleRelation(
5820                 css::accessibility::AccessibleRelationType::LABELED_BY, aSequence));
5821         }
5822         vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
5823         if (pMemberOf && pMemberOf != pWindow)
5824         {
5825             css::uno::Sequence<css::uno::Reference<css::uno::XInterface>> aSequence{
5826                 pMemberOf->GetAccessible()
5827             };
5828             pRelationSetHelper->AddRelation(css::accessibility::AccessibleRelation(
5829                 css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence));
5830         }
5831     }
5832     return xSet;
5833 }
5834 
5835 Point SalInstanceDrawingArea::get_accessible_location()
5836 {
5837     return m_xDrawingArea->OutputToAbsoluteScreenPixel(Point());
5838 }
5839 
5840 void SalInstanceDrawingArea::enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper,
5841                                 sal_uInt8 eDNDConstants)
5842 {
5843     m_xDrawingArea->SetDragHelper(rHelper, eDNDConstants);
5844 }
5845 
5846 SalInstanceDrawingArea::~SalInstanceDrawingArea()
5847 {
5848     m_xDrawingArea->SetQueryTooltipHdl(Link<tools::Rectangle&, OUString>());
5849     m_xDrawingArea->SetCommandHdl(Link<const CommandEvent&, bool>());
5850     m_xDrawingArea->SetStyleUpdatedHdl(Link<VclDrawingArea&, void>());
5851     m_xDrawingArea->SetMousePressHdl(Link<const MouseEvent&, bool>());
5852     m_xDrawingArea->SetMouseMoveHdl(Link<const MouseEvent&, bool>());
5853     m_xDrawingArea->SetMouseReleaseHdl(Link<const MouseEvent&, bool>());
5854     m_xDrawingArea->SetKeyPressHdl(Link<const KeyEvent&, bool>());
5855     m_xDrawingArea->SetKeyReleaseHdl(Link<const KeyEvent&, bool>());
5856     m_xDrawingArea->SetResizeHdl(Link<const Size&, void>());
5857     m_xDrawingArea->SetPaintHdl(
5858         Link<std::pair<vcl::RenderContext&, const tools::Rectangle&>, void>());
5859 }
5860 
5861 OutputDevice& SalInstanceDrawingArea::get_ref_device() { return *m_xDrawingArea; }
5862 
5863 void SalInstanceDrawingArea::click(const Point& rPos)
5864 {
5865     MouseEvent aEvent(rPos);
5866     m_xDrawingArea->MouseButtonDown(aEvent);
5867     m_xDrawingArea->MouseButtonUp(aEvent);
5868 }
5869 
5870 IMPL_LINK(SalInstanceDrawingArea, PaintHdl, target_and_area, aPayload, void)
5871 {
5872     m_aDrawHdl.Call(aPayload);
5873     tools::Rectangle aFocusRect(m_aGetFocusRectHdl.Call(*this));
5874     if (!aFocusRect.IsEmpty())
5875         DrawFocusRect(aPayload.first, aFocusRect);
5876 }
5877 
5878 IMPL_LINK(SalInstanceDrawingArea, ResizeHdl, const Size&, rSize, void)
5879 {
5880     m_aSizeAllocateHdl.Call(rSize);
5881 }
5882 
5883 IMPL_LINK(SalInstanceDrawingArea, MousePressHdl, const MouseEvent&, rEvent, bool)
5884 {
5885     return m_aMousePressHdl.Call(rEvent);
5886 }
5887 
5888 IMPL_LINK(SalInstanceDrawingArea, MouseMoveHdl, const MouseEvent&, rEvent, bool)
5889 {
5890     return m_aMouseMotionHdl.Call(rEvent);
5891 }
5892 
5893 IMPL_LINK(SalInstanceDrawingArea, MouseReleaseHdl, const MouseEvent&, rEvent, bool)
5894 {
5895     return m_aMouseReleaseHdl.Call(rEvent);
5896 }
5897 
5898 IMPL_LINK(SalInstanceDrawingArea, KeyPressHdl, const KeyEvent&, rEvent, bool)
5899 {
5900     return m_aKeyPressHdl.Call(rEvent);
5901 }
5902 
5903 IMPL_LINK(SalInstanceDrawingArea, KeyReleaseHdl, const KeyEvent&, rEvent, bool)
5904 {
5905     return m_aKeyReleaseHdl.Call(rEvent);
5906 }
5907 
5908 IMPL_LINK_NOARG(SalInstanceDrawingArea, StyleUpdatedHdl, VclDrawingArea&, void)
5909 {
5910     m_aStyleUpdatedHdl.Call(*this);
5911 }
5912 
5913 IMPL_LINK(SalInstanceDrawingArea, CommandHdl, const CommandEvent&, rEvent, bool)
5914 {
5915     return m_aCommandHdl.Call(rEvent);
5916 }
5917 
5918 IMPL_LINK(SalInstanceDrawingArea, QueryTooltipHdl, tools::Rectangle&, rHelpArea, OUString)
5919 {
5920     return m_aQueryTooltipHdl.Call(rHelpArea);
5921 }
5922 
5923 IMPL_LINK_NOARG(SalInstanceDrawingArea, StartDragHdl, VclDrawingArea*, bool)
5924 {
5925     if (m_aDragBeginHdl.Call(*this))
5926         return true;
5927     return false;
5928 }
5929 
5930 SalInstanceComboBoxWithoutEdit::SalInstanceComboBoxWithoutEdit(ListBox* pListBox, SalInstanceBuilder* pBuilder,
5931                                 bool bTakeOwnership)
5932     : SalInstanceComboBox<ListBox>(pListBox, pBuilder, bTakeOwnership)
5933 {
5934     m_xComboBox->SetSelectHdl(LINK(this, SalInstanceComboBoxWithoutEdit, SelectHdl));
5935 }
5936 
5937 OUString SalInstanceComboBoxWithoutEdit::get_active_text() const { return m_xComboBox->GetSelectedEntry(); }
5938 
5939 void SalInstanceComboBoxWithoutEdit::remove(int pos) { m_xComboBox->RemoveEntry(pos); }
5940 
5941 void SalInstanceComboBoxWithoutEdit::insert(int pos, const OUString& rStr, const OUString* pId,
5942                     const OUString* pIconName, VirtualDevice* pImageSurface)
5943 {
5944     auto nInsertPos = pos == -1 ? COMBOBOX_APPEND : pos;
5945     sal_Int32 nInsertedAt;
5946     if (!pIconName && !pImageSurface)
5947         nInsertedAt = m_xComboBox->InsertEntry(rStr, nInsertPos);
5948     else if (pIconName)
5949         nInsertedAt = m_xComboBox->InsertEntry(rStr, createImage(*pIconName), nInsertPos);
5950     else
5951         nInsertedAt = m_xComboBox->InsertEntry(rStr, createImage(*pImageSurface), nInsertPos);
5952     if (pId)
5953     {
5954         m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
5955         m_xComboBox->SetEntryData(nInsertedAt, m_aUserData.back().get());
5956     }
5957 }
5958 
5959 void SalInstanceComboBoxWithoutEdit::insert_separator(int pos, const OUString& /*rId*/)
5960 {
5961     auto nInsertPos = pos == -1 ? m_xComboBox->GetEntryCount() : pos;
5962     m_xComboBox->AddSeparator(nInsertPos - 1);
5963 }
5964 
5965 bool SalInstanceComboBoxWithoutEdit::has_entry() const { return false; }
5966 
5967 bool SalInstanceComboBoxWithoutEdit::changed_by_direct_pick() const { return true; }
5968 
5969 void SalInstanceComboBoxWithoutEdit::set_entry_message_type(weld::EntryMessageType /*eType*/)
5970 {
5971     assert(false);
5972 }
5973 
5974 void SalInstanceComboBoxWithoutEdit::set_entry_text(const OUString& /*rText*/) { assert(false); }
5975 
5976 void SalInstanceComboBoxWithoutEdit::select_entry_region(int /*nStartPos*/, int /*nEndPos*/) { assert(false); }
5977 
5978 bool SalInstanceComboBoxWithoutEdit::get_entry_selection_bounds(int& /*rStartPos*/, int& /*rEndPos*/)
5979 {
5980     assert(false);
5981     return false;
5982 }
5983 
5984 void SalInstanceComboBoxWithoutEdit::set_entry_width_chars(int /*nChars*/) { assert(false); }
5985 
5986 void SalInstanceComboBoxWithoutEdit::set_entry_max_length(int /*nChars*/) { assert(false); }
5987 
5988 void SalInstanceComboBoxWithoutEdit::set_entry_completion(bool, bool) { assert(false); }
5989 
5990 void SalInstanceComboBoxWithoutEdit::set_entry_placeholder_text(const OUString&) { assert(false); }
5991 
5992 void SalInstanceComboBoxWithoutEdit::set_entry_editable(bool /*bEditable*/) { assert(false); }
5993 
5994 void SalInstanceComboBoxWithoutEdit::cut_entry_clipboard() { assert(false); }
5995 
5996 void SalInstanceComboBoxWithoutEdit::copy_entry_clipboard() { assert(false); }
5997 
5998 void SalInstanceComboBoxWithoutEdit::paste_entry_clipboard() { assert(false); }
5999 
6000 void SalInstanceComboBoxWithoutEdit::set_entry_font(const vcl::Font&) { assert(false); }
6001 
6002 vcl::Font SalInstanceComboBoxWithoutEdit::get_entry_font() { assert(false); return vcl::Font(); }
6003 
6004 void SalInstanceComboBoxWithoutEdit::set_custom_renderer(bool /*bOn*/)
6005 {
6006     assert(false && "not implemented");
6007 }
6008 
6009 int SalInstanceComboBoxWithoutEdit::get_max_mru_count() const
6010 {
6011     assert(false && "not implemented");
6012     return 0;
6013 }
6014 
6015 void SalInstanceComboBoxWithoutEdit::set_max_mru_count(int)
6016 {
6017     assert(false && "not implemented");
6018 }
6019 
6020 OUString SalInstanceComboBoxWithoutEdit::get_mru_entries() const
6021 {
6022     assert(false && "not implemented");
6023     return OUString();
6024 }
6025 
6026 void SalInstanceComboBoxWithoutEdit::set_mru_entries(const OUString&)
6027 {
6028     assert(false && "not implemented");
6029 }
6030 
6031 void SalInstanceComboBoxWithoutEdit::HandleEventListener(VclWindowEvent& rEvent)
6032 {
6033     CallHandleEventListener(rEvent);
6034 }
6035 
6036 SalInstanceComboBoxWithoutEdit::~SalInstanceComboBoxWithoutEdit()
6037 {
6038     m_xComboBox->SetSelectHdl(Link<ListBox&, void>());
6039 }
6040 
6041 IMPL_LINK_NOARG(SalInstanceComboBoxWithoutEdit, SelectHdl, ListBox&, void)
6042 {
6043     return signal_changed();
6044 }
6045 
6046 SalInstanceComboBoxWithEdit::SalInstanceComboBoxWithEdit(::ComboBox* pComboBox, SalInstanceBuilder* pBuilder,
6047                             bool bTakeOwnership)
6048     : SalInstanceComboBox<::ComboBox>(pComboBox, pBuilder, bTakeOwnership)
6049     , m_aTextFilter(m_aEntryInsertTextHdl)
6050     , m_bInSelect(false)
6051 {
6052     m_xComboBox->SetModifyHdl(LINK(this, SalInstanceComboBoxWithEdit, ChangeHdl));
6053     m_xComboBox->SetSelectHdl(LINK(this, SalInstanceComboBoxWithEdit, SelectHdl));
6054     m_xComboBox->SetEntryActivateHdl(LINK(this, SalInstanceComboBoxWithEdit, EntryActivateHdl));
6055     m_xComboBox->SetTextFilter(&m_aTextFilter);
6056 }
6057 
6058 bool SalInstanceComboBoxWithEdit::has_entry() const { return true; }
6059 
6060 bool SalInstanceComboBoxWithEdit::changed_by_direct_pick() const
6061 {
6062     return m_bInSelect && !m_xComboBox->IsModifyByKeyboard() && !m_xComboBox->IsTravelSelect();
6063 }
6064 
6065 void SalInstanceComboBoxWithEdit::set_entry_message_type(weld::EntryMessageType eType)
6066 {
6067     switch (eType)
6068     {
6069         case weld::EntryMessageType::Normal:
6070             m_xComboBox->SetControlForeground();
6071             break;
6072         case weld::EntryMessageType::Warning:
6073             m_xComboBox->SetControlForeground(COL_YELLOW);
6074             break;
6075         case weld::EntryMessageType::Error:
6076             m_xComboBox->SetControlForeground(Color(0xf0, 0, 0));
6077             break;
6078     }
6079 }
6080 
6081 OUString SalInstanceComboBoxWithEdit::get_active_text() const { return m_xComboBox->GetText(); }
6082 
6083 void SalInstanceComboBoxWithEdit::remove(int pos) { m_xComboBox->RemoveEntryAt(pos); }
6084 
6085 void SalInstanceComboBoxWithEdit::insert(int pos, const OUString& rStr, const OUString* pId,
6086                     const OUString* pIconName, VirtualDevice* pImageSurface)
6087 {
6088     auto nInsertPos = pos == -1 ? COMBOBOX_APPEND : pos;
6089     sal_Int32 nInsertedAt;
6090     if (!pIconName && !pImageSurface)
6091         nInsertedAt = m_xComboBox->InsertEntry(rStr, nInsertPos);
6092     else if (pIconName)
6093         nInsertedAt
6094             = m_xComboBox->InsertEntryWithImage(rStr, createImage(*pIconName), nInsertPos);
6095     else
6096         nInsertedAt
6097             = m_xComboBox->InsertEntryWithImage(rStr, createImage(*pImageSurface), nInsertPos);
6098     if (pId)
6099     {
6100         m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
6101         m_xComboBox->SetEntryData(nInsertedAt, m_aUserData.back().get());
6102     }
6103 }
6104 
6105 void SalInstanceComboBoxWithEdit::insert_separator(int pos, const OUString& /*rId*/)
6106 {
6107     auto nInsertPos = pos == -1 ? m_xComboBox->GetEntryCount() : pos;
6108     m_xComboBox->AddSeparator(nInsertPos - 1);
6109 }
6110 
6111 void SalInstanceComboBoxWithEdit::set_entry_text(const OUString& rText) { m_xComboBox->SetText(rText); }
6112 
6113 void SalInstanceComboBoxWithEdit::set_entry_width_chars(int nChars)
6114 {
6115     m_xComboBox->SetWidthInChars(nChars);
6116 }
6117 
6118 void SalInstanceComboBoxWithEdit::set_entry_max_length(int nChars) { m_xComboBox->SetMaxTextLen(nChars); }
6119 
6120 void SalInstanceComboBoxWithEdit::set_entry_completion(bool bEnable, bool bCaseSensitive)
6121 {
6122     m_xComboBox->EnableAutocomplete(bEnable, bCaseSensitive);
6123 }
6124 
6125 void SalInstanceComboBoxWithEdit::set_entry_placeholder_text(const OUString& rText)
6126 {
6127     m_xComboBox->SetPlaceholderText(rText);
6128 }
6129 
6130 void SalInstanceComboBoxWithEdit::set_entry_editable(bool bEditable)
6131 {
6132     m_xComboBox->SetReadOnly(!bEditable);
6133 }
6134 
6135 void SalInstanceComboBoxWithEdit::cut_entry_clipboard()
6136 {
6137     m_xComboBox->Cut();
6138 }
6139 
6140 void SalInstanceComboBoxWithEdit::copy_entry_clipboard()
6141 {
6142     m_xComboBox->Copy();
6143 }
6144 
6145 void SalInstanceComboBoxWithEdit::paste_entry_clipboard()
6146 {
6147     m_xComboBox->Paste();
6148 }
6149 
6150 void SalInstanceComboBoxWithEdit::select_entry_region(int nStartPos, int nEndPos)
6151 {
6152     m_xComboBox->SetSelection(Selection(nStartPos, nEndPos < 0 ? SELECTION_MAX : nEndPos));
6153 }
6154 
6155 bool SalInstanceComboBoxWithEdit::get_entry_selection_bounds(int& rStartPos, int& rEndPos)
6156 {
6157     const Selection& rSelection = m_xComboBox->GetSelection();
6158     rStartPos = rSelection.Min();
6159     rEndPos = rSelection.Max();
6160     return rSelection.Len();
6161 }
6162 
6163 void SalInstanceComboBoxWithEdit::set_entry_font(const vcl::Font& rFont)
6164 {
6165     Edit* pEdit = m_xComboBox->GetSubEdit();
6166     assert(pEdit);
6167     pEdit->SetPointFont(*pEdit, rFont);
6168     m_xComboBox->SetControlFont(rFont); // tdf#134601 set it as control font to take effect properly
6169     pEdit->Invalidate();
6170 }
6171 
6172 vcl::Font SalInstanceComboBoxWithEdit::get_entry_font()
6173 {
6174     Edit* pEdit = m_xComboBox->GetSubEdit();
6175     assert(pEdit);
6176     return pEdit->GetPointFont(*pEdit);
6177 }
6178 
6179 void SalInstanceComboBoxWithEdit::set_custom_renderer(bool bOn)
6180 {
6181     if (m_xComboBox->IsUserDrawEnabled() == bOn)
6182         return;
6183 
6184     auto nOldEntryHeight = m_xComboBox->GetDropDownEntryHeight();
6185     auto nDropDownLineCount = m_xComboBox->GetDropDownLineCount();
6186 
6187     m_xComboBox->EnableUserDraw(bOn);
6188     if (bOn)
6189         m_xComboBox->SetUserDrawHdl(LINK(this, SalInstanceComboBoxWithEdit, UserDrawHdl));
6190     else
6191         m_xComboBox->SetUserDrawHdl(Link<UserDrawEvent*, void>());
6192 
6193     // adjust the line count to fit approx the height it would have been before
6194     // changing the renderer
6195     auto nNewEntryHeight = m_xComboBox->GetDropDownEntryHeight();
6196     double fRatio = nOldEntryHeight / static_cast<double>(nNewEntryHeight);
6197     m_xComboBox->SetDropDownLineCount(nDropDownLineCount * fRatio);
6198 }
6199 
6200 int SalInstanceComboBoxWithEdit::get_max_mru_count() const
6201 {
6202     return m_xComboBox->GetMaxMRUCount();
6203 }
6204 
6205 void SalInstanceComboBoxWithEdit::set_max_mru_count(int nCount)
6206 {
6207     return m_xComboBox->SetMaxMRUCount(nCount);
6208 }
6209 
6210 OUString SalInstanceComboBoxWithEdit::get_mru_entries() const
6211 {
6212     return m_xComboBox->GetMRUEntries();
6213 }
6214 
6215 void SalInstanceComboBoxWithEdit::set_mru_entries(const OUString& rEntries)
6216 {
6217     m_xComboBox->SetMRUEntries(rEntries);
6218 }
6219 
6220 void SalInstanceComboBoxWithEdit::HandleEventListener(VclWindowEvent& rEvent)
6221 {
6222     if (rEvent.GetId() == VclEventId::DropdownPreOpen)
6223     {
6224         Size aRowSize(signal_custom_get_size(*m_xComboBox));
6225         m_xComboBox->SetUserItemSize(aRowSize);
6226     }
6227     CallHandleEventListener(rEvent);
6228 }
6229 
6230 SalInstanceComboBoxWithEdit::~SalInstanceComboBoxWithEdit()
6231 {
6232     m_xComboBox->SetTextFilter(nullptr);
6233     m_xComboBox->SetEntryActivateHdl(Link<Edit&, bool>());
6234     m_xComboBox->SetModifyHdl(Link<Edit&, void>());
6235     m_xComboBox->SetSelectHdl(Link<::ComboBox&, void>());
6236 }
6237 
6238 IMPL_LINK_NOARG(SalInstanceComboBoxWithEdit, ChangeHdl, Edit&, void)
6239 {
6240     if (!m_xComboBox->IsSyntheticModify()) // SelectHdl will be called
6241         signal_changed();
6242 }
6243 
6244 IMPL_LINK_NOARG(SalInstanceComboBoxWithEdit, SelectHdl, ::ComboBox&, void)
6245 {
6246     m_bInSelect = true;
6247     signal_changed();
6248     m_bInSelect = false;
6249 }
6250 
6251 IMPL_LINK_NOARG(SalInstanceComboBoxWithEdit, EntryActivateHdl, Edit&, bool)
6252 {
6253     return m_aEntryActivateHdl.Call(*this);
6254 }
6255 
6256 IMPL_LINK(SalInstanceComboBoxWithEdit, UserDrawHdl, UserDrawEvent*, pEvent, void)
6257 {
6258     call_signal_custom_render(pEvent);
6259 }
6260 
6261 class SalInstanceEntryTreeView : public SalInstanceContainer, public virtual weld::EntryTreeView
6262 {
6263 private:
6264     DECL_LINK(AutocompleteHdl, Edit&, void);
6265     DECL_LINK(KeyPressListener, VclWindowEvent&, void);
6266     SalInstanceEntry* m_pEntry;
6267     SalInstanceTreeView* m_pTreeView;
6268     bool m_bTreeChange;
6269 
6270 public:
6271     SalInstanceEntryTreeView(vcl::Window* pContainer, SalInstanceBuilder* pBuilder,
6272                              bool bTakeOwnership, std::unique_ptr<weld::Entry> xEntry,
6273                              std::unique_ptr<weld::TreeView> xTreeView)
6274         : EntryTreeView(std::move(xEntry), std::move(xTreeView))
6275         , SalInstanceContainer(pContainer, pBuilder, bTakeOwnership)
6276         , m_pEntry(dynamic_cast<SalInstanceEntry*>(m_xEntry.get()))
6277         , m_pTreeView(dynamic_cast<SalInstanceTreeView*>(m_xTreeView.get()))
6278         , m_bTreeChange(false)
6279     {
6280         assert(m_pEntry && m_pTreeView);
6281 
6282         Edit& rEntry = m_pEntry->getEntry();
6283         rEntry.SetAutocompleteHdl(LINK(this, SalInstanceEntryTreeView, AutocompleteHdl));
6284         rEntry.AddEventListener(LINK(this, SalInstanceEntryTreeView, KeyPressListener));
6285     }
6286 
6287     virtual void insert_separator(int /*pos*/, const OUString& /*rId*/) override { assert(false); }
6288 
6289     virtual void make_sorted() override
6290     {
6291         vcl::Window* pTreeView = m_pTreeView->getWidget();
6292         pTreeView->SetStyle(pTreeView->GetStyle() | WB_SORT);
6293     }
6294 
6295     virtual void set_entry_completion(bool bEnable, bool /*bCaseSensitive*/) override
6296     {
6297         assert(!bEnable && "not implemented yet");
6298         (void)bEnable;
6299         Edit& rEntry = m_pEntry->getEntry();
6300         rEntry.SetAutocompleteHdl(Link<Edit&, void>());
6301     }
6302 
6303     virtual void set_entry_font(const vcl::Font& rFont) override
6304     {
6305         Edit& rEntry = m_pEntry->getEntry();
6306         rEntry.SetPointFont(rEntry, rFont);
6307         rEntry.Invalidate();
6308     }
6309 
6310     virtual vcl::Font get_entry_font() override
6311     {
6312         Edit& rEntry = m_pEntry->getEntry();
6313         return rEntry.GetPointFont(rEntry);
6314     }
6315 
6316     virtual void set_entry_placeholder_text(const OUString& rText) override
6317     {
6318         Edit& rEntry = m_pEntry->getEntry();
6319         rEntry.SetPlaceholderText(rText);
6320     }
6321 
6322     virtual void set_entry_editable(bool bEditable) override
6323     {
6324         Edit& rEntry = m_pEntry->getEntry();
6325         rEntry.SetReadOnly(!bEditable);
6326     }
6327 
6328     virtual void cut_entry_clipboard() override
6329     {
6330         Edit& rEntry = m_pEntry->getEntry();
6331         rEntry.Cut();
6332     }
6333 
6334     virtual void copy_entry_clipboard() override
6335     {
6336         Edit& rEntry = m_pEntry->getEntry();
6337         rEntry.Copy();
6338     }
6339 
6340     virtual void paste_entry_clipboard() override
6341     {
6342         Edit& rEntry = m_pEntry->getEntry();
6343         rEntry.Paste();
6344     }
6345 
6346     virtual void grab_focus() override { m_xEntry->grab_focus(); }
6347 
6348     virtual void connect_focus_in(const Link<Widget&, void>& rLink) override
6349     {
6350         m_xEntry->connect_focus_in(rLink);
6351     }
6352 
6353     virtual void connect_focus_out(const Link<Widget&, void>& rLink) override
6354     {
6355         m_xEntry->connect_focus_out(rLink);
6356     }
6357 
6358     virtual bool changed_by_direct_pick() const override { return m_bTreeChange; }
6359 
6360     virtual void set_custom_renderer(bool /*bOn*/) override
6361     {
6362         assert(false && "not implemented");
6363     }
6364 
6365     virtual int get_max_mru_count() const override
6366     {
6367         assert(false && "not implemented");
6368         return 0;
6369     }
6370 
6371     virtual void set_max_mru_count(int) override
6372     {
6373         assert(false && "not implemented");
6374     }
6375 
6376     virtual OUString get_mru_entries() const override
6377     {
6378         assert(false && "not implemented");
6379         return OUString();
6380     }
6381 
6382     virtual void set_mru_entries(const OUString&) override
6383     {
6384         assert(false && "not implemented");
6385     }
6386 
6387     virtual void set_item_menu(const OString&, weld::Menu*) override
6388     {
6389         assert(false && "not implemented");
6390     }
6391 
6392     int get_menu_button_width() const override
6393     {
6394         assert(false && "not implemented");
6395         return 0;
6396     }
6397 
6398     VclPtr<VirtualDevice> create_render_virtual_device() const override
6399     {
6400         return VclPtr<VirtualDevice>::Create();
6401     }
6402 
6403     virtual ~SalInstanceEntryTreeView() override
6404     {
6405         Edit& rEntry = m_pEntry->getEntry();
6406         rEntry.RemoveEventListener(LINK(this, SalInstanceEntryTreeView, KeyPressListener));
6407         rEntry.SetAutocompleteHdl(Link<Edit&, void>());
6408     }
6409 };
6410 
6411 IMPL_LINK(SalInstanceEntryTreeView, KeyPressListener, VclWindowEvent&, rEvent, void)
6412 {
6413     if (rEvent.GetId() != VclEventId::WindowKeyInput)
6414         return;
6415     const KeyEvent& rKeyEvent = *static_cast<KeyEvent*>(rEvent.GetData());
6416     sal_uInt16 nKeyCode = rKeyEvent.GetKeyCode().GetCode();
6417     if (!(nKeyCode == KEY_UP || nKeyCode == KEY_DOWN || nKeyCode == KEY_PAGEUP
6418         || nKeyCode == KEY_PAGEDOWN))
6419         return;
6420 
6421     m_pTreeView->disable_notify_events();
6422     auto& rListBox = m_pTreeView->getTreeView();
6423     if (!rListBox.FirstSelected())
6424     {
6425         if (SvTreeListEntry* pEntry = rListBox.First())
6426             rListBox.Select(pEntry, true);
6427     }
6428     else
6429         rListBox.KeyInput(rKeyEvent);
6430     m_xEntry->set_text(m_xTreeView->get_selected_text());
6431     m_xEntry->select_region(0, -1);
6432     m_pTreeView->enable_notify_events();
6433     m_bTreeChange = true;
6434     m_pEntry->fire_signal_changed();
6435     m_bTreeChange = false;
6436 }
6437 
6438 IMPL_LINK(SalInstanceEntryTreeView, AutocompleteHdl, Edit&, rEdit, void)
6439 {
6440     Selection aSel = rEdit.GetSelection();
6441 
6442     OUString aFullText = rEdit.GetText();
6443     OUString aStartText = aFullText.copy(0, static_cast<sal_Int32>(aSel.Max()));
6444 
6445     int nPos = -1;
6446     int nCount = m_xTreeView->n_children();
6447     for (int i = 0; i < nCount; ++i)
6448     {
6449         if (m_xTreeView->get_text(i).startsWithIgnoreAsciiCase(aStartText))
6450         {
6451             nPos = i;
6452             break;
6453         }
6454     }
6455 
6456     m_xTreeView->select(nPos);
6457 
6458     if (nPos != -1)
6459     {
6460         OUString aText = m_xTreeView->get_text(nPos);
6461         Selection aSelection(aText.getLength(), aStartText.getLength());
6462         rEdit.SetText(aText, aSelection);
6463     }
6464 }
6465 
6466 SalInstanceBuilder::SalInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot,
6467                                        const OUString& rUIFile, const css::uno::Reference<css::frame::XFrame>& rFrame)
6468     : weld::Builder()
6469     , m_xBuilder(new VclBuilder(pParent, rUIRoot, rUIFile, OString(), rFrame, false))
6470 {
6471 }
6472 
6473 std::unique_ptr<weld::MessageDialog> SalInstanceBuilder::weld_message_dialog(const OString& id,
6474                                                                              bool bTakeOwnership)
6475 {
6476     MessageDialog* pMessageDialog = m_xBuilder->get<MessageDialog>(id);
6477     std::unique_ptr<weld::MessageDialog> pRet(
6478         pMessageDialog ? new SalInstanceMessageDialog(pMessageDialog, this, false) : nullptr);
6479     if (bTakeOwnership && pMessageDialog)
6480     {
6481         assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
6482         m_aOwnedToplevel.set(pMessageDialog);
6483         m_xBuilder->drop_ownership(pMessageDialog);
6484     }
6485     return pRet;
6486 }
6487 
6488 std::unique_ptr<weld::Dialog> SalInstanceBuilder::weld_dialog(const OString& id,
6489                                                               bool bTakeOwnership)
6490 {
6491     Dialog* pDialog = m_xBuilder->get<Dialog>(id);
6492     std::unique_ptr<weld::Dialog> pRet(pDialog ? new SalInstanceDialog(pDialog, this, false)
6493                                                : nullptr);
6494     if (bTakeOwnership && pDialog)
6495     {
6496         assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
6497         m_aOwnedToplevel.set(pDialog);
6498         m_xBuilder->drop_ownership(pDialog);
6499     }
6500     return pRet;
6501 }
6502 
6503 std::unique_ptr<weld::Assistant> SalInstanceBuilder::weld_assistant(const OString& id,
6504                                                                     bool bTakeOwnership)
6505 {
6506     vcl::RoadmapWizard* pDialog = m_xBuilder->get<vcl::RoadmapWizard>(id);
6507     std::unique_ptr<weld::Assistant> pRet(pDialog ? new SalInstanceAssistant(pDialog, this, false)
6508                                                   : nullptr);
6509     if (bTakeOwnership && pDialog)
6510     {
6511         assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
6512         m_aOwnedToplevel.set(pDialog);
6513         m_xBuilder->drop_ownership(pDialog);
6514     }
6515     return pRet;
6516 }
6517 
6518 std::unique_ptr<weld::Window> SalInstanceBuilder::create_screenshot_window()
6519 {
6520     assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
6521 
6522     vcl::Window* pRoot = m_xBuilder->get_widget_root();
6523     if (SystemWindow* pWindow = dynamic_cast<SystemWindow*>(pRoot))
6524     {
6525         std::unique_ptr<weld::Window> xRet(new SalInstanceWindow(pWindow, this, false));
6526         m_aOwnedToplevel.set(pWindow);
6527         m_xBuilder->drop_ownership(pWindow);
6528         return xRet;
6529     }
6530 
6531     VclPtrInstance<Dialog> xDialog(nullptr, WB_HIDE | WB_STDDIALOG | WB_SIZEABLE | WB_CLOSEABLE,
6532                                    Dialog::InitFlag::NoParent);
6533     xDialog->SetText(utl::ConfigManager::getProductName());
6534 
6535     auto xContentArea = VclPtr<VclVBox>::Create(xDialog, false, 12);
6536     pRoot->SetParent(xContentArea);
6537     assert(pRoot == xContentArea->GetWindow(GetWindowType::FirstChild));
6538     xContentArea->Show();
6539     pRoot->Show();
6540     xDialog->SetHelpId(pRoot->GetHelpId());
6541 
6542     m_aOwnedToplevel.set(xDialog);
6543 
6544     return std::unique_ptr<weld::Dialog>(new SalInstanceDialog(xDialog, this, false));
6545 }
6546 
6547 std::unique_ptr<weld::Window> SalInstanceBuilder::weld_window(const OString& id,
6548                                                               bool bTakeOwnership)
6549 {
6550     SystemWindow* pWindow = m_xBuilder->get<SystemWindow>(id);
6551     return pWindow ? std::make_unique<SalInstanceWindow>(pWindow, this, bTakeOwnership) : nullptr;
6552 }
6553 
6554 std::unique_ptr<weld::Widget> SalInstanceBuilder::weld_widget(const OString& id,
6555                                                               bool bTakeOwnership)
6556 {
6557     vcl::Window* pWidget = m_xBuilder->get(id);
6558     return pWidget ? std::make_unique<SalInstanceWidget>(pWidget, this, bTakeOwnership) : nullptr;
6559 }
6560 
6561 std::unique_ptr<weld::Container> SalInstanceBuilder::weld_container(const OString& id,
6562                                                                     bool bTakeOwnership)
6563 {
6564     vcl::Window* pContainer = m_xBuilder->get(id);
6565     return pContainer ? std::make_unique<SalInstanceContainer>(pContainer, this, bTakeOwnership)
6566                       : nullptr;
6567 }
6568 
6569 std::unique_ptr<weld::Box> SalInstanceBuilder::weld_box(const OString& id, bool bTakeOwnership)
6570 {
6571     VclBox* pContainer = m_xBuilder->get<VclBox>(id);
6572     return pContainer ? std::make_unique<SalInstanceBox>(pContainer, this, bTakeOwnership)
6573                       : nullptr;
6574 }
6575 
6576 std::unique_ptr<weld::Paned> SalInstanceBuilder::weld_paned(const OString& id,
6577                                                             bool bTakeOwnership)
6578 {
6579     VclPaned* pPaned = m_xBuilder->get<VclPaned>(id);
6580     return pPaned ? std::make_unique<SalInstancePaned>(pPaned, this, bTakeOwnership)
6581                   : nullptr;
6582 }
6583 
6584 std::unique_ptr<weld::Frame> SalInstanceBuilder::weld_frame(const OString& id, bool bTakeOwnership)
6585 {
6586     VclFrame* pFrame = m_xBuilder->get<VclFrame>(id);
6587     std::unique_ptr<weld::Frame> pRet(pFrame ? new SalInstanceFrame(pFrame, this, false) : nullptr);
6588     if (bTakeOwnership && pFrame)
6589     {
6590         assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
6591         m_aOwnedToplevel.set(pFrame);
6592         m_xBuilder->drop_ownership(pFrame);
6593     }
6594     return pRet;
6595 }
6596 
6597 std::unique_ptr<weld::ScrolledWindow> SalInstanceBuilder::weld_scrolled_window(const OString& id,
6598                                                                                bool bTakeOwnership)
6599 {
6600     VclScrolledWindow* pScrolledWindow = m_xBuilder->get<VclScrolledWindow>(id);
6601     return pScrolledWindow
6602                ? std::make_unique<SalInstanceScrolledWindow>(pScrolledWindow, this, bTakeOwnership)
6603                : nullptr;
6604 }
6605 
6606 std::unique_ptr<weld::Notebook> SalInstanceBuilder::weld_notebook(const OString& id,
6607                                                                   bool bTakeOwnership)
6608 {
6609     vcl::Window* pNotebook = m_xBuilder->get(id);
6610     if (!pNotebook)
6611         return nullptr;
6612     if (pNotebook->GetType() == WindowType::TABCONTROL)
6613         return std::make_unique<SalInstanceNotebook>(static_cast<TabControl*>(pNotebook), this,
6614                                                      bTakeOwnership);
6615     if (pNotebook->GetType() == WindowType::VERTICALTABCONTROL)
6616         return std::make_unique<SalInstanceVerticalNotebook>(
6617             static_cast<VerticalTabControl*>(pNotebook), this, bTakeOwnership);
6618     return nullptr;
6619 }
6620 
6621 std::unique_ptr<weld::Button> SalInstanceBuilder::weld_button(const OString& id,
6622                                                               bool bTakeOwnership)
6623 {
6624     Button* pButton = m_xBuilder->get<Button>(id);
6625     return pButton ? std::make_unique<SalInstanceButton>(pButton, this, bTakeOwnership) : nullptr;
6626 }
6627 
6628 std::unique_ptr<weld::MenuButton> SalInstanceBuilder::weld_menu_button(const OString& id,
6629                                                                        bool bTakeOwnership)
6630 {
6631     MenuButton* pButton = m_xBuilder->get<MenuButton>(id);
6632     return pButton ? std::make_unique<SalInstanceMenuButton>(pButton, this, bTakeOwnership)
6633                    : nullptr;
6634 }
6635 
6636 std::unique_ptr<weld::LinkButton> SalInstanceBuilder::weld_link_button(const OString& id,
6637                                                                        bool bTakeOwnership)
6638 {
6639     FixedHyperlink* pButton = m_xBuilder->get<FixedHyperlink>(id);
6640     return pButton ? std::make_unique<SalInstanceLinkButton>(pButton, this, bTakeOwnership)
6641                    : nullptr;
6642 }
6643 
6644 std::unique_ptr<weld::ToggleButton> SalInstanceBuilder::weld_toggle_button(const OString& id,
6645                                                                            bool bTakeOwnership)
6646 {
6647     PushButton* pToggleButton = m_xBuilder->get<PushButton>(id);
6648     return pToggleButton
6649                ? std::make_unique<SalInstanceToggleButton>(pToggleButton, this, bTakeOwnership)
6650                : nullptr;
6651 }
6652 
6653 std::unique_ptr<weld::RadioButton> SalInstanceBuilder::weld_radio_button(const OString& id,
6654                                                                          bool bTakeOwnership)
6655 {
6656     RadioButton* pRadioButton = m_xBuilder->get<RadioButton>(id);
6657     return pRadioButton
6658                ? std::make_unique<SalInstanceRadioButton>(pRadioButton, this, bTakeOwnership)
6659                : nullptr;
6660 }
6661 
6662 std::unique_ptr<weld::CheckButton> SalInstanceBuilder::weld_check_button(const OString& id,
6663                                                                          bool bTakeOwnership)
6664 {
6665     CheckBox* pCheckButton = m_xBuilder->get<CheckBox>(id);
6666     return pCheckButton
6667                ? std::make_unique<SalInstanceCheckButton>(pCheckButton, this, bTakeOwnership)
6668                : nullptr;
6669 }
6670 
6671 std::unique_ptr<weld::Scale> SalInstanceBuilder::weld_scale(const OString& id, bool bTakeOwnership)
6672 {
6673     Slider* pSlider = m_xBuilder->get<Slider>(id);
6674     return pSlider ? std::make_unique<SalInstanceScale>(pSlider, this, bTakeOwnership) : nullptr;
6675 }
6676 
6677 std::unique_ptr<weld::ProgressBar> SalInstanceBuilder::weld_progress_bar(const OString& id,
6678                                                                          bool bTakeOwnership)
6679 {
6680     ::ProgressBar* pProgress = m_xBuilder->get<::ProgressBar>(id);
6681     return pProgress ? std::make_unique<SalInstanceProgressBar>(pProgress, this, bTakeOwnership)
6682                      : nullptr;
6683 }
6684 
6685 std::unique_ptr<weld::Spinner> SalInstanceBuilder::weld_spinner(const OString& id,
6686                                                                 bool bTakeOwnership)
6687 {
6688     Throbber* pThrobber = m_xBuilder->get<Throbber>(id);
6689     return pThrobber ? std::make_unique<SalInstanceSpinner>(pThrobber, this, bTakeOwnership)
6690                      : nullptr;
6691 }
6692 
6693 std::unique_ptr<weld::Image> SalInstanceBuilder::weld_image(const OString& id, bool bTakeOwnership)
6694 {
6695     FixedImage* pImage = m_xBuilder->get<FixedImage>(id);
6696     return pImage ? std::make_unique<SalInstanceImage>(pImage, this, bTakeOwnership) : nullptr;
6697 }
6698 
6699 std::unique_ptr<weld::Calendar> SalInstanceBuilder::weld_calendar(const OString& id,
6700                                                                   bool bTakeOwnership)
6701 {
6702     Calendar* pCalendar = m_xBuilder->get<Calendar>(id);
6703     return pCalendar ? std::make_unique<SalInstanceCalendar>(pCalendar, this, bTakeOwnership)
6704                      : nullptr;
6705 }
6706 
6707 std::unique_ptr<weld::Entry> SalInstanceBuilder::weld_entry(const OString& id, bool bTakeOwnership)
6708 {
6709     Edit* pEntry = m_xBuilder->get<Edit>(id);
6710     return pEntry ? std::make_unique<SalInstanceEntry>(pEntry, this, bTakeOwnership) : nullptr;
6711 }
6712 
6713 std::unique_ptr<weld::SpinButton> SalInstanceBuilder::weld_spin_button(const OString& id,
6714                                                                        bool bTakeOwnership)
6715 {
6716     FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id);
6717     return pSpinButton ? std::make_unique<SalInstanceSpinButton>(pSpinButton, this, bTakeOwnership)
6718                        : nullptr;
6719 }
6720 
6721 std::unique_ptr<weld::MetricSpinButton>
6722 SalInstanceBuilder::weld_metric_spin_button(const OString& id, FieldUnit eUnit, bool bTakeOwnership)
6723 {
6724     std::unique_ptr<weld::SpinButton> xButton(weld_spin_button(id, bTakeOwnership));
6725     if (xButton)
6726     {
6727         SalInstanceSpinButton& rButton = dynamic_cast<SalInstanceSpinButton&>(*xButton);
6728         rButton.SetUseThousandSep();
6729     }
6730     return std::make_unique<weld::MetricSpinButton>(std::move(xButton), eUnit);
6731 }
6732 
6733 std::unique_ptr<weld::FormattedSpinButton>
6734 SalInstanceBuilder::weld_formatted_spin_button(const OString& id, bool bTakeOwnership)
6735 {
6736     FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id);
6737     return pSpinButton
6738                ? std::make_unique<SalInstanceFormattedSpinButton>(pSpinButton, this, bTakeOwnership)
6739                : nullptr;
6740 }
6741 
6742 std::unique_ptr<weld::ComboBox> SalInstanceBuilder::weld_combo_box(const OString& id,
6743                                                                    bool bTakeOwnership)
6744 {
6745     vcl::Window* pWidget = m_xBuilder->get(id);
6746     ::ComboBox* pComboBox = dynamic_cast<::ComboBox*>(pWidget);
6747     if (pComboBox)
6748         return std::make_unique<SalInstanceComboBoxWithEdit>(pComboBox, this, bTakeOwnership);
6749     ListBox* pListBox = dynamic_cast<ListBox*>(pWidget);
6750     return pListBox
6751                ? std::make_unique<SalInstanceComboBoxWithoutEdit>(pListBox, this, bTakeOwnership)
6752                : nullptr;
6753 }
6754 
6755 std::unique_ptr<weld::EntryTreeView>
6756 SalInstanceBuilder::weld_entry_tree_view(const OString& containerid, const OString& entryid,
6757                                          const OString& treeviewid, bool bTakeOwnership)
6758 {
6759     vcl::Window* pContainer = m_xBuilder->get(containerid);
6760     return pContainer ? std::make_unique<SalInstanceEntryTreeView>(
6761                             pContainer, this, bTakeOwnership, weld_entry(entryid, bTakeOwnership),
6762                             weld_tree_view(treeviewid, bTakeOwnership))
6763                       : nullptr;
6764 }
6765 
6766 std::unique_ptr<weld::TreeView> SalInstanceBuilder::weld_tree_view(const OString& id,
6767                                                                    bool bTakeOwnership)
6768 {
6769     SvTabListBox* pTreeView = m_xBuilder->get<SvTabListBox>(id);
6770     return pTreeView ? std::make_unique<SalInstanceTreeView>(pTreeView, this, bTakeOwnership)
6771                      : nullptr;
6772 }
6773 
6774 std::unique_ptr<weld::IconView> SalInstanceBuilder::weld_icon_view(const OString& id,
6775                                                                    bool bTakeOwnership)
6776 {
6777     IconView* pIconView = m_xBuilder->get<IconView>(id);
6778     return pIconView ? std::make_unique<SalInstanceIconView>(pIconView, this, bTakeOwnership)
6779                      : nullptr;
6780 }
6781 
6782 std::unique_ptr<weld::Label> SalInstanceBuilder::weld_label(const OString& id, bool bTakeOwnership)
6783 {
6784     Control* pLabel = m_xBuilder->get<Control>(id);
6785     return pLabel ? std::make_unique<SalInstanceLabel>(pLabel, this, bTakeOwnership) : nullptr;
6786 }
6787 
6788 std::unique_ptr<weld::TextView> SalInstanceBuilder::weld_text_view(const OString& id,
6789                                                                    bool bTakeOwnership)
6790 {
6791     VclMultiLineEdit* pTextView = m_xBuilder->get<VclMultiLineEdit>(id);
6792     return pTextView ? std::make_unique<SalInstanceTextView>(pTextView, this, bTakeOwnership)
6793                      : nullptr;
6794 }
6795 
6796 std::unique_ptr<weld::Expander> SalInstanceBuilder::weld_expander(const OString& id,
6797                                                                   bool bTakeOwnership)
6798 {
6799     VclExpander* pExpander = m_xBuilder->get<VclExpander>(id);
6800     return pExpander ? std::make_unique<SalInstanceExpander>(pExpander, this, bTakeOwnership)
6801                      : nullptr;
6802 }
6803 
6804 std::unique_ptr<weld::DrawingArea>
6805 SalInstanceBuilder::weld_drawing_area(const OString& id, const a11yref& rA11yImpl,
6806                                       FactoryFunction pUITestFactoryFunction, void* pUserData,
6807                                       bool bTakeOwnership)
6808 {
6809     VclDrawingArea* pDrawingArea = m_xBuilder->get<VclDrawingArea>(id);
6810     return pDrawingArea ? std::make_unique<SalInstanceDrawingArea>(pDrawingArea, this, rA11yImpl,
6811                                                                    pUITestFactoryFunction,
6812                                                                    pUserData, bTakeOwnership)
6813                         : nullptr;
6814 }
6815 
6816 std::unique_ptr<weld::Menu> SalInstanceBuilder::weld_menu(const OString& id, bool bTakeOwnership)
6817 {
6818     PopupMenu* pMenu = m_xBuilder->get_menu(id);
6819     return pMenu ? std::make_unique<SalInstanceMenu>(pMenu, bTakeOwnership) : nullptr;
6820 }
6821 
6822 std::unique_ptr<weld::Toolbar> SalInstanceBuilder::weld_toolbar(const OString& id,
6823                                                                 bool bTakeOwnership)
6824 {
6825     ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id);
6826     return pToolBox ? std::make_unique<SalInstanceToolbar>(pToolBox, this, bTakeOwnership)
6827                     : nullptr;
6828 }
6829 
6830 std::unique_ptr<weld::SizeGroup> SalInstanceBuilder::create_size_group()
6831 {
6832     return std::make_unique<SalInstanceSizeGroup>();
6833 }
6834 
6835 OString SalInstanceBuilder::get_current_page_help_id() const
6836 {
6837     TabControl* pCtrl = m_xBuilder->get<TabControl>("tabcontrol");
6838     TabPage* pTabPage = pCtrl ? pCtrl->GetTabPage(pCtrl->GetCurPageId()) : nullptr;
6839     vcl::Window* pTabChild = pTabPage ? pTabPage->GetWindow(GetWindowType::FirstChild) : nullptr;
6840     pTabChild = pTabChild ? pTabChild->GetWindow(GetWindowType::FirstChild) : nullptr;
6841     if (pTabChild)
6842         return pTabChild->GetHelpId();
6843     return OString();
6844 }
6845 
6846 SalInstanceBuilder::~SalInstanceBuilder()
6847 {
6848     if (VclBuilderContainer* pOwnedToplevel
6849         = dynamic_cast<VclBuilderContainer*>(m_aOwnedToplevel.get()))
6850         pOwnedToplevel->m_pUIBuilder = std::move(m_xBuilder);
6851     else
6852         m_xBuilder.reset();
6853     m_aOwnedToplevel.disposeAndClear();
6854 }
6855 
6856 weld::Builder* SalInstance::CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot,
6857                                           const OUString& rUIFile)
6858 {
6859     SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent);
6860     vcl::Window* pParentWidget = pParentInstance ? pParentInstance->getWidget() : nullptr;
6861     return new SalInstanceBuilder(pParentWidget, rUIRoot, rUIFile);
6862 }
6863 
6864 weld::Builder* SalInstance::CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot,
6865                                                  const OUString& rUIFile, bool, sal_uInt64)
6866 {
6867     return new SalInstanceBuilder(pParent, rUIRoot, rUIFile);
6868 }
6869 
6870 void SalInstanceWindow::help()
6871 {
6872     //show help for widget with keyboard focus
6873     vcl::Window* pWidget = ImplGetSVData()->mpWinData->mpFocusWin;
6874     if (!pWidget)
6875         pWidget = m_xWindow;
6876     OString sHelpId = pWidget->GetHelpId();
6877     while (sHelpId.isEmpty())
6878     {
6879         pWidget = pWidget->GetParent();
6880         if (!pWidget)
6881             break;
6882         sHelpId = pWidget->GetHelpId();
6883     }
6884     std::unique_ptr<weld::Widget> xTemp(
6885         pWidget != m_xWindow ? new SalInstanceWidget(pWidget, m_pBuilder, false) : nullptr);
6886     weld::Widget* pSource = xTemp ? xTemp.get() : this;
6887     bool bRunNormalHelpRequest = !m_aHelpRequestHdl.IsSet() || m_aHelpRequestHdl.Call(*pSource);
6888     Help* pHelp = bRunNormalHelpRequest ? Application::GetHelp() : nullptr;
6889     if (!pHelp)
6890         return;
6891 
6892     // tdf#126007, there's a nice fallback route for offline help where
6893     // the current page of a notebook will get checked when the help
6894     // button is pressed and there was no help for the dialog found.
6895     //
6896     // But for online help that route doesn't get taken, so bodge this here
6897     // by using the page help id if available and if the help button itself
6898     // was the original id
6899     if (m_pBuilder && sHelpId.endsWith("/help"))
6900     {
6901         OString sPageId = m_pBuilder->get_current_page_help_id();
6902         if (!sPageId.isEmpty())
6903             sHelpId = sPageId;
6904         else
6905         {
6906             // tdf#129068 likewise the help for the wrapping dialog is less
6907             // helpful than the help for the content area could be
6908             vcl::Window* pContentArea = nullptr;
6909             if (::Dialog* pDialog = dynamic_cast<::Dialog*>(m_xWindow.get()))
6910                 pContentArea = pDialog->get_content_area();
6911             if (pContentArea)
6912             {
6913                 vcl::Window* pContentWidget = pContentArea->GetWindow(GetWindowType::LastChild);
6914                 if (pContentWidget)
6915                     sHelpId = pContentWidget->GetHelpId();
6916             }
6917         }
6918     }
6919     pHelp->Start(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), pSource);
6920 }
6921 
6922 //iterate upwards through the hierarchy from this widgets through its parents
6923 //calling func with their helpid until func returns true or we run out of parents
6924 void SalInstanceWidget::help_hierarchy_foreach(const std::function<bool(const OString&)>& func)
6925 {
6926     vcl::Window* pParent = m_xWidget;
6927     while ((pParent = pParent->GetParent()))
6928     {
6929         if (func(pParent->GetHelpId()))
6930             return;
6931     }
6932 }
6933 
6934 weld::MessageDialog* SalInstance::CreateMessageDialog(weld::Widget* pParent,
6935                                                       VclMessageType eMessageType,
6936                                                       VclButtonsType eButtonsType,
6937                                                       const OUString& rPrimaryMessage)
6938 {
6939     SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent);
6940     SystemWindow* pParentWidget = pParentInstance ? pParentInstance->getSystemWindow() : nullptr;
6941     VclPtrInstance<MessageDialog> xMessageDialog(pParentWidget, rPrimaryMessage, eMessageType,
6942                                                  eButtonsType);
6943     return new SalInstanceMessageDialog(xMessageDialog, nullptr, true);
6944 }
6945 
6946 weld::Window* SalInstance::GetFrameWeld(const css::uno::Reference<css::awt::XWindow>& rWindow)
6947 {
6948     UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
6949     if (!pWrapper)
6950         return nullptr;
6951     VclPtr<vcl::Window> xWindow = pWrapper->GetWindow(rWindow);
6952     if (!xWindow)
6953         return nullptr;
6954     return xWindow->GetFrameWeld();
6955 }
6956 
6957 weld::Window* SalFrame::GetFrameWeld() const
6958 {
6959     if (!m_xFrameWeld)
6960     {
6961         vcl::Window* pWindow = GetWindow();
6962         pWindow = pWindow ? pWindow->ImplGetWindow() : nullptr;
6963         assert(!pWindow || (pWindow->IsSystemWindow() || pWindow->IsDockingWindow()));
6964         if (pWindow)
6965             m_xFrameWeld.reset(new SalInstanceWindow(pWindow, nullptr, false));
6966     }
6967     return m_xFrameWeld.get();
6968 }
6969 
6970 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
6971