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