vcl/Library_vcl.mk                     |    1 
 vcl/source/control/ivctrl.cxx          |  303 ------------------------------
 vcl/source/control/verticaltabctrl.cxx |  328 +++++++++++++++++++++++++++++++++
 3 files changed, 330 insertions(+), 302 deletions(-)

New commits:
commit de9ada85ae274a77a0b03b7cfa89feac66216464
Author:     Michael Weghorn <[email protected]>
AuthorDate: Thu Nov 20 09:53:20 2025 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Nov 21 08:10:47 2025 +0100

    tdf#167125 tdf#169383 vcl: Handle Ctrl{,+Shift}+Tab within vertical tab page
    
    Earlier commit
    
        commit fedc32852981682df6919147ecf410d7a06964d6
        Author: Heiko Tietze <[email protected]>
        Date:   Tue Nov 11 14:46:11 2025 +0100
    
            Resolves tdf#169383 - Accept ctrl+tab / shift+ctrl+tab on vertical 
tabs
    
    implemented switching between tabs when Ctrl+Tab
    or Ctrl+Shift+Tab are pressed while the tab bar
    itself has focus.
    
    As is the case for the horizontal tab pages, also
    switch between tab pages when Ctrl+Tab or Ctrl+Shift+Tab
    are pressed while any widget within the
    tab bar page (i.e. page content) has focus, and nothing
    handles it before it gets propagated to the
    VerticalTabControl ancestor.
    
    Change-Id: I69c79abbb469cb9cd6df724da8a21b10269e230c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194207
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/vcl/source/control/verticaltabctrl.cxx 
b/vcl/source/control/verticaltabctrl.cxx
index 1145c8b58527..972ced91bd9f 100644
--- a/vcl/source/control/verticaltabctrl.cxx
+++ b/vcl/source/control/verticaltabctrl.cxx
@@ -100,7 +100,8 @@ bool VerticalTabControl::EventNotify(NotifyEvent& rNEvt)
     if (rNEvt.GetType() == NotifyEventType::KEYINPUT)
     {
         sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
-        if (nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN)
+        if (nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN
+            || (nCode == KEY_TAB && 
rNEvt.GetKeyEvent()->GetKeyCode().IsMod1()))
         {
             m_xChooser->DoKeyInput(*(rNEvt.GetKeyEvent()));
             m_xChooser->GrabFocus();
commit ad61fa37eb2d6573f61cfac0ac4acbb14690e17c
Author:     Michael Weghorn <[email protected]>
AuthorDate: Thu Nov 20 09:28:19 2025 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Nov 21 08:10:41 2025 +0100

    tdf#167125 vcl a11y: Don't completely lose keyboard focus in 
VerticalTabControl
    
    Similar to the issue for Calc's conditional formatting
    dialog fixed by
    
        commit 752adf6cc9d869bbcf34fcf09c80da502398cb81
        Author: Michael Weghorn <[email protected]>
        Date:   Tue Nov 4 19:35:47 2025 +0100
    
            tdf#169006 sc a11y: Keep keyboard focus in conditional formatting 
dlg
    
    , keyboard focus could get lost completely when switching
    between tabs in the VerticalTabControl by using the
    keyboard.
    
    Sample steps to reproduce:
    
    * start Writer using the gen vcl plugin
    * "Format" -> "Page Style"
    * click on the "Footer" tab
    * press Tab to move focus to the "Footer on" checkbox
    * press PgDown key to switch toh the last tab
    
    Without this change in place, there would be
    no more way to switch focus to anything using the
    keyboard any more, as focus is still in the no
    longer visible tab.
    
    To fix this, move focus to the tab bar when
    the VerticalTabControl switches between tabs
    due to a keyboard event on a control in the
    tab that was propagated to the VerticalTabControl
    ancestor because it wasn't handled earlier.
    
    Change-Id: Iacea0135c5f3e04d542f8d534540651d50196405
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194249
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/source/control/verticaltabctrl.cxx 
b/vcl/source/control/verticaltabctrl.cxx
index acf28ca16c86..1145c8b58527 100644
--- a/vcl/source/control/verticaltabctrl.cxx
+++ b/vcl/source/control/verticaltabctrl.cxx
@@ -103,6 +103,7 @@ bool VerticalTabControl::EventNotify(NotifyEvent& rNEvt)
         if (nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN)
         {
             m_xChooser->DoKeyInput(*(rNEvt.GetKeyEvent()));
+            m_xChooser->GrabFocus();
             return true;
         }
     }
commit 69f7b6e7c8dd8cbfcad14e1e4f994215b4a075bb
Author:     Michael Weghorn <[email protected]>
AuthorDate: Thu Nov 20 09:22:38 2025 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Nov 21 08:10:34 2025 +0100

    vcl: Move VerticalTabControl implementation to own source file
    
    The SvtIconChoiceCtrl and VerticalTabControl classes
    are already defined in different headers.
    Move the VerticalTabControl also to a separate source file
    whose naming is in line with its header, to make the
    scope of each source file clearer.
    
    Change-Id: I13793e02f43d2309ebc6725e2db04cd4b3a53b96
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194248
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 00f64eb8e2e1..617e22e31dc1 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -260,6 +260,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/control/spinfld \
     vcl/source/control/tabctrl \
     vcl/source/control/throbber \
+    vcl/source/control/verticaltabctrl \
     vcl/source/control/wizardmachine \
     vcl/source/edit/IdleFormatter \
     vcl/source/edit/vclmedit \
diff --git a/vcl/source/control/ivctrl.cxx b/vcl/source/control/ivctrl.cxx
index 71778054bb5b..bfa5af18a35f 100644
--- a/vcl/source/control/ivctrl.cxx
+++ b/vcl/source/control/ivctrl.cxx
@@ -23,31 +23,17 @@
 #include "imivctl.hxx"
 #include <vcl/bitmap.hxx>
 #include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
 #include <vcl/mnemonic.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/tabctrl.hxx>
 #include <vcl/vclevent.hxx>
-#include <vcl/uitest/uiobject.hxx>
 #include <vcl/uitest/logger.hxx>
 #include <vcl/uitest/eventdescription.hxx>
 #include <accessibility/accessibleiconchoicectrl.hxx>
-#include <verticaltabctrl.hxx>
 
 using namespace ::com::sun::star::accessibility;
 
-namespace
-{
-void collectUIInformation( const OUString& aID, const OUString& aPos)
-{
-    EventDescription aDescription;
-    aDescription.aID = aID;
-    aDescription.aParameters = {{ "POS" ,  aPos}};
-    aDescription.aAction = "SELECT";
-    aDescription.aKeyWord = "VerticalTab";
-    UITestLogger::getInstance().logEvent(aDescription);
-}
-}
-
 SvxIconChoiceCtrlEntry::SvxIconChoiceCtrlEntry( OUString _aText,
                                                 Image _aImage )
     : aImage(std::move(_aImage))
@@ -346,291 +332,4 @@ rtl::Reference<comphelper::OAccessible> 
SvtIconChoiceCtrl::CreateAccessible()
     return new AccessibleIconChoiceCtrl(*this);
 }
 
-struct VerticalTabPageData
-{
-    OUString sId;
-    SvxIconChoiceCtrlEntry* pEntry;
-    VclPtr<vcl::Window> xPage;      ///< the TabPage itself
-};
-
-VerticalTabControl::VerticalTabControl(vcl::Window* pParent, bool bWithIcons)
-    : VclHBox(pParent)
-    , m_xChooser(VclPtr<SvtIconChoiceCtrl>::Create(this, WB_3DLOOK | 
(bWithIcons ?  WB_ICON : WB_SMALLICON) |
-#ifdef MACOSX
-                                                         WB_NOBORDER |
-#else
-                                                         WB_BORDER |
-#endif
-                                                         WB_NOCOLUMNHEADER |
-                                                         WB_NODRAGSELECTION | 
WB_TABSTOP | WB_CLIPCHILDREN |
-                                                         WB_NOHSCROLL))
-    , m_xBox(VclPtr<VclVBox>::Create(this))
-{
-    SetStyle(GetStyle() | WB_DIALOGCONTROL);
-    SetType(WindowType::VERTICALTABCONTROL);
-    m_xChooser->SetClickHdl(LINK(this, VerticalTabControl, ChosePageHdl_Impl));
-    m_xChooser->set_width_request(150);
-    m_xChooser->set_height_request(400);
-    m_xChooser->SetSizePixel(Size(150, 400));
-    m_xBox->set_vexpand(true);
-    m_xBox->set_hexpand(true);
-    m_xBox->set_expand(true);
-    m_xBox->Show();
-    m_xChooser->Show();
-}
-
-VerticalTabControl::~VerticalTabControl()
-{
-    disposeOnce();
-}
-
-void VerticalTabControl::dispose()
-{
-    m_xChooser.disposeAndClear();
-    m_xBox.disposeAndClear();
-    VclHBox::dispose();
-}
-
-IMPL_LINK_NOARG(VerticalTabControl, ChosePageHdl_Impl, SvtIconChoiceCtrl*, 
void)
-{
-    SvxIconChoiceCtrlEntry *pEntry = m_xChooser->GetSelectedEntry();
-    if (!pEntry)
-        pEntry = m_xChooser->GetCursor();
-
-    VerticalTabPageData* pData = GetPageData(pEntry);
-
-    if (pData->sId != m_sCurrentPageId)
-        SetCurPageId(pData->sId);
-}
-
-bool VerticalTabControl::EventNotify(NotifyEvent& rNEvt)
-{
-    if (rNEvt.GetType() == NotifyEventType::KEYINPUT)
-    {
-        sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
-        if (nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN)
-        {
-            m_xChooser->DoKeyInput(*(rNEvt.GetKeyEvent()));
-            return true;
-        }
-    }
-    return VclHBox::EventNotify(rNEvt);
-}
-
-void VerticalTabControl::ActivatePage()
-{
-    m_aActivateHdl.Call( this );
-}
-
-bool VerticalTabControl::DeactivatePage()
-{
-    return !m_aDeactivateHdl.IsSet() || m_aDeactivateHdl.Call(this);
-}
-
-VerticalTabPageData* VerticalTabControl::GetPageData(const 
SvxIconChoiceCtrlEntry* pEntry) const
-{
-    VerticalTabPageData* pRet = nullptr;
-    for (auto & pData : maPageList)
-    {
-        if (pData->pEntry == pEntry)
-        {
-            pRet = pData.get();
-            break;
-        }
-    }
-    return pRet;
-}
-
-VerticalTabPageData* VerticalTabControl::GetPageData(std::u16string_view rId) 
const
-{
-    VerticalTabPageData* pRet = nullptr;
-    for (auto & pData : maPageList)
-    {
-        if (pData->sId == rId)
-        {
-            pRet = pData.get();
-            break;
-        }
-    }
-    return pRet;
-}
-
-void VerticalTabControl::SetCurPageId(const OUString& rId)
-{
-    OUString sOldPageId = GetCurPageId();
-    if (sOldPageId == rId)
-        return;
-
-    VerticalTabPageData* pOldData = GetPageData(sOldPageId);
-    if (pOldData && pOldData->xPage)
-    {
-        if (!DeactivatePage())
-            return;
-        pOldData->xPage->Hide();
-    }
-
-    m_sCurrentPageId = "";
-
-    VerticalTabPageData* pNewData = GetPageData(rId);
-    if (pNewData && pNewData->xPage)
-    {
-        m_sCurrentPageId = rId;
-        m_xChooser->SetCursor(pNewData->pEntry);
-
-        ActivatePage();
-        pNewData->xPage->Show();
-    }
-    collectUIInformation(get_id(),m_sCurrentPageId);
-}
-
-const OUString & VerticalTabControl::GetPageId(sal_uInt16 nIndex) const
-{
-    return maPageList[nIndex]->sId;
-}
-
-void VerticalTabControl::InsertPage(const rtl::OUString &rIdent, const 
rtl::OUString& rLabel, const Image& rImage,
-                                    const rtl::OUString& rTooltip, 
VclPtr<vcl::Window> xPage, int nPos)
-{
-    SvxIconChoiceCtrlEntry* pEntry = m_xChooser->InsertEntry(rLabel, rImage);
-    pEntry->SetQuickHelpText(rTooltip);
-    m_xChooser->ArrangeIcons();
-    VerticalTabPageData* pNew;
-    if (nPos == -1)
-    {
-        maPageList.emplace_back(new VerticalTabPageData);
-        pNew = maPageList.back().get();
-    }
-    else
-    {
-        maPageList.emplace(maPageList.begin() + nPos, new VerticalTabPageData);
-        pNew = maPageList[nPos].get();
-    }
-    pNew->sId = rIdent;
-    pNew->pEntry = pEntry;
-    pNew->xPage = xPage;
-    Size aOrigPrefSize(m_xBox->get_preferred_size());
-    Size aPagePrefSize(xPage->get_preferred_size());
-    m_xBox->set_width_request(std::max(aOrigPrefSize.Width(), 
aPagePrefSize.Width()));
-    m_xBox->set_height_request(std::max(aOrigPrefSize.Height(), 
aPagePrefSize.Height()));
-    pNew->xPage->Hide();
-}
-
-void VerticalTabControl::RemovePage(std::u16string_view rPageId)
-{
-    for (auto it = maPageList.begin(), end = maPageList.end(); it != end; ++it)
-    {
-        VerticalTabPageData* pData = it->get();
-        if (pData->sId == rPageId)
-        {
-            sal_Int32 nEntryListPos = 
m_xChooser->GetEntryListPos(pData->pEntry);
-            assert(nEntryListPos >= 0);
-            m_xChooser->RemoveEntry(nEntryListPos);
-            m_xChooser->ArrangeIcons();
-            maPageList.erase(it);
-            break;
-        }
-    }
-}
-
-sal_uInt16 VerticalTabControl::GetPagePos(std::u16string_view rPageId) const
-{
-    VerticalTabPageData* pData = GetPageData(rPageId);
-    if (!pData)
-        return TAB_PAGE_NOTFOUND;
-    return m_xChooser->GetEntryListPos(pData->pEntry);
-}
-
-VclPtr<vcl::Window> VerticalTabControl::GetPage(std::u16string_view rPageId) 
const
-{
-    VerticalTabPageData* pData = GetPageData(rPageId);
-    if (!pData)
-        return nullptr;
-    return pData->xPage;
-}
-
-OUString VerticalTabControl::GetPageText(std::u16string_view rPageId) const
-{
-    VerticalTabPageData* pData = GetPageData(rPageId);
-    if (!pData)
-        return OUString();
-    return pData->pEntry->GetText();
-}
-
-void VerticalTabControl::SetPageText(std::u16string_view rPageId, const 
OUString& rText)
-{
-    VerticalTabPageData* pData = GetPageData(rPageId);
-    if (!pData)
-        return;
-    pData->pEntry->SetText(rText);
-}
-
-Size VerticalTabControl::GetOptimalSize() const
-{
-    // re-calculate size - we might have replaced dummy tab pages with
-    // actual content
-    Size aOptimalPageSize(m_xBox->get_preferred_size());
-
-    for (auto const& item : maPageList)
-    {
-        Size aPagePrefSize(item->xPage->get_preferred_size());
-        if (aPagePrefSize.Width() > aOptimalPageSize.Width())
-            aOptimalPageSize.setWidth( aPagePrefSize.Width() );
-        if (aPagePrefSize.Height() > aOptimalPageSize.Height())
-            aOptimalPageSize.setHeight( aPagePrefSize.Height() );
-    }
-
-    Size aChooserSize(m_xChooser->get_preferred_size());
-    return Size(aChooserSize.Width() + aOptimalPageSize.Width(),
-                std::max(aChooserSize.Height(), aOptimalPageSize.Height()));
-}
-
-void VerticalTabControl::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
-{
-    rJsonWriter.put("id", get_id());
-    rJsonWriter.put("type", "tabcontrol");
-    rJsonWriter.put("vertical", true);
-    rJsonWriter.put("selected", GetCurPageId());
-
-    {
-        auto childrenNode = rJsonWriter.startArray("children");
-        for (int i = 0; i < GetPageCount(); i++)
-        {
-            VclPtr<vcl::Window> pChild = GetPage(GetPageId(i));
-
-            if (pChild)
-            {
-                if (!pChild->GetChildCount())
-                    continue;
-
-                auto aChildNode = rJsonWriter.startStruct();
-                pChild->DumpAsPropertyTree(rJsonWriter);
-            }
-        }
-    }
-    {
-        auto tabsNode = rJsonWriter.startArray("tabs");
-        for(int i = 0; i < GetPageCount(); i++)
-        {
-            VclPtr<vcl::Window> pChild = GetPage(GetPageId(i));
-
-            if (pChild)
-            {
-                if (!pChild->GetChildCount())
-                    continue;
-
-                auto aTabNode = rJsonWriter.startStruct();
-                auto sId = GetPageId(i);
-                rJsonWriter.put("text", GetPageText(sId));
-                rJsonWriter.put("id", sId);
-                rJsonWriter.put("name", GetPageText(sId));
-            }
-        }
-    }
-}
-
-FactoryFunction VerticalTabControl::GetUITestFactory() const
-{
-    return VerticalTabControlUIObject::create;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/control/verticaltabctrl.cxx 
b/vcl/source/control/verticaltabctrl.cxx
new file mode 100644
index 000000000000..acf28ca16c86
--- /dev/null
+++ b/vcl/source/control/verticaltabctrl.cxx
@@ -0,0 +1,326 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <verticaltabctrl.hxx>
+
+#include <vcl/commandevent.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/toolkit/ivctrl.hxx>
+#include <vcl/uitest/uiobject.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+#include <vcl/vclevent.hxx>
+
+namespace
+{
+void collectUIInformation(const OUString& aID, const OUString& aPos)
+{
+    EventDescription aDescription;
+    aDescription.aID = aID;
+    aDescription.aParameters = { { "POS", aPos } };
+    aDescription.aAction = "SELECT";
+    aDescription.aKeyWord = "VerticalTab";
+    UITestLogger::getInstance().logEvent(aDescription);
+}
+}
+
+struct VerticalTabPageData
+{
+    OUString sId;
+    SvxIconChoiceCtrlEntry* pEntry;
+    VclPtr<vcl::Window> xPage; ///< the TabPage itself
+};
+
+VerticalTabControl::VerticalTabControl(vcl::Window* pParent, bool bWithIcons)
+    : VclHBox(pParent)
+    , m_xChooser(VclPtr<SvtIconChoiceCtrl>::Create(
+          this, WB_3DLOOK | (bWithIcons ? WB_ICON : WB_SMALLICON) |
+#ifdef MACOSX
+                    WB_NOBORDER |
+#else
+                    WB_BORDER |
+#endif
+                    WB_NOCOLUMNHEADER | WB_NODRAGSELECTION | WB_TABSTOP | 
WB_CLIPCHILDREN
+                    | WB_NOHSCROLL))
+    , m_xBox(VclPtr<VclVBox>::Create(this))
+{
+    SetStyle(GetStyle() | WB_DIALOGCONTROL);
+    SetType(WindowType::VERTICALTABCONTROL);
+    m_xChooser->SetClickHdl(LINK(this, VerticalTabControl, ChosePageHdl_Impl));
+    m_xChooser->set_width_request(150);
+    m_xChooser->set_height_request(400);
+    m_xChooser->SetSizePixel(Size(150, 400));
+    m_xBox->set_vexpand(true);
+    m_xBox->set_hexpand(true);
+    m_xBox->set_expand(true);
+    m_xBox->Show();
+    m_xChooser->Show();
+}
+
+VerticalTabControl::~VerticalTabControl() { disposeOnce(); }
+
+void VerticalTabControl::dispose()
+{
+    m_xChooser.disposeAndClear();
+    m_xBox.disposeAndClear();
+    VclHBox::dispose();
+}
+
+IMPL_LINK_NOARG(VerticalTabControl, ChosePageHdl_Impl, SvtIconChoiceCtrl*, 
void)
+{
+    SvxIconChoiceCtrlEntry* pEntry = m_xChooser->GetSelectedEntry();
+    if (!pEntry)
+        pEntry = m_xChooser->GetCursor();
+
+    VerticalTabPageData* pData = GetPageData(pEntry);
+
+    if (pData->sId != m_sCurrentPageId)
+        SetCurPageId(pData->sId);
+}
+
+bool VerticalTabControl::EventNotify(NotifyEvent& rNEvt)
+{
+    if (rNEvt.GetType() == NotifyEventType::KEYINPUT)
+    {
+        sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
+        if (nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN)
+        {
+            m_xChooser->DoKeyInput(*(rNEvt.GetKeyEvent()));
+            return true;
+        }
+    }
+    return VclHBox::EventNotify(rNEvt);
+}
+
+void VerticalTabControl::ActivatePage() { m_aActivateHdl.Call(this); }
+
+bool VerticalTabControl::DeactivatePage()
+{
+    return !m_aDeactivateHdl.IsSet() || m_aDeactivateHdl.Call(this);
+}
+
+VerticalTabPageData* VerticalTabControl::GetPageData(const 
SvxIconChoiceCtrlEntry* pEntry) const
+{
+    VerticalTabPageData* pRet = nullptr;
+    for (auto& pData : maPageList)
+    {
+        if (pData->pEntry == pEntry)
+        {
+            pRet = pData.get();
+            break;
+        }
+    }
+    return pRet;
+}
+
+VerticalTabPageData* VerticalTabControl::GetPageData(std::u16string_view rId) 
const
+{
+    VerticalTabPageData* pRet = nullptr;
+    for (auto& pData : maPageList)
+    {
+        if (pData->sId == rId)
+        {
+            pRet = pData.get();
+            break;
+        }
+    }
+    return pRet;
+}
+
+void VerticalTabControl::SetCurPageId(const OUString& rId)
+{
+    OUString sOldPageId = GetCurPageId();
+    if (sOldPageId == rId)
+        return;
+
+    VerticalTabPageData* pOldData = GetPageData(sOldPageId);
+    if (pOldData && pOldData->xPage)
+    {
+        if (!DeactivatePage())
+            return;
+        pOldData->xPage->Hide();
+    }
+
+    m_sCurrentPageId = "";
+
+    VerticalTabPageData* pNewData = GetPageData(rId);
+    if (pNewData && pNewData->xPage)
+    {
+        m_sCurrentPageId = rId;
+        m_xChooser->SetCursor(pNewData->pEntry);
+
+        ActivatePage();
+        pNewData->xPage->Show();
+    }
+    collectUIInformation(get_id(), m_sCurrentPageId);
+}
+
+const OUString& VerticalTabControl::GetPageId(sal_uInt16 nIndex) const
+{
+    return maPageList[nIndex]->sId;
+}
+
+void VerticalTabControl::InsertPage(const rtl::OUString& rIdent, const 
rtl::OUString& rLabel,
+                                    const Image& rImage, const rtl::OUString& 
rTooltip,
+                                    VclPtr<vcl::Window> xPage, int nPos)
+{
+    SvxIconChoiceCtrlEntry* pEntry = m_xChooser->InsertEntry(rLabel, rImage);
+    pEntry->SetQuickHelpText(rTooltip);
+    m_xChooser->ArrangeIcons();
+    VerticalTabPageData* pNew;
+    if (nPos == -1)
+    {
+        maPageList.emplace_back(new VerticalTabPageData);
+        pNew = maPageList.back().get();
+    }
+    else
+    {
+        maPageList.emplace(maPageList.begin() + nPos, new VerticalTabPageData);
+        pNew = maPageList[nPos].get();
+    }
+    pNew->sId = rIdent;
+    pNew->pEntry = pEntry;
+    pNew->xPage = xPage;
+    Size aOrigPrefSize(m_xBox->get_preferred_size());
+    Size aPagePrefSize(xPage->get_preferred_size());
+    m_xBox->set_width_request(std::max(aOrigPrefSize.Width(), 
aPagePrefSize.Width()));
+    m_xBox->set_height_request(std::max(aOrigPrefSize.Height(), 
aPagePrefSize.Height()));
+    pNew->xPage->Hide();
+}
+
+void VerticalTabControl::RemovePage(std::u16string_view rPageId)
+{
+    for (auto it = maPageList.begin(), end = maPageList.end(); it != end; ++it)
+    {
+        VerticalTabPageData* pData = it->get();
+        if (pData->sId == rPageId)
+        {
+            sal_Int32 nEntryListPos = 
m_xChooser->GetEntryListPos(pData->pEntry);
+            assert(nEntryListPos >= 0);
+            m_xChooser->RemoveEntry(nEntryListPos);
+            m_xChooser->ArrangeIcons();
+            maPageList.erase(it);
+            break;
+        }
+    }
+}
+
+sal_uInt16 VerticalTabControl::GetPagePos(std::u16string_view rPageId) const
+{
+    VerticalTabPageData* pData = GetPageData(rPageId);
+    if (!pData)
+        return TAB_PAGE_NOTFOUND;
+    return m_xChooser->GetEntryListPos(pData->pEntry);
+}
+
+VclPtr<vcl::Window> VerticalTabControl::GetPage(std::u16string_view rPageId) 
const
+{
+    VerticalTabPageData* pData = GetPageData(rPageId);
+    if (!pData)
+        return nullptr;
+    return pData->xPage;
+}
+
+OUString VerticalTabControl::GetPageText(std::u16string_view rPageId) const
+{
+    VerticalTabPageData* pData = GetPageData(rPageId);
+    if (!pData)
+        return OUString();
+    return pData->pEntry->GetText();
+}
+
+void VerticalTabControl::SetPageText(std::u16string_view rPageId, const 
OUString& rText)
+{
+    VerticalTabPageData* pData = GetPageData(rPageId);
+    if (!pData)
+        return;
+    pData->pEntry->SetText(rText);
+}
+
+Size VerticalTabControl::GetOptimalSize() const
+{
+    // re-calculate size - we might have replaced dummy tab pages with
+    // actual content
+    Size aOptimalPageSize(m_xBox->get_preferred_size());
+
+    for (auto const& item : maPageList)
+    {
+        Size aPagePrefSize(item->xPage->get_preferred_size());
+        if (aPagePrefSize.Width() > aOptimalPageSize.Width())
+            aOptimalPageSize.setWidth(aPagePrefSize.Width());
+        if (aPagePrefSize.Height() > aOptimalPageSize.Height())
+            aOptimalPageSize.setHeight(aPagePrefSize.Height());
+    }
+
+    Size aChooserSize(m_xChooser->get_preferred_size());
+    return Size(aChooserSize.Width() + aOptimalPageSize.Width(),
+                std::max(aChooserSize.Height(), aOptimalPageSize.Height()));
+}
+
+void VerticalTabControl::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
+{
+    rJsonWriter.put("id", get_id());
+    rJsonWriter.put("type", "tabcontrol");
+    rJsonWriter.put("vertical", true);
+    rJsonWriter.put("selected", GetCurPageId());
+
+    {
+        auto childrenNode = rJsonWriter.startArray("children");
+        for (int i = 0; i < GetPageCount(); i++)
+        {
+            VclPtr<vcl::Window> pChild = GetPage(GetPageId(i));
+
+            if (pChild)
+            {
+                if (!pChild->GetChildCount())
+                    continue;
+
+                auto aChildNode = rJsonWriter.startStruct();
+                pChild->DumpAsPropertyTree(rJsonWriter);
+            }
+        }
+    }
+    {
+        auto tabsNode = rJsonWriter.startArray("tabs");
+        for (int i = 0; i < GetPageCount(); i++)
+        {
+            VclPtr<vcl::Window> pChild = GetPage(GetPageId(i));
+
+            if (pChild)
+            {
+                if (!pChild->GetChildCount())
+                    continue;
+
+                auto aTabNode = rJsonWriter.startStruct();
+                auto sId = GetPageId(i);
+                rJsonWriter.put("text", GetPageText(sId));
+                rJsonWriter.put("id", sId);
+                rJsonWriter.put("name", GetPageText(sId));
+            }
+        }
+    }
+}
+
+FactoryFunction VerticalTabControl::GetUITestFactory() const
+{
+    return VerticalTabControlUIObject::create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to