1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
11 #include <com/sun/star/text/XNumberingFormatter.hpp>
12 #include <com/sun/star/uno/Sequence.hxx>
14 #include <comphelper/propertysequence.hxx>
15 #include <i18nlangtag/languagetag.hxx>
16 #include <officecfg/Office/Common.hxx>
17 #include <svtools/popupwindowcontroller.hxx>
18 #include <svtools/toolbarmenu.hxx>
19 #include <svx/strings.hrc>
20 #include <svx/dialmgr.hxx>
21 #include <svx/numvset.hxx>
22 #include <vcl/commandinfoprovider.hxx>
23 #include <vcl/toolbox.hxx>
24 #include <vcl/settings.hxx>
25 #include <vcl/svapp.hxx>
29 class NumberingToolBoxControl
;
31 class NumberingPopup
: public WeldToolbarPopup
33 NumberingPageType mePageType
;
34 NumberingToolBoxControl
& mrController
;
35 std::unique_ptr
<SvxNumValueSet
> mxValueSet
;
36 std::unique_ptr
<weld::CustomWeld
> mxValueSetWin
;
37 std::unique_ptr
<SvxNumValueSet
> mxValueSetDoc
;
38 std::unique_ptr
<weld::CustomWeld
> mxValueSetWinDoc
;
39 std::unique_ptr
<weld::Button
> mxMoreButton
;
40 std::unique_ptr
<weld::Label
> mxBulletsLabel
;
41 std::unique_ptr
<weld::Label
> mxDocBulletsLabel
;
42 DECL_LINK(VSSelectValueSetHdl
, ValueSet
*, void);
43 DECL_LINK(VSSelectValueSetDocHdl
, ValueSet
*, void);
44 DECL_LINK(VSButtonClickSetHdl
, weld::Button
&, void);
46 virtual void GrabFocus() override
;
49 NumberingPopup(NumberingToolBoxControl
& rController
, weld::Widget
* pParent
, NumberingPageType ePageType
);
51 virtual void statusChanged( const css::frame::FeatureStateEvent
& rEvent
) override
;
54 class NumberingToolBoxControl
: public svt::PopupWindowController
56 NumberingPageType mePageType
;
59 explicit NumberingToolBoxControl( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
60 virtual VclPtr
<vcl::Window
> createVclPopupWindow( vcl::Window
* pParent
) override
;
61 std::unique_ptr
<WeldToolbarPopup
> weldPopupWindow() override
;
64 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
67 virtual OUString SAL_CALL
getImplementationName() override
;
68 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
73 NumberingPopup::NumberingPopup(NumberingToolBoxControl
& rController
,
74 weld::Widget
* pParent
, NumberingPageType ePageType
)
75 : WeldToolbarPopup(rController
.getFrameInterface(), pParent
, u
"svx/ui/numberingwindow.ui"_ustr
, u
"NumberingWindow"_ustr
)
76 , mePageType(ePageType
)
77 , mrController(rController
)
78 , mxValueSet(new SvxNumValueSet(m_xBuilder
->weld_scrolled_window(u
"valuesetwin"_ustr
, true)))
79 , mxValueSetWin(new weld::CustomWeld(*m_xBuilder
, u
"valueset"_ustr
, *mxValueSet
))
80 , mxValueSetDoc(new SvxNumValueSet(m_xBuilder
->weld_scrolled_window(u
"valuesetwin_doc"_ustr
, true)))
81 , mxValueSetWinDoc(new weld::CustomWeld(*m_xBuilder
, u
"valueset_doc"_ustr
, *mxValueSetDoc
))
82 , mxMoreButton(m_xBuilder
->weld_button(u
"more"_ustr
))
83 , mxBulletsLabel(m_xBuilder
->weld_label(u
"label_default"_ustr
))
84 , mxDocBulletsLabel(m_xBuilder
->weld_label(u
"label_doc"_ustr
))
86 mxValueSet
->SetStyle(WB_MENUSTYLEVALUESET
| WB_FLATVALUESET
| WB_NO_DIRECTSELECT
);
87 mxValueSetDoc
->SetStyle(WB_MENUSTYLEVALUESET
| WB_FLATVALUESET
| WB_NO_DIRECTSELECT
);
88 mxValueSet
->init(mePageType
);
89 mxValueSetDoc
->init(NumberingPageType::DOCBULLET
);
90 mxValueSetWinDoc
->hide();
91 mxDocBulletsLabel
->hide();
93 if ( mePageType
!= NumberingPageType::BULLET
)
95 mxBulletsLabel
->hide();
96 css::uno::Reference
< css::text::XDefaultNumberingProvider
> xDefNum
= css::text::DefaultNumberingProvider::create( mrController
.getContext() );
99 css::lang::Locale aLocale
= Application::GetSettings().GetLanguageTag().getLocale();
100 css::uno::Reference
< css::text::XNumberingFormatter
> xFormat( xDefNum
, css::uno::UNO_QUERY
);
102 if ( mePageType
== NumberingPageType::SINGLENUM
)
104 css::uno::Sequence
< css::uno::Sequence
< css::beans::PropertyValue
> > aNumberings(
105 xDefNum
->getDefaultContinuousNumberingLevels( aLocale
) );
106 mxValueSet
->SetNumberingSettings( aNumberings
, xFormat
, aLocale
);
108 else if ( mePageType
== NumberingPageType::OUTLINE
)
110 css::uno::Sequence
< css::uno::Reference
< css::container::XIndexAccess
> > aOutline(
111 xDefNum
->getDefaultOutlineNumberings( aLocale
) );
112 mxValueSet
->SetOutlineNumberingSettings( aOutline
, xFormat
, aLocale
);
117 weld::DrawingArea
* pDrawingArea
= mxValueSet
->GetDrawingArea();
118 weld::DrawingArea
* pDrawingAreaDoc
= mxValueSetDoc
->GetDrawingArea();
119 OutputDevice
& rRefDevice
= pDrawingArea
->get_ref_device();
120 Size
aItemSize(rRefDevice
.LogicToPixel(Size(30, 42), MapMode(MapUnit::MapAppFont
)));
121 mxValueSet
->SetExtraSpacing( 2 );
122 mxValueSetDoc
->SetExtraSpacing( 2 );
123 Size
aSize(mxValueSet
->CalcWindowSizePixel(aItemSize
));
124 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
125 pDrawingAreaDoc
->set_size_request(aSize
.Width(), aSize
.Height());
126 mxValueSet
->SetOutputSizePixel(aSize
);
127 mxValueSetDoc
->SetOutputSizePixel(aSize
);
128 mxValueSet
->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor());
129 mxValueSetDoc
->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor());
131 if ( mePageType
== NumberingPageType::BULLET
)
133 AddStatusListener( u
".uno:CurrentBulletListType"_ustr
);
134 AddStatusListener( u
".uno:DocumentBulletList"_ustr
);
136 else if ( mePageType
== NumberingPageType::SINGLENUM
)
137 AddStatusListener( u
".uno:CurrentNumListType"_ustr
);
139 AddStatusListener( u
".uno:CurrentOutlineType"_ustr
);
141 auto xImage
= vcl::CommandInfoProvider::GetXGraphicForCommand(u
".uno:OutlineBullet"_ustr
, mrController
.getFrameInterface());
142 mxMoreButton
->set_image(xImage
);
143 mxMoreButton
->connect_clicked(LINK(this, NumberingPopup
, VSButtonClickSetHdl
));
145 mxValueSet
->SetSelectHdl(LINK(this, NumberingPopup
, VSSelectValueSetHdl
));
146 mxValueSetDoc
->SetSelectHdl(LINK(this, NumberingPopup
, VSSelectValueSetDocHdl
));
151 bool lcl_BulletIsDefault(std::u16string_view aSymbol
, std::u16string_view aFont
)
153 css::uno::Sequence
<OUString
> aBulletSymbols
154 = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get();
155 css::uno::Sequence
<OUString
> aBulletFonts
156 = officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get();
157 for (sal_Int32 i
= 0; i
< aBulletSymbols
.getLength(); i
++)
159 if (aBulletSymbols
[i
] == aSymbol
&& aBulletFonts
[i
] == aFont
)
166 void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent
& rEvent
)
168 if (rEvent
.FeatureURL
.Complete
== ".uno:DocumentBulletList")
170 css::uno::Sequence
<OUString
> aSeq
;
171 if (rEvent
.State
>>= aSeq
)
173 std::vector
<std::pair
<OUString
, OUString
>> aList
;
174 mxValueSetDoc
->Clear();
176 // The string contains the bullet as first character, and then the font name
177 for (const OUString
& sBulletFont
: aSeq
)
179 OUString
sBullet(sBulletFont
.copy(0, 1));
180 OUString
sFont(sBulletFont
.copy(1, sBulletFont
.getLength() - 1));
181 if (lcl_BulletIsDefault(sBullet
, sFont
))
183 mxValueSetDoc
->InsertItem(i
, sBullet
, i
);
184 aList
.emplace_back(sBullet
, sFont
);
189 mxValueSetWinDoc
->show();
190 mxDocBulletsLabel
->show();
191 mxValueSetDoc
->SetCustomBullets(aList
);
195 mxValueSetWinDoc
->hide();
196 mxDocBulletsLabel
->hide();
202 mxValueSet
->SetNoSelection();
204 if ( rEvent
.State
>>= nSelItem
)
205 mxValueSet
->SelectItem( nSelItem
);
209 IMPL_LINK_NOARG(NumberingPopup
, VSSelectValueSetHdl
, ValueSet
*, void)
211 sal_uInt16 nSelItem
= mxValueSet
->GetSelectedItemId();
212 if ( mePageType
== NumberingPageType::BULLET
)
214 auto aArgs( comphelper::InitPropertySequence( { { "BulletIndex", css::uno::Any( nSelItem
) } } ) );
215 mrController
.dispatchCommand( u
".uno:SetBullet"_ustr
, aArgs
);
217 else if ( mePageType
== NumberingPageType::SINGLENUM
)
219 auto aArgs( comphelper::InitPropertySequence( { { "SetNumber", css::uno::Any( nSelItem
) } } ) );
220 mrController
.dispatchCommand( u
".uno:SetNumber"_ustr
, aArgs
);
224 auto aArgs( comphelper::InitPropertySequence( { { "SetOutline", css::uno::Any( nSelItem
) } } ) );
225 mrController
.dispatchCommand( u
".uno:SetOutline"_ustr
, aArgs
);
227 mrController
.EndPopupMode();
230 IMPL_LINK_NOARG(NumberingPopup
, VSSelectValueSetDocHdl
, ValueSet
*, void)
232 sal_uInt16 nSelItem
= mxValueSetDoc
->GetSelectedItemId() - 1;
233 auto aCustomBullets
= mxValueSetDoc
->GetCustomBullets();
234 OUString
nChar(aCustomBullets
[nSelItem
].first
);
235 OUString
sFont(aCustomBullets
[nSelItem
].second
);
236 auto aArgs(comphelper::InitPropertySequence(
237 { { "BulletChar", css::uno::Any(nChar
) }, { "BulletFont", css::uno::Any(sFont
) } }));
238 mrController
.dispatchCommand(u
".uno:SetBullet"_ustr
, aArgs
);
239 mrController
.EndPopupMode();
242 void NumberingPopup::GrabFocus()
244 mxValueSet
->GrabFocus();
247 IMPL_LINK_NOARG(NumberingPopup
, VSButtonClickSetHdl
, weld::Button
&, void)
249 auto aArgs( comphelper::InitPropertySequence( { { "Page", css::uno::Any( u
"customize"_ustr
) } } ) );
250 mrController
.dispatchCommand( u
".uno:OutlineBullet"_ustr
, aArgs
);
252 mrController
.EndPopupMode();
255 NumberingToolBoxControl::NumberingToolBoxControl( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
):
256 svt::PopupWindowController( rxContext
, css::uno::Reference
< css::frame::XFrame
>(), OUString() ),
257 mePageType( NumberingPageType::SINGLENUM
)
261 std::unique_ptr
<WeldToolbarPopup
> NumberingToolBoxControl::weldPopupWindow()
263 return std::make_unique
<NumberingPopup
>(*this, m_pToolbar
, mePageType
);
266 VclPtr
<vcl::Window
> NumberingToolBoxControl::createVclPopupWindow( vcl::Window
* pParent
)
268 mxInterimPopover
= VclPtr
<InterimToolbarPopup
>::Create(getFrameInterface(), pParent
,
269 std::make_unique
<NumberingPopup
>(*this, pParent
->GetFrameWeld(), mePageType
));
271 mxInterimPopover
->Show();
273 return mxInterimPopover
;
276 void SAL_CALL
NumberingToolBoxControl::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
278 svt::PopupWindowController::initialize( aArguments
);
280 if ( m_aCommandURL
== ".uno:DefaultBullet" )
281 mePageType
= NumberingPageType::BULLET
;
282 else if ( m_aCommandURL
== ".uno:SetOutline" )
283 mePageType
= NumberingPageType::OUTLINE
;
287 mxPopoverContainer
.reset(new ToolbarPopupContainer(m_pToolbar
));
288 m_pToolbar
->set_item_popover(m_aCommandURL
, mxPopoverContainer
->getTopLevel());
292 ToolBox
* pToolBox
= nullptr;
294 if (getToolboxId(nId
, &pToolBox
))
296 ToolBoxItemBits nBits
= mePageType
== NumberingPageType::OUTLINE
297 ? ToolBoxItemBits::DROPDOWNONLY
298 : ToolBoxItemBits::DROPDOWN
;
299 pToolBox
->SetItemBits( nId
, pToolBox
->GetItemBits( nId
) | nBits
);
303 OUString SAL_CALL
NumberingToolBoxControl::getImplementationName()
305 return u
"com.sun.star.comp.svx.NumberingToolBoxControl"_ustr
;
308 css::uno::Sequence
< OUString
> SAL_CALL
NumberingToolBoxControl::getSupportedServiceNames()
310 return { u
"com.sun.star.frame.ToolbarController"_ustr
};
313 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
314 com_sun_star_comp_svx_NumberingToolBoxControl_get_implementation(
315 css::uno::XComponentContext
*rxContext
,
316 css::uno::Sequence
<css::uno::Any
> const & )
318 return cppu::acquire( new NumberingToolBoxControl( rxContext
) );
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */