include/svx/svxbmpnumiconview.hxx | 73 ++++ solenv/clang-format/excludelist | 2 svx/Library_svx.mk | 1 svx/source/dialog/svxbmpnumiconview.cxx | 539 +++++++++++++++++++++++++++++++ svx/source/tbxctrls/bulletsnumbering.cxx | 191 ++++++---- svx/uiconfig/ui/numberingwindow.ui | 66 ++- 6 files changed, 768 insertions(+), 104 deletions(-)
New commits: commit 48914aaa33dbd1eeec11f60449c8d0d2acb581da Author: Parth Raiyani <parth.raiy...@collabora.com> AuthorDate: Fri Aug 22 12:56:38 2025 +0530 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Aug 25 12:41:37 2025 +0200 Switch to IconView in bullets numbering popup for improved UI handling - Replaced SvxNumValueSet with weld::IconView in the bullets numbering popup - Updated UI in numberingwindow.ui to include GtkIconView and GtkTreeStore - Refactors related logic to accommodate IconView, including preview generation, selection handling, and tooltip support Change-Id: I0b9b2fa5e9612488662548edc1fb78bf7eaa95e0 Signed-off-by: Parth Raiyani <parth.raiy...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189605 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/include/svx/svxbmpnumiconview.hxx b/include/svx/svxbmpnumiconview.hxx new file mode 100644 index 000000000000..853ad3ae29a1 --- /dev/null +++ b/include/svx/svxbmpnumiconview.hxx @@ -0,0 +1,73 @@ +/* -*- 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 <svx/numvset.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::text; +using namespace com::sun::star::container; +using namespace com::sun::star::style; + +class SVX_DLLPUBLIC SvxBmpNumIconView +{ +public: + static vcl::Font& GetDefaultBulletFont(); + + static void PopulateIconView( + weld::IconView* pIconView, + NumberingPageType ePageType, + Size previewSize, + const Sequence<Sequence<PropertyValue>>& rNumSettings = Sequence<Sequence<PropertyValue>>(), + const Sequence<Reference<XIndexAccess>>& rOutlineSettings = Sequence<Reference<XIndexAccess>>(), + Reference<XNumberingFormatter> const& xFormatter = nullptr, + const Locale& rLocale = Locale()); + + static VclPtr<VirtualDevice> CreatePreviewFromUserDraw( + NumberingPageType ePageType, + sal_Int32 nIndex, + Size previewSize, + const Sequence<Sequence<PropertyValue>>& rNumSettings = Sequence<Sequence<PropertyValue>>(), + const Sequence<Reference<XIndexAccess>>& rOutlineSettings = Sequence<Reference<XIndexAccess>>(), + Reference<XNumberingFormatter> const& xFormatter = nullptr, + const Locale& rLocale = Locale(), + const std::vector<std::pair<OUString, OUString>>& rCustomBullets = std::vector<std::pair<OUString, OUString>>()); + + static VclPtr<VirtualDevice> CreateCustomBulletPreview(const OUString& rBulletChar, const OUString& rFontName); + static OUString GetNumberingDescription(NumberingPageType ePageType, sal_Int32 nIndex); + + static void SetNumberingSettings( + weld::IconView* mxIconView, + Size previewSize, + const Sequence<Sequence<PropertyValue>>& aNum, + Reference<XNumberingFormatter> const& xFormat, + const Locale& rLocale, + std::vector<std::pair<OUString, OUString>> maCustomBullets = std::vector<std::pair<OUString, OUString>>()); + + static void SetOutlineNumberingSettings( + weld::IconView* mxIconView, + Size previewSize, + const Sequence<Reference<XIndexAccess>>& rOutline, + Reference<XNumberingFormatter> const& xFormat, + const Locale& rLocale, + std::vector<std::pair<OUString, OUString>> maCustomBullets = std::vector<std::pair<OUString, OUString>>()); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index f8c6642f9316..2a99f09fcc7c 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -5731,6 +5731,7 @@ include/svx/ParseContext.hxx include/svx/ShapeTypeHandler.hxx include/svx/SmartTagItem.hxx include/svx/SmartTagMgr.hxx +include/svx/svxbmpnumiconview.hxx include/svx/SvxColorChildWindow.hxx include/svx/SvxPresetListBox.hxx include/svx/algitem.hxx @@ -11318,6 +11319,7 @@ svx/source/dialog/searchcharmap.cxx svx/source/dialog/spacinglistbox.cxx svx/source/dialog/srchctrl.cxx svx/source/dialog/srchdlg.cxx +svx/source/dialog/svxbmpnumiconview.cxx svx/source/dialog/svxbmpnumvalueset.cxx svx/source/dialog/svxgraphicitem.cxx svx/source/dialog/svxruler.cxx diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk index 4dd372c5bda4..9ba2b77f6aaa 100644 --- a/svx/Library_svx.mk +++ b/svx/Library_svx.mk @@ -173,6 +173,7 @@ $(eval $(call gb_Library_add_exception_objects,svx,\ svx/source/dialog/srchdlg \ svx/source/dialog/strarray \ svx/source/dialog/svxbmpnumvalueset \ + svx/source/dialog/svxbmpnumiconview \ svx/source/dialog/svxgraphicitem \ svx/source/dialog/svxruler \ svx/source/dialog/swframeexample \ diff --git a/svx/source/dialog/svxbmpnumiconview.cxx b/svx/source/dialog/svxbmpnumiconview.cxx new file mode 100644 index 000000000000..84582570821c --- /dev/null +++ b/svx/source/dialog/svxbmpnumiconview.cxx @@ -0,0 +1,539 @@ +/* -*- 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 <com/sun/star/text/DefaultNumberingProvider.hpp> +#include <com/sun/star/text/XNumberingFormatter.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/graphic/XGraphic.hpp> + +#include <vcl/virdev.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <editeng/svxenum.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <officecfg/Office/Common.hxx> + +#include <svx/svxbmpnumiconview.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::text; +using namespace com::sun::star::container; +using namespace com::sun::star::style; + +const TranslateId OUTLINE_DESCRIPTIONS[] = { + RID_SVXSTR_OUTLINENUM_DESCRIPTION_0, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_1, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_2, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_3, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_4, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_5, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_6, + RID_SVXSTR_OUTLINENUM_DESCRIPTION_7 +}; + +const TranslateId SINGLENUM_DESCRIPTIONS[] = { + RID_SVXSTR_SINGLENUM_DESCRIPTION_0, + RID_SVXSTR_SINGLENUM_DESCRIPTION_1, + RID_SVXSTR_SINGLENUM_DESCRIPTION_2, + RID_SVXSTR_SINGLENUM_DESCRIPTION_3, + RID_SVXSTR_SINGLENUM_DESCRIPTION_4, + RID_SVXSTR_SINGLENUM_DESCRIPTION_5, + RID_SVXSTR_SINGLENUM_DESCRIPTION_6, + RID_SVXSTR_SINGLENUM_DESCRIPTION_7 +}; + +vcl::Font& SvxBmpNumIconView::GetDefaultBulletFont() +{ + static vcl::Font aDefBulletFont = []() + { + static vcl::Font tmp(u"OpenSymbol"_ustr, u""_ustr, Size(0, 14)); + tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL ); + tmp.SetFamily( FAMILY_DONTKNOW ); + tmp.SetPitch( PITCH_DONTKNOW ); + tmp.SetWeight( WEIGHT_DONTKNOW ); + tmp.SetTransparent( true ); + return tmp; + }(); + return aDefBulletFont; +} + +void SvxBmpNumIconView::PopulateIconView( + weld::IconView* pIconView, + NumberingPageType ePageType, + Size previewSize, + const Sequence<Sequence<PropertyValue>>& rNumSettings, + const Sequence<Reference<XIndexAccess>>& rOutlineSettings, + Reference<XNumberingFormatter> const& xFormatter, + const Locale& rLocale) +{ + if (!pIconView) + return; + + pIconView->clear(); + + if (ePageType == NumberingPageType::BULLET) + { + Sequence<OUString> aBulletSymbols = + officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); + + for (sal_Int32 i = 0; i < std::min(aBulletSymbols.getLength(), sal_Int32(8)); ++i) + { + VclPtr<VirtualDevice> pVDev = CreatePreviewFromUserDraw(NumberingPageType::BULLET, i, previewSize, rNumSettings, rOutlineSettings, xFormatter, rLocale); + OUString sId = OUString::number(i); + OUString sText = GetNumberingDescription(ePageType, i); + pIconView->insert(-1, &sText, &sId, pVDev, nullptr); + } + } +} + +VclPtr<VirtualDevice> SvxBmpNumIconView::CreatePreviewFromUserDraw( + NumberingPageType ePageType, + sal_Int32 nIndex, + Size previewSize, + const Sequence<Sequence<PropertyValue>>& rNumSettings, + const Sequence<Reference<XIndexAccess>>& rOutlineSettings, + Reference<XNumberingFormatter> const& xFormatter, + const Locale& rLocale, + const std::vector<std::pair<OUString, OUString>>& rCustomBullets) +{ + static const sal_uInt16 aLinesArr[] = + { + 15, 10, + 20, 30, + 25, 50, + 30, 70, + 35, 90, // up to here line positions + 5, 10, // character positions + 10, 30, + 15, 50, + 20, 70, + 25, 90, + }; + + const Color aBackColor(COL_WHITE); + const Color aTextColor(COL_BLACK); + + VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); + pVDev->SetOutputSizePixel(previewSize); + + + tools::Long nRectWidth = previewSize.Width(); + tools::Long nRectHeight = previewSize.Height(); + Point aBLPos(0, 0); + + vcl::Font aFont(OutputDevice::GetDefaultFont( + DefaultFontType::UI_SANS, MsLangId::getConfiguredSystemLanguage(), GetDefaultFontFlags::OnlyOne)); + + Size aSize = aFont.GetFontSize(); + + vcl::Font aRuleFont( GetDefaultBulletFont() ); + Sequence<OUString> aBulletSymbols; + + if(ePageType == NumberingPageType::BULLET || ePageType == NumberingPageType::DOCBULLET) + { + if(ePageType == NumberingPageType::BULLET) + { + aBulletSymbols = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); + Sequence< OUString > aBulletFonts = + officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get(); + if (nIndex < aBulletFonts.getLength()) + { + aRuleFont.SetFamilyName(aBulletFonts[nIndex]); + } + } + else // DOCBULLET + { + if (o3tl::make_unsigned(nIndex) < rCustomBullets.size()) + { + aRuleFont.SetFamilyName(rCustomBullets[nIndex].second); + } + } + aSize.setHeight(nRectHeight/6); + aRuleFont.SetFontSize(aSize); + aRuleFont.SetColor(aTextColor); + aRuleFont.SetFillColor(aBackColor); + aFont = aRuleFont; + } + else if(ePageType == NumberingPageType::OUTLINE) + { + aSize.setHeight( nRectHeight/8 ); + } + else // SINGLENUM + { + aSize.setHeight(nRectHeight/6); + } + + aFont.SetColor(aTextColor); + aFont.SetFillColor(aBackColor); + aFont.SetFontSize( aSize ); + pVDev->SetFont(aFont); + + pVDev->SetFillColor(aBackColor); + pVDev->SetLineColor(aTextColor); + pVDev->DrawRect(tools::Rectangle(Point(0,0), previewSize)); + + // Draw background lines for non-outline types + if(ePageType != NumberingPageType::OUTLINE) + { + pVDev->SetLineColor(COL_LIGHTGRAY); + Point aStart(aBLPos.X() + nRectWidth * 25 / 100, 0); + Point aEnd(aBLPos.X() + nRectWidth * 9 / 10, 0); + for(sal_uInt16 i = 11; i < 100; i += 33) + { + aStart.setY(aBLPos.Y() + nRectHeight * i / 100); + aEnd.setY(aStart.Y()); + pVDev->DrawLine(aStart, aEnd); + aStart.setY(aBLPos.Y() + nRectHeight * (i + 11) / 100); + aEnd.setY(aStart.Y()); + pVDev->DrawLine(aStart, aEnd); + } + } + + // Render content based on page type + if(ePageType == NumberingPageType::SINGLENUM || + ePageType == NumberingPageType::BULLET || + ePageType == NumberingPageType::DOCBULLET) + { + Point aStart(aBLPos.X() + nRectWidth / 9, 0); + for(sal_uInt16 i = 0; i < 3; i++) + { + sal_uInt16 nY = 11 + i * 33; + aStart.setY(aBLPos.Y() + nRectHeight * nY / 100); + OUString sText; + + if(ePageType == NumberingPageType::BULLET) + { + if (nIndex < aBulletSymbols.getLength()) + sText = aBulletSymbols[nIndex]; + aStart.AdjustY(-(pVDev->GetTextHeight()/2)); + aStart.setX(aBLPos.X() + 5); + } + else if(ePageType == NumberingPageType::DOCBULLET) + { + if (o3tl::make_unsigned(nIndex) < rCustomBullets.size()) + sText = rCustomBullets[nIndex].first; + aStart.AdjustY(-(pVDev->GetTextHeight()/2)); + aStart.setX(aBLPos.X() + 5); + } + else // SINGLENUM + { + if(xFormatter.is() && rNumSettings.getLength() > nIndex) + { + Sequence<PropertyValue> aLevel = rNumSettings.getConstArray()[nIndex]; + try + { + aLevel.realloc(aLevel.getLength() + 1); + PropertyValue& rValue = aLevel.getArray()[aLevel.getLength() - 1]; + rValue.Name = "Value"; + rValue.Value <<= static_cast<sal_Int32>(i + 1); + sText = xFormatter->makeNumberingString(aLevel, rLocale); + } + catch(Exception&) + { + sText = OUString::number(i + 1); + } + } + aStart.setX(aBLPos.X() + 2); + aStart.AdjustY(-(pVDev->GetTextHeight()/2)); + } + pVDev->DrawText(aStart, sText); + } + } + else if(ePageType == NumberingPageType::OUTLINE) + { + tools::Long nStartX = 0; + tools::Long nStartY = 0; + + if(xFormatter.is() && rOutlineSettings.getLength() > nIndex) + { + Reference<XIndexAccess> xLevel = rOutlineSettings.getConstArray()[nIndex]; + try + { + OUString sLevelTexts[5]; + OUString sFontNames[5]; + OUString sBulletChars[5]; + sal_Int16 aNumberingTypes[5]; + OUString sPrefixes[5]; + OUString sSuffixes[5]; + sal_Int16 aParentNumberings[5]; + + sal_Int32 nLevelCount = xLevel->getCount(); + if(nLevelCount > 5) + nLevelCount = 5; + + for(sal_Int32 i = 0; i < nLevelCount; i++) + { + tools::Long nTop = nStartY + nRectHeight * (aLinesArr[2 * i + 11])/100; + Point aLeft(nStartX + nRectWidth * (aLinesArr[2 * i + 10])/100, nTop); + + Any aLevelAny = xLevel->getByIndex(i); + Sequence<PropertyValue> aLevel; + aLevelAny >>= aLevel; + + aNumberingTypes[i] = 0; + aParentNumberings[i] = 0; + + for (const PropertyValue& rProp : aLevel) + { + if (rProp.Name == "NumberingType") + rProp.Value >>= aNumberingTypes[i]; + else if (rProp.Name == "BulletFontName") + rProp.Value >>= sFontNames[i]; + else if (rProp.Name == "BulletChar") + rProp.Value >>= sBulletChars[i]; + else if (rProp.Name == "Prefix") + rProp.Value >>= sPrefixes[i]; + else if (rProp.Name == "Suffix") + rProp.Value >>= sSuffixes[i]; + else if (rProp.Name == "ParentNumbering") + rProp.Value >>= aParentNumberings[i]; + } + + // Generate numbering text using formatter + Sequence<PropertyValue> aProperties(2); + PropertyValue* pProperties = aProperties.getArray(); + pProperties[0].Name = "NumberingType"; + pProperties[0].Value <<= aNumberingTypes[i]; + pProperties[1].Name = "Value"; + pProperties[1].Value <<= sal_Int32(1); + + try + { + sLevelTexts[i] = xFormatter->makeNumberingString(aProperties, rLocale); + } + catch(Exception&) + { + sLevelTexts[i] = "1"; + } + + aLeft.AdjustY(-(pVDev->GetTextHeight()/2)); + + // Draw prefix + if(!sPrefixes[i].isEmpty() && sPrefixes[i] != " ") + { + pVDev->SetFont(aFont); + pVDev->DrawText(aLeft, sPrefixes[i]); + aLeft.AdjustX(pVDev->GetTextWidth(sPrefixes[i])); + } + + // Draw parent numbering + if(aParentNumberings[i]) + { + sal_Int32 nStartLevel = std::min(static_cast<sal_Int32>(aParentNumberings[i]), i); + for(sal_Int32 nParentLevel = i - nStartLevel; nParentLevel < i; nParentLevel++) + { + OUString sTmp = sLevelTexts[nParentLevel] + "."; + + if(aNumberingTypes[nParentLevel] == SVX_NUM_CHAR_SPECIAL && !sBulletChars[nParentLevel].isEmpty()) + { + if(!sFontNames[nParentLevel].isEmpty()) + { + vcl::Font aBulletFont(sFontNames[nParentLevel], aSize); + aBulletFont.SetColor(aTextColor); + pVDev->SetFont(aBulletFont); + } + pVDev->DrawText(aLeft, sBulletChars[nParentLevel]); + aLeft.AdjustX(pVDev->GetTextWidth(sBulletChars[nParentLevel])); + } + else + { + pVDev->SetFont(aFont); + pVDev->DrawText(aLeft, sTmp); + aLeft.AdjustX(pVDev->GetTextWidth(sTmp)); + } + } + } + + // Draw current level + if(aNumberingTypes[i] == SVX_NUM_CHAR_SPECIAL && !sBulletChars[i].isEmpty()) + { + if(!sFontNames[i].isEmpty()) + { + vcl::Font aBulletFont(sFontNames[i], aSize); + aBulletFont.SetColor(aTextColor); + pVDev->SetFont(aBulletFont); + } + pVDev->DrawText(aLeft, sBulletChars[i]); + aLeft.AdjustX(pVDev->GetTextWidth(sBulletChars[i])); + } + else + { + pVDev->SetFont(aFont); + pVDev->DrawText(aLeft, sLevelTexts[i]); + aLeft.AdjustX(pVDev->GetTextWidth(sLevelTexts[i])); + } + + // Draw suffix + if(!sSuffixes[i].isEmpty() && !sSuffixes[i].startsWith(" ")) + { + pVDev->SetFont(aFont); + pVDev->DrawText(aLeft, sSuffixes[i]); + aLeft.AdjustX(pVDev->GetTextWidth(sSuffixes[i])); + } + + // Draw horizontal line + tools::Long nLineTop = nStartY + nRectHeight * aLinesArr[2 * i + 1]/100; + Point aLineLeft(aLeft.X(), nLineTop); + Point aLineRight(nStartX + nRectWidth * 90/100, nLineTop); + pVDev->SetLineColor(COL_LIGHTGRAY); + pVDev->DrawLine(aLineLeft, aLineRight); + } + + } + #ifdef DBG_UTIL + catch(Exception&) + { + static bool bAssert = false; + if(!bAssert) + { + TOOLS_WARN_EXCEPTION("svx.dialog", ""); + bAssert = true; + } + } +#else + catch(Exception&) + { + } +#endif + } + } + + return pVDev; +} + +VclPtr<VirtualDevice> SvxBmpNumIconView::CreateCustomBulletPreview(const OUString& rBulletChar, const OUString& rFontName) +{ + VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); + Size aSize(80, 100); + pVDev->SetOutputSizePixel(aSize); + + const Color aBackColor(COL_WHITE); + const Color aTextColor(COL_BLACK); + + pVDev->SetFillColor(aBackColor); + pVDev->SetLineColor(aTextColor); + pVDev->DrawRect(tools::Rectangle(Point(0,0), aSize)); + + // Add horizontal lines + pVDev->SetLineColor(COL_LIGHTGRAY); + Point aStart(aSize.Width() * 25 / 100, 0); + Point aEnd(aSize.Width() * 9 / 10, 0); + for (sal_uInt16 i = 11; i < 100; i += 33) + { + aStart.setY(aSize.Height() * i / 100); + aEnd.setY(aStart.Y()); + pVDev->DrawLine(aStart, aEnd); + aStart.setY(aSize.Height() * (i + 11) / 100); + aEnd.setY(aStart.Y()); + pVDev->DrawLine(aStart, aEnd); + } + + vcl::Font aRuleFont(rFontName, Size(0, aSize.Height()/6)); + aRuleFont.SetCharSet(RTL_TEXTENCODING_SYMBOL); + aRuleFont.SetColor(aTextColor); + aRuleFont.SetFillColor(aBackColor); + pVDev->SetFont(aRuleFont); + + for (sal_uInt16 i = 0; i < 3; i++) // Show 3 sample lines + { + sal_uInt16 nY = 11 + i * 33; + Point pStart(5, aSize.Height() * nY / 100); + pStart.AdjustY(-(pVDev->GetTextHeight()/2)); + pVDev->DrawText(pStart, rBulletChar); + } + + return pVDev; +} + +OUString SvxBmpNumIconView::GetNumberingDescription(NumberingPageType ePageType, sal_Int32 nIndex) +{ + if (nIndex < 0) + return OUString(); + + switch (ePageType) + { + case NumberingPageType::OUTLINE: { + constexpr auto size = std::size(OUTLINE_DESCRIPTIONS); + if (nIndex < static_cast<sal_Int32>(size)) + return SvxResId(OUTLINE_DESCRIPTIONS[nIndex]); + break; + } + case NumberingPageType::SINGLENUM: { + constexpr auto size = std::size(SINGLENUM_DESCRIPTIONS); + if (nIndex < static_cast<sal_Int32>(size)) + return SvxResId(SINGLENUM_DESCRIPTIONS[nIndex]); + break; + } + case NumberingPageType::BULLET: + return u"Bullet " + OUString::number(nIndex + 1); // convert and display 1-based index + default: + break; + } + + return OUString(); +} + +void SvxBmpNumIconView::SetNumberingSettings( + weld::IconView* mxIconView, + Size previewSize, + const Sequence<Sequence<PropertyValue>>& aNum, + Reference<XNumberingFormatter> const& xFormat, + const Locale& rLocale, + std::vector<std::pair<OUString, OUString>> maCustomBullets) +{ + mxIconView->clear(); + + for (sal_Int32 i = 0; i < aNum.getLength(); ++i) + { + VclPtr<VirtualDevice> pVDev = CreatePreviewFromUserDraw( + NumberingPageType::SINGLENUM, i, previewSize, aNum, Sequence<Reference<XIndexAccess>>(), + xFormat, rLocale, maCustomBullets); + + OUString sId = OUString::number(i); + OUString sText = GetNumberingDescription(NumberingPageType::SINGLENUM, i); + mxIconView->insert(-1, &sText, &sId, pVDev, nullptr); + } +} + +void SvxBmpNumIconView::SetOutlineNumberingSettings( + weld::IconView* mxIconView, + Size previewSize, + const Sequence<Reference<XIndexAccess>>& rOutline, + Reference<XNumberingFormatter> const& xFormat, + const Locale& rLocale, + std::vector<std::pair<OUString, OUString>> maCustomBullets) +{ + mxIconView->clear(); + + for (sal_Int32 i = 0; i < rOutline.getLength(); ++i) + { + VclPtr<VirtualDevice> pVDev = CreatePreviewFromUserDraw( + NumberingPageType::OUTLINE, i, previewSize, Sequence<Sequence<PropertyValue>>(), rOutline, + xFormat, rLocale, maCustomBullets); + + OUString sId = OUString::number(i); + OUString sText = GetNumberingDescription(NumberingPageType::OUTLINE, i); + mxIconView->insert(-1, &sText, &sId, pVDev, nullptr); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx b/svx/source/tbxctrls/bulletsnumbering.cxx index 8e06d125ae4f..9e16d687a581 100644 --- a/svx/source/tbxctrls/bulletsnumbering.cxx +++ b/svx/source/tbxctrls/bulletsnumbering.cxx @@ -23,6 +23,18 @@ #include <vcl/toolbox.hxx> #include <vcl/settings.hxx> #include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <editeng/svxenum.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <svx/svxbmpnumiconview.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::text; +using namespace com::sun::star::container; +using namespace com::sun::star::style; namespace { @@ -32,19 +44,23 @@ class NumberingPopup : public WeldToolbarPopup { NumberingPageType mePageType; NumberingToolBoxControl& mrController; - std::unique_ptr<SvxNumValueSet> mxValueSet; - std::unique_ptr<weld::CustomWeld> mxValueSetWin; - std::unique_ptr<SvxNumValueSet> mxValueSetDoc; - std::unique_ptr<weld::CustomWeld> mxValueSetWinDoc; + std::unique_ptr<weld::IconView> mxIconView; + std::unique_ptr<weld::IconView> mxIconViewDoc; std::unique_ptr<weld::Button> mxMoreButton; std::unique_ptr<weld::Label> mxBulletsLabel; std::unique_ptr<weld::Label> mxDocBulletsLabel; - DECL_LINK(VSSelectValueSetHdl, ValueSet*, void); - DECL_LINK(VSSelectValueSetDocHdl, ValueSet*, void); + DECL_LINK(ItemActivatedHdl, weld::IconView&, bool); + DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString); + + DECL_LINK(DocItemActivatedHdl, weld::IconView&, bool); DECL_LINK(VSButtonClickSetHdl, weld::Button&, void); virtual void GrabFocus() override; +private: + std::vector<std::pair<OUString, OUString>> maCustomBullets; + Size aPreviewSize; + public: NumberingPopup(NumberingToolBoxControl& rController, weld::Widget* pParent, NumberingPageType ePageType); @@ -56,16 +72,16 @@ class NumberingToolBoxControl : public svt::PopupWindowController NumberingPageType mePageType; public: - explicit NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + explicit NumberingToolBoxControl( const Reference< XComponentContext >& rxContext ); virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; // XInitialization - virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override; }; } @@ -75,59 +91,43 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, : WeldToolbarPopup(rController.getFrameInterface(), pParent, u"svx/ui/numberingwindow.ui"_ustr, u"NumberingWindow"_ustr) , mePageType(ePageType) , mrController(rController) - , mxValueSet(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true))) - , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *mxValueSet)) - , mxValueSetDoc(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin_doc"_ustr, true))) - , mxValueSetWinDoc(new weld::CustomWeld(*m_xBuilder, u"valueset_doc"_ustr, *mxValueSetDoc)) + , mxIconView(m_xBuilder->weld_icon_view(u"numbering_window_iconview"_ustr)) + , mxIconViewDoc(m_xBuilder->weld_icon_view(u"numbering_window_iconview_doc"_ustr)) , mxMoreButton(m_xBuilder->weld_button(u"more"_ustr)) , mxBulletsLabel(m_xBuilder->weld_label(u"label_default"_ustr)) , mxDocBulletsLabel(m_xBuilder->weld_label(u"label_doc"_ustr)) + , aPreviewSize(80, 100) { - mxValueSet->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NO_DIRECTSELECT); - mxValueSetDoc->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NO_DIRECTSELECT); - mxValueSet->init(mePageType); - mxValueSetDoc->init(NumberingPageType::DOCBULLET); - mxValueSetWinDoc->hide(); + SvxBmpNumIconView::PopulateIconView(mxIconView.get(), mePageType, aPreviewSize); + SvxBmpNumIconView::PopulateIconView(mxIconViewDoc.get(), NumberingPageType::DOCBULLET, aPreviewSize); + + mxIconViewDoc->hide(); mxDocBulletsLabel->hide(); if ( mePageType != NumberingPageType::BULLET ) { mxBulletsLabel->hide(); - css::uno::Reference< css::text::XDefaultNumberingProvider > xDefNum = css::text::DefaultNumberingProvider::create( mrController.getContext() ); + Reference< XDefaultNumberingProvider > xDefNum = DefaultNumberingProvider::create( mrController.getContext() ); if ( xDefNum.is() ) { - css::lang::Locale aLocale = Application::GetSettings().GetLanguageTag().getLocale(); - css::uno::Reference< css::text::XNumberingFormatter > xFormat( xDefNum, css::uno::UNO_QUERY ); + Locale aLocale = Application::GetSettings().GetLanguageTag().getLocale(); + Reference< XNumberingFormatter > xFormat( xDefNum, UNO_QUERY ); if ( mePageType == NumberingPageType::SINGLENUM ) { - css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aNumberings( + Sequence< Sequence< PropertyValue > > aNumberings( xDefNum->getDefaultContinuousNumberingLevels( aLocale ) ); - mxValueSet->SetNumberingSettings( aNumberings, xFormat, aLocale ); + SvxBmpNumIconView::SetNumberingSettings( mxIconView.get(), aPreviewSize, aNumberings, xFormat, aLocale ); } else if ( mePageType == NumberingPageType::OUTLINE ) { - css::uno::Sequence< css::uno::Reference< css::container::XIndexAccess > > aOutline( + Sequence< Reference< XIndexAccess > > aOutline( xDefNum->getDefaultOutlineNumberings( aLocale ) ); - mxValueSet->SetOutlineNumberingSettings( aOutline, xFormat, aLocale ); + SvxBmpNumIconView::SetOutlineNumberingSettings( mxIconView.get(), aPreviewSize, aOutline, xFormat, aLocale ); } } } - weld::DrawingArea* pDrawingArea = mxValueSet->GetDrawingArea(); - weld::DrawingArea* pDrawingAreaDoc = mxValueSetDoc->GetDrawingArea(); - OutputDevice& rRefDevice = pDrawingArea->get_ref_device(); - Size aItemSize(rRefDevice.LogicToPixel(Size(30, 42), MapMode(MapUnit::MapAppFont))); - mxValueSet->SetExtraSpacing( 2 ); - mxValueSetDoc->SetExtraSpacing( 2 ); - Size aSize(mxValueSet->CalcWindowSizePixel(aItemSize)); - pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); - pDrawingAreaDoc->set_size_request(aSize.Width(), aSize.Height()); - mxValueSet->SetOutputSizePixel(aSize); - mxValueSetDoc->SetOutputSizePixel(aSize); - mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor()); - mxValueSetDoc->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor()); - if ( mePageType == NumberingPageType::BULLET ) { AddStatusListener( u".uno:CurrentBulletListType"_ustr ); @@ -142,17 +142,19 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, mxMoreButton->set_image(xImage); mxMoreButton->connect_clicked(LINK(this, NumberingPopup, VSButtonClickSetHdl)); - mxValueSet->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetHdl)); - mxValueSetDoc->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetDocHdl)); + mxIconView->connect_item_activated(LINK(this, NumberingPopup, ItemActivatedHdl)); + mxIconView->connect_query_tooltip(LINK(this, NumberingPopup, QueryTooltipHdl)); + + mxIconViewDoc->connect_item_activated(LINK(this, NumberingPopup, DocItemActivatedHdl)); } namespace { bool lcl_BulletIsDefault(std::u16string_view aSymbol, std::u16string_view aFont) { - css::uno::Sequence<OUString> aBulletSymbols + Sequence<OUString> aBulletSymbols = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); - css::uno::Sequence<OUString> aBulletFonts + Sequence<OUString> aBulletFonts = officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get(); for (sal_Int32 i = 0; i < aBulletSymbols.getLength(); i++) { @@ -167,12 +169,12 @@ void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent { if (rEvent.FeatureURL.Complete == ".uno:DocumentBulletList") { - css::uno::Sequence<OUString> aSeq; + Sequence<OUString> aSeq; if (rEvent.State >>= aSeq) { std::vector<std::pair<OUString, OUString>> aList; - mxValueSetDoc->Clear(); - int i = 1; + mxIconViewDoc->clear(); + // The string contains the bullet as first character, and then the font name for (const OUString& sBulletFont : aSeq) { @@ -180,80 +182,113 @@ void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent OUString sFont(sBulletFont.copy(1, sBulletFont.getLength() - 1)); if (lcl_BulletIsDefault(sBullet, sFont)) continue; - mxValueSetDoc->InsertItem(i, sBullet, i); + + VclPtr<VirtualDevice> pVDev = SvxBmpNumIconView::CreateCustomBulletPreview(sBullet, sFont); + OUString sId = OUString::number(aList.size()); + mxIconViewDoc->insert(-1, nullptr, &sId, pVDev, nullptr); aList.emplace_back(sBullet, sFont); - i++; } + if (!aList.empty()) { - mxValueSetWinDoc->show(); mxDocBulletsLabel->show(); - mxValueSetDoc->SetCustomBullets(aList); + mxIconViewDoc->show(); + maCustomBullets = aList; } else { - mxValueSetWinDoc->hide(); mxDocBulletsLabel->hide(); + mxIconViewDoc->hide(); } } } else { - mxValueSet->SetNoSelection(); - sal_Int32 nSelItem; - if ( rEvent.State >>= nSelItem ) - mxValueSet->SelectItem( nSelItem ); + OUString sId = mxIconView->get_selected_id(); + sal_Int32 nSelItem = !sId.isEmpty() ? sId.toInt32() : -1; + if(nSelItem == -1) { + if ( rEvent.State >>= nSelItem ) + { + nSelItem--; // convert to 0-based index for iconview + if(nSelItem > -1 && nSelItem < mxIconView->n_children()) + mxIconView->select( nSelItem ); + } + } } } -IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void) +IMPL_LINK(NumberingPopup, ItemActivatedHdl, weld::IconView&, rIconView, bool) { - sal_uInt16 nSelItem = mxValueSet->GetSelectedItemId(); + OUString sId = rIconView.get_selected_id(); + if (sId.isEmpty()) + return false; + + sal_Int32 nId = sId.toInt32(); + if ( mePageType == NumberingPageType::BULLET ) { - auto aArgs( comphelper::InitPropertySequence( { { "BulletIndex", css::uno::Any( nSelItem ) } } ) ); + auto aArgs( comphelper::InitPropertySequence( { { "BulletIndex", Any( nId + 1 ) } } ) ); mrController.dispatchCommand( u".uno:SetBullet"_ustr, aArgs ); } else if ( mePageType == NumberingPageType::SINGLENUM ) { - auto aArgs( comphelper::InitPropertySequence( { { "SetNumber", css::uno::Any( nSelItem ) } } ) ); + auto aArgs( comphelper::InitPropertySequence( { { "SetNumber", Any( nId + 1 ) } } ) ); mrController.dispatchCommand( u".uno:SetNumber"_ustr, aArgs ); } else { - auto aArgs( comphelper::InitPropertySequence( { { "SetOutline", css::uno::Any( nSelItem ) } } ) ); + auto aArgs( comphelper::InitPropertySequence( { { "SetOutline", Any( nId + 1 ) } } ) ); mrController.dispatchCommand( u".uno:SetOutline"_ustr, aArgs ); } mrController.EndPopupMode(); + return true; } -IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetDocHdl, ValueSet*, void) +IMPL_LINK(NumberingPopup, DocItemActivatedHdl, weld::IconView&, rIconView, bool) { - sal_uInt16 nSelItem = mxValueSetDoc->GetSelectedItemId() - 1; - auto aCustomBullets = mxValueSetDoc->GetCustomBullets(); - OUString nChar(aCustomBullets[nSelItem].first); - OUString sFont(aCustomBullets[nSelItem].second); - auto aArgs(comphelper::InitPropertySequence( - { { "BulletChar", css::uno::Any(nChar) }, { "BulletFont", css::uno::Any(sFont) } })); - mrController.dispatchCommand(u".uno:SetBullet"_ustr, aArgs); - mrController.EndPopupMode(); + OUString sId = rIconView.get_selected_id(); + if (sId.isEmpty()) + return false; + + sal_Int32 nId = sId.toInt32(); + + if (nId >= 0 && nId < static_cast<sal_Int32>(maCustomBullets.size())) + { + OUString nChar(maCustomBullets[nId].first); + OUString sFont(maCustomBullets[nId].second); + auto aArgs(comphelper::InitPropertySequence( + { { "BulletChar", Any(nChar) }, { "BulletFont", Any(sFont) } })); + mrController.dispatchCommand(u".uno:SetBullet"_ustr, aArgs); + mrController.EndPopupMode(); + } + return true; +} + +IMPL_LINK(NumberingPopup, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString) +{ + const OUString sId = mxIconView->get_id(rIter); + if (sId.isEmpty()) + return OUString(); + + sal_Int32 nIndex = sId.toInt32(); + return SvxBmpNumIconView::GetNumberingDescription(mePageType, nIndex); } void NumberingPopup::GrabFocus() { - mxValueSet->GrabFocus(); + mxIconView->grab_focus(); } IMPL_LINK_NOARG(NumberingPopup, VSButtonClickSetHdl, weld::Button&, void) { - auto aArgs( comphelper::InitPropertySequence( { { "Page", css::uno::Any( u"customize"_ustr ) } } ) ); + auto aArgs( comphelper::InitPropertySequence( { { "Page", Any( u"customize"_ustr ) } } ) ); mrController.dispatchCommand( u".uno:OutlineBullet"_ustr, aArgs ); mrController.EndPopupMode(); } -NumberingToolBoxControl::NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ): - svt::PopupWindowController( rxContext, css::uno::Reference< css::frame::XFrame >(), OUString() ), +NumberingToolBoxControl::NumberingToolBoxControl( const Reference< XComponentContext >& rxContext ): + svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), OUString() ), mePageType( NumberingPageType::SINGLENUM ) { } @@ -273,7 +308,7 @@ VclPtr<vcl::Window> NumberingToolBoxControl::createVclPopupWindow( vcl::Window* return mxInterimPopover; } -void SAL_CALL NumberingToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +void SAL_CALL NumberingToolBoxControl::initialize( const Sequence< Any >& aArguments ) { svt::PopupWindowController::initialize( aArguments ); @@ -305,15 +340,15 @@ OUString SAL_CALL NumberingToolBoxControl::getImplementationName() return u"com.sun.star.comp.svx.NumberingToolBoxControl"_ustr; } -css::uno::Sequence< OUString > SAL_CALL NumberingToolBoxControl::getSupportedServiceNames() +Sequence< OUString > SAL_CALL NumberingToolBoxControl::getSupportedServiceNames() { return { u"com.sun.star.frame.ToolbarController"_ustr }; } -extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +extern "C" SAL_DLLPUBLIC_EXPORT XInterface * com_sun_star_comp_svx_NumberingToolBoxControl_get_implementation( - css::uno::XComponentContext *rxContext, - css::uno::Sequence<css::uno::Any> const & ) + XComponentContext *rxContext, + Sequence<Any> const & ) { return cppu::acquire( new NumberingToolBoxControl( rxContext ) ); } diff --git a/svx/uiconfig/ui/numberingwindow.ui b/svx/uiconfig/ui/numberingwindow.ui index c92acae81edc..42d1f46c4938 100644 --- a/svx/uiconfig/ui/numberingwindow.ui +++ b/svx/uiconfig/ui/numberingwindow.ui @@ -13,6 +13,22 @@ <property name="border-width">4</property> <property name="constrain-to">none</property> <child> + <object class="GtkTreeStore" id="liststore1"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="liststore2"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> <object class="GtkBox" id="container"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -24,7 +40,7 @@ <property name="can-focus">False</property> <property name="label" translatable="yes" context="numberingwindow|label_default">Bullet Library</property> <accessibility> - <relation type="label-for" target="valueset"/> + <relation type="label-for" target="numbering_window_iconview"/> </accessibility> </object> <packing> @@ -34,7 +50,7 @@ </packing> </child> <child> - <object class="GtkScrolledWindow" id="valuesetwin"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> @@ -43,21 +59,20 @@ <property name="vscrollbar-policy">never</property> <property name="shadow-type">in</property> <child> - <object class="GtkViewport"> + <object class="GtkIconView" id="numbering_window_iconview"> <property name="visible">True</property> - <property name="can-focus">False</property> - <child> - <object class="GtkDrawingArea" id="valueset"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <accessibility> - <relation type="labelled-by" target="label_default"/> - </accessibility> - </object> - </child> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore1</property> + <property name="pixbuf-column">0</property> + <property name="columns">4</property> + <property name="item-width">80</property> + <property name="selection-mode">single</property> + <property name="activate-on-single-click">True</property> + <accessibility> + <relation type="labelled-by" target="label_default"/> + </accessibility> </object> </child> </object> @@ -73,7 +88,7 @@ <property name="can-focus">False</property> <property name="label" translatable="yes" context="numberingwindow|label_doc">Document Bullets</property> <accessibility> - <relation type="label-for" target="valueset_doc"/> + <relation type="label-for" target="numbering_window_iconview_doc"/> </accessibility> </object> <packing> @@ -83,7 +98,7 @@ </packing> </child> <child> - <object class="GtkScrolledWindow" id="valuesetwin_doc"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> @@ -92,23 +107,22 @@ <property name="vscrollbar-policy">never</property> <property name="shadow-type">in</property> <child> - <object class="GtkViewport"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <child> - <object class="GtkDrawingArea" id="valueset_doc"> + <object class="GtkIconView" id="numbering_window_iconview_doc"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property> <property name="hexpand">True</property> <property name="vexpand">True</property> + <property name="model">liststore2</property> + <property name="pixbuf-column">0</property> + <property name="columns">4</property> + <property name="item-width">80</property> + <property name="selection-mode">single</property> + <property name="activate-on-single-click">True</property> <accessibility> <relation type="labelled-by" target="label_doc"/> </accessibility> </object> </child> - </object> - </child> </object> <packing> <property name="expand">False</property>