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: */
