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