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/sdi/_textsh.sdi                       |    5 +
 sw/source/core/doc/docnum.cxx            |   20 ++++++
 sw/source/core/edit/ednumber.cxx         |    5 +
 sw/source/uibase/shells/textsh1.cxx      |   10 +++
 sw/source/uibase/shells/txtnum.cxx       |   18 ++++-
 16 files changed, 300 insertions(+), 16 deletions(-)

New commits:
commit c8a5dc46d11f2ef1e3a66d633730d9a700ced24a
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Mon May 6 09:20:58 2024 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Thu May 16 09:17:09 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 <samuel.mehrbr...@allotropia.de>

diff --git a/include/svx/nbdtmg.hxx b/include/svx/nbdtmg.hxx
index 894304e4c37d..8979b736e40c 100644
--- a/include/svx/nbdtmg.hxx
+++ b/include/svx/nbdtmg.hxx
@@ -145,7 +145,7 @@ class SVX_DLLPUBLIC NBOTypeMgrBase
 };
 
 
-class BulletsTypeMgr final : public NBOTypeMgrBase
+class SVX_DLLPUBLIC BulletsTypeMgr final : public NBOTypeMgrBase
 {
     friend class OutlineTypeMgr;
     friend class NumberingTypeMgr;
@@ -161,6 +161,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 b4e1a91d386a..68d02d4a86fc 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 5c518d435c35..076c09753409 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 d1eea8e2ca68..59bae8338825 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 442256081e5b..a934a972cf74 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 ed88addb88b2..14a27feaedbb 100644
--- a/svx/source/sidebar/nbdtmg.cxx
+++ b/svx/source/sidebar/nbdtmg.cxx
@@ -341,6 +341,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*/)
 {
     return OUString();
diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx 
b/svx/source/tbxctrls/bulletsnumbering.cxx
index f6ca64be5bdb..0ce9057012e0 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(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))
     , 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))
 {
     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,16 +115,24 @@ 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());
 
     if ( mePageType == NumberingPageType::BULLET )
+    {
         AddStatusListener( u".uno:CurrentBulletListType"_ustr );
+        AddStatusListener( u".uno:DocumentBulletList"_ustr );
+    }
     else if ( mePageType == NumberingPageType::SINGLENUM )
         AddStatusListener( u".uno:CurrentNumListType"_ustr );
     else
@@ -119,15 +143,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)
@@ -135,7 +211,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( u".uno:SetBullet"_ustr, aArgs );
     }
     else if ( mePageType == NumberingPageType::SINGLENUM )
@@ -151,6 +227,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 db44aeee4d8c..c92acae81edc 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="label" translatable="yes" 
context="numberingwindow|more">Customize...</property>
@@ -62,7 +129,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 5dc62530454a..b4d3d0e54f86 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1095,6 +1095,7 @@ public:
         const SvxNumberFormat::SvxNumPositionAndSpaceMode 
eDefaultNumberFormatPositionAndSpaceMode =
             SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
     sal_uInt16 FindNumRule( std::u16string_view rName ) const;
+    std::vector<OUString> GetUsedBullets();
     SW_DLLPUBLIC SwNumRule* FindNumRulePtr( const OUString& rName ) const;
 
     // Deletion only possible if Rule is not used!
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index a4dcecd6d449..85eb84bca3f5 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 5378a960320d..301fe709f9e4 100644
--- a/sw/source/core/doc/docnum.cxx
+++ b/sw/source/core/doc/docnum.cxx
@@ -2458,6 +2458,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 372e7b1e48ad..ad585e9b85bd 100644
--- a/sw/source/core/edit/ednumber.cxx
+++ b/sw/source/core/edit/ednumber.cxx
@@ -874,4 +874,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 39f655d115bd..fa4de6bd9d0d 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -2852,6 +2852,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 bdad7870afbf..1ef46f09ab45 100644
--- a/sw/source/uibase/shells/txtnum.cxx
+++ b/sw/source/uibase/shells/txtnum.cxx
@@ -260,10 +260,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;
@@ -301,7 +303,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 );

Reply via email to