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