/src/libreoffice/svx/source/tbxctrls/bulletsnumbering.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | */ |
9 | | |
10 | | #include <com/sun/star/text/DefaultNumberingProvider.hpp> |
11 | | #include <com/sun/star/text/XNumberingFormatter.hpp> |
12 | | #include <com/sun/star/uno/Sequence.hxx> |
13 | | |
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/numvset.hxx> |
20 | | #include <tools/mapunit.hxx> |
21 | | #include <vcl/commandinfoprovider.hxx> |
22 | | #include <vcl/toolbox.hxx> |
23 | | #include <vcl/settings.hxx> |
24 | | #include <vcl/svapp.hxx> |
25 | | #include <vcl/weld/Builder.hxx> |
26 | | #include <vcl/weld/Button.hxx> |
27 | | #include <vcl/weld/Label.hxx> |
28 | | #include <vcl/weld/ScrolledWindow.hxx> |
29 | | #include <vcl/weld/Window.hxx> |
30 | | #include <vcl/weld/Toolbar.hxx> |
31 | | |
32 | | namespace { |
33 | | |
34 | | class NumberingToolBoxControl; |
35 | | |
36 | | class NumberingPopup : public WeldToolbarPopup |
37 | | { |
38 | | NumberingPageType mePageType; |
39 | | NumberingToolBoxControl& mrController; |
40 | | std::unique_ptr<SvxNumValueSet> mxValueSet; |
41 | | std::unique_ptr<weld::CustomWeld> mxValueSetWin; |
42 | | std::unique_ptr<SvxNumValueSet> mxValueSetDoc; |
43 | | std::unique_ptr<weld::CustomWeld> mxValueSetWinDoc; |
44 | | std::unique_ptr<weld::Button> mxMoreButton; |
45 | | std::unique_ptr<weld::Label> mxBulletsLabel; |
46 | | std::unique_ptr<weld::Label> mxDocBulletsLabel; |
47 | | DECL_LINK(VSSelectValueSetHdl, ValueSet*, void); |
48 | | DECL_LINK(VSSelectValueSetDocHdl, ValueSet*, void); |
49 | | DECL_LINK(VSButtonClickSetHdl, weld::Button&, void); |
50 | | |
51 | | virtual void GrabFocus() override; |
52 | | |
53 | | public: |
54 | | NumberingPopup(NumberingToolBoxControl& rController, weld::Widget* pParent, NumberingPageType ePageType); |
55 | | |
56 | | virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; |
57 | | }; |
58 | | |
59 | | class NumberingToolBoxControl : public svt::PopupWindowController |
60 | | { |
61 | | NumberingPageType mePageType; |
62 | | |
63 | | public: |
64 | | explicit NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); |
65 | | virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; |
66 | | std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; |
67 | | |
68 | | // XInitialization |
69 | | virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override; |
70 | | |
71 | | // XServiceInfo |
72 | | virtual OUString SAL_CALL getImplementationName() override; |
73 | | virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; |
74 | | }; |
75 | | |
76 | | } |
77 | | |
78 | | NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, |
79 | | weld::Widget* pParent, NumberingPageType ePageType) |
80 | 0 | : WeldToolbarPopup(rController.getFrameInterface(), pParent, u"svx/ui/numberingwindow.ui"_ustr, u"NumberingWindow"_ustr) |
81 | 0 | , mePageType(ePageType) |
82 | 0 | , mrController(rController) |
83 | 0 | , mxValueSet(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true))) |
84 | 0 | , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *mxValueSet)) |
85 | 0 | , mxValueSetDoc(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin_doc"_ustr, true))) |
86 | 0 | , mxValueSetWinDoc(new weld::CustomWeld(*m_xBuilder, u"valueset_doc"_ustr, *mxValueSetDoc)) |
87 | 0 | , mxMoreButton(m_xBuilder->weld_button(u"more"_ustr)) |
88 | 0 | , mxBulletsLabel(m_xBuilder->weld_label(u"label_default"_ustr)) |
89 | 0 | , mxDocBulletsLabel(m_xBuilder->weld_label(u"label_doc"_ustr)) |
90 | 0 | { |
91 | 0 | mxValueSet->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NO_DIRECTSELECT); |
92 | 0 | mxValueSetDoc->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NO_DIRECTSELECT); |
93 | 0 | mxValueSet->init(mePageType); |
94 | 0 | mxValueSetDoc->init(NumberingPageType::DOCBULLET); |
95 | 0 | mxValueSetDoc->Hide(); |
96 | 0 | mxDocBulletsLabel->hide(); |
97 | |
|
98 | 0 | if ( mePageType != NumberingPageType::BULLET ) |
99 | 0 | { |
100 | 0 | mxBulletsLabel->hide(); |
101 | 0 | css::uno::Reference< css::text::XDefaultNumberingProvider > xDefNum = css::text::DefaultNumberingProvider::create( mrController.getContext() ); |
102 | 0 | if ( xDefNum.is() ) |
103 | 0 | { |
104 | 0 | css::lang::Locale aLocale = Application::GetSettings().GetLanguageTag().getLocale(); |
105 | 0 | css::uno::Reference< css::text::XNumberingFormatter > xFormat( xDefNum, css::uno::UNO_QUERY ); |
106 | |
|
107 | 0 | if ( mePageType == NumberingPageType::SINGLENUM ) |
108 | 0 | { |
109 | 0 | css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aNumberings( |
110 | 0 | xDefNum->getDefaultContinuousNumberingLevels( aLocale ) ); |
111 | 0 | mxValueSet->SetNumberingSettings( aNumberings, xFormat, aLocale ); |
112 | 0 | } |
113 | 0 | else if ( mePageType == NumberingPageType::OUTLINE ) |
114 | 0 | { |
115 | 0 | css::uno::Sequence< css::uno::Reference< css::container::XIndexAccess > > aOutline( |
116 | 0 | xDefNum->getDefaultOutlineNumberings( aLocale ) ); |
117 | 0 | mxValueSet->SetOutlineNumberingSettings( aOutline, xFormat, aLocale ); |
118 | 0 | } |
119 | 0 | } |
120 | 0 | } |
121 | |
|
122 | 0 | weld::DrawingArea* pDrawingArea = mxValueSet->GetDrawingArea(); |
123 | 0 | weld::DrawingArea* pDrawingAreaDoc = mxValueSetDoc->GetDrawingArea(); |
124 | 0 | OutputDevice& rRefDevice = pDrawingArea->get_ref_device(); |
125 | 0 | Size aItemSize(rRefDevice.LogicToPixel(Size(30, 42), MapMode(MapUnit::MapAppFont))); |
126 | 0 | mxValueSet->SetExtraSpacing( 2 ); |
127 | 0 | mxValueSetDoc->SetExtraSpacing( 2 ); |
128 | 0 | Size aSize(mxValueSet->CalcWindowSizePixel(aItemSize)); |
129 | 0 | pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); |
130 | 0 | pDrawingAreaDoc->set_size_request(aSize.Width(), aSize.Height()); |
131 | 0 | mxValueSet->SetOutputSizePixel(aSize); |
132 | 0 | mxValueSetDoc->SetOutputSizePixel(aSize); |
133 | 0 | mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor()); |
134 | 0 | mxValueSetDoc->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor()); |
135 | |
|
136 | 0 | if ( mePageType == NumberingPageType::BULLET ) |
137 | 0 | { |
138 | 0 | AddStatusListener( u".uno:CurrentBulletListType"_ustr ); |
139 | 0 | AddStatusListener( u".uno:DocumentBulletList"_ustr ); |
140 | 0 | } |
141 | 0 | else if ( mePageType == NumberingPageType::SINGLENUM ) |
142 | 0 | AddStatusListener( u".uno:CurrentNumListType"_ustr ); |
143 | 0 | else |
144 | 0 | AddStatusListener( u".uno:CurrentOutlineType"_ustr ); |
145 | |
|
146 | 0 | auto xImage = vcl::CommandInfoProvider::GetXGraphicForCommand(u".uno:OutlineBullet"_ustr, mrController.getFrameInterface()); |
147 | 0 | mxMoreButton->set_image(xImage); |
148 | 0 | mxMoreButton->connect_clicked(LINK(this, NumberingPopup, VSButtonClickSetHdl)); |
149 | |
|
150 | 0 | mxValueSet->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetHdl)); |
151 | 0 | mxValueSetDoc->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetDocHdl)); |
152 | 0 | } |
153 | | |
154 | | namespace |
155 | | { |
156 | | bool lcl_BulletIsDefault(std::u16string_view aSymbol, std::u16string_view aFont) |
157 | 0 | { |
158 | 0 | css::uno::Sequence<OUString> aBulletSymbols |
159 | 0 | = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); |
160 | 0 | css::uno::Sequence<OUString> aBulletFonts |
161 | 0 | = officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get(); |
162 | 0 | for (sal_Int32 i = 0; i < aBulletSymbols.getLength(); i++) |
163 | 0 | { |
164 | 0 | if (aBulletSymbols[i] == aSymbol && aBulletFonts[i] == aFont) |
165 | 0 | return true; |
166 | 0 | } |
167 | 0 | return false; |
168 | 0 | } |
169 | | } |
170 | | |
171 | | void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
172 | 0 | { |
173 | 0 | if (rEvent.FeatureURL.Complete == ".uno:DocumentBulletList") |
174 | 0 | { |
175 | 0 | css::uno::Sequence<OUString> aSeq; |
176 | 0 | if (rEvent.State >>= aSeq) |
177 | 0 | { |
178 | 0 | std::vector<std::pair<OUString, OUString>> aList; |
179 | 0 | mxValueSetDoc->Clear(); |
180 | 0 | int i = 1; |
181 | | // The string contains the bullet as first character, and then the font name |
182 | 0 | for (const OUString& sBulletFont : aSeq) |
183 | 0 | { |
184 | 0 | OUString sBullet(sBulletFont.copy(0, 1)); |
185 | 0 | OUString sFont(sBulletFont.copy(1, sBulletFont.getLength() - 1)); |
186 | 0 | if (lcl_BulletIsDefault(sBullet, sFont)) |
187 | 0 | continue; |
188 | 0 | mxValueSetDoc->InsertItem(i, sBullet, i); |
189 | 0 | aList.emplace_back(sBullet, sFont); |
190 | 0 | i++; |
191 | 0 | } |
192 | 0 | if (!aList.empty()) |
193 | 0 | { |
194 | 0 | mxValueSetDoc->Show(); |
195 | 0 | mxDocBulletsLabel->show(); |
196 | 0 | mxValueSetDoc->SetCustomBullets(aList); |
197 | 0 | } |
198 | 0 | else |
199 | 0 | { |
200 | 0 | mxValueSetDoc->Hide(); |
201 | 0 | mxDocBulletsLabel->hide(); |
202 | 0 | } |
203 | 0 | } |
204 | 0 | } |
205 | 0 | else |
206 | 0 | { |
207 | 0 | mxValueSet->SetNoSelection(); |
208 | 0 | sal_Int32 nSelItem; |
209 | 0 | if ( rEvent.State >>= nSelItem ) |
210 | 0 | mxValueSet->SelectItem( nSelItem ); |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void) |
215 | 0 | { |
216 | 0 | sal_uInt16 nSelItem = mxValueSet->GetSelectedItemId(); |
217 | 0 | if ( mePageType == NumberingPageType::BULLET ) |
218 | 0 | { |
219 | 0 | auto aArgs( comphelper::InitPropertySequence( { { "BulletIndex", css::uno::Any( nSelItem ) } } ) ); |
220 | 0 | mrController.dispatchCommand( u".uno:SetBullet"_ustr, aArgs ); |
221 | 0 | } |
222 | 0 | else if ( mePageType == NumberingPageType::SINGLENUM ) |
223 | 0 | { |
224 | 0 | auto aArgs( comphelper::InitPropertySequence( { { "SetNumber", css::uno::Any( nSelItem ) } } ) ); |
225 | 0 | mrController.dispatchCommand( u".uno:SetNumber"_ustr, aArgs ); |
226 | 0 | } |
227 | 0 | else |
228 | 0 | { |
229 | 0 | auto aArgs( comphelper::InitPropertySequence( { { "SetOutline", css::uno::Any( nSelItem ) } } ) ); |
230 | 0 | mrController.dispatchCommand( u".uno:SetOutline"_ustr, aArgs ); |
231 | 0 | } |
232 | 0 | mrController.EndPopupMode(); |
233 | 0 | } |
234 | | |
235 | | IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetDocHdl, ValueSet*, void) |
236 | 0 | { |
237 | 0 | sal_uInt16 nSelItem = mxValueSetDoc->GetSelectedItemId() - 1; |
238 | 0 | auto aCustomBullets = mxValueSetDoc->GetCustomBullets(); |
239 | 0 | OUString nChar(aCustomBullets[nSelItem].first); |
240 | 0 | OUString sFont(aCustomBullets[nSelItem].second); |
241 | 0 | auto aArgs(comphelper::InitPropertySequence( |
242 | 0 | { { "BulletChar", css::uno::Any(nChar) }, { "BulletFont", css::uno::Any(sFont) } })); |
243 | 0 | mrController.dispatchCommand(u".uno:SetBullet"_ustr, aArgs); |
244 | 0 | mrController.EndPopupMode(); |
245 | 0 | } |
246 | | |
247 | | void NumberingPopup::GrabFocus() |
248 | 0 | { |
249 | 0 | mxValueSet->GrabFocus(); |
250 | 0 | } |
251 | | |
252 | | IMPL_LINK_NOARG(NumberingPopup, VSButtonClickSetHdl, weld::Button&, void) |
253 | 0 | { |
254 | 0 | auto aArgs( comphelper::InitPropertySequence( { { "Page", css::uno::Any( u"customize"_ustr ) } } ) ); |
255 | 0 | mrController.dispatchCommand( u".uno:OutlineBullet"_ustr, aArgs ); |
256 | |
|
257 | 0 | mrController.EndPopupMode(); |
258 | 0 | } |
259 | | |
260 | | NumberingToolBoxControl::NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ): |
261 | 0 | svt::PopupWindowController( rxContext, css::uno::Reference< css::frame::XFrame >(), OUString() ), |
262 | 0 | mePageType( NumberingPageType::SINGLENUM ) |
263 | 0 | { |
264 | 0 | } |
265 | | |
266 | | std::unique_ptr<WeldToolbarPopup> NumberingToolBoxControl::weldPopupWindow() |
267 | 0 | { |
268 | 0 | return std::make_unique<NumberingPopup>(*this, m_pToolbar, mePageType); |
269 | 0 | } |
270 | | |
271 | | VclPtr<vcl::Window> NumberingToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) |
272 | 0 | { |
273 | 0 | mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, |
274 | 0 | std::make_unique<NumberingPopup>(*this, pParent->GetFrameWeld(), mePageType)); |
275 | |
|
276 | 0 | mxInterimPopover->Show(); |
277 | |
|
278 | 0 | return mxInterimPopover; |
279 | 0 | } |
280 | | |
281 | | void SAL_CALL NumberingToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) |
282 | 0 | { |
283 | 0 | svt::PopupWindowController::initialize( rArguments ); |
284 | |
|
285 | 0 | if ( m_aCommandURL == ".uno:DefaultBullet" ) |
286 | 0 | mePageType = NumberingPageType::BULLET; |
287 | 0 | else if ( m_aCommandURL == ".uno:SetOutline" ) |
288 | 0 | mePageType = NumberingPageType::OUTLINE; |
289 | |
|
290 | 0 | if (m_pToolbar) |
291 | 0 | { |
292 | 0 | mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); |
293 | 0 | m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); |
294 | 0 | return; |
295 | 0 | } |
296 | | |
297 | 0 | ToolBox* pToolBox = nullptr; |
298 | 0 | ToolBoxItemId nId; |
299 | 0 | if (getToolboxId(nId, &pToolBox)) |
300 | 0 | { |
301 | 0 | ToolBoxItemBits nBits = mePageType == NumberingPageType::OUTLINE |
302 | 0 | ? ToolBoxItemBits::DROPDOWNONLY |
303 | 0 | : ToolBoxItemBits::DROPDOWN; |
304 | 0 | pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | nBits ); |
305 | 0 | } |
306 | 0 | } |
307 | | |
308 | | OUString SAL_CALL NumberingToolBoxControl::getImplementationName() |
309 | 0 | { |
310 | 0 | return u"com.sun.star.comp.svx.NumberingToolBoxControl"_ustr; |
311 | 0 | } |
312 | | |
313 | | css::uno::Sequence< OUString > SAL_CALL NumberingToolBoxControl::getSupportedServiceNames() |
314 | 0 | { |
315 | 0 | return { u"com.sun.star.frame.ToolbarController"_ustr }; |
316 | 0 | } |
317 | | |
318 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
319 | | com_sun_star_comp_svx_NumberingToolBoxControl_get_implementation( |
320 | | css::uno::XComponentContext *rxContext, |
321 | | css::uno::Sequence<css::uno::Any> const & ) |
322 | 0 | { |
323 | 0 | return cppu::acquire( new NumberingToolBoxControl( rxContext ) ); |
324 | 0 | } |
325 | | |
326 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |