include/svx/nbdtmg.hxx | 3 include/svx/numvset.hxx | 7 + include/svx/svxids.hrc | 7 + sd/source/ui/func/fuolbull.cxx | 2 svx/sdi/svx.sdi | 18 +++ svx/source/dialog/svxbmpnumvalueset.cxx | 26 ++++ svx/source/sidebar/nbdtmg.cxx | 24 ++++ svx/source/tbxctrls/bulletsnumbering.cxx | 100 +++++++++++++++++-- svx/uiconfig/ui/numberingwindow.ui | 69 ++++++++++++- sw/inc/doc.hxx | 1 sw/inc/editsh.hxx | 1 sw/qa/uitest/writer_tests2/formatBulletsNumbering.py | 7 + sw/sdi/_textsh.sdi | 5 sw/source/core/doc/docnum.cxx | 23 ++++ sw/source/core/edit/ednumber.cxx | 5 sw/source/uibase/shells/textsh1.cxx | 10 + sw/source/uibase/shells/txtnum.cxx | 18 ++- 17 files changed, 310 insertions(+), 16 deletions(-)
New commits: commit 61b38f766f14255297ec56d4e928dff40df21d92 Author: Tibor Nagy <[email protected]> AuthorDate: Sat May 18 23:31:56 2024 +0200 Commit: Samuel Mehrbrodt <[email protected]> CommitDate: Thu Jun 6 12:57:57 2024 +0200 fix crash when push the Bullets button on the toolbar and then press the dropdown part of the button caused by commit I40cfc39501006146f7c6c04a1f3c7cf877c6f1c4 (tdf#161056 Show bullets used in document in bullets dropdown) Change-Id: I215d7cb677825821917a4fd8c498deaaab9fc9b8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167838 Tested-by: Jenkins Reviewed-by: Nagy Tibor <[email protected]> (cherry picked from commit 708d619e32f251f06af8e8a057bf802627b81fbd) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168369 Tested-by: allotropia jenkins <[email protected]> Reviewed-by: Samuel Mehrbrodt <[email protected]> diff --git a/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py b/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py index b3c5484964d4..abf090f7d16e 100644 --- a/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py +++ b/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py @@ -259,4 +259,11 @@ class formatBulletsNumbering(UITestCase): self.assertEqual(get_state_as_dict(xselector)["SelectedItemId"], "73") + def test_bullets_and_numbering_document_bullet_list(self): + with self.ui_test.create_doc_in_start_center("writer"): + self.xUITest.executeCommand(".uno:DefaultBullet") + # Without the fix in place, this test would have crashed here + self.xUITest.executeCommand(".uno:DocumentBulletList") + + # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx index d571c3709c7d..afc6e7134b4b 100644 --- a/sw/source/core/doc/docnum.cxx +++ b/sw/source/core/doc/docnum.cxx @@ -2529,8 +2529,11 @@ std::vector<OUString> SwDoc::GetUsedBullets() for (int nLevel=0; nLevel<10; ++nLevel) { const SwNumFormat& rFormat = (*mpNumRuleTable)[nRule]->Get(nLevel); - if (SVX_NUM_CHAR_SPECIAL != rFormat.GetNumberingType()) + if (SVX_NUM_CHAR_SPECIAL != rFormat.GetNumberingType() + || !rFormat.GetBulletFont().has_value()) + { continue; + } vcl::Font aFont(*rFormat.GetBulletFont()); sal_UCS4 cBullet = rFormat.GetBulletChar(); OUString sBullet(&cBullet, 1); commit 240c0ffe5c2bfaebddbb97f0300c197b81b1a14e Author: Samuel Mehrbrodt <[email protected]> AuthorDate: Mon May 6 09:20:58 2024 +0200 Commit: Samuel Mehrbrodt <[email protected]> CommitDate: Thu Jun 6 12:57:48 2024 +0200 tdf#161056 Show bullets used in document in bullets dropdown Change-Id: I40cfc39501006146f7c6c04a1f3c7cf877c6f1c4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167186 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <[email protected]> (cherry picked from commit c8a5dc46d11f2ef1e3a66d633730d9a700ced24a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168368 Tested-by: allotropia jenkins <[email protected]> diff --git a/include/svx/nbdtmg.hxx b/include/svx/nbdtmg.hxx index 81ef80223496..9dfc1b16c67f 100644 --- a/include/svx/nbdtmg.hxx +++ b/include/svx/nbdtmg.hxx @@ -146,7 +146,7 @@ class SVX_DLLPUBLIC NBOTypeMgrBase }; -class BulletsTypeMgr final : public NBOTypeMgrBase +class SVX_DLLPUBLIC BulletsTypeMgr final : public NBOTypeMgrBase { friend class OutlineTypeMgr; friend class NumberingTypeMgr; @@ -162,6 +162,7 @@ class BulletsTypeMgr final : public NBOTypeMgrBase virtual sal_uInt16 GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex=0) override; virtual void ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel) override; virtual void ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool isDefault=false,bool isResetSize=false) override; + void ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet, std::u16string_view sFont, sal_uInt16 mLevel,bool isResetSize=false); virtual OUString GetDescription(sal_uInt16 nIndex, bool isDefault) override; virtual bool IsCustomized(sal_uInt16 nIndex) override; static BulletsTypeMgr& GetInstance(); diff --git a/include/svx/numvset.hxx b/include/svx/numvset.hxx index 059d6b7bc558..d3b6e71a69e1 100644 --- a/include/svx/numvset.hxx +++ b/include/svx/numvset.hxx @@ -40,6 +40,7 @@ namespace com::sun::star { enum class NumberingPageType { + DOCBULLET, BULLET, SINGLENUM, OUTLINE, @@ -55,6 +56,9 @@ class SVX_DLLPUBLIC SvxNumValueSet : public ValueSet css::uno::Reference<css::text::XNumberingFormatter> xFormatter; css::lang::Locale aLocale; + // Pair of bullet chars (first), and their respective font (second) + std::vector<std::pair<OUString, OUString>> maCustomBullets; + css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue> > aNumSettings; @@ -82,6 +86,9 @@ public: css::uno::Reference<css::text::XNumberingFormatter> const & xFormatter, const css::lang::Locale& rLocale); + std::vector<std::pair<OUString, OUString>> GetCustomBullets() { return maCustomBullets; } + void SetCustomBullets(std::vector<std::pair<OUString, OUString>> aCustomBullets); + virtual FactoryFunction GetUITestFactory() const override; }; diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc index 7cc55ac02813..11470d0c673e 100644 --- a/include/svx/svxids.hrc +++ b/include/svx/svxids.hrc @@ -185,6 +185,7 @@ class XFillGradientItem; #define FN_BUL_NUM_RULE_INDEX TypedWhichId<SfxUInt16Item>(FN_EDIT + 120) // achieving num rule index #define FN_NUM_NUM_RULE_INDEX TypedWhichId<SfxUInt16Item>(FN_EDIT + 121) #define FN_OUTLINE_RULE_INDEX TypedWhichId<SfxUInt16Item>(FN_EDIT + 122) +#define FN_BUL_GET_DOC_BULLETS TypedWhichId<SfxStringListItem>(FN_EDIT + 123) #define FN_INSERT (SID_SW_START + 300) // 20300 #define FN_DELETE_BOOKMARK TypedWhichId<SfxStringItem>(FN_INSERT + 1) @@ -1058,8 +1059,12 @@ class XFillGradientItem; #define SID_CHAR_DLG_FOR_PARAGRAPH ( SID_SVX_START + 1210 ) #define SID_SET_DOCUMENT_LANGUAGE TypedWhichId<SfxBoolItem>( SID_SVX_START + 1211 ) +#define SID_ATTR_BULLET_CHAR TypedWhichId<SfxStringItem>(SID_SVX_START + 1212) +#define SID_ATTR_BULLET_FONT TypedWhichId<SfxStringItem>(SID_SVX_START + 1213) +#define SID_ATTR_BULLET_INDEX TypedWhichId<SfxUInt16Item>(SID_SVX_START + 1214) + // IMPORTANT NOTE: adjust SID_SVX_FIRSTFREE, when adding new slot id -#define SID_SVX_FIRSTFREE ( SID_SVX_START + 1211 + 1 ) +#define SID_SVX_FIRSTFREE ( SID_SVX_START + 1214 + 1 ) // Overflow check for slot IDs diff --git a/sd/source/ui/func/fuolbull.cxx b/sd/source/ui/func/fuolbull.cxx index 1f5a056b7ef7..ef9412956ece 100644 --- a/sd/source/ui/func/fuolbull.cxx +++ b/sd/source/ui/func/fuolbull.cxx @@ -123,7 +123,7 @@ void FuBulletAndPosition::SetCurrentBulletsNumbering(SfxRequest& rReq) return; } - const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSId); + const SfxUInt16Item* pItem = rReq.GetArgs()->GetItem(SID_ATTR_BULLET_INDEX); if ( !pItem ) { rReq.Done(); diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi index fad6109d6add..270d679cc04f 100644 --- a/svx/sdi/svx.sdi +++ b/svx/sdi/svx.sdi @@ -4991,6 +4991,21 @@ SfxUInt16Item CurrentNumListType FN_NUM_NUM_RULE_INDEX GroupId = SfxGroupId::Enumeration; ] +SfxStringListItem DocumentBulletList FN_BUL_GET_DOC_BULLETS +[ + AutoUpdate = TRUE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = TRUE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Enumeration; +] SfxVoidItem InsertObject SID_INSERT_OBJECT ( SfxGlobalNameItem ClassId SID_INSERT_OBJECT ) @@ -6137,6 +6152,9 @@ SfxUInt16Item SetNumber FN_SVX_SET_NUMBER SfxUInt16Item SetBullet FN_SVX_SET_BULLET +(SfxStringItem BulletChar SID_ATTR_BULLET_CHAR, + SfxStringItem BulletFont SID_ATTR_BULLET_FONT, + SfxUInt16Item BulletIndex SID_ATTR_BULLET_INDEX) [ AutoUpdate = TRUE, FastCall = FALSE, diff --git a/svx/source/dialog/svxbmpnumvalueset.cxx b/svx/source/dialog/svxbmpnumvalueset.cxx index 17a39aad618f..a0c3761b13eb 100644 --- a/svx/source/dialog/svxbmpnumvalueset.cxx +++ b/svx/source/dialog/svxbmpnumvalueset.cxx @@ -149,13 +149,18 @@ void SvxNumValueSet::UserDraw( const UserDrawEvent& rUDEvt ) aRuleFont.SetFillColor(aBackColor); css::uno::Sequence< OUString > aBulletSymbols; - if(ePageType == NumberingPageType::BULLET) + if(ePageType == NumberingPageType::BULLET || ePageType == NumberingPageType::DOCBULLET) { aBulletSymbols = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); css::uno::Sequence< OUString > aBulletFonts(officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get()); aRuleFont.SetFamilyName(aBulletFonts[nIndex]); aFont = aRuleFont; } + else if (ePageType == NumberingPageType::DOCBULLET) + { + aRuleFont.SetFamilyName(maCustomBullets[nIndex].second); + aFont = aRuleFont; + } else if(ePageType == NumberingPageType::OUTLINE) { aSize.setHeight( nRectHeight/8 ); @@ -198,7 +203,8 @@ void SvxNumValueSet::UserDraw( const UserDrawEvent& rUDEvt ) // Now comes the text static constexpr OUStringLiteral sValue(u"Value"); if( NumberingPageType::SINGLENUM == ePageType || - NumberingPageType::BULLET == ePageType ) + NumberingPageType::BULLET == ePageType || + NumberingPageType::DOCBULLET == ePageType) { Point aStart(aBLPos.X() + nRectWidth / 9,0); for( sal_uInt16 i = 0; i < 3; i++ ) @@ -212,6 +218,12 @@ void SvxNumValueSet::UserDraw( const UserDrawEvent& rUDEvt ) aStart.AdjustY( -(pDev->GetTextHeight()/2) ); aStart.setX( aBLPos.X() + 5 ); } + else if (ePageType == NumberingPageType::DOCBULLET) + { + sText = maCustomBullets[nIndex].first; + aStart.AdjustY( -(pDev->GetTextHeight()/2) ); + aStart.setX( aBLPos.X() + 5 ); + } else { if(xFormatter.is() && aNumSettings.getLength() > nIndex) @@ -446,6 +458,16 @@ void SvxNumValueSet::SetOutlineNumberingSettings( } } +void SvxNumValueSet::SetCustomBullets(std::vector<std::pair<OUString, OUString>> aCustomBullets) +{ + Clear(); + maCustomBullets = aCustomBullets; + for (size_t i = 0; i < aCustomBullets.size(); i++) + { + InsertItem(i + 1, i); + } +} + SvxBmpNumValueSet::SvxBmpNumValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow) : SvxNumValueSet(std::move(pScrolledWindow)) , aFormatIdle("SvxBmpNumValueSet FormatIdle") diff --git a/svx/source/sidebar/nbdtmg.cxx b/svx/source/sidebar/nbdtmg.cxx index f26301d54a76..dca5e176e571 100644 --- a/svx/source/sidebar/nbdtmg.cxx +++ b/svx/source/sidebar/nbdtmg.cxx @@ -342,6 +342,30 @@ void BulletsTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt1 } } +void BulletsTypeMgr::ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet, + std::u16string_view sFont, sal_uInt16 mLevel, bool isResetSize) +{ + sal_uInt16 nMask = 1; + OUString sBulletCharFormatName = GetBulletCharFmtName(); + const vcl::Font aFont(OUString(sFont), Size(1, 1)); + for (sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++) + { + if (mLevel & nMask) + { + SvxNumberFormat aFmt(aNum.GetLevel(i)); + aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL); + aFmt.SetBulletFont(&aFont); + aFmt.SetBulletChar(sBullet[0]); + aFmt.SetCharFormatName(sBulletCharFormatName); + aFmt.SetListFormat(""); + if (isResetSize) + aFmt.SetBulletRelSize(45); + aNum.SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + OUString BulletsTypeMgr::GetDescription(sal_uInt16 nIndex, bool /*isDefault*/) { OUString sRet; diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx b/svx/source/tbxctrls/bulletsnumbering.cxx index e1a55a112346..78ec7601d5aa 100644 --- a/svx/source/tbxctrls/bulletsnumbering.cxx +++ b/svx/source/tbxctrls/bulletsnumbering.cxx @@ -9,9 +9,11 @@ #include <com/sun/star/text/DefaultNumberingProvider.hpp> #include <com/sun/star/text/XNumberingFormatter.hpp> +#include <com/sun/star/uno/Sequence.hxx> #include <comphelper/propertysequence.hxx> #include <i18nlangtag/languagetag.hxx> +#include <officecfg/Office/Common.hxx> #include <svtools/popupwindowcontroller.hxx> #include <svtools/toolbarmenu.hxx> #include <svx/strings.hrc> @@ -32,8 +34,13 @@ class NumberingPopup : public WeldToolbarPopup 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::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(VSButtonClickSetHdl, weld::Button&, void); virtual void GrabFocus() override; @@ -70,13 +77,22 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, , mrController(rController) , mxValueSet(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true))) , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *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)) , mxMoreButton(m_xBuilder->weld_button("more")) + , mxBulletsLabel(m_xBuilder->weld_label(u"label_default"_ustr)) + , mxDocBulletsLabel(m_xBuilder->weld_label(u"label_doc"_ustr)) { 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(); + mxDocBulletsLabel->hide(); if ( mePageType != NumberingPageType::BULLET ) { + mxBulletsLabel->hide(); css::uno::Reference< css::text::XDefaultNumberingProvider > xDefNum = css::text::DefaultNumberingProvider::create( mrController.getContext() ); if ( xDefNum.is() ) { @@ -99,17 +115,25 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, } 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()); OUString aMoreItemText = SvxResId( RID_SVXSTR_CUSTOMIZE ); if ( mePageType == NumberingPageType::BULLET ) + { AddStatusListener( ".uno:CurrentBulletListType" ); + AddStatusListener( ".uno:DocumentBulletList" ); + } else if ( mePageType == NumberingPageType::SINGLENUM ) AddStatusListener( ".uno:CurrentNumListType" ); else @@ -121,15 +145,67 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, mxMoreButton->connect_clicked(LINK(this, NumberingPopup, VSButtonClickSetHdl)); mxValueSet->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetHdl)); + mxValueSetDoc->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetDocHdl)); } -void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +namespace +{ +bool lcl_BulletIsDefault(std::u16string_view aSymbol, std::u16string_view aFont) { - mxValueSet->SetNoSelection(); + css::uno::Sequence<OUString> aBulletSymbols + = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); + css::uno::Sequence<OUString> aBulletFonts + = officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get(); + for (sal_Int32 i = 0; i < aBulletSymbols.getLength(); i++) + { + if (aBulletSymbols[i] == aSymbol && aBulletFonts[i] == aFont) + return true; + } + return false; +} +} - sal_Int32 nSelItem; - if ( rEvent.State >>= nSelItem ) - mxValueSet->SelectItem( nSelItem ); +void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + if (rEvent.FeatureURL.Complete == ".uno:DocumentBulletList") + { + css::uno::Sequence<OUString> aSeq; + if (rEvent.State >>= aSeq) + { + std::vector<std::pair<OUString, OUString>> aList; + mxValueSetDoc->Clear(); + int i = 1; + // The string contains the bullet as first character, and then the font name + for (const OUString& sBulletFont : aSeq) + { + OUString sBullet(sBulletFont.copy(0, 1)); + OUString sFont(sBulletFont.copy(1, sBulletFont.getLength() - 1)); + if (lcl_BulletIsDefault(sBullet, sFont)) + continue; + mxValueSetDoc->InsertItem(i, sBullet, i); + aList.emplace_back(sBullet, sFont); + i++; + } + if (!aList.empty()) + { + mxValueSetWinDoc->show(); + mxDocBulletsLabel->show(); + mxValueSetDoc->SetCustomBullets(aList); + } + else + { + mxValueSetWinDoc->hide(); + mxDocBulletsLabel->hide(); + } + } + } + else + { + mxValueSet->SetNoSelection(); + sal_Int32 nSelItem; + if ( rEvent.State >>= nSelItem ) + mxValueSet->SelectItem( nSelItem ); + } } IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void) @@ -137,7 +213,7 @@ IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void) sal_uInt16 nSelItem = mxValueSet->GetSelectedItemId(); if ( mePageType == NumberingPageType::BULLET ) { - auto aArgs( comphelper::InitPropertySequence( { { "SetBullet", css::uno::Any( nSelItem ) } } ) ); + auto aArgs( comphelper::InitPropertySequence( { { "BulletIndex", css::uno::Any( nSelItem ) } } ) ); mrController.dispatchCommand( ".uno:SetBullet", aArgs ); } else if ( mePageType == NumberingPageType::SINGLENUM ) @@ -153,6 +229,18 @@ IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void) mrController.EndPopupMode(); } +IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetDocHdl, ValueSet*, void) +{ + 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(".uno:SetBullet", aArgs); + mrController.EndPopupMode(); +} + void NumberingPopup::GrabFocus() { mxValueSet->GrabFocus(); diff --git a/svx/uiconfig/ui/numberingwindow.ui b/svx/uiconfig/ui/numberingwindow.ui index e303830fc01e..af5bcadf96ff 100644 --- a/svx/uiconfig/ui/numberingwindow.ui +++ b/svx/uiconfig/ui/numberingwindow.ui @@ -18,6 +18,21 @@ <property name="can-focus">False</property> <property name="orientation">vertical</property> <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_default"> + <property name="visible">True</property> + <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"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> <child> <object class="GtkScrolledWindow" id="valuesetwin"> <property name="visible">True</property> @@ -38,6 +53,9 @@ <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> </object> @@ -49,6 +67,55 @@ <property name="position">1</property> </packing> </child> + <child> + <object class="GtkLabel" id="label_doc"> + <property name="visible">True</property> + <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"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="valuesetwin_doc"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="hscrollbar-policy">never</property> + <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"> + <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> + <accessibility> + <relation type="labelled-by" target="label_doc"/> + </accessibility> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> <child> <object class="GtkButton" id="more"> <property name="visible">True</property> @@ -61,7 +128,7 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">2</property> + <property name="position">4</property> </packing> </child> </object> diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 946c96fd29db..8f530d8646fa 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -1103,6 +1103,7 @@ public: SvxNumberFormat::LABEL_WIDTH_AND_POSITION ); sal_uInt16 FindNumRule( std::u16string_view rName ) const; SwNumRule* FindNumRulePtr( const OUString& rName ) const; + std::vector<OUString> GetUsedBullets(); // Deletion only possible if Rule is not used! bool RenameNumRule(const OUString & aOldName, const OUString & aNewName, diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx index 2b753530159a..96433ea89955 100644 --- a/sw/inc/editsh.hxx +++ b/sw/inc/editsh.hxx @@ -578,6 +578,7 @@ public: text node belongs, which applies the found list style. */ const SwNumRule * SearchNumRule(const bool bNum, OUString& sListId ); + std::vector<OUString> GetUsedBullets(); /** Undo. Maintain UndoHistory in Document. diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi index e5a4bfd0ad54..4c5a48b7d697 100644 --- a/sw/sdi/_textsh.sdi +++ b/sw/sdi/_textsh.sdi @@ -810,6 +810,11 @@ interface BaseText StateMethod = GetState ; DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; ] + FN_BUL_GET_DOC_BULLETS // status(final|play) + [ + StateMethod = GetState ; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] FN_NUMBER_BULLETS // status(final|play) [ ExecMethod = ExecEnterNum ; diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx index 01c4a1b3874a..d571c3709c7d 100644 --- a/sw/source/core/doc/docnum.cxx +++ b/sw/source/core/doc/docnum.cxx @@ -2521,6 +2521,26 @@ sal_uInt16 SwDoc::FindNumRule( std::u16string_view rName ) const return USHRT_MAX; } +std::vector<OUString> SwDoc::GetUsedBullets() +{ + std::vector<OUString> aUsedBullets; + for (size_t nRule = 0; nRule < mpNumRuleTable->size(); ++nRule) + { + for (int nLevel=0; nLevel<10; ++nLevel) + { + const SwNumFormat& rFormat = (*mpNumRuleTable)[nRule]->Get(nLevel); + if (SVX_NUM_CHAR_SPECIAL != rFormat.GetNumberingType()) + continue; + vcl::Font aFont(*rFormat.GetBulletFont()); + sal_UCS4 cBullet = rFormat.GetBulletChar(); + OUString sBullet(&cBullet, 1); + OUString sFontName(aFont.GetFamilyName()); + aUsedBullets.emplace_back(sBullet + sFontName); + } + } + return aUsedBullets; +} + SwNumRule* SwDoc::FindNumRulePtr( const OUString& rName ) const { SwNumRule * pResult = maNumRuleMap[rName]; diff --git a/sw/source/core/edit/ednumber.cxx b/sw/source/core/edit/ednumber.cxx index 65391d376b4a..7217b7fbd989 100644 --- a/sw/source/core/edit/ednumber.cxx +++ b/sw/source/core/edit/ednumber.cxx @@ -879,4 +879,9 @@ const SwNumRule * SwEditShell::SearchNumRule( const bool bNum, sListId, GetLayout() ); } +std::vector<OUString> SwEditShell::GetUsedBullets() +{ + return GetDoc()->GetUsedBullets(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx index 2bf6c670e489..4f452a8add37 100644 --- a/sw/source/uibase/shells/textsh1.cxx +++ b/sw/source/uibase/shells/textsh1.cxx @@ -2733,6 +2733,16 @@ void SwTextShell::GetState( SfxItemSet &rSet ) } } } + break; + case FN_BUL_GET_DOC_BULLETS: + { + std::vector<OUString> aBullets = rSh.GetUsedBullets(); + SfxStringListItem aItem(FN_BUL_GET_DOC_BULLETS); + uno::Sequence<OUString> aSeq(aBullets.data(), + static_cast<sal_Int32>(aBullets.size())); + aItem.SetStringList(aSeq); + rSet.Put(aItem); + } break; case FN_NUM_CONTINUE: { diff --git a/sw/source/uibase/shells/txtnum.cxx b/sw/source/uibase/shells/txtnum.cxx index e769b7f46347..43c1b8d1aedd 100644 --- a/sw/source/uibase/shells/txtnum.cxx +++ b/sw/source/uibase/shells/txtnum.cxx @@ -261,10 +261,12 @@ void SwTextShell::ExecSetNumber(SfxRequest const &rReq) case FN_SVX_SET_BULLET: case FN_SVX_SET_OUTLINE: { - const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSlot); - if ( pItem != nullptr ) + const SfxUInt16Item* pIndexItem = rReq.GetArgs()->GetItem( SID_ATTR_BULLET_INDEX ); + const SfxStringItem* pCharItem = rReq.GetArgs()->GetItem( SID_ATTR_BULLET_CHAR ); + const SfxStringItem* pFontItem = rReq.GetArgs()->GetItem( SID_ATTR_BULLET_FONT ); + + if ( pIndexItem != nullptr || ( pCharItem != nullptr && pFontItem != nullptr ) ) { - const sal_uInt16 nChosenItemIdx = pItem->GetValue(); svx::sidebar::NBOType nNBOType = svx::sidebar::NBOType::Bullets; if ( nSlot == FN_SVX_SET_NUMBER ) nNBOType = svx::sidebar::NBOType::Numbering; @@ -302,7 +304,15 @@ void SwTextShell::ExecSetNumber(SfxRequest const &rReq) aSet.Put( SvxNumBulletItem( aNewSvxNumRule, SID_ATTR_NUMBERING_RULE ) ); pNBOTypeMgr->SetItems( &aSet ); - pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, nChosenItemIdx - 1, nActNumLvl ); + if (pIndexItem) + pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, pIndexItem->GetValue() - 1, nActNumLvl ); + else + { + svx::sidebar::BulletsTypeMgr* pBulletsTypeMgr + = dynamic_cast<svx::sidebar::BulletsTypeMgr*>(pNBOTypeMgr); + pBulletsTypeMgr->ApplyCustomRule(aNewSvxNumRule, pCharItem->GetValue(), + pFontItem->GetValue(), nActNumLvl); + } aNewNumRule.SetSvxRule( aNewSvxNumRule, GetShell().GetDoc() ); aNewNumRule.SetAutoRule( true );
