LibreOffice Module vcl (master) 1
salvtables.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <limits>
23#include <string_view>
24
25#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
26#include <com/sun/star/awt/XWindow.hpp>
27#include <com/sun/star/awt/XVclWindowPeer.hpp>
28#include <o3tl/safeint.hxx>
30#include <o3tl/string_view.hxx>
31#include <officecfg/Office/Common.hxx>
32#include <salframe.hxx>
33#include <salinst.hxx>
34#include <salvd.hxx>
35#include <salprn.hxx>
36#include <saltimer.hxx>
37#include <salsession.hxx>
38#include <salsys.hxx>
39#include <salbmp.hxx>
40#include <salobj.hxx>
41#include <salmenu.hxx>
42#include <strings.hrc>
43#include <svdata.hxx>
44#include <svimpbox.hxx>
45#include <messagedialog.hxx>
46#include <treeglue.hxx>
49#include <utility>
50#include <tools/helpers.hxx>
51#include <vcl/abstdlg.hxx>
52#include <vcl/builder.hxx>
55#include <vcl/toolkit/fixed.hxx>
57#include <vcl/headbar.hxx>
59#include <vcl/layout.hxx>
62#include <vcl/ptrstyle.hxx>
63#include <slider.hxx>
64#include <vcl/sysdata.hxx>
67#include <vcl/tabctrl.hxx>
68#include <vcl/tabpage.hxx>
69#include <vcl/toolbox.hxx>
73#include <vcl/weld.hxx>
74#include <vcl/weldutils.hxx>
77#include <vcl/virdev.hxx>
78#include <bitmaps.hlst>
79#include <calendar.hxx>
80#include <menutogglebutton.hxx>
81#include <verticaltabctrl.hxx>
82#include <window.h>
83#include <wizdlg.hxx>
84#include <salvtables.hxx>
85#include <comphelper/lok.hxx>
86
88 : m_pWindow(nullptr)
89 , m_pProc(nullptr)
90{
91}
92
93// this file contains the virtual destructors of the sal interface
94// compilers usually put their vtables where the destructor is
95
97
99{
100 m_pWindow = pWindow;
101 m_pProc = pProc;
102}
103
104// default to full-frame flushes
105// on ports where partial-flushes are much cheaper this method should be overridden
108void SalFrame::SetRepresentedURL(const OUString&)
109{
110 // currently this is Mac only functionality
111}
112
114 tools::Long nHeight, sal_uInt16 nFlags)
115{
116 // assuming the 4 integers normally don't have more than 4 digits, but might be negative
117 OUStringBuffer aBuffer(4 * 5 + 5);
118 if (nFlags & SAL_FRAME_POSSIZE_WIDTH)
119 aBuffer << nWidth << "x";
120 else
121 aBuffer << "?x";
122 if (nFlags & SAL_FRAME_POSSIZE_HEIGHT)
123 aBuffer << nHeight << "@(";
124 else
125 aBuffer << "?@(";
126 if (nFlags & SAL_FRAME_POSSIZE_X)
127 aBuffer << nX << ",";
128 else
129 aBuffer << "?,";
130 if (nFlags & SAL_FRAME_POSSIZE_Y)
131 aBuffer << nY << ")";
132 else
133 aBuffer << "?)";
134 return aBuffer.makeStringAndClear();
135}
136
137SalInstance::SalInstance(std::unique_ptr<comphelper::SolarMutex> pMutex)
138 : m_pYieldMutex(std::move(pMutex))
139{
140}
141
143
145
146sal_uInt32 SalInstance::ReleaseYieldMutexAll() { return m_pYieldMutex->release(true); }
147
148void SalInstance::AcquireYieldMutex(sal_uInt32 nCount) { m_pYieldMutex->acquire(nCount); }
149
150std::unique_ptr<SalSession> SalInstance::CreateSalSession() { return nullptr; }
151
153{
154 assert(!m_bSupportsOpenGL);
155 std::abort();
156}
157
158std::unique_ptr<SalMenu> SalInstance::CreateMenu(bool, Menu*)
159{
160 // default: no native menus
161 return nullptr;
162}
163
164std::unique_ptr<SalMenuItem> SalInstance::CreateMenuItem(const SalItemParams&) { return nullptr; }
165
166bool SalInstance::CallEventCallback(void const* pEvent, int nBytes)
167{
168 return m_pEventInst.is() && m_pEventInst->dispatchEvent(pEvent, nBytes);
169}
170
172{
173 // can't run on system event loop without implementing DoExecute and DoQuit
175 std::abort();
176 return false;
177}
178
180{
182 std::abort();
183}
184
185SalTimer::~SalTimer() COVERITY_NOEXCEPT_FALSE {}
186
188{
189 if (ImplSVData* pSVData = ImplGetSVData())
190 {
191 auto& rCache = pSVData->maGDIData.maScaleCache;
192
193 rCache.remove_if([this](const lru_scale_cache::key_value_pair_t& rKeyValuePair) {
194 return rKeyValuePair.first.mpBitmap == this;
195 });
196 }
197}
198
200
202
204
205bool SalPrinter::StartJob(const OUString*, const OUString&, const OUString&, ImplJobSetup*,
207{
208 return false;
209}
210
212
214
216
218
220{
221 return false;
222}
223
226bool SalMenu::AddMenuBarButton(const SalMenuButtonItem&) { return false; }
229
231{
232 return tools::Rectangle();
233}
234
235int SalMenu::GetMenuBarHeight() const { return 0; }
236
238
240
242{
243private:
250
251 void SetFlash()
252 {
253 Color aColor(Application::GetSettings().GetStyleSettings().GetHighlightColor());
255 }
256
258 {
261 else
263 }
264
265 void Flash()
266 {
267 constexpr int FlashesWanted = 1;
268
269 if (m_nFlashCount % 2 == 0)
270 ClearFlash();
271 else
272 SetFlash();
273
274 if (m_nFlashCount == FlashesWanted * 2)
275 return;
276
278
280 }
281
282 DECL_LINK(FlashTimeout, Timer*, void);
283
284public:
286 : m_xWidget(std::move(xWidget))
287 , m_aFlashTimer("SalFlashAttention")
289 , m_nFlashCount(1)
290 {
293 }
294
295 void Start()
296 {
301 }
302
304};
305
306IMPL_LINK_NOARG(SalFlashAttention, FlashTimeout, Timer*, void) { Flash(); }
307
309{
310 if (!m_bEventListener)
311 {
312 m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, EventListener));
313 m_bEventListener = true;
314 }
315}
316
317// we want the ability to mark key events as handled, so use this variant
318// for those, we get all keystrokes in this case, so we will need to filter
319// them later
321{
323 {
324 Application::AddKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
325 m_bKeyEventListener = true;
326 }
327}
328
329// we want the ability to know about mouse events that happen in our children
330// so use this variant, we will need to filter them later
332{
334 {
335 m_xWidget->AddChildEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
337 }
338}
339
341{
345 {
346 // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under"
347 // transparent children of the widget e.g. expander in sidebar panel header
349 // and toggle mbClipChildren on instead otherwise the bg won't fill e.g.
350 // deck titlebar header when its width is stretched
352 pImpl->mbClipChildren = true;
353 }
354}
355
357 bool bTakeOwnership)
358 : m_xWidget(pWidget)
359 , m_pBuilder(pBuilder)
360 , m_bTakeOwnership(bTakeOwnership)
361 , m_bEventListener(false)
362 , m_bKeyEventListener(false)
363 , m_bMouseEventListener(false)
364 , m_nBlockNotify(0)
365 , m_nFreezeCount(0)
366{
367}
368
369void SalInstanceWidget::set_sensitive(bool sensitive) { m_xWidget->Enable(sensitive); }
370
372
374
376
378{
379 auto nStyle = m_xWidget->GetStyle() & ~(WB_TABSTOP | WB_NOTABSTOP);
380 if (bCanFocus)
381 nStyle |= WB_TABSTOP;
382 else
383 nStyle |= WB_NOTABSTOP;
384 m_xWidget->SetStyle(nStyle);
385}
386
388{
389 if (has_focus())
390 return;
392}
393
395
397
399
401
403
404void SalInstanceWidget::set_size_request(int nWidth, int nHeight)
405{
408}
409
411{
413}
414
416
418{
420}
421
423
424Size SalInstanceWidget::get_pixel_size(const OUString& rText) const
425{
426 //TODO, or do I want GetTextBoundRect ?, just using width at the moment anyway
428}
429
431
433
434void SalInstanceWidget::set_buildable_name(const OUString& rId) { return m_xWidget->set_id(rId); }
435
436void SalInstanceWidget::set_help_id(const OUString& rId) { return m_xWidget->SetHelpId(rId); }
437
439
441{
443}
444
446
448
450{
452}
453
455
456void SalInstanceWidget::set_hexpand(bool bExpand) { m_xWidget->set_hexpand(bExpand); }
457
459
460void SalInstanceWidget::set_vexpand(bool bExpand) { m_xWidget->set_vexpand(bExpand); }
461
463
465
467
469
471
473
475
477
479
480void SalInstanceWidget::set_accessible_name(const OUString& rName)
481{
483}
484
485void SalInstanceWidget::set_accessible_description(const OUString& rDescription)
486{
487 m_xWidget->SetAccessibleDescription(rDescription);
488}
489
491
493{
495}
496
498{
500 pOldLabel->SetAccessibleRelationLabelFor(nullptr);
501 vcl::Window* pA11yLabel
502 = pLabel ? dynamic_cast<SalInstanceWidget&>(*pLabel).getWidget() : nullptr;
504 if (pA11yLabel)
506}
507
508void SalInstanceWidget::set_tooltip_text(const OUString& rTip)
509{
511}
512
514
516{
517 vcl::Cursor* pCursor = static_cast<vcl::Cursor*>(pData);
518 if (!pCursor)
519 return;
520
521 m_xWidget->SetCursor(pCursor);
522}
523
525{
528}
529
531{
532 m_xWidget->SetMnemonicActivateHdl(LINK(this, SalInstanceWidget, MnemonicActivateHdl));
534}
535
537{
540}
541
543{
546}
547
549{
552}
553
555{
558}
559
561{
564}
565
567{
570}
571
573{
576}
577
578IMPL_LINK(SalInstanceWidget, SettingsChangedHdl, VclWindowEvent&, rEvent, void)
579{
580 if (rEvent.GetId() != VclEventId::WindowDataChanged)
581 return;
582
583 DataChangedEvent* pData = static_cast<DataChangedEvent*>(rEvent.GetData());
584 if (pData->GetType() == DataChangedEventType::SETTINGS)
585 m_aStyleUpdatedHdl.Call(*this);
586}
587
589{
590 if (m_aStyleUpdatedHdl.IsSet())
591 m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, SettingsChangedHdl));
593 if (m_aStyleUpdatedHdl.IsSet())
594 m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, SettingsChangedHdl));
595}
596
597bool SalInstanceWidget::get_extents_relative_to(const Widget& rRelative, int& x, int& y, int& width,
598 int& height) const
599{
601 dynamic_cast<const SalInstanceWidget&>(rRelative).getWidget()));
602 x = aRect.Left();
603 y = aRect.Top();
604 width = aRect.GetWidth();
605 height = aRect.GetHeight();
606 return true;
607}
608
610
612
614
616
618
620{
621 if (m_nFreezeCount == 0)
622 m_xWidget->SetUpdateMode(false);
624}
625
627{
629 if (m_nFreezeCount == 0)
631}
632
634{
635 if (!m_xWidget)
636 {
637 return;
638 }
639
640 if (bBusy)
642 else
644}
645
647
649{
650 if (m_aStyleUpdatedHdl.IsSet())
651 m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, SettingsChangedHdl));
652 if (m_aMnemonicActivateHdl.IsSet())
655 m_xWidget->RemoveChildEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
657 Application::RemoveKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
659 m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, EventListener));
662}
663
665
667
669
671
672OUString SalInstanceWidget::strip_mnemonic(const OUString& rLabel) const
673{
674 return rLabel.replaceFirst("~", "");
675}
676
678{
679 // create with (annoying) separate alpha layer that LibreOffice itself uses
682}
683
685{
687 m_xFlashAttention->Start();
688}
689
690css::uno::Reference<css::datatransfer::dnd::XDropTarget> SalInstanceWidget::get_drop_target()
691{
692 return m_xWidget->GetDropTarget();
693}
694
695css::uno::Reference<css::datatransfer::clipboard::XClipboard>
697{
698 return m_xWidget->GetClipboard();
699}
700
702{
704}
705
707{
708 m_xWidget->DumpAsPropertyTree(rJsonWriter);
709}
710
712{
714}
715
717{
719}
720
722{
725}
726
728{
730}
731
733
735{
736 if (rEvent.GetId() == VclEventId::WindowGetFocus)
737 m_aFocusInHdl.Call(*this);
738 else if (rEvent.GetId() == VclEventId::WindowLoseFocus)
739 m_aFocusOutHdl.Call(*this);
740 else if (rEvent.GetId() == VclEventId::WindowResize)
742}
743
744namespace
745{
746MouseEvent TransformEvent(const MouseEvent& rEvent, const vcl::Window* pParent,
747 const vcl::Window* pChild)
748{
749 return MouseEvent(
750 pParent->ScreenToOutputPixel(pChild->OutputToScreenPixel(rEvent.GetPosPixel())),
751 rEvent.GetClicks(), rEvent.GetMode(), rEvent.GetButtons(), rEvent.GetModifier());
752}
753}
754
756{
757 if (rWinEvent.GetId() == VclEventId::WindowMouseButtonDown)
758 {
759 if (m_xWidget == rWinEvent.GetWindow())
760 {
761 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
762 m_aMousePressHdl.Call(*pMouseEvent);
763 }
764 else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
765 {
766 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
767 const MouseEvent aTransformedEvent(
768 TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
769 m_aMousePressHdl.Call(aTransformedEvent);
770 }
771 }
772 else if (rWinEvent.GetId() == VclEventId::WindowMouseButtonUp)
773 {
774 if (m_xWidget == rWinEvent.GetWindow())
775 {
776 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
777 m_aMouseReleaseHdl.Call(*pMouseEvent);
778 }
779 else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
780 {
781 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
782 const MouseEvent aTransformedEvent(
783 TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
784 m_aMouseReleaseHdl.Call(aTransformedEvent);
785 }
786 }
787 else if (rWinEvent.GetId() == VclEventId::WindowMouseMove)
788 {
789 if (m_xWidget == rWinEvent.GetWindow())
790 {
791 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
792 m_aMouseMotionHdl.Call(*pMouseEvent);
793 }
794 else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
795 {
796 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
797 const MouseEvent aTransformedEvent(
798 TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
799 m_aMouseMotionHdl.Call(aTransformedEvent);
800 }
801 }
802}
803
805{
806 // we get all key events here, ignore them unless we have focus
808 return false;
809 if (rEvent.GetId() == VclEventId::WindowKeyInput)
810 {
811 const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
812 return m_aKeyPressHdl.Call(*pKeyEvent);
813 }
814 else if (rEvent.GetId() == VclEventId::WindowKeyUp)
815 {
816 const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
817 return m_aKeyReleaseHdl.Call(*pKeyEvent);
818 }
819 return false;
820}
821
822IMPL_LINK(SalInstanceWidget, EventListener, VclWindowEvent&, rEvent, void)
823{
824 HandleEventListener(rEvent);
825}
826
827IMPL_LINK(SalInstanceWidget, KeyEventListener, VclWindowEvent&, rEvent, bool)
828{
829 return HandleKeyEventListener(rEvent);
830}
831
832IMPL_LINK(SalInstanceWidget, MouseEventListener, VclWindowEvent&, rEvent, void)
833{
834 HandleMouseEventListener(rEvent);
835}
836
837IMPL_LINK_NOARG(SalInstanceWidget, MnemonicActivateHdl, vcl::Window&, bool)
838{
839 return m_aMnemonicActivateHdl.Call(*this);
840}
841
842namespace
843{
844Image createImage(const OUString& rImage)
845{
846 if (rImage.isEmpty())
847 return Image();
848 if (rImage.lastIndexOf('.') != rImage.getLength() - 4)
849 {
850 assert((rImage == "dialog-warning" || rImage == "dialog-error"
851 || rImage == "dialog-information")
852 && "unknown stock image");
853 if (rImage == "dialog-warning")
854 return Image(StockImage::Yes, IMG_WARN);
855 else if (rImage == "dialog-error")
856 return Image(StockImage::Yes, IMG_ERROR);
857 else if (rImage == "dialog-information")
858 return Image(StockImage::Yes, IMG_INFO);
859 }
860 return Image(StockImage::Yes, rImage);
861}
862
863Image createImage(const VirtualDevice& rDevice)
864{
865 return Image(rDevice.GetBitmapEx(Point(), rDevice.GetOutputSizePixel()));
866}
867
868sal_uInt16 insert_to_menu(sal_uInt16 nLastId, PopupMenu* pMenu, int pos, const OUString& rId,
869 const OUString& rStr, const OUString* pIconName,
870 const VirtualDevice* pImageSurface,
871 const css::uno::Reference<css::graphic::XGraphic>& rImage,
872 TriState eCheckRadioFalse)
873{
874 const sal_uInt16 nNewid = nLastId + 1;
875
876 MenuItemBits nBits;
877 if (eCheckRadioFalse == TRISTATE_TRUE)
879 else if (eCheckRadioFalse == TRISTATE_FALSE)
881 else
882 nBits = MenuItemBits::NONE;
883
884 pMenu->InsertItem(nNewid, rStr, nBits, rId, pos == -1 ? MENU_APPEND : pos);
885 if (pIconName)
886 {
887 pMenu->SetItemImage(nNewid, createImage(*pIconName));
888 }
889 else if (pImageSurface)
890 {
891 pMenu->SetItemImage(nNewid, createImage(*pImageSurface));
892 }
893 else if (rImage)
894 {
895 pMenu->SetItemImage(nNewid, Image(rImage));
896 }
897 return nNewid;
898}
899}
900
901SalInstanceMenu::SalInstanceMenu(PopupMenu* pMenu, bool bTakeOwnership)
902 : m_xMenu(pMenu)
903 , m_bTakeOwnership(bTakeOwnership)
904{
905 const auto nCount = m_xMenu->GetItemCount();
906 m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
907 m_xMenu->SetSelectHdl(LINK(this, SalInstanceMenu, SelectMenuHdl));
908}
910 weld::Placement ePlace)
911{
912 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent);
913 assert(pVclWidget);
915 if (ePlace == weld::Placement::Under)
916 eFlags = eFlags | PopupMenuFlags::ExecuteDown;
917 else
918 eFlags = eFlags | PopupMenuFlags::ExecuteRight;
919 m_xMenu->Execute(pVclWidget->getWidget(), rRect, eFlags);
920 return m_xMenu->GetCurItemIdent();
921}
922void SalInstanceMenu::set_sensitive(const OUString& rIdent, bool bSensitive)
923{
924 m_xMenu->EnableItem(rIdent, bSensitive);
925}
926bool SalInstanceMenu::get_sensitive(const OUString& rIdent) const
927{
928 return m_xMenu->IsItemEnabled(m_xMenu->GetItemId(rIdent));
929}
930void SalInstanceMenu::set_active(const OUString& rIdent, bool bActive)
931{
932 m_xMenu->CheckItem(rIdent, bActive);
933}
934bool SalInstanceMenu::get_active(const OUString& rIdent) const
935{
936 return m_xMenu->IsItemChecked(m_xMenu->GetItemId(rIdent));
937}
938void SalInstanceMenu::set_label(const OUString& rIdent, const OUString& rLabel)
939{
940 m_xMenu->SetItemText(m_xMenu->GetItemId(rIdent), rLabel);
941}
942OUString SalInstanceMenu::get_label(const OUString& rIdent) const
943{
944 return m_xMenu->GetItemText(m_xMenu->GetItemId(rIdent));
945}
946void SalInstanceMenu::set_visible(const OUString& rIdent, bool bShow)
947{
948 m_xMenu->ShowItem(m_xMenu->GetItemId(rIdent), bShow);
949}
951void SalInstanceMenu::insert(int pos, const OUString& rId, const OUString& rStr,
952 const OUString* pIconName, VirtualDevice* pImageSurface,
953 const css::uno::Reference<css::graphic::XGraphic>& rImage,
954 TriState eCheckRadioFalse)
955{
956 m_nLastId = insert_to_menu(m_nLastId, m_xMenu, pos, rId, rStr, pIconName, pImageSurface, rImage,
957 eCheckRadioFalse);
958}
959void SalInstanceMenu::insert_separator(int pos, const OUString& rId)
960{
961 auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
962 m_xMenu->InsertSeparator(rId, nInsertPos);
963}
964void SalInstanceMenu::remove(const OUString& rId)
965{
967}
969OUString SalInstanceMenu::get_id(int pos) const
970{
972}
975{
979}
980
982{
983 signal_activate(m_xMenu->GetCurItemIdent());
984 /* tdf#131333 Menu::Select depends on a false here to allow
985 propagating a submens's selected id to its parent menu to become its
986 selected id.
987
988 without this, while gen menus already have propagated this to its parent
989 in MenuFloatingWindow::EndExecute, SalMenus as used under kf5/macOS
990 won't propagate the selected id
991 */
992 return false;
993}
994
996 bool bTakeOwnership)
997 : SalInstanceWidget(pToolBox, pBuilder, bTakeOwnership)
998 , m_xToolBox(pToolBox)
999{
1001 m_xToolBox->SetDropdownClickHdl(LINK(this, SalInstanceToolbar, DropdownClick));
1002}
1003
1004void SalInstanceToolbar::set_item_sensitive(const OUString& rIdent, bool bSensitive)
1005{
1006 m_xToolBox->EnableItem(m_xToolBox->GetItemId(rIdent), bSensitive);
1007}
1008
1009bool SalInstanceToolbar::get_item_sensitive(const OUString& rIdent) const
1010{
1011 return m_xToolBox->IsItemEnabled(m_xToolBox->GetItemId(rIdent));
1012}
1013
1014void SalInstanceToolbar::set_item_visible(const OUString& rIdent, bool bVisible)
1015{
1017}
1018
1019void SalInstanceToolbar::set_item_help_id(const OUString& rIdent, const OUString& rHelpId)
1020{
1021 m_xToolBox->SetHelpId(m_xToolBox->GetItemId(rIdent), rHelpId);
1022}
1023
1024bool SalInstanceToolbar::get_item_visible(const OUString& rIdent) const
1025{
1026 return m_xToolBox->IsItemVisible(m_xToolBox->GetItemId(rIdent));
1027}
1028
1029void SalInstanceToolbar::set_item_active(const OUString& rIdent, bool bActive)
1030{
1031 ToolBoxItemId nItemId = m_xToolBox->GetItemId(rIdent);
1032 m_xToolBox->CheckItem(nItemId, bActive);
1033}
1034
1035bool SalInstanceToolbar::get_item_active(const OUString& rIdent) const
1036{
1037 return m_xToolBox->IsItemChecked(m_xToolBox->GetItemId(rIdent));
1038}
1039
1040void SalInstanceToolbar::set_menu_item_active(const OUString& rIdent, bool bActive)
1041{
1042 ToolBoxItemId nItemId = m_xToolBox->GetItemId(rIdent);
1044
1045 if (bActive)
1046 {
1049 }
1050
1051 auto pFloat = m_aFloats[nItemId];
1052 if (pFloat)
1053 {
1054 if (bActive)
1057 else
1059 }
1060 auto pPopup = m_aMenus[nItemId];
1061 if (pPopup)
1062 {
1063 if (bActive)
1064 {
1065 tools::Rectangle aRect = m_xToolBox->GetItemRect(nItemId);
1066 pPopup->Execute(m_xToolBox, aRect, PopupMenuFlags::ExecuteDown);
1067 }
1068 else
1069 pPopup->EndExecute();
1070 }
1071
1072 m_sStartShowIdent.clear();
1073}
1074
1075bool SalInstanceToolbar::get_menu_item_active(const OUString& rIdent) const
1076{
1077 ToolBoxItemId nItemId = m_xToolBox->GetItemId(rIdent);
1079
1080 if (rIdent == m_sStartShowIdent)
1081 return true;
1082
1083 auto aFloat = m_aFloats.find(nItemId);
1084 if (aFloat != m_aFloats.end())
1085 {
1086 return vcl::Window::GetDockingManager()->IsInPopupMode(aFloat->second);
1087 }
1088
1089 auto aPopup = m_aMenus.find(nItemId);
1090 if (aPopup != m_aMenus.end())
1091 {
1092 return PopupMenu::GetActivePopupMenu() == aPopup->second;
1093 }
1094
1095 return false;
1096}
1097
1098void SalInstanceToolbar::set_item_popover(const OUString& rIdent, weld::Widget* pPopover)
1099{
1100 SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
1101
1102 vcl::Window* pFloat = pPopoverWidget ? pPopoverWidget->getWidget() : nullptr;
1103 if (pFloat)
1104 {
1105 pFloat->AddEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
1106 pFloat->EnableDocking();
1107 }
1108
1110 auto xOldFloat = m_aFloats[nId];
1111 if (xOldFloat)
1112 {
1113 xOldFloat->RemoveEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
1114 }
1115 m_aFloats[nId] = pFloat;
1116 m_aMenus[nId] = nullptr;
1117}
1118
1119void SalInstanceToolbar::set_item_menu(const OUString& rIdent, weld::Menu* pMenu)
1120{
1121 SalInstanceMenu* pInstanceMenu = dynamic_cast<SalInstanceMenu*>(pMenu);
1122
1123 PopupMenu* pPopup = pInstanceMenu ? pInstanceMenu->getMenu() : nullptr;
1124
1126 m_aMenus[nId] = pPopup;
1127 m_aFloats[nId] = nullptr;
1128}
1129
1130void SalInstanceToolbar::insert_item(int pos, const OUString& rId)
1131{
1134}
1135
1136void SalInstanceToolbar::insert_separator(int pos, const OUString& /*rId*/)
1137{
1138 auto nInsertPos = pos == -1 ? ToolBox::APPEND : pos;
1139 m_xToolBox->InsertSeparator(nInsertPos, 5);
1140}
1141
1143
1144OUString SalInstanceToolbar::get_item_ident(int nIndex) const
1145{
1147}
1148
1149void SalInstanceToolbar::set_item_ident(int nIndex, const OUString& rIdent)
1150{
1152}
1153
1154void SalInstanceToolbar::set_item_label(int nIndex, const OUString& rLabel)
1155{
1157}
1158
1159OUString SalInstanceToolbar::get_item_label(const OUString& rIdent) const
1160{
1161 return m_xToolBox->GetItemText(m_xToolBox->GetItemId(rIdent));
1162}
1163
1164void SalInstanceToolbar::set_item_label(const OUString& rIdent, const OUString& rLabel)
1165{
1166 m_xToolBox->SetItemText(m_xToolBox->GetItemId(rIdent), rLabel);
1167}
1168
1169void SalInstanceToolbar::set_item_icon_name(const OUString& rIdent, const OUString& rIconName)
1170{
1172}
1173
1174void SalInstanceToolbar::set_item_image_mirrored(const OUString& rIdent, bool bMirrored)
1175{
1177}
1178
1179void SalInstanceToolbar::set_item_image(const OUString& rIdent,
1180 const css::uno::Reference<css::graphic::XGraphic>& rIcon)
1181{
1183}
1184
1185void SalInstanceToolbar::set_item_image(const OUString& rIdent, VirtualDevice* pDevice)
1186{
1187 if (pDevice)
1188 m_xToolBox->SetItemImage(m_xToolBox->GetItemId(rIdent), createImage(*pDevice));
1189 else
1191}
1192
1194 const css::uno::Reference<css::graphic::XGraphic>& rIcon)
1195{
1197}
1198
1199void SalInstanceToolbar::set_item_tooltip_text(int nIndex, const OUString& rTip)
1200{
1202}
1203
1204void SalInstanceToolbar::set_item_tooltip_text(const OUString& rIdent, const OUString& rTip)
1205{
1207}
1208
1209OUString SalInstanceToolbar::get_item_tooltip_text(const OUString& rIdent) const
1210{
1212}
1213
1215
1217{
1219 switch (eType)
1220 {
1222 eButtonSize = ToolBoxButtonSize::Small;
1223 break;
1225 eButtonSize = ToolBoxButtonSize::Large;
1226 break;
1228 eButtonSize = ToolBoxButtonSize::Size32;
1229 break;
1230 }
1231 if (m_xToolBox->GetToolboxButtonSize() != eButtonSize)
1232 {
1233 m_xToolBox->SetToolboxButtonSize(eButtonSize);
1235 }
1236}
1237
1239
1240int SalInstanceToolbar::get_drop_index(const Point& rPoint) const
1241{
1242 auto nRet = m_xToolBox->GetItemPos(rPoint);
1243 if (nRet == ToolBox::ITEM_NOTFOUND)
1244 return 0;
1245 return nRet;
1246}
1247
1249{
1252}
1253
1255{
1256 ToolBoxItemId nItemId = m_xToolBox->GetCurItemId();
1257 signal_clicked(m_xToolBox->GetItemCommand(nItemId));
1258}
1259
1261{
1262 ToolBoxItemId nItemId = m_xToolBox->GetCurItemId();
1263 set_menu_item_active(m_xToolBox->GetItemCommand(nItemId), true);
1264}
1265
1266IMPL_LINK(SalInstanceToolbar, MenuToggleListener, VclWindowEvent&, rEvent, void)
1267{
1268 if (rEvent.GetId() == VclEventId::WindowEndPopupMode)
1269 {
1270 for (const auto& rFloat : m_aFloats)
1271 {
1272 if (rEvent.GetWindow() == rFloat.second)
1273 {
1274 ToolBoxItemId nItemId = rFloat.first;
1275 signal_toggle_menu(m_xToolBox->GetItemCommand(nItemId));
1276 break;
1277 }
1278 }
1279 }
1280}
1281
1282namespace
1283{
1284class SalInstanceSizeGroup : public weld::SizeGroup
1285{
1286private:
1287 std::shared_ptr<VclSizeGroup> m_xGroup;
1288
1289public:
1290 SalInstanceSizeGroup()
1291 : m_xGroup(std::make_shared<VclSizeGroup>())
1292 {
1293 }
1294 virtual void add_widget(weld::Widget* pWidget) override
1295 {
1296 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1297 assert(pVclWidget && pVclWidget->getWidget());
1298 pVclWidget->getWidget()->add_to_size_group(m_xGroup);
1299 }
1300 virtual void set_mode(VclSizeGroupMode eMode) override { m_xGroup->set_mode(eMode); }
1301};
1302}
1303
1305{
1308}
1309
1311{
1312 if (rEvent.GetId() == VclEventId::WindowActivate
1313 || rEvent.GetId() == VclEventId::WindowDeactivate)
1314 {
1316 return;
1317 }
1319}
1320
1322 bool bTakeOwnership)
1323 : SalInstanceWidget(pContainer, pBuilder, bTakeOwnership)
1324 , m_xContainer(pContainer)
1325{
1326}
1327
1329{
1330 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1331 assert(pVclWidget);
1332 SalInstanceContainer* pNewVclParent = dynamic_cast<SalInstanceContainer*>(pNewParent);
1333 assert(!pNewParent || pNewVclParent);
1334 vcl::Window* pVclWindow = pVclWidget->getWidget();
1335 if (pNewVclParent)
1336 {
1337 vcl::Window* pNew = pNewVclParent->getWidget();
1338 if (!pNew->isDisposed())
1339 pVclWindow->SetParent(pNewVclParent->getWidget());
1340 else
1341 SAL_WARN("vcl", "ignoring move because new parent is already disposed");
1342 }
1343 else
1344 {
1345 pVclWindow->Hide();
1346 pVclWindow->SetParent(ImplGetDefaultWindow());
1347 }
1348}
1349
1351{
1354 pFirstChild->ImplControlFocus();
1355}
1356
1357css::uno::Reference<css::awt::XWindow> SalInstanceContainer::CreateChildFrame()
1358{
1359 auto xPage = VclPtr<VclBin>::Create(m_xContainer.get());
1360 xPage->set_expand(true);
1361 xPage->Show();
1362 return css::uno::Reference<css::awt::XWindow>(xPage->GetComponentInterface(),
1363 css::uno::UNO_QUERY);
1364}
1365
1366std::unique_ptr<weld::Container> SalInstanceWidget::weld_parent() const
1367{
1368 vcl::Window* pParent = m_xWidget->GetParent();
1369 if (!pParent)
1370 return nullptr;
1371 return std::make_unique<SalInstanceContainer>(pParent, m_pBuilder, false);
1372}
1373
1374void SalInstanceWidget::DoRecursivePaint(vcl::Window* pWindow, const Point& rRenderLogicPos,
1375 OutputDevice& rOutput)
1376{
1377 rOutput.Push();
1378 bool bOldMapModeEnabled = pWindow->IsMapModeEnabled();
1379
1380 if (pWindow->GetMapMode().GetMapUnit() != rOutput.GetMapMode().GetMapUnit())
1381 {
1382 // This is needed for e.g. the scrollbar in writer comments in margins that has its map unit in pixels
1383 // as seen with bin/run gtktiledviewer --enable-tiled-annotations on a document containing a comment
1384 // long enough to need a scrollbar
1385 pWindow->EnableMapMode();
1386 MapMode aMapMode = pWindow->GetMapMode();
1387 aMapMode.SetMapUnit(rOutput.GetMapMode().GetMapUnit());
1388 aMapMode.SetScaleX(rOutput.GetMapMode().GetScaleX());
1389 aMapMode.SetScaleY(rOutput.GetMapMode().GetScaleY());
1390 pWindow->SetMapMode(aMapMode);
1391 }
1392
1394 Size aChildSizePixel(pWindow->GetSizePixel());
1395 xOutput->SetOutputSizePixel(aChildSizePixel);
1396
1397 MapMode aMapMode(xOutput->GetMapMode());
1398 aMapMode.SetMapUnit(rOutput.GetMapMode().GetMapUnit());
1399 aMapMode.SetScaleX(rOutput.GetMapMode().GetScaleX());
1400 aMapMode.SetScaleY(rOutput.GetMapMode().GetScaleY());
1401 xOutput->SetMapMode(aMapMode);
1402
1403 Size aTempLogicSize(xOutput->PixelToLogic(aChildSizePixel));
1404 Size aRenderLogicSize(rOutput.PixelToLogic(aChildSizePixel));
1405
1406 switch (rOutput.GetOutDevType())
1407 {
1408 case OUTDEV_WINDOW:
1409 case OUTDEV_VIRDEV:
1410 xOutput->DrawOutDev(Point(), aTempLogicSize, rRenderLogicPos, aRenderLogicSize,
1411 rOutput);
1412 break;
1413 case OUTDEV_PRINTER:
1414 case OUTDEV_PDF:
1415 xOutput->SetBackground(rOutput.GetBackground());
1416 xOutput->Erase();
1417 break;
1418 }
1419
1420 //set ReallyVisible to match Visible, we restore the original state after Paint
1421 WindowImpl* pImpl = pWindow->ImplGetWindowImpl();
1422 bool bRVisible = pImpl->mbReallyVisible;
1423 pImpl->mbReallyVisible = pWindow->IsVisible();
1424
1425 pWindow->ApplySettings(*xOutput);
1426 pWindow->Paint(*xOutput, tools::Rectangle(Point(), pWindow->PixelToLogic(aChildSizePixel)));
1427
1428 pImpl->mbReallyVisible = bRVisible;
1429
1430 switch (rOutput.GetOutDevType())
1431 {
1432 case OUTDEV_WINDOW:
1433 case OUTDEV_VIRDEV:
1434 rOutput.DrawOutDev(rRenderLogicPos, aRenderLogicSize, Point(), aTempLogicSize,
1435 *xOutput);
1436 break;
1437 case OUTDEV_PRINTER:
1438 case OUTDEV_PDF:
1439 rOutput.DrawBitmapEx(rRenderLogicPos, aRenderLogicSize,
1440 xOutput->GetBitmapEx(Point(), aTempLogicSize));
1441 break;
1442 }
1443
1444 bool bHasMirroredGraphics = pWindow->GetOutDev()->HasMirroredGraphics();
1445
1446 xOutput.disposeAndClear();
1447
1448 pWindow->EnableMapMode(bOldMapModeEnabled);
1449 rOutput.Pop();
1450
1451 for (vcl::Window* pChild = pWindow->GetWindow(GetWindowType::FirstChild); pChild;
1452 pChild = pChild->GetWindow(GetWindowType::Next))
1453 {
1454 if (!pChild->IsVisible())
1455 continue;
1456
1457 tools::Long nDeltaX
1458 = pChild->GetOutDev()->GetOutOffXPixel() - pWindow->GetOutDev()->GetOutOffXPixel();
1459 if (bHasMirroredGraphics)
1460 nDeltaX = pWindow->GetOutDev()->GetOutputWidthPixel() - nDeltaX
1461 - pChild->GetOutDev()->GetOutputWidthPixel();
1462
1463 tools::Long nDeltaY
1464 = pChild->GetOutDev()->GetOutOffYPixel() - pWindow->GetOutDev()->GetOutOffYPixel();
1465
1466 Point aPos(rRenderLogicPos);
1467 aPos += Point(nDeltaX, nDeltaY);
1468
1469 DoRecursivePaint(pChild, aPos, rOutput);
1470 }
1471}
1472
1473void SalInstanceWidget::draw(OutputDevice& rOutput, const Point& rPos, const Size& rSizePixel)
1474{
1475 Size aOrigSize(m_xWidget->GetSizePixel());
1476 bool bChangeSize = aOrigSize != rSizePixel;
1477 if (bChangeSize)
1478 m_xWidget->SetSizePixel(rSizePixel);
1479
1480 DoRecursivePaint(m_xWidget, rPos, rOutput);
1481
1482 if (bChangeSize)
1483 m_xWidget->SetSizePixel(aOrigSize);
1484}
1485
1487 bool bTakeOwnership)
1488 : SalInstanceContainer(pContainer, pBuilder, bTakeOwnership)
1489 , m_xBox(pContainer)
1490{
1491}
1492void SalInstanceBox::reorder_child(weld::Widget* pWidget, int nNewPosition)
1493{
1494 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1495 assert(pVclWidget);
1496 pVclWidget->getWidget()->reorderWithinParent(nNewPosition);
1497}
1498
1500
1501namespace
1502{
1503void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& rTopLeft,
1504 weld::ScreenShotCollection& rControlDataCollection)
1505{
1506 if (!rCurrent.IsVisible())
1507 return;
1508
1509 const Point aCurrentPos(rCurrent.GetPosPixel());
1510 const Size aCurrentSize(rCurrent.GetSizePixel());
1511 const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + aCurrentPos.X(),
1512 rTopLeft.getY() + aCurrentPos.Y());
1513 const basegfx::B2IRange aCurrentRange(
1514 aCurrentTopLeft,
1515 aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), aCurrentSize.Height()));
1516
1517 if (!aCurrentRange.isEmpty())
1518 {
1519 rControlDataCollection.emplace_back(rCurrent.GetHelpId(), aCurrentRange);
1520 }
1521
1522 for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++)
1523 {
1524 vcl::Window* pChild = rCurrent.GetChild(a);
1525 if (nullptr != pChild)
1526 {
1527 CollectChildren(*pChild, aCurrentTopLeft, rControlDataCollection);
1528 }
1529 }
1530}
1531}
1532
1534{
1535 for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1536 pChild = pChild->GetWindow(GetWindowType::Next))
1537 override_child_help(pChild);
1538 pParent->SetHelpHdl(LINK(this, SalInstanceWindow, HelpHdl));
1539}
1540
1542{
1543 for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1544 pChild = pChild->GetWindow(GetWindowType::Next))
1545 clear_child_help(pChild);
1547}
1548
1550 bool bTakeOwnership)
1551 : SalInstanceContainer(pWindow, pBuilder, bTakeOwnership)
1552 , m_xWindow(pWindow)
1553{
1554 // tdf#129745 only override child help for the normal case, not for
1555 // m_pBuilder of null which is the toplevel application frame case.
1556 if (m_pBuilder)
1558}
1559
1560void SalInstanceWindow::set_title(const OUString& rTitle) { m_xWindow->SetText(rTitle); }
1561
1562OUString SalInstanceWindow::get_title() const { return m_xWindow->GetText(); }
1563
1564css::uno::Reference<css::awt::XWindow> SalInstanceWindow::GetXWindow()
1565{
1566 css::uno::Reference<css::awt::XWindow> xWindow(m_xWindow->GetComponentInterface(),
1567 css::uno::UNO_QUERY);
1568 return xWindow;
1569}
1570
1571namespace
1572{
1573void resize_to_request(vcl::Window* pWindow)
1574{
1575 if (SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(pWindow))
1576 {
1577 pSysWin->setOptimalLayoutSize(true);
1578 return;
1579 }
1580 if (DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(pWindow))
1581 {
1582 pDockWin->setOptimalLayoutSize();
1583 return;
1585 assert(false && "must be system or docking window");
1586}
1587}
1588
1590
1592
1594
1596
1598
1600
1602{
1604}
1605
1606void SalInstanceWindow::set_centered_on_parent(bool /*bTrackGeometryRequests*/)
1607{
1608 if (vcl::Window* pParent = m_xWidget->GetParent())
1609 {
1610 Size aParentGeometry(pParent->GetSizePixel());
1611 Size aGeometry(m_xWidget->get_preferred_size());
1612 auto nX = (aParentGeometry.Width() - aGeometry.Width()) / 2;
1613 auto nY = (aParentGeometry.Height() - aGeometry.Height()) / 2;
1614 m_xWidget->SetPosPixel(Point(nX, nY));
1615 }
1616}
1617
1619
1623{
1625}
1626
1628{
1629 vcl::Window* pChildLoop = _pWindow->GetWindow(GetWindowType::FirstChild);
1630 while (pChildLoop)
1631 {
1632 // does the window participate in the tabbing order?
1633 if (pChildLoop->GetStyle() & WB_DIALOGCONTROL)
1634 implResetDefault(pChildLoop);
1635
1636 // is it a button?
1637 WindowType eType = pChildLoop->GetType();
1639 || (WindowType::CANCELBUTTON == eType) || (WindowType::HELPBUTTON == eType)
1640 || (WindowType::IMAGEBUTTON == eType) || (WindowType::MENUBUTTON == eType)
1641 || (WindowType::MOREBUTTON == eType))
1642 {
1643 pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON);
1644 }
1645
1646 // the next one ...
1647 pChildLoop = pChildLoop->GetWindow(GetWindowType::Next);
1648 }
1649}
1650
1654{
1655 SalInstanceWidget* pVclNew = dynamic_cast<SalInstanceWidget*>(pNew);
1656 vcl::Window* pWidgetNew = pVclNew ? pVclNew->getWidget() : nullptr;
1657 SalInstanceWidget* pVclOld = dynamic_cast<SalInstanceWidget*>(pOld);
1658 vcl::Window* pWidgetOld = pVclOld ? pVclOld->getWidget() : nullptr;
1659 if (pWidgetOld)
1660 pWidgetOld->set_property("has-default", OUString::boolean(false));
1661 else
1663 if (pWidgetNew)
1664 pWidgetNew->set_property("has-default", OUString::boolean(true));
1665}
1666
1668{
1669 const SalInstanceWidget* pVclCandidate = dynamic_cast<const SalInstanceWidget*>(pCandidate);
1670 vcl::Window* pWidget = pVclCandidate ? pVclCandidate->getWidget() : nullptr;
1671 return pWidget && pWidget->GetStyle() & WB_DEFBUTTON;
1672}
1673
1674void SalInstanceWindow::set_window_state(const OUString& rStr)
1675{
1676 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1677 assert(pSysWin);
1678 pSysWin->SetWindowState(rStr);
1679}
1680
1682{
1683 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1684 assert(pSysWin);
1685 return pSysWin->GetWindowState(nMask);
1686}
1687
1689
1691{
1692 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1693 assert(pSysWin);
1694 return pSysWin->createScreenshot();
1695}
1698{
1700
1701 // collect all children. Choose start pos to be negative
1702 // of target dialog's position to get all positions relative to (0,0)
1703 const Point aParentPos(m_xWindow->GetPosPixel());
1704 const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y());
1705 CollectChildren(*m_xWindow, aTopLeft, aRet);
1706
1707 return aRet;
1708}
1709
1711{
1712 return m_xWindow ? m_xWindow->GetLOKNotifier() : nullptr;
1713}
1714
1716{
1717 // tdf#129745 only undo overriding child help for the normal case, not for
1718 // m_pBuilder of null which is the toplevel application frame case.
1719 if (m_pBuilder)
1721}
1722
1724{
1725 help();
1726 return false;
1727}
1728
1729typedef std::set<VclPtr<vcl::Window>> winset;
1730
1731namespace
1732{
1733void hideUnless(const vcl::Window* pTop, const winset& rVisibleWidgets,
1734 std::vector<VclPtr<vcl::Window>>& rWasVisibleWidgets)
1735{
1736 for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild;
1737 pChild = pChild->GetWindow(GetWindowType::Next))
1738 {
1739 if (!pChild->IsVisible())
1740 continue;
1741 if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
1742 {
1743 rWasVisibleWidgets.emplace_back(pChild);
1744 pChild->Hide();
1745 }
1746 else if (isContainerWindow(pChild))
1747 {
1748 hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
1749 }
1750 }
1751}
1752}
1753
1755 bool bTakeOwnership)
1756 : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership)
1757 , m_xDialog(pDialog)
1758 , m_nOldEditWidthReq(0)
1759 , m_nOldBorderWidth(0)
1760{
1761 const bool bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
1762 if (bScreenshotMode)
1763 {
1764 m_xDialog->SetPopupMenuHdl(LINK(this, SalInstanceDialog, PopupScreenShotMenuHdl));
1765 }
1766}
1767
1768bool SalInstanceDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner,
1769 const std::function<void(sal_Int32)>& rEndDialogFn)
1770{
1772 aCtx.mxOwnerDialogController = aOwner;
1773 aCtx.maEndDialogFn = rEndDialogFn;
1774 VclButtonBox* pActionArea = m_xDialog->get_action_area();
1775 if (pActionArea)
1776 sort_native_button_order(*pActionArea);
1777 return m_xDialog->StartExecuteAsync(aCtx);
1778}
1779
1780bool SalInstanceDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf,
1781 const std::function<void(sal_Int32)>& rEndDialogFn)
1782{
1783 assert(rxSelf.get() == this);
1785 // In order to store a shared_ptr to ourself, we have to have been constructed by make_shared,
1786 // which is that rxSelf enforces.
1787 aCtx.mxOwnerSelf = rxSelf;
1788 aCtx.maEndDialogFn = rEndDialogFn;
1789 VclButtonBox* pActionArea = m_xDialog->get_action_area();
1790 if (pActionArea)
1791 sort_native_button_order(*pActionArea);
1792 return m_xDialog->StartExecuteAsync(aCtx);
1793}
1794
1796{
1797 SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit);
1798 assert(pVclEdit);
1799 SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton);
1800
1801 vcl::Window* pRefEdit = pVclEdit->getWidget();
1802 vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr;
1803
1804 auto nOldEditWidth = pRefEdit->GetSizePixel().Width();
1806
1807 //We want just pRefBtn and pRefEdit to be shown
1808 //mark widgets we want to be visible, starting with pRefEdit
1809 //and all its direct parents.
1810 winset aVisibleWidgets;
1811 vcl::Window* pContentArea = m_xDialog->get_content_area();
1812 for (vcl::Window* pCandidate = pRefEdit;
1813 pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1814 pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1815 {
1816 aVisibleWidgets.insert(pCandidate);
1817 }
1818 //same again with pRefBtn, except stop if there's a
1819 //shared parent in the existing widgets
1820 for (vcl::Window* pCandidate = pRefBtn;
1821 pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1822 pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1823 {
1824 if (aVisibleWidgets.insert(pCandidate).second)
1825 break;
1826 }
1827
1828 //hide everything except the aVisibleWidgets
1829 hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets);
1830
1831 // the insert function case has an initially hidden edit widget, so it has
1832 // not start size, so take larger of actual size and size request
1833 pRefEdit->set_width_request(std::max(nOldEditWidth, m_nOldEditWidthReq));
1834 m_nOldBorderWidth = m_xDialog->get_border_width();
1835 m_xDialog->set_border_width(0);
1836 if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1837 pActionArea->Hide();
1838 m_xDialog->setOptimalLayoutSize(true);
1839 m_xRefEdit = pRefEdit;
1840}
1841
1843{
1844 // All others: Show();
1845 for (VclPtr<vcl::Window> const& pWindow : m_aHiddenWidgets)
1846 {
1847 pWindow->Show();
1848 }
1849 m_aHiddenWidgets.clear();
1850
1852 m_xRefEdit.clear();
1853 m_xDialog->set_border_width(m_nOldBorderWidth);
1854 if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1855 pActionArea->Show();
1856 m_xDialog->setOptimalLayoutSize(true);
1857}
1858
1861{
1862 m_xDialog->SetInstallLOKNotifierHdl(rLink);
1863}
1864
1866{
1867 VclButtonBox* pActionArea = m_xDialog->get_action_area();
1868 if (pActionArea)
1869 sort_native_button_order(*pActionArea);
1870 return m_xDialog->Execute();
1871}
1872
1873void SalInstanceDialog::response(int nResponse) { m_xDialog->EndDialog(nResponse); }
1874
1875void SalInstanceDialog::add_button(const OUString& rText, int nResponse, const OUString& rHelpId)
1876{
1877 VclButtonBox* pBox = m_xDialog->get_action_area();
1878 VclPtr<PushButton> xButton(
1880 xButton->SetText(rText);
1881 xButton->SetHelpId(rHelpId);
1882
1883 switch (nResponse)
1884 {
1885 case RET_OK:
1886 xButton->set_id("ok");
1887 break;
1888 case RET_CLOSE:
1889 xButton->set_id("close");
1890 break;
1891 case RET_CANCEL:
1892 xButton->set_id("cancel");
1893 break;
1894 case RET_YES:
1895 xButton->set_id("yes");
1896 break;
1897 case RET_NO:
1898 xButton->set_id("no");
1899 break;
1900 }
1901
1902 xButton->Show();
1903 m_xDialog->add_button(xButton, nResponse, true);
1904}
1905
1907{
1908 if (get_modal() == bModal)
1909 return;
1910 m_xDialog->SetModalInputMode(bModal);
1911}
1912
1913bool SalInstanceDialog::get_modal() const { return m_xDialog->IsModalInputMode(); }
1914
1916{
1917 m_xDialog->set_default_response(nResponse);
1918}
1919
1921{
1922 return new SalInstanceContainer(m_xDialog->get_content_area(), m_pBuilder, false);
1923}
1924
1925IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, rCEvt, bool)
1926{
1927 if (CommandEventId::ContextMenu == rCEvt.GetCommand())
1928 {
1929 const Point aMenuPos(rCEvt.GetMousePosPixel());
1931 sal_uInt16 nLocalID(1);
1932
1933 aMenu->InsertItem(nLocalID, VclResId(SV_BUTTONTEXT_SCREENSHOT));
1934 aMenu->SetHelpText(nLocalID, VclResId(SV_HELPTEXT_SCREENSHOT));
1935 aMenu->SetHelpId(nLocalID, "InteractiveScreenshotMode");
1936 aMenu->EnableItem(nLocalID);
1937
1938 const sal_uInt16 nId(aMenu->Execute(m_xDialog, aMenuPos));
1939
1940 // 0 == no selection (so not usable as ID)
1941 if (0 != nId)
1942 {
1943 // open screenshot annotation dialog
1946 = pFact->CreateScreenshotAnnotationDlg(*this);
1948
1949 if (pDialog)
1950 {
1951 // currently just execute the dialog, no need to do
1952 // different things for ok/cancel. This may change later,
1953 // for that case use 'if (pDlg->Execute() == RET_OK)'
1954 pDialog->Execute();
1955 }
1956 }
1957
1958 // consume event when:
1959 // - CommandEventId::ContextMenu
1960 // - bScreenshotMode
1961 return true;
1962 }
1963
1964 return false;
1965}
1966
1968 SalInstanceBuilder* pBuilder,
1969 bool bTakeOwnership)
1970 : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1971 , m_xMessageDialog(pDialog)
1972{
1973}
1974
1976{
1977 m_xMessageDialog->set_primary_text(rText);
1978}
1979
1981{
1982 return m_xMessageDialog->get_primary_text();
1983}
1984
1986{
1987 m_xMessageDialog->set_secondary_text(rText);
1988}
1989
1991{
1992 return m_xMessageDialog->get_secondary_text();
1993}
1994
1996{
1997 return new SalInstanceContainer(m_xMessageDialog->get_message_area(), m_pBuilder, false);
1998}
1999
2000int SalInstanceAssistant::find_page(std::u16string_view rIdent) const
2001{
2002 for (size_t i = 0; i < m_aAddedPages.size(); ++i)
2003 {
2004 if (m_aAddedPages[i]->get_id() == rIdent)
2005 return i;
2006 }
2007 return -1;
2008}
2009
2011{
2012 for (size_t i = 0; i < m_aIds.size(); ++i)
2013 {
2014 if (nId == m_aIds[i])
2015 return i;
2016 }
2017 return -1;
2018}
2019
2021 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2022 : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
2023 , m_xWizard(pDialog)
2024 , m_aUpdateRoadmapIdle("SalInstanceAssistant m_aUpdateRoadmapIdle")
2025{
2026 m_xWizard->SetItemSelectHdl(LINK(this, SalInstanceAssistant, OnRoadmapItemSelected));
2027
2030}
2031
2033
2035
2037{
2038 return m_aAddedPages[nPage]->get_id();
2039}
2040
2042{
2044}
2045
2047{
2049
2050 // take the first shown page as the size for all pages
2051 if (m_xWizard->GetPageSizePixel().Width() == 0)
2052 {
2053 Size aFinalSize;
2054 for (int i = 0, nPages = get_n_pages(); i < nPages; ++i)
2055 {
2056 TabPage* pPage = m_xWizard->GetPage(m_aIds[i]);
2057 assert(pPage);
2058 Size aPageSize(pPage->get_preferred_size());
2059 if (aPageSize.Width() > aFinalSize.Width())
2060 aFinalSize.setWidth(aPageSize.Width());
2061 if (aPageSize.Height() > aFinalSize.Height())
2062 aFinalSize.setHeight(aPageSize.Height());
2063 }
2064 m_xWizard->SetPageSizePixel(aFinalSize);
2065 }
2066
2067 (void)m_xWizard->ShowPage(m_aIds[nPage]);
2069}
2070
2071void SalInstanceAssistant::set_current_page(const OUString& rIdent)
2072{
2073 int nIndex = find_page(rIdent);
2074 if (nIndex == -1)
2075 return;
2077}
2078
2079void SalInstanceAssistant::set_page_index(const OUString& rIdent, int nNewIndex)
2080{
2081 int nOldIndex = find_page(rIdent);
2082
2083 if (nOldIndex == -1)
2084 return;
2085
2086 if (nOldIndex == nNewIndex)
2087 return;
2088
2090
2091 auto entry = std::move(m_aAddedPages[nOldIndex]);
2092 m_aAddedPages.erase(m_aAddedPages.begin() + nOldIndex);
2093 m_aAddedPages.insert(m_aAddedPages.begin() + nNewIndex, std::move(entry));
2094
2095 int nId = m_aIds[nOldIndex];
2096 m_aIds.erase(m_aIds.begin() + nOldIndex);
2097 m_aIds.insert(m_aIds.begin() + nNewIndex, nId);
2098
2100
2102}
2103
2105{
2107 VclPtrInstance<VclGrid> xGrid(xPage);
2108 xPage->set_id(rIdent);
2109 xPage->Show();
2110 xGrid->set_hexpand(true);
2111 xGrid->set_vexpand(true);
2112 xGrid->Show();
2113 m_xWizard->AddPage(xPage);
2114 m_aIds.push_back(m_aAddedPages.size());
2115 m_xWizard->SetPage(m_aIds.back(), xPage);
2116 m_aAddedPages.push_back(xPage);
2117 m_aAddedGrids.push_back(xGrid);
2118
2120
2121 m_aPages.emplace_back(new SalInstanceContainer(xGrid, m_pBuilder, false));
2122 return m_aPages.back().get();
2123}
2124
2125OUString SalInstanceAssistant::get_page_title(const OUString& rIdent) const
2126{
2127 int nIndex = find_page(rIdent);
2128 if (nIndex == -1)
2129 return OUString();
2130 return m_aAddedPages[nIndex]->GetText();
2131}
2132
2133void SalInstanceAssistant::set_page_title(const OUString& rIdent, const OUString& rTitle)
2134{
2135 int nIndex = find_page(rIdent);
2136 if (nIndex == -1)
2137 return;
2138 if (m_aAddedPages[nIndex]->GetText() != rTitle)
2139 {
2141 m_aAddedPages[nIndex]->SetText(rTitle);
2144 }
2145}
2146
2147void SalInstanceAssistant::set_page_sensitive(const OUString& rIdent, bool bSensitive)
2148{
2149 int nIndex = find_page(rIdent);
2150 if (nIndex == -1)
2151 return;
2152 if (m_aAddedPages[nIndex]->IsEnabled() != bSensitive)
2153 {
2155 m_aAddedPages[nIndex]->Enable(bSensitive);
2158 }
2159}
2160
2162{
2163 m_xWizard->SetRoadmapHelpId(rHelpId);
2164}
2165
2167{
2168 m_xWizard->SetRoadmapBitmap(createImage(rImage).GetBitmapEx());
2169}
2170
2172{
2173 for (auto& rGrid : m_aAddedGrids)
2174 rGrid.disposeAndClear();
2175 for (auto& rPage : m_aAddedPages)
2176 rPage.disposeAndClear();
2177}
2178
2180{
2181 if (notify_events_disabled())
2182 return;
2183 auto nCurItemId = m_xWizard->GetCurrentRoadmapItemID();
2184 int nPageIndex(find_id(nCurItemId));
2185 if (!signal_jump_page(get_page_ident(nPageIndex)) && nCurItemId != m_xWizard->GetCurLevel())
2186 m_xWizard->SelectRoadmapItemByID(m_xWizard->GetCurLevel());
2187}
2188
2189IMPL_LINK_NOARG(SalInstanceAssistant, UpdateRoadmap_Hdl, Timer*, void)
2190{
2191 disable_notify_events();
2192
2193 m_xWizard->DeleteRoadmapItems();
2194
2195 int nPos = 0;
2196 for (size_t i = 0; i < m_aAddedPages.size(); ++i)
2197 {
2198 const OUString& rLabel = m_aAddedPages[i]->GetText();
2199 bool bSensitive = m_aAddedPages[i]->IsEnabled();
2200 if (rLabel.isEmpty())
2201 continue;
2202 m_xWizard->InsertRoadmapItem(nPos++, rLabel, m_aIds[i], bSensitive);
2203 }
2204
2205 m_xWizard->SelectRoadmapItemByID(m_aIds[get_current_page()], false);
2206
2207 m_xWizard->ShowRoadmap(nPos != 0);
2208
2209 enable_notify_events();
2210}
2211
2213 bool bTakeOwnership)
2214 : SalInstanceContainer(pFrame, pBuilder, bTakeOwnership)
2215 , m_xFrame(pFrame)
2216{
2217}
2218
2219void SalInstanceFrame::set_label(const OUString& rText) { m_xFrame->set_label(rText); }
2220
2221OUString SalInstanceFrame::get_label() const { return m_xFrame->get_label(); }
2222
2223namespace
2224{
2225class SalInstancePaned : public SalInstanceContainer, public virtual weld::Paned
2226{
2227private:
2228 VclPtr<VclPaned> m_xPaned;
2229
2230public:
2231 SalInstancePaned(VclPaned* pPaned, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2232 : SalInstanceContainer(pPaned, pBuilder, bTakeOwnership)
2233 , m_xPaned(pPaned)
2234 {
2235 }
2236
2237 virtual void set_position(int nPos) override { m_xPaned->set_position(nPos); }
2238
2239 virtual int get_position() const override { return m_xPaned->get_position(); }
2240};
2241}
2242
2244 const Color& rButtonTextColor,
2245 const Color& rBackgroundColor,
2246 const Color& rShadowColor,
2247 const Color& rFaceColor)
2248{
2249 rScrollBar.EnableNativeWidget(false);
2250 AllSettings aSettings = rScrollBar.GetSettings();
2251 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2252 aStyleSettings.SetButtonTextColor(rButtonTextColor);
2253 aStyleSettings.SetCheckedColor(rBackgroundColor); // background
2254 aStyleSettings.SetShadowColor(rShadowColor);
2255 aStyleSettings.SetFaceColor(rFaceColor);
2256 aSettings.SetStyleSettings(aStyleSettings);
2257 rScrollBar.SetSettings(aSettings);
2258}
2259
2261 SalInstanceBuilder* pBuilder,
2262 bool bTakeOwnership,
2263 bool bUserManagedScrolling)
2264 : SalInstanceContainer(pScrolledWindow, pBuilder, bTakeOwnership)
2265 , m_xScrolledWindow(pScrolledWindow)
2266 , m_bUserManagedScrolling(bUserManagedScrolling)
2267{
2268 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2269 m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl();
2270 rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, VscrollHdl));
2271 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2272 m_aOrigHScrollHdl = rHorzScrollBar.GetScrollHdl();
2273 rHorzScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, HscrollHdl));
2275}
2276
2277void SalInstanceScrolledWindow::hadjustment_configure(int value, int lower, int upper,
2278 int step_increment, int page_increment,
2279 int page_size)
2280{
2281 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2282 rHorzScrollBar.SetRangeMin(lower);
2283 rHorzScrollBar.SetRangeMax(upper);
2284 rHorzScrollBar.SetLineSize(step_increment);
2285 rHorzScrollBar.SetPageSize(page_increment);
2286 rHorzScrollBar.SetThumbPos(value);
2287 rHorzScrollBar.SetVisibleSize(page_size);
2288}
2289
2291{
2292 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2293 return rHorzScrollBar.GetThumbPos();
2294}
2295
2297{
2298 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2299 rHorzScrollBar.SetThumbPos(value);
2301 m_aOrigHScrollHdl.Call(&rHorzScrollBar);
2302}
2303
2305{
2306 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2307 return rHorzScrollBar.GetRangeMax();
2308}
2309
2311{
2312 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2313 rHorzScrollBar.SetRangeMax(upper);
2314}
2315
2317{
2318 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2319 return rHorzScrollBar.GetVisibleSize();
2320}
2321
2323{
2324 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2325 return rHorzScrollBar.SetVisibleSize(size);
2326}
2327
2329{
2330 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2331 return rHorzScrollBar.SetPageSize(size);
2332}
2333
2335{
2336 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2337 return rHorzScrollBar.SetLineSize(size);
2338}
2339
2341{
2342 WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOHSCROLL | WB_HSCROLL);
2343 if (eHPolicy == VclPolicyType::ALWAYS)
2344 nWinBits |= WB_HSCROLL;
2345 else if (eHPolicy == VclPolicyType::AUTOMATIC)
2346 nWinBits |= WB_AUTOHSCROLL;
2347 m_xScrolledWindow->SetStyle(nWinBits);
2348 m_xScrolledWindow->queue_resize();
2349}
2350
2352{
2353 WinBits nWinBits = m_xScrolledWindow->GetStyle();
2354 if (nWinBits & WB_AUTOHSCROLL)
2356 else if (nWinBits & WB_HSCROLL)
2357 return VclPolicyType::ALWAYS;
2358 return VclPolicyType::NEVER;
2359}
2360
2361void SalInstanceScrolledWindow::vadjustment_configure(int value, int lower, int upper,
2362 int step_increment, int page_increment,
2363 int page_size)
2364{
2365 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2366 rVertScrollBar.SetRangeMin(lower);
2367 rVertScrollBar.SetRangeMax(upper);
2368 rVertScrollBar.SetLineSize(step_increment);
2369 rVertScrollBar.SetPageSize(page_increment);
2370 rVertScrollBar.SetThumbPos(value);
2371 rVertScrollBar.SetVisibleSize(page_size);
2372}
2373
2375{
2376 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2377 return rVertScrollBar.GetThumbPos();
2378}
2379
2381{
2382 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2383 rVertScrollBar.SetThumbPos(value);
2385 m_aOrigVScrollHdl.Call(&rVertScrollBar);
2386}
2387
2389{
2390 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2391 return rVertScrollBar.GetRangeMax();
2392}
2393
2395{
2396 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2397 rVertScrollBar.SetRangeMax(upper);
2398}
2399
2401{
2402 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2403 return rVertScrollBar.GetRangeMin();
2404}
2405
2407{
2408 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2409 rVertScrollBar.SetRangeMin(lower);
2410}
2411
2413{
2414 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2415 return rVertScrollBar.GetVisibleSize();
2416}
2417
2419{
2420 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2421 return rVertScrollBar.SetVisibleSize(size);
2422}
2423
2425{
2426 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2427 return rVertScrollBar.SetPageSize(size);
2428}
2429
2431{
2432 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2433 return rVertScrollBar.SetLineSize(size);
2434}
2435
2437{
2438 WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOVSCROLL | WB_VSCROLL);
2439 if (eVPolicy == VclPolicyType::ALWAYS)
2440 nWinBits |= WB_VSCROLL;
2441 else if (eVPolicy == VclPolicyType::AUTOMATIC)
2442 nWinBits |= WB_AUTOVSCROLL;
2443 m_xScrolledWindow->SetStyle(nWinBits);
2444 m_xScrolledWindow->queue_resize();
2445}
2446
2448{
2449 WinBits nWinBits = m_xScrolledWindow->GetStyle();
2450 if (nWinBits & WB_AUTOVSCROLL)
2452 else if (nWinBits & WB_VSCROLL)
2453 return VclPolicyType::ALWAYS;
2454 return VclPolicyType::NEVER;
2455}
2456
2458{
2460}
2461
2463{
2464 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2465 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2466 rHorzScrollBar.set_height_request(nThickness);
2467 rVertScrollBar.set_width_request(nThickness);
2468}
2469
2471 const Color& rShadowColor,
2472 const Color& rFaceColor)
2473{
2474 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
2475 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2476 customize_scrollbars(rHorzScrollBar, Color(0, 0, 0), rBackgroundColor, rShadowColor,
2477 rFaceColor);
2478 customize_scrollbars(rVertScrollBar, Color(0, 0, 0), rBackgroundColor, rShadowColor,
2479 rFaceColor);
2480}
2481
2483{
2484 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2485 rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl);
2486}
2487
2488IMPL_LINK(SalInstanceScrolledWindow, VscrollHdl, ScrollBar*, pScrollBar, void)
2489{
2490 signal_vadjustment_changed();
2491 if (!m_bUserManagedScrolling)
2492 m_aOrigVScrollHdl.Call(pScrollBar);
2493}
2494
2496{
2497 signal_hadjustment_changed();
2498 if (!m_bUserManagedScrolling)
2499 m_aOrigHScrollHdl.Call(&m_xScrolledWindow->getHorzScrollBar());
2500}
2501
2502namespace
2503{
2504class SalInstanceScrollbar : public SalInstanceWidget, public virtual weld::Scrollbar
2505{
2506private:
2507 VclPtr<ScrollBar> m_xScrollBar;
2508
2509 DECL_LINK(ScrollHdl, ScrollBar*, void);
2510
2511public:
2512 SalInstanceScrollbar(ScrollBar* pScrollbar, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2513 : SalInstanceWidget(pScrollbar, pBuilder, bTakeOwnership)
2514 , m_xScrollBar(pScrollbar)
2515 {
2516 m_xScrollBar->SetScrollHdl(LINK(this, SalInstanceScrollbar, ScrollHdl));
2517 m_xScrollBar->EnableDrag();
2518 }
2519
2520 virtual void adjustment_configure(int value, int lower, int upper, int step_increment,
2521 int page_increment, int page_size) override
2522 {
2523 m_xScrollBar->SetRangeMin(lower);
2524 m_xScrollBar->SetRangeMax(upper);
2525 m_xScrollBar->SetLineSize(step_increment);
2526 m_xScrollBar->SetPageSize(page_increment);
2527 m_xScrollBar->SetThumbPos(value);
2528 m_xScrollBar->SetVisibleSize(page_size);
2529 }
2530
2531 virtual int adjustment_get_value() const override { return m_xScrollBar->GetThumbPos(); }
2532
2533 virtual void adjustment_set_value(int value) override { m_xScrollBar->SetThumbPos(value); }
2534
2535 virtual int adjustment_get_upper() const override { return m_xScrollBar->GetRangeMax(); }
2536
2537 virtual void adjustment_set_upper(int upper) override { m_xScrollBar->SetRangeMax(upper); }
2538
2539 virtual int adjustment_get_lower() const override { return m_xScrollBar->GetRangeMin(); }
2540
2541 virtual void adjustment_set_lower(int lower) override { m_xScrollBar->SetRangeMin(lower); }
2542
2543 virtual int adjustment_get_page_size() const override { return m_xScrollBar->GetVisibleSize(); }
2544
2545 virtual void adjustment_set_page_size(int size) override { m_xScrollBar->SetVisibleSize(size); }
2546
2547 virtual int adjustment_get_page_increment() const override
2548 {
2549 return m_xScrollBar->GetPageSize();
2550 }
2551
2552 virtual void adjustment_set_page_increment(int size) override
2553 {
2554 m_xScrollBar->SetPageSize(size);
2555 }
2556
2557 virtual int adjustment_get_step_increment() const override
2558 {
2559 return m_xScrollBar->GetLineSize();
2560 }
2561
2562 virtual void adjustment_set_step_increment(int size) override
2563 {
2564 m_xScrollBar->SetLineSize(size);
2565 }
2566
2567 virtual ScrollType get_scroll_type() const override { return m_xScrollBar->GetType(); }
2568
2569 virtual int get_scroll_thickness() const override
2570 {
2571 if (m_xScrollBar->GetStyle() & WB_HORZ)
2572 return m_xScrollBar->get_preferred_size().Height();
2573 return m_xScrollBar->get_preferred_size().Width();
2574 }
2575
2576 virtual void set_scroll_thickness(int nThickness) override
2577 {
2578 if (m_xScrollBar->GetStyle() & WB_HORZ)
2579 m_xScrollBar->set_height_request(nThickness);
2580 else
2581 m_xScrollBar->set_width_request(nThickness);
2582 }
2583};
2584}
2585
2586IMPL_LINK_NOARG(SalInstanceScrollbar, ScrollHdl, ScrollBar*, void) { signal_adjustment_changed(); }
2587
2589 bool bTakeOwnership)
2590 : SalInstanceWidget(pNotebook, pBuilder, bTakeOwnership)
2591 , m_xNotebook(pNotebook)
2592{
2593 m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceNotebook, ActivatePageHdl));
2594 m_xNotebook->SetDeactivatePageHdl(LINK(this, SalInstanceNotebook, DeactivatePageHdl));
2595}
2596
2598{
2600}
2601
2603{
2605}
2606
2608{
2610}
2611
2612int SalInstanceNotebook::get_page_index(const OUString& rIdent) const
2613{
2614 sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2615 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2616 if (nPageIndex == TAB_PAGE_NOTFOUND)
2617 return -1;
2618 return nPageIndex;
2619}
2620
2622{
2623 int nPageIndex = get_page_index(rIdent);
2624 if (nPageIndex == -1)
2625 return nullptr;
2626 sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2628 vcl::Window* pChild = pPage->GetChild(0);
2629 if (m_aPages.size() < nPageIndex + 1U)
2630 m_aPages.resize(nPageIndex + 1U);
2631 if (!m_aPages[nPageIndex])
2632 m_aPages[nPageIndex] = std::make_shared<SalInstanceContainer>(pChild, m_pBuilder, false);
2633 return m_aPages[nPageIndex].get();
2634}
2635
2637{
2639}
2640
2641void SalInstanceNotebook::set_current_page(const OUString& rIdent)
2642{
2644}
2645
2646void SalInstanceNotebook::remove_page(const OUString& rIdent)
2647{
2648 sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2649 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2650 if (nPageIndex == TAB_PAGE_NOTFOUND)
2651 return;
2652
2654 if (nPageIndex < m_aPages.size())
2655 m_aPages.erase(m_aPages.begin() + nPageIndex);
2656
2657 auto iter = m_aAddedPages.find(rIdent);
2658 if (iter != m_aAddedPages.end())
2659 {
2660 iter->second.second.disposeAndClear();
2661 iter->second.first.disposeAndClear();
2662 m_aAddedPages.erase(iter);
2663 }
2664}
2665
2666void SalInstanceNotebook::insert_page(const OUString& rIdent, const OUString& rLabel, int nPos)
2667{
2668 sal_uInt16 nPageCount = m_xNotebook->GetPageCount();
2669 sal_uInt16 nLastPageId = nPageCount ? m_xNotebook->GetPageId(nPageCount - 1) : 0;
2670 sal_uInt16 nNewPageId = nLastPageId + 1;
2671 while (m_xNotebook->GetPagePos(nNewPageId) != TAB_PAGE_NOTFOUND)
2672 ++nNewPageId;
2673 m_xNotebook->InsertPage(nNewPageId, rLabel, nPos == -1 ? TAB_APPEND : nPos);
2675 VclPtrInstance<VclGrid> xGrid(xPage);
2676 xPage->Show();
2677 xGrid->set_hexpand(true);
2678 xGrid->set_vexpand(true);
2679 xGrid->Show();
2680 m_xNotebook->SetTabPage(nNewPageId, xPage);
2681 m_xNotebook->SetPageName(nNewPageId, rIdent);
2682 m_aAddedPages.try_emplace(rIdent, xPage, xGrid);
2683
2684 if (nPos != -1)
2685 {
2686 unsigned int nPageIndex = static_cast<unsigned int>(nPos);
2687 if (nPageIndex < m_aPages.size())
2688 m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr);
2689 }
2690}
2691
2693
2694OUString SalInstanceNotebook::get_tab_label_text(const OUString& rIdent) const
2695{
2696 return m_xNotebook->GetPageText(m_xNotebook->GetPageId(rIdent));
2697}
2698
2699void SalInstanceNotebook::set_tab_label_text(const OUString& rIdent, const OUString& rText)
2700{
2701 return m_xNotebook->SetPageText(m_xNotebook->GetPageId(rIdent), rText);
2702}
2703
2705{
2706 m_xNotebook->set_property("show-tabs", OUString::boolean(bShow));
2707}
2708
2710{
2711 for (auto& rItem : m_aAddedPages)
2712 {
2713 rItem.second.second.disposeAndClear();
2714 rItem.second.first.disposeAndClear();
2715 }
2718}
2719
2721{
2722 return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2723}
2724
2726{
2727 m_aEnterPageHdl.Call(get_current_page_ident());
2728}
2729
2730namespace
2731{
2732class SalInstanceVerticalNotebook : public SalInstanceWidget, public virtual weld::Notebook
2733{
2734private:
2735 VclPtr<VerticalTabControl> m_xNotebook;
2736 mutable std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
2737
2738 DECL_LINK(DeactivatePageHdl, VerticalTabControl*, bool);
2739 DECL_LINK(ActivatePageHdl, VerticalTabControl*, void);
2740
2741public:
2742 SalInstanceVerticalNotebook(VerticalTabControl* pNotebook, SalInstanceBuilder* pBuilder,
2743 bool bTakeOwnership)
2744 : SalInstanceWidget(pNotebook, pBuilder, bTakeOwnership)
2745 , m_xNotebook(pNotebook)
2746 {
2747 m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceVerticalNotebook, ActivatePageHdl));
2748 m_xNotebook->SetDeactivatePageHdl(
2749 LINK(this, SalInstanceVerticalNotebook, DeactivatePageHdl));
2750 }
2751
2752 virtual int get_current_page() const override
2753 {
2754 return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId());
2755 }
2756
2757 virtual OUString get_page_ident(int nPage) const override
2758 {
2759 return m_xNotebook->GetPageId(nPage);
2760 }
2761
2762 virtual OUString get_current_page_ident() const override { return m_xNotebook->GetCurPageId(); }
2763
2764 virtual int get_page_index(const OUString& rIdent) const override
2765 {
2766 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2767 if (nPageIndex == TAB_PAGE_NOTFOUND)
2768 return -1;
2769 return nPageIndex;
2770 }
2771
2772 virtual weld::Container* get_page(const OUString& rIdent) const override
2773 {
2774 int nPageIndex = get_page_index(rIdent);
2775 if (nPageIndex == -1)
2776 return nullptr;
2777 auto pChild = m_xNotebook->GetPage(rIdent);
2778 if (m_aPages.size() < nPageIndex + 1U)
2779 m_aPages.resize(nPageIndex + 1U);
2780 if (!m_aPages[nPageIndex])
2781 m_aPages[nPageIndex].reset(new SalInstanceContainer(pChild, m_pBuilder, false));
2782 return m_aPages[nPageIndex].get();
2783 }
2784
2785 virtual void set_current_page(int nPage) override
2786 {
2787 m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage));
2788 }
2789
2790 virtual void set_current_page(const OUString& rIdent) override
2791 {
2792 m_xNotebook->SetCurPageId(rIdent);
2793 }
2794
2795 virtual void remove_page(const OUString& rIdent) override
2796 {
2797 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2798 if (nPageIndex == TAB_PAGE_NOTFOUND)
2799 return;
2800 m_xNotebook->RemovePage(rIdent);
2801 if (nPageIndex < m_aPages.size())
2802 m_aPages.erase(m_aPages.begin() + nPageIndex);
2803 }
2804
2805 virtual void insert_page(const OUString& rIdent, const OUString& rLabel, int nPos) override
2806 {
2807 VclPtrInstance<VclGrid> xGrid(m_xNotebook->GetPageParent());
2808 xGrid->set_hexpand(true);
2809 xGrid->set_vexpand(true);
2810 m_xNotebook->InsertPage(rIdent, rLabel, Image(), "", xGrid, nPos);
2811
2812 if (nPos != -1)
2813 {
2814 unsigned int nPageIndex = static_cast<unsigned int>(nPos);
2815 if (nPageIndex < m_aPages.size())
2816 m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr);
2817 }
2818 }
2819
2820 virtual int get_n_pages() const override { return m_xNotebook->GetPageCount(); }
2821
2822 virtual void set_tab_label_text(const OUString& rIdent, const OUString& rText) override
2823 {
2824 return m_xNotebook->SetPageText(rIdent, rText);
2825 }
2826
2827 virtual OUString get_tab_label_text(const OUString& rIdent) const override
2828 {
2829 return m_xNotebook->GetPageText(rIdent);
2830 }
2831
2832 virtual void set_show_tabs(bool /*bShow*/) override
2833 {
2834 // if someone needs this they will have to implement it in VerticalTabControl
2835 assert(false && "not implemented");
2836 }
2837
2838 virtual ~SalInstanceVerticalNotebook() override
2839 {
2842 }
2843};
2844}
2845
2846IMPL_LINK_NOARG(SalInstanceVerticalNotebook, DeactivatePageHdl, VerticalTabControl*, bool)
2847{
2848 return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2849}
2850
2851IMPL_LINK_NOARG(SalInstanceVerticalNotebook, ActivatePageHdl, VerticalTabControl*, void)
2852{
2853 m_aEnterPageHdl.Call(get_current_page_ident());
2854}
2855
2857 bool bTakeOwnership)
2858 : SalInstanceWidget(pButton, pBuilder, bTakeOwnership)
2859 , m_xButton(pButton)
2860 , m_aOldClickHdl(pButton->GetClickHdl())
2861{
2862 m_xButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2863}
2864
2865void SalInstanceButton::set_label(const OUString& rText) { m_xButton->SetText(rText); }
2866
2868{
2869 m_xButton->SetImageAlign(ImageAlign::Left);
2870 if (pDevice)
2871 m_xButton->SetModeImage(createImage(*pDevice));
2872 else
2873 m_xButton->SetModeImage(Image());
2874}
2875
2876void SalInstanceButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage)
2877{
2878 m_xButton->SetImageAlign(ImageAlign::Left);
2879 m_xButton->SetModeImage(Image(rImage));
2880}
2881
2882void SalInstanceButton::set_from_icon_name(const OUString& rIconName)
2883{
2884 m_xButton->SetModeImage(Image(StockImage::Yes, rIconName));
2885}
2886
2888{
2889 WinBits nBits = m_xButton->GetStyle();
2890 nBits &= ~WB_WORDBREAK;
2891 if (wrap)
2892 nBits |= WB_WORDBREAK;
2893 m_xButton->SetStyle(nBits);
2894 m_xButton->queue_resize();
2895}
2896
2898{
2899 m_xButton->SetControlFont(rFont);
2900 m_xButton->Invalidate();
2901}
2902
2904{
2905 if (pDevice)
2906 m_xButton->SetCustomButtonImage(createImage(*pDevice));
2907 else
2908 m_xButton->SetCustomButtonImage(Image());
2909 m_xButton->Invalidate();
2910}
2911
2912OUString SalInstanceButton::get_label() const { return m_xButton->GetText(); }
2913
2915
2916IMPL_LINK(SalInstanceButton, ClickHdl, ::Button*, pButton, void)
2917{
2918 //if there's no handler set, disengage our intercept and
2919 //run the click again to get default behaviour for cancel/ok
2920 //etc buttons.
2921 if (!m_aClickHdl.IsSet())
2922 {
2923 pButton->SetClickHdl(m_aOldClickHdl);
2924 pButton->Click();
2925 pButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2926 return;
2927 }
2928 signal_clicked();
2929}
2930
2932{
2933 PushButton* pButton = dynamic_cast<PushButton*>(m_xDialog->get_widget_for_response(nResponse));
2934 return pButton ? new SalInstanceButton(pButton, nullptr, false) : nullptr;
2935}
2936
2938{
2939 PushButton* pButton = nullptr;
2940 if (nResponse == RET_YES)
2941 pButton = m_xWizard->m_pNextPage;
2942 else if (nResponse == RET_NO)
2943 pButton = m_xWizard->m_pPrevPage;
2944 else if (nResponse == RET_OK)
2945 pButton = m_xWizard->m_pFinish;
2946 else if (nResponse == RET_CANCEL)
2947 pButton = m_xWizard->m_pCancel;
2948 else if (nResponse == RET_HELP)
2949 pButton = m_xWizard->m_pHelp;
2950 if (pButton)
2951 return new SalInstanceButton(pButton, nullptr, false);
2952 return nullptr;
2953}
2954
2956 bool bTakeOwnership)
2957 : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2958 , m_xMenuButton(pButton)
2959 , m_nLastId(0)
2960{
2961 m_xMenuButton->SetActivateHdl(LINK(this, SalInstanceMenuButton, ActivateHdl));
2962 m_xMenuButton->SetSelectHdl(LINK(this, SalInstanceMenuButton, MenuSelectHdl));
2963 if (PopupMenu* pMenu = m_xMenuButton->GetPopupMenu())
2964 {
2966 const auto nCount = pMenu->GetItemCount();
2967 m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
2968 }
2969}
2970
2972{
2973 if (active == get_active())
2974 return;
2975 if (active)
2976 m_xMenuButton->ExecuteMenu();
2977 else
2978 m_xMenuButton->CancelMenu();
2979}
2980
2981bool SalInstanceMenuButton::get_active() const { return m_xMenuButton->InPopupMode(); }
2982
2984{
2985 //not available
2986}
2987
2988bool SalInstanceMenuButton::get_inconsistent() const { return false; }
2989
2990void SalInstanceMenuButton::insert_item(int pos, const OUString& rId, const OUString& rStr,
2991 const OUString* pIconName, VirtualDevice* pImageSurface,
2992 TriState eCheckRadioFalse)
2993{
2994 m_nLastId = insert_to_menu(m_nLastId, m_xMenuButton->GetPopupMenu(), pos, rId, rStr, pIconName,
2995 pImageSurface, nullptr, eCheckRadioFalse);
2996}
2997
2998void SalInstanceMenuButton::insert_separator(int pos, const OUString& rId)
2999{
3000 auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
3001 m_xMenuButton->GetPopupMenu()->InsertSeparator(rId, nInsertPos);
3002}
3003
3004void SalInstanceMenuButton::set_item_sensitive(const OUString& rIdent, bool bSensitive)
3005{
3006 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3007 pMenu->EnableItem(rIdent, bSensitive);
3008}
3009
3010void SalInstanceMenuButton::remove_item(const OUString& rId)
3011{
3012 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3013 pMenu->RemoveItem(pMenu->GetItemPos(pMenu->GetItemId(rId)));
3014}
3015
3017{
3018 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3019 pMenu->Clear();
3020}
3021
3022void SalInstanceMenuButton::set_item_active(const OUString& rIdent, bool bActive)
3023{
3024 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3025 pMenu->CheckItem(rIdent, bActive);
3026}
3027
3028void SalInstanceMenuButton::set_item_label(const OUString& rIdent, const OUString& rText)
3029{
3030 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3031 pMenu->SetItemText(pMenu->GetItemId(rIdent), rText);
3032}
3033
3034OUString SalInstanceMenuButton::get_item_label(const OUString& rIdent) const
3035{
3036 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3037 return pMenu->GetItemText(pMenu->GetItemId(rIdent));
3038}
3039
3040void SalInstanceMenuButton::set_item_visible(const OUString& rIdent, bool bShow)
3041{
3042 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
3043 pMenu->ShowItem(pMenu->GetItemId(rIdent), bShow);
3044}
3045
3047{
3048 SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
3049 m_xMenuButton->SetPopover(pPopoverWidget ? pPopoverWidget->getWidget() : nullptr);
3050}
3051
3053{
3055 m_xMenuButton->SetActivateHdl(Link<::MenuButton*, void>());
3056}
3057
3059{
3060 signal_selected(m_xMenuButton->GetCurItemIdent());
3061}
3062
3064{
3065 if (notify_events_disabled())
3066 return;
3067 signal_toggled();
3068}
3069
3070namespace
3071{
3072class SalInstanceMenuToggleButton : public SalInstanceMenuButton,
3073 public virtual weld::MenuToggleButton
3074{
3075private:
3076 VclPtr<::MenuToggleButton> m_xMenuToggleButton;
3077
3078public:
3079 SalInstanceMenuToggleButton(::MenuToggleButton* pButton, SalInstanceBuilder* pBuilder,
3080 bool bTakeOwnership)
3081 : SalInstanceMenuButton(pButton, pBuilder, bTakeOwnership)
3082 , m_xMenuToggleButton(pButton)
3083 {
3084 m_xMenuToggleButton->SetDelayMenu(true);
3085 m_xMenuToggleButton->SetDropDown(PushButtonDropdownStyle::SplitMenuButton);
3086 }
3087
3088 virtual void set_active(bool active) override
3089 {
3091 m_xMenuToggleButton->SetActive(active);
3093 }
3094
3095 virtual bool get_active() const override { return m_xMenuToggleButton->GetActive(); }
3096};
3097}
3098
3099IMPL_LINK(SalInstanceLinkButton, ClickHdl, FixedHyperlink&, rButton, void)
3100{
3101 bool bConsumed = signal_activate_link();
3102 if (!bConsumed)
3103 m_aOrigClickHdl.Call(rButton);
3104}
3105
3107 bool bTakeOwnership)
3108 : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
3109 , m_xRadioButton(pButton)
3110{
3111 m_xRadioButton->SetToggleHdl(LINK(this, SalInstanceRadioButton, ToggleHdl));
3112}
3113
3115{
3117 m_xRadioButton->Check(active);
3119}
3120
3121bool SalInstanceRadioButton::get_active() const { return m_xRadioButton->IsChecked(); }
3122
3124{
3125 m_xRadioButton->SetImageAlign(ImageAlign::Center);
3126 if (pDevice)
3127 m_xRadioButton->SetModeImage(createImage(*pDevice));
3128 else
3129 m_xRadioButton->SetModeImage(Image());
3130}
3131
3132void SalInstanceRadioButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage)
3133{
3134 m_xRadioButton->SetImageAlign(ImageAlign::Center);
3135 m_xRadioButton->SetModeImage(Image(rImage));
3136}
3137
3138void SalInstanceRadioButton::set_from_icon_name(const OUString& rIconName)
3139{
3140 m_xRadioButton->SetModeRadioImage(Image(StockImage::Yes, rIconName));
3141}
3142
3144{
3145 //not available
3146}
3147
3148bool SalInstanceRadioButton::get_inconsistent() const { return false; }
3149
3151{
3153}
3154
3156{
3157 if (notify_events_disabled())
3158 return;
3159 signal_toggled();
3160}
3161
3162IMPL_LINK(SalInstanceToggleButton, ToggleListener, VclWindowEvent&, rEvent, void)
3163{
3164 if (notify_events_disabled())
3165 return;
3166 if (rEvent.GetId() == VclEventId::PushbuttonToggle)
3167 signal_toggled();
3168}
3169
3171 bool bTakeOwnership)
3172 : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
3173 , m_xCheckButton(pButton)
3174{
3176}
3177
3179{
3182 m_xCheckButton->Check(active);
3184}
3185
3187
3189{
3194}
3195
3197{
3199}
3200
3202{
3204}
3205
3207{
3208 if (notify_events_disabled())
3209 return;
3210 m_xCheckButton->EnableTriState(false);
3211 signal_toggled();
3212}
3213
3214namespace
3215{
3216class SalInstanceScale : public SalInstanceWidget, public virtual weld::Scale
3217{
3218private:
3219 VclPtr<Slider> m_xScale;
3220
3221 DECL_LINK(SlideHdl, Slider*, void);
3222
3223public:
3224 SalInstanceScale(Slider* pScale, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3225 : SalInstanceWidget(pScale, pBuilder, bTakeOwnership)
3226 , m_xScale(pScale)
3227 {
3228 m_xScale->SetSlideHdl(LINK(this, SalInstanceScale, SlideHdl));
3229 }
3230
3231 virtual void set_value(int value) override { m_xScale->SetThumbPos(value); }
3232
3233 virtual void set_range(int min, int max) override
3234 {
3235 m_xScale->SetRangeMin(min);
3236 m_xScale->SetRangeMax(max);
3237 }
3238
3239 virtual int get_value() const override { return m_xScale->GetThumbPos(); }
3240
3241 virtual void set_increments(int step, int page) override
3242 {
3243 m_xScale->SetLineSize(step);
3244 m_xScale->SetPageSize(page);
3245 }
3246
3247 virtual void get_increments(int& step, int& page) const override
3248 {
3249 step = m_xScale->GetLineSize();
3250 page = m_xScale->GetPageSize();
3251 }
3252
3253 virtual ~SalInstanceScale() override { m_xScale->SetSlideHdl(Link<Slider*, void>()); }
3254};
3255}
3256
3257IMPL_LINK_NOARG(SalInstanceScale, SlideHdl, Slider*, void) { signal_value_changed(); }
3258
3259namespace
3260{
3261class SalInstanceSpinner : public SalInstanceWidget, public virtual weld::Spinner
3262{
3263private:
3264 VclPtr<Throbber> m_xThrobber;
3265
3266public:
3267 SalInstanceSpinner(Throbber* pThrobber, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3268 : SalInstanceWidget(pThrobber, pBuilder, bTakeOwnership)
3269 , m_xThrobber(pThrobber)
3270 {
3271 }
3272
3273 virtual void start() override { m_xThrobber->start(); }
3274
3275 virtual void stop() override { m_xThrobber->stop(); }
3276};
3277
3278class SalInstanceProgressBar : public SalInstanceWidget, public virtual weld::ProgressBar
3279{
3280private:
3281 VclPtr<::ProgressBar> m_xProgressBar;
3282
3283public:
3284 SalInstanceProgressBar(::ProgressBar* pProgressBar, SalInstanceBuilder* pBuilder,
3285 bool bTakeOwnership)
3286 : SalInstanceWidget(pProgressBar, pBuilder, bTakeOwnership)
3287 , m_xProgressBar(pProgressBar)
3288 {
3289 }
3290
3291 virtual void set_percentage(int value) override { m_xProgressBar->SetValue(value); }
3292
3293 virtual OUString get_text() const override { return m_xProgressBar->GetText(); }
3294
3295 virtual void set_text(const OUString& rText) override { m_xProgressBar->SetText(rText); }
3296};
3297
3298class SalInstanceCalendar : public SalInstanceWidget, public virtual weld::Calendar
3299{
3300private:
3301 VclPtr<::Calendar> m_xCalendar;
3302
3303 DECL_LINK(SelectHdl, ::Calendar*, void);
3304 DECL_LINK(ActivateHdl, ::Calendar*, void);
3305
3306public:
3307 SalInstanceCalendar(::Calendar* pCalendar, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3308 : SalInstanceWidget(pCalendar, pBuilder, bTakeOwnership)
3309 , m_xCalendar(pCalendar)
3310 {
3311 m_xCalendar->SetSelectHdl(LINK(this, SalInstanceCalendar, SelectHdl));
3312 m_xCalendar->SetActivateHdl(LINK(this, SalInstanceCalendar, ActivateHdl));
3313 }
3314
3315 virtual void set_date(const Date& rDate) override { m_xCalendar->SetCurDate(rDate); }
3316
3317 virtual Date get_date() const override { return m_xCalendar->GetFirstSelectedDate(); }
3318
3319 virtual ~SalInstanceCalendar() override
3320 {
3321 m_xCalendar->SetSelectHdl(Link<::Calendar*, void>());
3322 m_xCalendar->SetActivateHdl(Link<::Calendar*, void>());
3323 }
3324};
3325}
3326
3327IMPL_LINK_NOARG(SalInstanceCalendar, SelectHdl, ::Calendar*, void)
3328{
3329 if (notify_events_disabled())
3330 return;
3331 signal_selected();
3332}
3333
3334IMPL_LINK_NOARG(SalInstanceCalendar, ActivateHdl, ::Calendar*, void)
3335{
3336 if (notify_events_disabled())
3337 return;
3338 signal_activated();
3339}
3340
3342 bool bTakeOwnership)
3343 : SalInstanceWidget(pImage, pBuilder, bTakeOwnership)
3344 , m_xImage(pImage)
3345{
3346}
3347
3348void SalInstanceImage::set_from_icon_name(const OUString& rIconName)
3349{
3351}
3352
3354{
3355 if (pDevice)
3356 m_xImage->SetImage(createImage(*pDevice));
3357 else
3359}
3360
3361void SalInstanceImage::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage)
3362{
3363 m_xImage->SetImage(::Image(rImage));
3364}
3365
3367 : TextFilter(OUString())
3368 , m_rInsertTextHdl(rInsertTextHdl)
3369{
3370}
3371
3372OUString WeldTextFilter::filter(const OUString& rText)
3373{
3374 if (!m_rInsertTextHdl.IsSet())
3375 return rText;
3376 OUString sText(rText);
3377 const bool bContinue = m_rInsertTextHdl.Call(sText);
3378 if (!bContinue)
3379 return OUString();
3380 return sText;
3381}
3382
3383SalInstanceEntry::SalInstanceEntry(Edit* pEntry, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3384 : SalInstanceWidget(pEntry, pBuilder, bTakeOwnership)
3385 , m_xEntry(pEntry)
3386 , m_aTextFilter(m_aInsertTextHdl)
3387{
3388 m_xEntry->SetModifyHdl(LINK(this, SalInstanceEntry, ChangeHdl));
3389 m_xEntry->SetActivateHdl(LINK(this, SalInstanceEntry, ActivateHdl));
3390 m_xEntry->SetTextFilter(&m_aTextFilter);
3391}
3392
3393void SalInstanceEntry::set_text(const OUString& rText)
3394{
3396 m_xEntry->SetText(rText);
3398}
3399
3400OUString SalInstanceEntry::get_text() const { return m_xEntry->GetText(); }
3401
3402void SalInstanceEntry::set_width_chars(int nChars) { m_xEntry->SetWidthInChars(nChars); }
3403
3404int SalInstanceEntry::get_width_chars() const { return m_xEntry->GetWidthInChars(); }
3405
3406void SalInstanceEntry::set_max_length(int nChars) { m_xEntry->SetMaxTextLen(nChars); }
3407
3408void SalInstanceEntry::select_region(int nStartPos, int nEndPos)
3409{
3411 tools::Long nStart = nStartPos < 0 ? SELECTION_MAX : nStartPos;
3412 tools::Long nEnd = nEndPos < 0 ? SELECTION_MAX : nEndPos;
3413 m_xEntry->SetSelection(Selection(nStart, nEnd));
3415}
3416
3417bool SalInstanceEntry::get_selection_bounds(int& rStartPos, int& rEndPos)
3418{
3419 const Selection& rSelection = m_xEntry->GetSelection();
3420 rStartPos = rSelection.Min();
3421 rEndPos = rSelection.Max();
3422 return rSelection.Len();
3423}
3424
3425void SalInstanceEntry::replace_selection(const OUString& rText)
3426{
3427 m_xEntry->ReplaceSelected(rText);
3428}
3429
3431{
3433 if (nCursorPos < 0)
3434 m_xEntry->SetCursorAtLast();
3435 else
3436 m_xEntry->SetSelection(Selection(nCursorPos, nCursorPos));
3438}
3439
3440int SalInstanceEntry::get_position() const { return m_xEntry->GetSelection().Max(); }
3441
3442void SalInstanceEntry::set_editable(bool bEditable) { m_xEntry->SetReadOnly(!bEditable); }
3443
3444bool SalInstanceEntry::get_editable() const { return !m_xEntry->IsReadOnly(); }
3445
3446void SalInstanceEntry::set_overwrite_mode(bool bOn) { m_xEntry->SetInsertMode(!bOn); }
3447
3448bool SalInstanceEntry::get_overwrite_mode() const { return !m_xEntry->IsInsertMode(); }
3449
3450namespace
3451{
3452void set_message_type(Edit* pEntry, weld::EntryMessageType eType)
3453{
3454 switch (eType)
3455 {
3457 pEntry->SetForceControlBackground(false);
3458 pEntry->SetControlForeground();
3459 pEntry->SetControlBackground();
3460 break;
3462 // tdf#114603: enable setting the background to a different color;
3463 // relevant for GTK; see also #i75179#
3464 pEntry->SetForceControlBackground(true);
3465 pEntry->SetControlForeground(COL_BLACK);
3466 pEntry->SetControlBackground(0xffff38); // "light yellow 1"
3467 break;
3469 // tdf#114603: enable setting the background to a different color;
3470 // relevant for GTK; see also #i75179#
3471 pEntry->SetForceControlBackground(true);
3472 pEntry->SetControlForeground(COL_BLACK); // contrast of 5.87 to the red background
3473 pEntry->SetControlBackground(0xff3838); // "light red 1"
3474 break;
3475 }
3476}
3477}
3478
3480{
3482}
3483
3485{
3486 m_xEntry->SetControlFont(rFont);
3487 m_xEntry->Invalidate();
3488}
3489
3491{
3492 if (rColor == COL_AUTO)
3493 m_xEntry->SetControlForeground();
3494 else
3495 m_xEntry->SetControlForeground(rColor);
3496}
3497
3499{
3500 assert(!m_aCursorPositionHdl.IsSet());
3501 m_xEntry->AddEventListener(LINK(this, SalInstanceEntry, CursorListener));
3503}
3504
3506{
3507 m_xEntry->SetPlaceholderText(rText);
3508}
3509
3511
3513
3515{
3516 m_xEntry->Cut();
3517 m_xEntry->Modify();
3518}
3519
3521
3523{
3524 m_xEntry->Paste();
3525 m_xEntry->Modify();
3526}
3527
3528namespace
3529{
3530void set_alignment(Edit& rEntry, TxtAlign eXAlign)
3531{
3532 WinBits nAlign(0);
3533 switch (eXAlign)
3534 {
3535 case TxtAlign::Left:
3536 nAlign = WB_LEFT;
3537 break;
3538 case TxtAlign::Center:
3539 nAlign = WB_CENTER;
3540 break;
3541 case TxtAlign::Right:
3542 nAlign = WB_RIGHT;
3543 break;
3544 }
3545 WinBits nBits = rEntry.GetStyle();
3546 nBits &= ~(WB_LEFT | WB_CENTER | WB_RIGHT);
3547 rEntry.SetStyle(nBits | nAlign);
3548}
3549}
3550
3552
3554{
3555 if (m_aCursorPositionHdl.IsSet())
3556 m_xEntry->RemoveEventListener(LINK(this, SalInstanceEntry, CursorListener));
3557 m_xEntry->SetTextFilter(nullptr);
3558 m_xEntry->SetActivateHdl(Link<Edit&, bool>());
3559 m_xEntry->SetModifyHdl(Link<Edit&, void>());
3560}
3561
3562IMPL_LINK_NOARG(SalInstanceEntry, ChangeHdl, Edit&, void) { signal_changed(); }
3563
3564IMPL_LINK(SalInstanceEntry, CursorListener, VclWindowEvent&, rEvent, void)
3565{
3566 if (notify_events_disabled())
3567 return;
3568 if (rEvent.GetId() == VclEventId::EditSelectionChanged
3569 || rEvent.GetId() == VclEventId::EditCaretChanged)
3570 signal_cursor_position();
3571}
3572
3573IMPL_LINK_NOARG(SalInstanceEntry, ActivateHdl, Edit&, bool) { return m_aActivateHdl.Call(*this); }
3574
3576
3578
3579namespace
3580{
3581// tdf#131581 if the TreeView is hidden then there are possibly additional
3582// optimizations available
3583class UpdateGuardIfHidden
3584{
3585private:
3586 SvTabListBox& m_rTreeView;
3587 bool m_bOrigUpdate;
3588 bool m_bOrigEnableInvalidate;
3589
3590public:
3591 UpdateGuardIfHidden(SvTabListBox& rTreeView)
3592 : m_rTreeView(rTreeView)
3593 // tdf#136962 only do SetUpdateMode(false) optimization if the widget is currently hidden
3594 , m_bOrigUpdate(!m_rTreeView.IsVisible() && m_rTreeView.IsUpdateMode())
3595 // tdf#137432 only do EnableInvalidate(false) optimization if the widget is currently hidden
3596 , m_bOrigEnableInvalidate(!m_rTreeView.IsVisible()
3597 && m_rTreeView.GetModel()->IsEnableInvalidate())
3598 {
3599 if (m_bOrigUpdate)
3600 m_rTreeView.SetUpdateMode(false);
3601 if (m_bOrigEnableInvalidate)
3602 m_rTreeView.GetModel()->EnableInvalidate(false);
3603 }
3604
3605 ~UpdateGuardIfHidden()
3606 {
3607 if (m_bOrigEnableInvalidate)
3608 m_rTreeView.GetModel()->EnableInvalidate(true);
3609 if (m_bOrigUpdate)
3610 m_rTreeView.SetUpdateMode(true);
3611 }
3612};
3613}
3614
3615// Each row has a cell for the expander image, (and an optional cell for a
3616// checkbutton if enable_toggle_buttons has been called) which precede
3617// index 0
3619{
3621 ++col; // skip checkbutton column
3622 ++col; //skip expander column
3623 return col;
3624}
3625
3627{
3629 --col; // skip checkbutton column
3630 --col; //skip expander column
3631 return col;
3632}
3633
3635{
3636 return o3tl::trim(m_xTreeView->GetEntryText(pEntry)) == u"<dummy>";
3637}
3638
3640{
3641 if (pEntry->HasChildren())
3642 {
3643 auto pChild = m_xTreeView->FirstChild(pEntry);
3644 assert(pChild);
3645 if (IsDummyEntry(pChild))
3646 return pChild;
3647 }
3648 return nullptr;
3649}
3650
3652{
3653 if (rColor == COL_AUTO)
3654 pEntry->SetTextColor(std::optional<Color>());
3655 else
3656 pEntry->SetTextColor(rColor);
3657}
3658
3659void SalInstanceTreeView::AddStringItem(SvTreeListEntry* pEntry, const OUString& rStr, int nCol)
3660{
3661 auto xCell = std::make_unique<SvLBoxString>(rStr);
3662 if (m_aCustomRenders.count(nCol))
3663 xCell->SetCustomRender();
3664 pEntry->AddItem(std::move(xCell));
3665}
3666
3667void SalInstanceTreeView::do_insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
3668 const OUString* pId, const OUString* pIconName,
3669 const VirtualDevice* pImageSurface, bool bChildrenOnDemand,
3670 weld::TreeIter* pRet, bool bIsSeparator)
3671{
3673 const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
3674 SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
3675 auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
3676 void* pUserData;
3677 if (pId)
3678 {
3679 m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
3680 pUserData = m_aUserData.back().get();
3681 }
3682 else
3683 pUserData = nullptr;
3684
3685 SvTreeListEntry* pEntry = new SvTreeListEntry;
3686 if (bIsSeparator)
3687 pEntry->SetFlags(pEntry->GetFlags() | SvTLEntryFlags::IS_SEPARATOR);
3688
3690 AddStringItem(pEntry, "", -1);
3691
3692 if (pIconName || pImageSurface)
3693 {
3694 Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface));
3695 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
3696 }
3697 else
3698 {
3699 Image aDummy;
3700 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3701 }
3702 if (pStr)
3703 AddStringItem(pEntry, *pStr, pEntry->ItemCount());
3704 pEntry->SetUserData(pUserData);
3705 m_xTreeView->Insert(pEntry, iter, nInsertPos);
3706
3707 if (pRet)
3708 {
3709 SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
3710 pVclRetIter->iter = pEntry;
3711 }
3712
3713 if (bChildrenOnDemand)
3714 {
3715 SvTreeListEntry* pPlaceHolder
3716 = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
3717 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
3718 pViewData->SetSelectable(false);
3719 }
3720
3721 if (bIsSeparator)
3722 {
3723 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3724 pViewData->SetSelectable(false);
3725 }
3726
3728}
3729
3731{
3732 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3733 m_xTreeView->InitViewData(pViewData, pEntry);
3735}
3736
3738{
3740 return;
3742}
3743
3745{
3746 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3747 // if it's the placeholder to allow a blank column, replace it now
3748 if (pEntry->GetItem(col).GetType() != SvLBoxItemType::Button)
3749 {
3751 pEntry->ReplaceItem(std::make_unique<SvLBoxButton>(pData), 0);
3753 }
3754 SvLBoxItem& rItem = pEntry->GetItem(col);
3755 assert(dynamic_cast<SvLBoxButton*>(&rItem));
3756 switch (eState)
3757 {
3758 case TRISTATE_TRUE:
3759 static_cast<SvLBoxButton&>(rItem).SetStateChecked();
3760 break;
3761 case TRISTATE_FALSE:
3762 static_cast<SvLBoxButton&>(rItem).SetStateUnchecked();
3763 break;
3764 case TRISTATE_INDET:
3765 static_cast<SvLBoxButton&>(rItem).SetStateTristate();
3766 break;
3767 }
3768
3769 InvalidateModelEntry(pEntry);
3770}
3771
3773{
3774 if (static_cast<size_t>(col) == pEntry->ItemCount())
3775 return TRISTATE_FALSE;
3776
3777 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3778 SvLBoxItem& rItem = pEntry->GetItem(col);
3779 assert(dynamic_cast<SvLBoxButton*>(&rItem));
3780 SvLBoxButton& rToggle = static_cast<SvLBoxButton&>(rItem);
3781 if (rToggle.IsStateTristate())
3782 return TRISTATE_INDET;
3783 else if (rToggle.IsStateChecked())
3784 return TRISTATE_TRUE;
3785 return TRISTATE_FALSE;
3786}
3787
3789{
3790 if (col == -1)
3791 {
3793 return do_get_toggle(pEntry, 0);
3794 }
3796 return do_get_toggle(pEntry, col);
3797}
3798
3800{
3801 if (col == -1)
3802 {
3804 do_set_toggle(pEntry, eState, 0);
3805 return;
3806 }
3807
3809
3810 // blank out missing entries
3811 for (int i = pEntry->ItemCount(); i < col; ++i)
3812 AddStringItem(pEntry, "", i - 1);
3813
3814 if (static_cast<size_t>(col) == pEntry->ItemCount())
3815 {
3817 pEntry->AddItem(std::make_unique<SvLBoxButton>(pData));
3819 }
3820
3821 do_set_toggle(pEntry, eState, col);
3822}
3823
3825{
3827
3828 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3829 SvLBoxItem& rItem = pEntry->GetItem(col);
3830 assert(dynamic_cast<SvLBoxString*>(&rItem));
3831 return static_cast<SvLBoxString&>(rItem).IsEmphasized();
3832}
3833
3834void SalInstanceTreeView::set_header_item_width(const std::vector<int>& rWidths)
3835{
3836 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3837 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3838 {
3839 for (size_t i = 0; i < rWidths.size(); ++i)
3840 pHeaderBar->SetItemSize(pHeaderBar->GetItemId(i), rWidths[i]);
3841 }
3842}
3843
3845 bool bTakeOwnership)
3846 : SalInstanceWidget(pTreeView, pBuilder, bTakeOwnership)
3847 , m_xTreeView(pTreeView)
3848 , m_aCheckButtonData(pTreeView, false)
3849 , m_aRadioButtonData(pTreeView, true)
3850 , m_bTogglesAsRadio(false)
3851 , m_nSortColumn(-1)
3852{
3856 m_xTreeView->SetDeselectHdl(LINK(this, SalInstanceTreeView, DeSelectHdl));
3857 m_xTreeView->SetDoubleClickHdl(LINK(this, SalInstanceTreeView, DoubleClickHdl));
3858 m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl));
3859 m_xTreeView->SetPopupMenuHdl(LINK(this, SalInstanceTreeView, PopupMenuHdl));
3860 m_xTreeView->SetCustomRenderHdl(LINK(this, SalInstanceTreeView, CustomRenderHdl));
3861 m_xTreeView->SetCustomMeasureHdl(LINK(this, SalInstanceTreeView, CustomMeasureHdl));
3862 const tools::Long aTabPositions[] = { 0 };
3863 m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions);
3864 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3865
3866 if (pHeaderBox)
3867 {
3868 if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
3869 {
3870 //make the last entry fill available space
3871 pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1),
3873 pHeaderBar->SetEndDragHdl(LINK(this, SalInstanceTreeView, EndDragHdl));
3874 pHeaderBar->SetSelectHdl(LINK(this, SalInstanceTreeView, HeaderBarClickedHdl));
3875 }
3876 pHeaderBox->SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3877 pHeaderBox->SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3878 }
3879 else
3880 {
3881 static_cast<LclTabListBox&>(*m_xTreeView)
3882 .SetModelChangedHdl(LINK(this, SalInstanceTreeView, ModelChangedHdl));
3883 static_cast<LclTabListBox&>(*m_xTreeView)
3884 .SetStartDragHdl(LINK(this, SalInstanceTreeView, StartDragHdl));
3885 static_cast<LclTabListBox&>(*m_xTreeView)
3886 .SetEndDragHdl(LINK(this, SalInstanceTreeView, FinishDragHdl));
3887 static_cast<LclTabListBox&>(*m_xTreeView)
3888 .SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3889 static_cast<LclTabListBox&>(*m_xTreeView)
3890 .SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3891 }
3894}
3895
3897{
3900}
3901
3903{
3904 std::vector<tools::Long> aWidths;
3906 if (aWidths.size() > 2)
3907 {
3908 std::vector<int> aColWidths;
3909 for (size_t i = 1; i < aWidths.size() - 1; ++i)
3910 aColWidths.push_back(aWidths[i] - aWidths[i - 1]);
3911 set_column_fixed_widths(aColWidths);
3912 }
3913}
3914
3916{
3917 bool bIsFirstFreeze = IsFirstFreeze();
3919 if (bIsFirstFreeze)
3920 {
3921 m_xTreeView->SetUpdateMode(false);
3923 }
3924}
3925
3927{
3928 bool bIsLastThaw = IsLastThaw();
3929 if (bIsLastThaw)
3930 {
3933 }
3935}
3936
3937void SalInstanceTreeView::set_column_fixed_widths(const std::vector<int>& rWidths)
3938{
3939 std::vector<tools::Long> aTabPositions{ 0 };
3940 for (size_t i = 0; i < rWidths.size(); ++i)
3941 aTabPositions.push_back(aTabPositions[i] + rWidths[i]);
3942 m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
3943 set_header_item_width(rWidths);
3944 // call Resize to recalculate based on the new tabs
3946}
3947
3948void SalInstanceTreeView::set_column_editables(const std::vector<bool>& rEditables)
3949{
3950 size_t nTabCount = rEditables.size();
3951 for (size_t i = 0; i < nTabCount; ++i)
3952 m_xTreeView->SetTabEditable(i, rEditables[i]);
3953}
3954
3956{
3958}
3959
3961{
3962 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3963 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3964 return pHeaderBar->GetItemSize(pHeaderBar->GetItemId(nColumn));
3965 // GetTab(0) gives the position of the bitmap which is automatically inserted by the TabListBox.
3966 // So the first text column's width is Tab(2)-Tab(1).
3967 auto nWidthPixel
3968 = m_xTreeView->GetLogicTab(nColumn + 2) - m_xTreeView->GetLogicTab(nColumn + 1);
3969 nWidthPixel -= SV_TAB_BORDER;
3970 return nWidthPixel;
3971}
3972
3973OUString SalInstanceTreeView::get_column_title(int nColumn) const
3974{
3975 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3976 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3977 {
3978 return pHeaderBar->GetItemText(pHeaderBar->GetItemId(nColumn));
3979 }
3980 return OUString();
3981}
3982
3983void SalInstanceTreeView::set_column_title(int nColumn, const OUString& rTitle)
3984{
3985 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3986 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3987 {
3988 return pHeaderBar->SetItemText(pHeaderBar->GetItemId(nColumn), rTitle);
3989 }
3990}
3991
3993{
3994 assert(n_children() == 0 && "tree must be empty");
3995 if (bEnable)
3996 m_aCustomRenders.insert(nColumn);
3997 else
3998 m_aCustomRenders.erase(nColumn);
3999}
4000
4002{
4003 // invalidate the entries
4004 SvTreeList* pModel = m_xTreeView->GetModel();
4005 for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; pEntry = m_xTreeView->Next(pEntry))
4006 pModel->InvalidateEntry(pEntry);
4007}
4008
4010{
4011 if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
4012 pHeaderBox->GetParent()->Show();
4014}
4015
4017{
4018 if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
4019 pHeaderBox->GetParent()->Hide();
4021}
4022
4023void SalInstanceTreeView::insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
4024 const OUString* pId, const OUString* pIconName,
4025 VirtualDevice* pImageSurface, bool bChildrenOnDemand,
4026 weld::TreeIter* pRet)
4027{
4028 do_insert(pParent, pos, pStr, pId, pIconName, pImageSurface, bChildrenOnDemand, pRet, false);
4029}
4030
4031void SalInstanceTreeView::insert_separator(int pos, const OUString& /*rId*/)
4032{
4033 OUString sSep(VclResId(STR_SEPARATOR));
4034 do_insert(nullptr, pos, &sSep, nullptr, nullptr, nullptr, false, nullptr, true);
4035}
4036
4038 int nSourceCount, const std::function<void(weld::TreeIter&, int nSourceIndex)>& func,
4039 const weld::TreeIter* pParent, const std::vector<int>* pFixedWidths)
4040{
4041 const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
4042 SvTreeListEntry* pVclParent = pVclIter ? pVclIter->iter : nullptr;
4043
4044 freeze();
4045 if (!pVclParent)
4046 clear();
4047 else
4048 {
4049 while (SvTreeListEntry* pChild = m_xTreeView->FirstChild(pVclParent))
4050 m_xTreeView->RemoveEntry(pChild);
4051 }
4052 SalInstanceTreeIter aVclIter(static_cast<SvTreeListEntry*>(nullptr));
4053
4055
4056 if (pFixedWidths)
4057 set_header_item_width(*pFixedWidths);
4058
4059 bool bHasAutoCheckButton(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
4060 size_t nExtraCols = bHasAutoCheckButton ? 2 : 1;
4061
4062 Image aDummy;
4063 for (int i = 0; i < nSourceCount; ++i)
4064 {
4065 aVclIter.iter = new SvTreeListEntry;
4066 if (bHasAutoCheckButton)
4067 AddStringItem(aVclIter.iter, "", -1);
4068 aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
4069 m_xTreeView->Insert(aVclIter.iter, pVclParent, TREELIST_APPEND);
4070 func(aVclIter, i);
4071
4072 if (!pFixedWidths)
4073 continue;
4074
4075 size_t nFixedWidths = std::min(pFixedWidths->size(), aVclIter.iter->ItemCount());
4076 for (size_t j = 0; j < nFixedWidths; ++j)
4077 {
4078 SvLBoxItem& rItem = aVclIter.iter->GetItem(j + nExtraCols);
4079 SvViewDataItem* pViewDataItem = m_xTreeView->GetViewDataItem(aVclIter.iter, &rItem);
4080 pViewDataItem->mnWidth = (*pFixedWidths)[j];
4081 }
4082 }
4083
4085
4086 thaw();
4087}
4088
4089void SalInstanceTreeView::set_font_color(int pos, const Color& rColor)
4090{
4091 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4092 set_font_color(pEntry, rColor);
4093}
4094
4096{
4097 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4098 set_font_color(rVclIter.iter, rColor);
4099}
4100
4102{
4104 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4105 m_xTreeView->RemoveEntry(pEntry);
4107}
4108
4109int SalInstanceTreeView::find_text(const OUString& rText) const
4110{
4111 for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; pEntry = m_xTreeView->Next(pEntry))
4112 {
4113 if (SvTabListBox::GetEntryText(pEntry, 0) == rText)
4114 return SvTreeList::GetRelPos(pEntry);
4115 }
4116 return -1;
4117}
4118
4119int SalInstanceTreeView::find_id(const OUString& rId) const
4120{
4121 for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; pEntry = m_xTreeView->Next(pEntry))
4122 {
4123 const OUString* pId = static_cast<const OUString*>(pEntry->GetUserData());
4124 if (!pId)
4125 continue;
4126 if (rId == *pId)
4127 return SvTreeList::GetRelPos(pEntry);
4128 }
4129 return -1;
4130}
4131
4132void SalInstanceTreeView::swap(int pos1, int pos2)
4133{
4134 int min = std::min(pos1, pos2);
4135 int max = std::max(pos1, pos2);
4136 SvTreeList* pModel = m_xTreeView->GetModel();
4137 SvTreeListEntry* pEntry1 = pModel->GetEntry(nullptr, min);
4138 SvTreeListEntry* pEntry2 = pModel->GetEntry(nullptr, max);
4139 pModel->Move(pEntry1, pEntry2);
4140}
4141
4143{
4145 m_xTreeView->Clear();
4146 m_aUserData.clear();
4148}
4149
4151{
4152 return m_xTreeView->GetModel()->GetChildList(nullptr).size();
4153}
4154
4156{
4157 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4158 return m_xTreeView->GetModel()->GetChildList(rVclIter.iter).size();
4159}
4160
4162{
4163 assert(m_xTreeView->IsUpdateMode()
4164 && "don't select when frozen, select after thaw. Note selection doesn't survive a "
4165 "freeze");
4167 if (pos == -1 || (pos == 0 && n_children() == 0))
4168 m_xTreeView->SelectAll(false);
4169 else
4170 {
4171 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4172 assert(pEntry && "bad pos?");
4173 m_xTreeView->Select(pEntry, true);
4174 m_xTreeView->MakeVisible(pEntry);
4175 }
4177}
4178
4180{
4182 if (!pEntry)
4183 return -1;
4184 return SvTreeList::GetRelPos(pEntry);
4185}
4186
4188{
4190 if (pos == -1)
4191 m_xTreeView->SetCurEntry(nullptr);
4192 else
4193 {
4194 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4195 m_xTreeView->SetCurEntry(pEntry);
4196 }
4198}
4199
4201{
4202 assert(m_xTreeView->IsUpdateMode()
4203 && "don't select when frozen, select after thaw. Note selection doesn't survive a "
4204 "freeze");
4206 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4207 m_xTreeView->MakeVisible(pEntry);
4209}
4210
4212{
4213 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4214 return m_xTreeView->IsSelected(pEntry);
4215}
4216
4218{
4219 assert(m_xTreeView->IsUpdateMode()
4220 && "don't select when frozen, select after thaw. Note selection doesn't survive a "
4221 "freeze");
4223 if (pos == -1)
4224 m_xTreeView->SelectAll(true);
4225 else
4226 {
4227 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4228 m_xTreeView->Select(pEntry, false);
4229 }
4231}
4232
4234{
4235 std::vector<int> aRows;
4236
4237 aRows.reserve(m_xTreeView->GetSelectionCount());
4238 for (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); pEntry;
4239 pEntry = m_xTreeView->NextSelected(pEntry))
4240 aRows.push_back(SvTreeList::GetRelPos(pEntry));
4241
4242 return aRows;
4243}
4244
4245OUString SalInstanceTreeView::get_text(SvTreeListEntry* pEntry, int col) const
4246{
4247 if (col == -1)
4248 return SvTabListBox::GetEntryText(pEntry, 0);
4249
4251
4252 if (static_cast<size_t>(col) == pEntry->ItemCount())
4253 return OUString();
4254
4255 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4256 SvLBoxItem& rItem = pEntry->GetItem(col);
4257 assert(dynamic_cast<SvLBoxString*>(&rItem));
4258 return static_cast<SvLBoxString&>(rItem).GetText();
4259}
4260
4261OUString SalInstanceTreeView::get_text(int pos, int col) const
4262{
4263 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4264 return get_text(pEntry, col);
4265}
4266
4267void SalInstanceTreeView::set_text(SvTreeListEntry* pEntry, const OUString& rText, int col)
4268{
4269 if (col == -1)
4270 {
4271 m_xTreeView->SetEntryText(pEntry, rText);
4272 return;
4273 }
4274
4276
4277 // blank out missing entries
4278 for (int i = pEntry->ItemCount(); i < col; ++i)
4279 AddStringItem(pEntry, "", i - 1);
4280
4281 if (static_cast<size_t>(col) == pEntry->ItemCount())
4282 {
4283 AddStringItem(pEntry, rText, col - 1);
4284 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
4285 m_xTreeView->InitViewData(pViewData, pEntry);
4286 }
4287 else
4288 {
4289 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4290 SvLBoxItem& rItem = pEntry->GetItem(col);
4291 assert(dynamic_cast<SvLBoxString*>(&rItem));
4292 static_cast<SvLBoxString&>(rItem).SetText(rText);
4293 }
4294
4295 InvalidateModelEntry(pEntry);
4296}
4297
4298void SalInstanceTreeView::set_text(int pos, const OUString& rText, int col)
4299{
4300 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4301 set_text(pEntry, rText, col);
4302}
4303
4304void SalInstanceTreeView::set_sensitive(SvTreeListEntry* pEntry, bool bSensitive, int col)
4305{
4306 if (col == -1)
4307 {
4308 auto nFlags = pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT;
4309 if (!bSensitive)
4310 nFlags = nFlags | SvTLEntryFlags::SEMITRANSPARENT;
4311 pEntry->SetFlags(nFlags);
4312 const sal_uInt16 nCount = pEntry->ItemCount();
4313 for (sal_uInt16 nCur = 0; nCur < nCount; ++nCur)
4314 {
4315 SvLBoxItem& rItem = pEntry->GetItem(nCur);
4316 if (rItem.GetType() == SvLBoxItemType::String
4317 || rItem.GetType() == SvLBoxItemType::Button
4318 || rItem.GetType() == SvLBoxItemType::ContextBmp)
4319 {
4320 rItem.Enable(bSensitive);
4321 InvalidateModelEntry(pEntry);
4322 }
4323 }
4324 return;
4325 }
4326
4328
4329 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4330 SvLBoxItem& rItem = pEntry->GetItem(col);
4331 rItem.Enable(bSensitive);
4332
4333 InvalidateModelEntry(pEntry);
4334}
4335
4337{
4338 if (static_cast<size_t>(col) == pEntry->ItemCount())
4339 return false;
4340
4341 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4342 SvLBoxItem& rItem = pEntry->GetItem(col);
4343 return rItem.isEnable();
4344}
4345
4347{
4349 return do_get_sensitive(pEntry, col);
4350}
4351
4352void SalInstanceTreeView::set_sensitive(int pos, bool bSensitive, int col)
4353{
4354 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4355 set_sensitive(pEntry, bSensitive, col);
4356}
4357
4358bool SalInstanceTreeView::get_sensitive(int pos, int col) const
4359{
4360 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4361 return get_sensitive(pEntry, col);
4362}
4363
4364void SalInstanceTreeView::set_sensitive(const weld::TreeIter& rIter, bool bSensitive, int col)
4365{
4366 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4367 set_sensitive(rVclIter.iter, bSensitive, col);
4368}
4369
4371{
4372 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4373 return get_sensitive(rVclIter.iter, col);
4374}
4375
4377{
4378 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4379 return get_toggle(pEntry, col);
4380}
4381
4383{
4384 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4385 return get_toggle(rVclIter.iter, col);
4386}
4387
4389{
4390 assert(n_children() == 0 && "tree must be empty");
4392
4395 // EnableCheckButton clobbered this, restore it
4396 pData->SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
4397}
4398
4399void SalInstanceTreeView::set_toggle(int pos, TriState eState, int col)
4400{
4401 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4402 set_toggle(pEntry, eState, col);
4403}
4404
4406{
4407 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4408 set_toggle(rVclIter.iter, eState, col);
4409}
4410
4412{
4413 m_xTreeView->SetClicksToToggle(nToggleBehavior);
4414}
4415
4417{
4418 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4419 rVclIter.iter->SetExtraIndent(nIndentLevel);
4420}
4421
4423{
4425
4426 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4427 SvLBoxItem& rItem = pEntry->GetItem(col);
4428 assert(dynamic_cast<SvLBoxString*>(&rItem));
4429 static_cast<SvLBoxString&>(rItem).Emphasize(bOn);
4430
4431 InvalidateModelEntry(pEntry);
4432}
4433
4434void SalInstanceTreeView::set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col)
4435{
4436 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4437 set_text_emphasis(rVclIter.iter, bOn, col);
4438}
4439
4440void SalInstanceTreeView::set_text_emphasis(int pos, bool bOn, int col)
4441{
4442 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4443 set_text_emphasis(pEntry, bOn, col);
4444}
4445
4447{
4448 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4449 return get_text_emphasis(rVclIter.iter, col);
4450}
4451
4452bool SalInstanceTreeView::get_text_emphasis(int pos, int col) const
4453{
4454 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4455 return get_text_emphasis(pEntry, col);
4456}
4457
4458void SalInstanceTreeView::set_text_align(SvTreeListEntry* pEntry, double fAlign, int col)
4459{
4461
4462 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4463 SvLBoxItem& rItem = pEntry->GetItem(col);
4464 assert(dynamic_cast<SvLBoxString*>(&rItem));
4465 static_cast<SvLBoxString&>(rItem).Align(fAlign);
4466
4467 InvalidateModelEntry(pEntry);
4468}
4469
4470void SalInstanceTreeView::set_text_align(const weld::TreeIter& rIter, double fAlign, int col)
4471{
4472 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4473 set_text_align(rVclIter.iter, fAlign, col);
4474}
4475
4476void SalInstanceTreeView::set_text_align(int pos, double fAlign, int col)
4477{
4478 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4479 set_text_align(pEntry, fAlign, col);
4480}
4481
4483 const Link<const iter_string&, bool>& rEndLink)
4484{
4485 m_xTreeView->EnableInplaceEditing(rStartLink.IsSet() || rEndLink.IsSet());
4486 weld::TreeView::connect_editing(rStartLink, rEndLink);
4487}
4488
4489void