/src/libreoffice/svx/source/tbxctrls/tbcontrl.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 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <utility> |
21 | | |
22 | | #include <comphelper/configurationlistener.hxx> |
23 | | #include <comphelper/propertysequence.hxx> |
24 | | #include <comphelper/propertyvalue.hxx> |
25 | | #include <comphelper/OAccessible.hxx> |
26 | | #include <tools/color.hxx> |
27 | | #include <tools/fldunit.hxx> |
28 | | #include <svl/numformat.hxx> |
29 | | #include <svl/poolitem.hxx> |
30 | | #include <svl/itemset.hxx> |
31 | | #include <svl/itempool.hxx> |
32 | | #include <vcl/commandinfoprovider.hxx> |
33 | | #include <vcl/event.hxx> |
34 | | #include <vcl/toolbox.hxx> |
35 | | #include <vcl/vclptr.hxx> |
36 | | #include <vcl/weld/Builder.hxx> |
37 | | #include <vcl/weld/Menu.hxx> |
38 | | #include <vcl/weld/ScrolledWindow.hxx> |
39 | | #include <vcl/weld/TreeView.hxx> |
40 | | #include <vcl/weld/customweld.hxx> |
41 | | #include <vcl/weld/weldutils.hxx> |
42 | | #include <svtools/valueset.hxx> |
43 | | #include <svtools/ctrlbox.hxx> |
44 | | #include <svl/style.hxx> |
45 | | #include <svtools/ctrltool.hxx> |
46 | | #include <svtools/borderhelper.hxx> |
47 | | #include <vcl/InterimItemWindow.hxx> |
48 | | #include <sfx2/tbxctrl.hxx> |
49 | | #include <sfx2/tplpitem.hxx> |
50 | | #include <sfx2/sfxstatuslistener.hxx> |
51 | | #include <sfx2/viewsh.hxx> |
52 | | #include <toolkit/helper/vclunohelper.hxx> |
53 | | #include <sfx2/viewfrm.hxx> |
54 | | #include <vcl/image.hxx> |
55 | | #include <vcl/svapp.hxx> |
56 | | #include <vcl/settings.hxx> |
57 | | #include <vcl/virdev.hxx> |
58 | | #include <com/sun/star/awt/FontDescriptor.hpp> |
59 | | #include <com/sun/star/table/BorderLine2.hpp> |
60 | | #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> |
61 | | #include <com/sun/star/lang/XServiceInfo.hpp> |
62 | | #include <com/sun/star/beans/XPropertySet.hpp> |
63 | | #include <com/sun/star/util/XNumberFormatsSupplier.hpp> |
64 | | #include <com/sun/star/frame/XDispatchProvider.hpp> |
65 | | #include <com/sun/star/frame/XFrame.hpp> |
66 | | #include <svx/strings.hrc> |
67 | | #include <svx/svxids.hrc> |
68 | | #include <helpids.h> |
69 | | #include <sfx2/sidebar/Sidebar.hxx> |
70 | | #include <svx/xtable.hxx> |
71 | | #include <editeng/borderline.hxx> |
72 | | #include <editeng/editids.hrc> |
73 | | #include <editeng/fontitem.hxx> |
74 | | #include <editeng/fhgtitem.hxx> |
75 | | #include <editeng/boxitem.hxx> |
76 | | #include <editeng/charreliefitem.hxx> |
77 | | #include <editeng/contouritem.hxx> |
78 | | #include <editeng/colritem.hxx> |
79 | | #include <editeng/crossedoutitem.hxx> |
80 | | #include <editeng/emphasismarkitem.hxx> |
81 | | #include <editeng/flstitem.hxx> |
82 | | #include <editeng/lineitem.hxx> |
83 | | #include <editeng/postitem.hxx> |
84 | | #include <editeng/shdditem.hxx> |
85 | | #include <editeng/udlnitem.hxx> |
86 | | #include <editeng/wghtitem.hxx> |
87 | | #include <editeng/svxfont.hxx> |
88 | | #include <editeng/cmapitem.hxx> |
89 | | #include <svx/colorwindow.hxx> |
90 | | #include <svx/colorbox.hxx> |
91 | | #include <svx/tbcontrl.hxx> |
92 | | #include <svx/dialmgr.hxx> |
93 | | #include <svx/PaletteManager.hxx> |
94 | | #include <memory> |
95 | | |
96 | | #include <tbxcolorupdate.hxx> |
97 | | #include <editeng/eerdll.hxx> |
98 | | #include <editeng/editrids.hrc> |
99 | | #include <svx/xdef.hxx> |
100 | | #include <svx/xfillit0.hxx> |
101 | | #include <svx/xflclit.hxx> |
102 | | #include <svl/currencytable.hxx> |
103 | | #include <svtools/langtab.hxx> |
104 | | #include <cppuhelper/supportsservice.hxx> |
105 | | #include <officecfg/Office/Common.hxx> |
106 | | #include <o3tl/temporary.hxx> |
107 | | #include <o3tl/safeint.hxx> |
108 | | #include <o3tl/string_view.hxx> |
109 | | #include <o3tl/typed_flags_set.hxx> |
110 | | #include <bitmaps.hlst> |
111 | | #include <sal/log.hxx> |
112 | | #include <unotools/collatorwrapper.hxx> |
113 | | #include <sfx2/IDocumentModelAccessor.hxx> |
114 | | |
115 | | #include <comphelper/lok.hxx> |
116 | | #include <tools/json_writer.hxx> |
117 | | |
118 | | #include <editeng/editeng.hxx> |
119 | | #include <tools/debug.hxx> |
120 | | |
121 | 0 | #define MAX_MRU_FONTNAME_ENTRIES 5 |
122 | | |
123 | 0 | #define COMBO_WIDTH_IN_CHARS 18 |
124 | | |
125 | | // namespaces |
126 | | using namespace ::editeng; |
127 | | using namespace ::com::sun::star; |
128 | | using namespace ::com::sun::star::uno; |
129 | | using namespace ::com::sun::star::frame; |
130 | | using namespace ::com::sun::star::beans; |
131 | | using namespace ::com::sun::star::lang; |
132 | | |
133 | | namespace |
134 | | { |
135 | | struct ScriptInfo |
136 | | { |
137 | | tools::Long textWidth; |
138 | | SvtScriptType scriptType; |
139 | | sal_Int32 changePos; |
140 | | ScriptInfo(SvtScriptType scrptType, sal_Int32 position) |
141 | 0 | : textWidth(0) |
142 | 0 | , scriptType(scrptType) |
143 | 0 | , changePos(position) |
144 | 0 | { |
145 | 0 | } |
146 | | }; |
147 | | |
148 | | class SvxStyleBox_Base |
149 | | { |
150 | | public: |
151 | | SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, OUString rCommand, SfxStyleFamily eFamily, |
152 | | const Reference<XFrame>& _xFrame, OUString aClearFormatKey, |
153 | | OUString aMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl); |
154 | | |
155 | | virtual ~SvxStyleBox_Base() |
156 | 0 | { |
157 | 0 | } |
158 | | |
159 | | void SetFamily( SfxStyleFamily eNewFamily ); |
160 | | |
161 | 0 | void SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; } |
162 | | |
163 | 0 | OUString get_text(int nIndex) const { return m_xWidget->get_text(nIndex); } |
164 | 0 | OUString get_active_text() const { return m_xWidget->get_active_text(); } |
165 | | |
166 | | void append_text(const OUString& rStr) |
167 | 0 | { |
168 | 0 | OUString sId(OUString::number(m_xWidget->get_count())); |
169 | 0 | m_xWidget->append(sId, rStr); |
170 | 0 | } |
171 | | |
172 | | void insert_separator(int pos, const OUString& rId) |
173 | 0 | { |
174 | 0 | m_xWidget->insert_separator(pos, rId); |
175 | 0 | } |
176 | | |
177 | | void set_active_or_entry_text(const OUString& rText) |
178 | 0 | { |
179 | 0 | const int nFound = m_xWidget->find_text(rText); |
180 | 0 | if (nFound != -1) |
181 | 0 | m_xWidget->set_active(nFound); |
182 | 0 | else |
183 | 0 | m_xWidget->set_entry_text(rText); |
184 | 0 | } |
185 | | |
186 | | void set_active(int nActive) |
187 | 0 | { |
188 | 0 | m_xWidget->set_active(nActive); |
189 | 0 | } |
190 | | |
191 | | void freeze() |
192 | 0 | { |
193 | 0 | m_xWidget->freeze(); |
194 | 0 | } |
195 | | |
196 | | void save_value() |
197 | 0 | { |
198 | 0 | m_xWidget->save_value(); |
199 | 0 | } |
200 | | |
201 | | void clear() |
202 | 0 | { |
203 | 0 | m_xWidget->clear(); |
204 | 0 | m_nMaxUserDrawFontWidth = 0; |
205 | 0 | } |
206 | | |
207 | | void thaw() |
208 | 0 | { |
209 | 0 | m_xWidget->thaw(); |
210 | 0 | } |
211 | | |
212 | | virtual bool DoKeyInput(const KeyEvent& rKEvt); |
213 | | |
214 | | private: |
215 | | std::optional<SvxFont> m_oFont; |
216 | | std::optional<SvxFont> m_oCJKFont; |
217 | | std::optional<SvxFont> m_oCTLFont; |
218 | | |
219 | | DECL_LINK(SelectHdl, weld::ComboBox&, void); |
220 | | DECL_LINK(KeyInputHdl, const KeyEvent&, bool); |
221 | | DECL_LINK(ActivateHdl, weld::ComboBox&, bool); |
222 | | DECL_LINK(FocusOutHdl, weld::Widget&, void); |
223 | | DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); |
224 | | DECL_LINK(CustomRenderHdl, weld::ComboBox::render_args, void); |
225 | | DECL_LINK(CustomGetSizeHdl, OutputDevice&, Size); |
226 | | |
227 | | /// Calculate the optimal width of the dropdown. Very expensive operation, triggers lots of font measurement. |
228 | | void CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext); |
229 | | |
230 | | void Select(bool bNonTravelSelect); |
231 | | |
232 | | tools::Rectangle CalcBoundRect(vcl::RenderContext& rRenderContext, const OUString &rStyleName, std::vector<ScriptInfo>& rScriptChanges, double fRatio = 1); |
233 | | |
234 | | protected: |
235 | | SvxStyleToolBoxControl& m_rCtrl; |
236 | | |
237 | | std::unique_ptr<weld::Builder> m_xMenuBuilder; |
238 | | std::unique_ptr<weld::Menu> m_xMenu; |
239 | | std::unique_ptr<weld::ComboBox> m_xWidget; |
240 | | |
241 | | SfxStyleFamily eStyleFamily; |
242 | | int m_nMaxUserDrawFontWidth; |
243 | | int m_nLastItemWithMenu; |
244 | | bool bRelease; |
245 | | Reference< XFrame > m_xFrame; |
246 | | OUString m_aCommand; |
247 | | OUString aClearFormatKey; |
248 | | OUString aMoreKey; |
249 | | OUString sDefaultStyle; |
250 | | bool bInSpecialMode; |
251 | | |
252 | | void ReleaseFocus(); |
253 | | static Color TestColorsVisible(const Color &FontCol, const Color &BackCol); |
254 | | void UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const tools::Rectangle& rTextRect, const OUString &rStyleName, const std::vector<ScriptInfo>& rScriptChanges); |
255 | | void SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, std::u16string_view rStyleName, bool bIsNotSelected); |
256 | | DECL_LINK(MenuSelectHdl, const OUString&, void); |
257 | | DECL_STATIC_LINK(SvxStyleBox_Base, ShowMoreHdl, void*, void); |
258 | | }; |
259 | | |
260 | | class SvxStyleBox_Impl final : public InterimItemWindow |
261 | | , public SvxStyleBox_Base |
262 | | { |
263 | | public: |
264 | | SvxStyleBox_Impl(vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, |
265 | | const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl); |
266 | | |
267 | | virtual ~SvxStyleBox_Impl() override |
268 | 0 | { |
269 | 0 | disposeOnce(); |
270 | 0 | } |
271 | | |
272 | | virtual void dispose() override |
273 | 0 | { |
274 | 0 | m_xWidget.reset(); |
275 | 0 | m_xMenu.reset(); |
276 | 0 | m_xMenuBuilder.reset(); |
277 | 0 | InterimItemWindow::dispose(); |
278 | 0 | } |
279 | | |
280 | | virtual bool DoKeyInput(const KeyEvent& rKEvt) override; |
281 | | |
282 | | private: |
283 | | |
284 | | virtual void DataChanged(const DataChangedEvent& rDCEvt) override; |
285 | | void SetOptimalSize(); |
286 | | }; |
287 | | |
288 | | class SvxFontNameBox_Impl; |
289 | | class SvxFontNameBox_Base; |
290 | | |
291 | | class SvxFontNameToolBoxControl final : public cppu::ImplInheritanceHelper<svt::ToolboxController, |
292 | | css::lang::XServiceInfo> |
293 | | { |
294 | | public: |
295 | | SvxFontNameToolBoxControl(); |
296 | | |
297 | | // XStatusListener |
298 | | virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; |
299 | | |
300 | | // XToolbarController |
301 | | virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override; |
302 | | |
303 | | // XComponent |
304 | | virtual void SAL_CALL dispose() override; |
305 | | |
306 | | // XServiceInfo |
307 | | virtual OUString SAL_CALL getImplementationName() override; |
308 | | virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; |
309 | | virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; |
310 | | |
311 | | private: |
312 | | VclPtr<SvxFontNameBox_Impl> m_xVclBox; |
313 | | std::unique_ptr<SvxFontNameBox_Base> m_xWeldBox; |
314 | | SvxFontNameBox_Base* m_pBox; |
315 | | }; |
316 | | |
317 | | class FontOptionsListener final : public comphelper::ConfigurationListenerProperty<bool> |
318 | | { |
319 | | private: |
320 | | SvxFontNameBox_Base& m_rBox; |
321 | | |
322 | | virtual void setProperty(const css::uno::Any &rProperty) override; |
323 | | public: |
324 | | FontOptionsListener(const rtl::Reference<comphelper::ConfigurationListener>& rListener, const OUString& rProp, SvxFontNameBox_Base& rBox) |
325 | 0 | : comphelper::ConfigurationListenerProperty<bool>(rListener, rProp) |
326 | 0 | , m_rBox(rBox) |
327 | 0 | { |
328 | 0 | } |
329 | | }; |
330 | | |
331 | | class SvxFontNameBox_Base |
332 | | { |
333 | | private: |
334 | | rtl::Reference<comphelper::ConfigurationListener> m_xListener; |
335 | | FontOptionsListener m_aWYSIWYG; |
336 | | FontOptionsListener m_aHistory; |
337 | | |
338 | | protected: |
339 | | SvxFontNameToolBoxControl& m_rCtrl; |
340 | | |
341 | | std::unique_ptr<FontNameBox> m_xWidget; |
342 | | const FontList* pFontList; |
343 | | ::std::unique_ptr<FontList> m_aOwnFontList; |
344 | | vcl::Font aCurFont; |
345 | | sal_uInt16 nFtCount; |
346 | | bool bRelease; |
347 | | Reference< XFrame > m_xFrame; |
348 | | bool mbCheckingUnknownFont; |
349 | | bool mbDropDownActive; |
350 | | |
351 | | void ReleaseFocus_Impl(); |
352 | | |
353 | | void Select(bool bNonTravelSelect); |
354 | | |
355 | | void EndPreview() |
356 | 0 | { |
357 | 0 | Sequence< PropertyValue > aArgs; |
358 | 0 | const Reference<XDispatchProvider> xProvider(m_xFrame, UNO_QUERY); |
359 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:CharEndPreviewFontName"_ustr, aArgs); |
360 | 0 | } |
361 | | |
362 | | bool CheckFontIsAvailable(std::u16string_view fontname); |
363 | | void CheckAndMarkUnknownFont(); |
364 | | |
365 | | public: |
366 | | SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget, const Reference<XFrame>& rFrame, |
367 | | SvxFontNameToolBoxControl& rCtrl); |
368 | | virtual ~SvxFontNameBox_Base() |
369 | 0 | { |
370 | 0 | m_xListener->dispose(); |
371 | 0 | } |
372 | | |
373 | | void FillList(); |
374 | | void Update( const css::awt::FontDescriptor* pFontDesc ); |
375 | 0 | sal_uInt16 GetListCount() const { return nFtCount; } |
376 | 0 | void Clear() { m_xWidget->clear(); nFtCount = 0; } |
377 | | void Fill( const FontList* pList ) |
378 | 0 | { |
379 | 0 | m_xWidget->Fill(pList); |
380 | 0 | nFtCount = pList->GetFontNameCount(); |
381 | 0 | } |
382 | | |
383 | 0 | void SetOwnFontList(::std::unique_ptr<FontList> && _aOwnFontList) { m_aOwnFontList = std::move(_aOwnFontList); } |
384 | | |
385 | | virtual void set_sensitive(bool bSensitive) |
386 | 0 | { |
387 | 0 | m_xWidget->set_sensitive(bSensitive); |
388 | 0 | } |
389 | | |
390 | | void set_active_or_entry_text(const OUString& rText); |
391 | | |
392 | | void statusChanged_Impl(const css::frame::FeatureStateEvent& rEvent); |
393 | | |
394 | | virtual bool DoKeyInput(const KeyEvent& rKEvt); |
395 | | |
396 | | void EnableControls(); |
397 | | |
398 | | DECL_LINK(SelectHdl, weld::ComboBox&, void); |
399 | | DECL_LINK(KeyInputHdl, const KeyEvent&, bool); |
400 | | DECL_LINK(ActivateHdl, weld::ComboBox&, bool); |
401 | | DECL_LINK(FocusInHdl, weld::Widget&, void); |
402 | | DECL_LINK(FocusOutHdl, weld::Widget&, void); |
403 | | DECL_LINK(PopupToggledHdl, weld::ComboBox&, void); |
404 | | DECL_LINK(LivePreviewHdl, const FontMetric&, void); |
405 | | DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); |
406 | | }; |
407 | | |
408 | | void FontOptionsListener::setProperty(const css::uno::Any &rProperty) |
409 | 0 | { |
410 | 0 | comphelper::ConfigurationListenerProperty<bool>::setProperty(rProperty); |
411 | 0 | m_rBox.EnableControls(); |
412 | 0 | } |
413 | | |
414 | | class SvxFontNameBox_Impl final : public InterimItemWindow |
415 | | , public SvxFontNameBox_Base |
416 | | { |
417 | | private: |
418 | | virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; |
419 | | virtual void GetFocus() override |
420 | 0 | { |
421 | 0 | if (m_xWidget) |
422 | 0 | m_xWidget->grab_focus(); |
423 | 0 | InterimItemWindow::GetFocus(); |
424 | 0 | } |
425 | | |
426 | | void SetOptimalSize(); |
427 | | |
428 | | virtual bool DoKeyInput(const KeyEvent& rKEvt) override; |
429 | | |
430 | | public: |
431 | | SvxFontNameBox_Impl(vcl::Window* pParent, |
432 | | const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl); |
433 | | |
434 | | virtual void dispose() override |
435 | 0 | { |
436 | 0 | m_xWidget.reset(); |
437 | 0 | InterimItemWindow::dispose(); |
438 | 0 | } |
439 | | |
440 | | virtual ~SvxFontNameBox_Impl() override |
441 | 0 | { |
442 | 0 | disposeOnce(); |
443 | 0 | } |
444 | | |
445 | | virtual rtl::Reference<comphelper::OAccessible> CreateAccessible() override; |
446 | | |
447 | | virtual void StateChanged(StateChangedType nStateChange) override |
448 | 0 | { |
449 | 0 | if (nStateChange == StateChangedType::Enable) |
450 | 0 | m_xWidget->set_sensitive(IsEnabled()); |
451 | 0 | InterimItemWindow::StateChanged(nStateChange); |
452 | 0 | } |
453 | | |
454 | | virtual void set_sensitive(bool bSensitive) override |
455 | 0 | { |
456 | 0 | m_xWidget->set_sensitive(bSensitive); |
457 | 0 | if (bSensitive) |
458 | 0 | InterimItemWindow::Enable(); |
459 | 0 | else |
460 | 0 | InterimItemWindow::Disable(); |
461 | 0 | } |
462 | | }; |
463 | | |
464 | | |
465 | | // SelectHdl needs the Modifiers, get them in MouseButtonUp |
466 | | class SvxFrmValueSet_Impl final : public ValueSet |
467 | | { |
468 | | private: |
469 | | sal_uInt16 nModifier; |
470 | | |
471 | | virtual bool MouseButtonUp(const MouseEvent& rMEvt) override |
472 | 0 | { |
473 | 0 | nModifier = rMEvt.GetModifier(); |
474 | 0 | return ValueSet::MouseButtonUp(rMEvt); |
475 | 0 | } |
476 | | |
477 | | public: |
478 | | SvxFrmValueSet_Impl() |
479 | 0 | : ValueSet(nullptr) |
480 | 0 | , nModifier(0) |
481 | 0 | { |
482 | 0 | } |
483 | 0 | sal_uInt16 GetModifier() const {return nModifier;} |
484 | | }; |
485 | | |
486 | | } |
487 | | |
488 | | namespace { |
489 | | |
490 | | class SvxFrameToolBoxControl; |
491 | | |
492 | | class SvxFrameWindow_Impl final : public WeldToolbarPopup |
493 | | { |
494 | | private: |
495 | | rtl::Reference<SvxFrameToolBoxControl> mxControl; |
496 | | std::unique_ptr<SvxFrmValueSet_Impl> mxFrameSet; |
497 | | std::unique_ptr<weld::CustomWeld> mxFrameSetWin; |
498 | | std::vector<std::pair<Bitmap, OUString>> aImgVec; |
499 | | bool bParagraphMode; |
500 | | bool m_bIsWriter; |
501 | | bool m_bIsCalc; |
502 | | |
503 | | void InitImageList(); |
504 | | void CalcSizeValueSet(); |
505 | | DECL_LINK( SelectHdl, ValueSet*, void ); |
506 | | |
507 | | void SetDiagonalDownBorder(const SvxLineItem& dDownLineItem); |
508 | | void SetDiagonalUpBorder(const SvxLineItem& dUpLineItem); |
509 | | |
510 | | public: |
511 | | SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); |
512 | | virtual void GrabFocus() override |
513 | 0 | { |
514 | 0 | mxFrameSet->GrabFocus(); |
515 | 0 | } |
516 | | |
517 | | virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; |
518 | | }; |
519 | | |
520 | | class SvxFrameToolBoxControl : public svt::PopupWindowController |
521 | | { |
522 | | public: |
523 | | explicit SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ); |
524 | | |
525 | | // XInitialization |
526 | | virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override; |
527 | | |
528 | | // XServiceInfo |
529 | | virtual OUString SAL_CALL getImplementationName() override; |
530 | | virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; |
531 | | |
532 | | virtual void SAL_CALL execute(sal_Int16 nKeyModifier) override; |
533 | | private: |
534 | | virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; |
535 | | virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; |
536 | | }; |
537 | | |
538 | | class LineListBox final : public ValueSet |
539 | | { |
540 | | public: |
541 | | typedef Color (*ColorFunc)(Color); |
542 | | typedef Color (*ColorDistFunc)(Color, Color); |
543 | | |
544 | | LineListBox(); |
545 | | |
546 | | /** Set the width in Twips */ |
547 | | Size SetWidth( tools::Long nWidth ) |
548 | 0 | { |
549 | 0 | tools::Long nOldWidth = m_nWidth; |
550 | 0 | m_nWidth = nWidth; |
551 | 0 | return UpdateEntries( nOldWidth ); |
552 | 0 | } |
553 | | |
554 | | void SetNone( const OUString& sNone ) |
555 | 0 | { |
556 | 0 | m_sNone = sNone; |
557 | 0 | } |
558 | | |
559 | | /** Insert a listbox entry with all widths in Twips. */ |
560 | | void InsertEntry(const BorderWidthImpl& rWidthImpl, |
561 | | SvxBorderLineStyle nStyle, tools::Long nMinWidth = 0, |
562 | | ColorFunc pColor1Fn = &sameColor, |
563 | | ColorFunc pColor2Fn = &sameColor, |
564 | | ColorDistFunc pColorDistFn = &sameDistColor); |
565 | | |
566 | | SvxBorderLineStyle GetEntryStyle( sal_Int32 nPos ) const; |
567 | | |
568 | | SvxBorderLineStyle GetSelectEntryStyle() const; |
569 | | |
570 | 0 | void SetSourceUnit( FieldUnit eNewUnit ) { eSourceUnit = eNewUnit; } |
571 | | |
572 | 0 | const Color& GetColor() const { return aColor; } |
573 | | |
574 | | virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; |
575 | | private: |
576 | | |
577 | | void ImpGetLine(tools::Long nLine1, tools::Long nLine2, tools::Long nDistance, |
578 | | Color nColor1, Color nColor2, Color nColorDist, |
579 | | SvxBorderLineStyle nStyle, Bitmap& rBmp); |
580 | | |
581 | | void UpdatePaintLineColor(); // returns sal_True if maPaintCol has changed |
582 | | |
583 | | Size UpdateEntries( tools::Long nOldWidth ); |
584 | | sal_Int32 GetStylePos( sal_Int32 nListPos, tools::Long nWidth ); |
585 | | |
586 | | const Color& GetPaintColor() const |
587 | 0 | { |
588 | 0 | return maPaintCol; |
589 | 0 | } |
590 | | |
591 | | Color GetColorLine1( sal_Int32 nPos ); |
592 | | Color GetColorLine2( sal_Int32 nPos ); |
593 | | Color GetColorDist( sal_Int32 nPos ); |
594 | | |
595 | | LineListBox( const LineListBox& ) = delete; |
596 | | LineListBox& operator =( const LineListBox& ) = delete; |
597 | | |
598 | | std::vector<std::unique_ptr<ImpLineListData>> m_vLineList; |
599 | | tools::Long m_nWidth; |
600 | | OUString m_sNone; |
601 | | ScopedVclPtr<VirtualDevice> aVirDev; |
602 | | Size aTxtSize; |
603 | | Color const aColor; |
604 | | Color maPaintCol; |
605 | | FieldUnit eSourceUnit; |
606 | | }; |
607 | | |
608 | | SvxBorderLineStyle LineListBox::GetSelectEntryStyle() const |
609 | 0 | { |
610 | 0 | SvxBorderLineStyle nStyle = SvxBorderLineStyle::SOLID; |
611 | 0 | size_t nPos = GetSelectItemPos(); |
612 | 0 | if (nPos != VALUESET_ITEM_NOTFOUND) |
613 | 0 | { |
614 | 0 | if (!m_sNone.isEmpty()) |
615 | 0 | --nPos; |
616 | 0 | nStyle = GetEntryStyle( nPos ); |
617 | 0 | } |
618 | |
|
619 | 0 | return nStyle; |
620 | 0 | } |
621 | | |
622 | | void LineListBox::ImpGetLine( tools::Long nLine1, tools::Long nLine2, tools::Long nDistance, |
623 | | Color aColor1, Color aColor2, Color aColorDist, |
624 | | SvxBorderLineStyle nStyle, Bitmap& rBmp ) |
625 | 0 | { |
626 | 0 | auto nMinWidth = GetDrawingArea()->get_ref_device().approximate_digit_width() * COMBO_WIDTH_IN_CHARS; |
627 | 0 | Size aSize(nMinWidth, aTxtSize.Height()); |
628 | 0 | aSize.AdjustWidth( -(aTxtSize.Width()) ); |
629 | 0 | aSize.AdjustWidth( -6 ); |
630 | | |
631 | | // SourceUnit to Twips |
632 | 0 | if ( eSourceUnit == FieldUnit::POINT ) |
633 | 0 | { |
634 | 0 | nLine1 /= 5; |
635 | 0 | nLine2 /= 5; |
636 | 0 | nDistance /= 5; |
637 | 0 | } |
638 | | |
639 | | // Paint the lines |
640 | 0 | aSize = aVirDev->PixelToLogic( aSize ); |
641 | 0 | tools::Long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height(); |
642 | 0 | sal_uInt32 n1 = nLine1; |
643 | 0 | sal_uInt32 n2 = nLine2; |
644 | 0 | tools::Long nDist = nDistance; |
645 | 0 | n1 += nPix-1; |
646 | 0 | n1 -= n1%nPix; |
647 | 0 | if ( n2 ) |
648 | 0 | { |
649 | 0 | nDist += nPix-1; |
650 | 0 | nDist -= nDist%nPix; |
651 | 0 | n2 += nPix-1; |
652 | 0 | n2 -= n2%nPix; |
653 | 0 | } |
654 | 0 | tools::Long nVirHeight = n1+nDist+n2; |
655 | 0 | if ( nVirHeight > aSize.Height() ) |
656 | 0 | aSize.setHeight( nVirHeight ); |
657 | | // negative width should not be drawn |
658 | 0 | if ( aSize.Width() <= 0 ) |
659 | 0 | return; |
660 | | |
661 | 0 | Size aVirSize = aVirDev->LogicToPixel( aSize ); |
662 | 0 | if ( aVirDev->GetOutputSizePixel() != aVirSize ) |
663 | 0 | aVirDev->SetOutputSizePixel( aVirSize ); |
664 | 0 | aVirDev->SetFillColor( aColorDist ); |
665 | 0 | aVirDev->DrawRect( tools::Rectangle( Point(), aSize ) ); |
666 | |
|
667 | 0 | aVirDev->SetFillColor( aColor1 ); |
668 | |
|
669 | 0 | double y1 = double( n1 ) / 2; |
670 | 0 | svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle ); |
671 | |
|
672 | 0 | if ( n2 ) |
673 | 0 | { |
674 | 0 | double y2 = n1 + nDist + double( n2 ) / 2; |
675 | 0 | aVirDev->SetFillColor( aColor2 ); |
676 | 0 | svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, SvxBorderLineStyle::SOLID ); |
677 | 0 | } |
678 | 0 | rBmp = aVirDev->GetBitmap( Point(), Size( aSize.Width(), n1+nDist+n2 ) ); |
679 | 0 | } |
680 | | |
681 | | LineListBox::LineListBox() |
682 | 0 | : ValueSet(nullptr) |
683 | 0 | , m_nWidth( 5 ) |
684 | 0 | , aVirDev(VclPtr<VirtualDevice>::Create()) |
685 | 0 | , aColor(Application::GetSettings().GetStyleSettings().GetWindowTextColor()) |
686 | 0 | , maPaintCol(COL_BLACK) |
687 | 0 | , eSourceUnit(FieldUnit::POINT) |
688 | 0 | { |
689 | 0 | aVirDev->SetLineColor(); |
690 | 0 | aVirDev->SetMapMode( MapMode( MapUnit::MapTwip ) ); |
691 | 0 | } |
692 | | |
693 | | void LineListBox::SetDrawingArea(weld::DrawingArea* pDrawingArea) |
694 | 0 | { |
695 | 0 | ValueSet::SetDrawingArea(pDrawingArea); |
696 | |
|
697 | 0 | OutputDevice& rDevice = pDrawingArea->get_ref_device(); |
698 | |
|
699 | 0 | aTxtSize.setWidth( rDevice.approximate_digit_width() ); |
700 | 0 | aTxtSize.setHeight( rDevice.GetTextHeight() ); |
701 | |
|
702 | 0 | UpdatePaintLineColor(); |
703 | 0 | } |
704 | | |
705 | | sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, tools::Long nWidth ) |
706 | 0 | { |
707 | 0 | sal_Int32 nPos = -1; |
708 | 0 | if (!m_sNone.isEmpty()) |
709 | 0 | nListPos--; |
710 | |
|
711 | 0 | sal_Int32 n = 0; |
712 | 0 | size_t i = 0; |
713 | 0 | size_t nCount = m_vLineList.size(); |
714 | 0 | while ( nPos == -1 && i < nCount ) |
715 | 0 | { |
716 | 0 | auto& pData = m_vLineList[ i ]; |
717 | 0 | if ( pData->GetMinWidth() <= nWidth ) |
718 | 0 | { |
719 | 0 | if ( nListPos == n ) |
720 | 0 | nPos = static_cast<sal_Int32>(i); |
721 | 0 | n++; |
722 | 0 | } |
723 | 0 | i++; |
724 | 0 | } |
725 | |
|
726 | 0 | return nPos; |
727 | 0 | } |
728 | | |
729 | | void LineListBox::InsertEntry( |
730 | | const BorderWidthImpl& rWidthImpl, SvxBorderLineStyle nStyle, tools::Long nMinWidth, |
731 | | ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn ) |
732 | 0 | { |
733 | 0 | m_vLineList.emplace_back(new ImpLineListData( |
734 | 0 | rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn)); |
735 | 0 | } |
736 | | |
737 | | SvxBorderLineStyle LineListBox::GetEntryStyle( sal_Int32 nPos ) const |
738 | 0 | { |
739 | 0 | ImpLineListData* pData = (0 <= nPos && o3tl::make_unsigned(nPos) < m_vLineList.size()) ? m_vLineList[ nPos ].get() : nullptr; |
740 | 0 | return pData ? pData->GetStyle() : SvxBorderLineStyle::NONE; |
741 | 0 | } |
742 | | |
743 | | void LineListBox::UpdatePaintLineColor() |
744 | 0 | { |
745 | 0 | const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); |
746 | 0 | Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor ); |
747 | |
|
748 | 0 | bool bRet = aNewCol != maPaintCol; |
749 | |
|
750 | 0 | if( bRet ) |
751 | 0 | maPaintCol = aNewCol; |
752 | 0 | } |
753 | | |
754 | | Size LineListBox::UpdateEntries( tools::Long nOldWidth ) |
755 | 0 | { |
756 | 0 | Size aSize; |
757 | |
|
758 | 0 | UpdatePaintLineColor( ); |
759 | |
|
760 | 0 | sal_Int32 nSelEntry = GetSelectItemPos(); |
761 | 0 | sal_Int32 nTypePos = GetStylePos( nSelEntry, nOldWidth ); |
762 | | |
763 | | // Remove the old entries |
764 | 0 | Clear(); |
765 | |
|
766 | 0 | sal_uInt16 nId(1); |
767 | | |
768 | | // Add the new entries based on the defined width |
769 | 0 | if (!m_sNone.isEmpty()) |
770 | 0 | InsertItem(nId++, Image(), m_sNone); |
771 | |
|
772 | 0 | sal_uInt16 n = 0; |
773 | 0 | sal_uInt16 nCount = m_vLineList.size( ); |
774 | 0 | while ( n < nCount ) |
775 | 0 | { |
776 | 0 | auto& pData = m_vLineList[ n ]; |
777 | 0 | if ( pData->GetMinWidth() <= m_nWidth ) |
778 | 0 | { |
779 | 0 | Bitmap aBmp; |
780 | 0 | ImpGetLine( pData->GetLine1ForWidth( m_nWidth ), |
781 | 0 | pData->GetLine2ForWidth( m_nWidth ), |
782 | 0 | pData->GetDistForWidth( m_nWidth ), |
783 | 0 | GetColorLine1( GetItemCount( ) ), |
784 | 0 | GetColorLine2( GetItemCount( ) ), |
785 | 0 | GetColorDist( GetItemCount( ) ), |
786 | 0 | pData->GetStyle(), aBmp ); |
787 | 0 | InsertItem(nId, Image(aBmp), SvtLineListBox::GetLineStyleName(pData->GetStyle())); |
788 | 0 | Size aBmpSize = aBmp.GetSizePixel(); |
789 | 0 | if (aBmpSize.Width() > aSize.Width()) |
790 | 0 | aSize.setWidth(aBmpSize.getWidth()); |
791 | 0 | if (aBmpSize.Height() > aSize.Height()) |
792 | 0 | aSize.setHeight(aBmpSize.getHeight()); |
793 | 0 | if ( n == nTypePos ) |
794 | 0 | SelectItem(nId); |
795 | 0 | } |
796 | 0 | else if ( n == nTypePos ) |
797 | 0 | SetNoSelection(); |
798 | 0 | n++; |
799 | 0 | ++nId; |
800 | 0 | } |
801 | |
|
802 | 0 | Invalidate(); |
803 | |
|
804 | 0 | return aSize; |
805 | 0 | } |
806 | | |
807 | | Color LineListBox::GetColorLine1( sal_Int32 nPos ) |
808 | 0 | { |
809 | 0 | sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); |
810 | 0 | if (nStyle == -1) |
811 | 0 | return GetPaintColor( ); |
812 | 0 | auto& pData = m_vLineList[ nStyle ]; |
813 | 0 | return pData->GetColorLine1( GetColor( ) ); |
814 | 0 | } |
815 | | |
816 | | Color LineListBox::GetColorLine2( sal_Int32 nPos ) |
817 | 0 | { |
818 | 0 | sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); |
819 | 0 | if (nStyle == -1) |
820 | 0 | return GetPaintColor( ); |
821 | 0 | auto& pData = m_vLineList[ nStyle ]; |
822 | 0 | return pData->GetColorLine2( GetColor( ) ); |
823 | 0 | } |
824 | | |
825 | | Color LineListBox::GetColorDist( sal_Int32 nPos ) |
826 | 0 | { |
827 | 0 | Color rResult = Application::GetSettings().GetStyleSettings().GetFieldColor(); |
828 | |
|
829 | 0 | sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); |
830 | 0 | if (nStyle == -1) |
831 | 0 | return rResult; |
832 | 0 | auto& pData = m_vLineList[ nStyle ]; |
833 | 0 | return pData->GetColorDist( GetColor( ), rResult ); |
834 | 0 | } |
835 | | } |
836 | | |
837 | | namespace { |
838 | | |
839 | | class SvxLineWindow_Impl final : public WeldToolbarPopup |
840 | | { |
841 | | private: |
842 | | rtl::Reference<SvxFrameToolBoxControl> m_xControl; |
843 | | std::unique_ptr<LineListBox> m_xLineStyleLb; |
844 | | std::unique_ptr<weld::CustomWeld> m_xLineStyleLbWin; |
845 | | bool m_bIsWriter; |
846 | | |
847 | | DECL_LINK( SelectHdl, ValueSet*, void ); |
848 | | |
849 | | public: |
850 | | SvxLineWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); |
851 | | virtual void GrabFocus() override |
852 | 0 | { |
853 | 0 | m_xLineStyleLb->GrabFocus(); |
854 | 0 | } |
855 | | }; |
856 | | |
857 | | } |
858 | | |
859 | | class SvxStyleToolBoxControl; |
860 | | |
861 | | class SfxStyleControllerItem_Impl : public SfxStatusListener |
862 | | { |
863 | | public: |
864 | | SfxStyleControllerItem_Impl( const Reference< XDispatchProvider >& rDispatchProvider, |
865 | | sal_uInt16 nSlotId, |
866 | | const OUString& rCommand, |
867 | | SvxStyleToolBoxControl& rTbxCtl ); |
868 | | |
869 | | protected: |
870 | | virtual void StateChangedAtStatusListener( SfxItemState eState, const SfxPoolItem* pState ) override; |
871 | | |
872 | | private: |
873 | | SvxStyleToolBoxControl& rControl; |
874 | | }; |
875 | | |
876 | 0 | #define BUTTON_PADDING 10 |
877 | 0 | #define ITEM_HEIGHT 30 |
878 | | |
879 | | SvxStyleBox_Base::SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, |
880 | | OUString aCommand, |
881 | | SfxStyleFamily eFamily, |
882 | | const Reference< XFrame >& _xFrame, |
883 | | OUString _aClearFormatKey, |
884 | | OUString _aMoreKey, |
885 | | bool bInSpec, SvxStyleToolBoxControl& rCtrl) |
886 | 0 | : m_rCtrl(rCtrl) |
887 | 0 | , m_xMenuBuilder(Application::CreateBuilder(nullptr, u"svx/ui/stylemenu.ui"_ustr)) |
888 | 0 | , m_xMenu(m_xMenuBuilder->weld_menu(u"menu"_ustr)) |
889 | 0 | , m_xWidget(std::move(xWidget)) |
890 | 0 | , eStyleFamily( eFamily ) |
891 | 0 | , m_nMaxUserDrawFontWidth(0) |
892 | 0 | , m_nLastItemWithMenu(-1) |
893 | 0 | , bRelease( true ) |
894 | 0 | , m_xFrame(_xFrame) |
895 | 0 | , m_aCommand(std::move( aCommand )) |
896 | 0 | , aClearFormatKey(std::move( _aClearFormatKey )) |
897 | 0 | , aMoreKey(std::move( _aMoreKey )) |
898 | 0 | , bInSpecialMode( bInSpec ) |
899 | 0 | { |
900 | 0 | m_xWidget->connect_changed(LINK(this, SvxStyleBox_Base, SelectHdl)); |
901 | 0 | m_xWidget->connect_key_press(LINK(this, SvxStyleBox_Base, KeyInputHdl)); |
902 | 0 | m_xWidget->connect_entry_activate(LINK(this, SvxStyleBox_Base, ActivateHdl)); |
903 | 0 | m_xWidget->connect_focus_out(LINK(this, SvxStyleBox_Base, FocusOutHdl)); |
904 | 0 | m_xWidget->connect_get_property_tree(LINK(this, SvxStyleBox_Base, DumpAsPropertyTreeHdl)); |
905 | 0 | m_xWidget->set_help_id(HID_STYLE_LISTBOX); |
906 | 0 | m_xWidget->set_entry_completion(true); |
907 | 0 | m_xMenu->connect_activate(LINK(this, SvxStyleBox_Base, MenuSelectHdl)); |
908 | |
|
909 | 0 | m_xWidget->connect_custom_get_size(LINK(this, SvxStyleBox_Base, CustomGetSizeHdl)); |
910 | 0 | m_xWidget->connect_custom_render(LINK(this, SvxStyleBox_Base, CustomRenderHdl)); |
911 | 0 | m_xWidget->set_custom_renderer(true); |
912 | |
|
913 | 0 | m_xWidget->set_entry_width_chars(COMBO_WIDTH_IN_CHARS + 3); |
914 | 0 | } |
915 | | |
916 | | IMPL_LINK(SvxStyleBox_Base, CustomGetSizeHdl, OutputDevice&, rArg, Size) |
917 | 0 | { |
918 | 0 | CalcOptimalExtraUserWidth(rArg); |
919 | 0 | if (comphelper::LibreOfficeKit::isActive()) |
920 | 0 | return Size(m_nMaxUserDrawFontWidth * rArg.GetDPIX() / 96, ITEM_HEIGHT * rArg.GetDPIY() / 96); |
921 | 0 | return Size(m_nMaxUserDrawFontWidth, ITEM_HEIGHT); |
922 | 0 | } |
923 | | |
924 | | SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent, |
925 | | const OUString& rCommand, |
926 | | SfxStyleFamily eFamily, |
927 | | const Reference< XFrame >& _xFrame, |
928 | | const OUString& rClearFormatKey, |
929 | | const OUString& rMoreKey, |
930 | | bool bInSpec, SvxStyleToolBoxControl& rCtrl) |
931 | 0 | : InterimItemWindow(pParent, u"svx/ui/applystylebox.ui"_ustr, u"ApplyStyleBox"_ustr) |
932 | 0 | , SvxStyleBox_Base(m_xBuilder->weld_combo_box(u"applystyle"_ustr), rCommand, eFamily, _xFrame, |
933 | 0 | rClearFormatKey, rMoreKey, bInSpec, rCtrl) |
934 | 0 | { |
935 | 0 | InitControlBase(m_xWidget.get()); |
936 | |
|
937 | 0 | set_id(u"applystyle"_ustr); |
938 | 0 | SetOptimalSize(); |
939 | 0 | } |
940 | | |
941 | | void SvxStyleBox_Base::ReleaseFocus() |
942 | 0 | { |
943 | 0 | if ( !bRelease ) |
944 | 0 | { |
945 | 0 | bRelease = true; |
946 | 0 | return; |
947 | 0 | } |
948 | 0 | if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) |
949 | 0 | m_xFrame->getContainerWindow()->setFocus(); |
950 | 0 | } |
951 | | |
952 | | IMPL_LINK(SvxStyleBox_Base, MenuSelectHdl, const OUString&, rMenuIdent, void) |
953 | 0 | { |
954 | 0 | if (m_nLastItemWithMenu < 0 || m_nLastItemWithMenu >= m_xWidget->get_count()) |
955 | 0 | return; |
956 | | |
957 | 0 | OUString sEntry = m_xWidget->get_text(m_nLastItemWithMenu); |
958 | |
|
959 | 0 | ReleaseFocus(); // It must be after getting entry pos! |
960 | 0 | Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue(u"Param"_ustr, sEntry), |
961 | 0 | comphelper::makePropertyValue(u"Family"_ustr, |
962 | 0 | sal_Int16( eStyleFamily )) }; |
963 | |
|
964 | 0 | const Reference<XDispatchProvider> xProvider(m_xFrame, UNO_QUERY); |
965 | 0 | if (rMenuIdent == "update") |
966 | 0 | { |
967 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:StyleUpdateByExample"_ustr, aArgs); |
968 | 0 | } |
969 | 0 | else if (rMenuIdent == "edit") |
970 | 0 | { |
971 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:EditStyle"_ustr, aArgs); |
972 | 0 | } |
973 | 0 | } |
974 | | |
975 | | IMPL_STATIC_LINK_NOARG(SvxStyleBox_Base, ShowMoreHdl, void*, void) |
976 | 0 | { |
977 | 0 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); |
978 | 0 | DBG_ASSERT( pViewFrm, "SvxStyleBox_Base::Select(): no viewframe" ); |
979 | 0 | if (!pViewFrm) |
980 | 0 | return; |
981 | 0 | pViewFrm->ShowChildWindow(SID_SIDEBAR); |
982 | 0 | ::sfx2::sidebar::Sidebar::ShowPanel(u"StyleListPanel", pViewFrm->GetFrame().GetFrameInterface(), true); |
983 | 0 | } |
984 | | |
985 | | IMPL_LINK(SvxStyleBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) |
986 | 0 | { |
987 | 0 | Select(rCombo.changed_by_direct_pick()); // only when picked from the list |
988 | 0 | } |
989 | | |
990 | | IMPL_LINK_NOARG(SvxStyleBox_Base, ActivateHdl, weld::ComboBox&, bool) |
991 | 0 | { |
992 | 0 | Select(true); |
993 | 0 | return true; |
994 | 0 | } |
995 | | |
996 | | void SvxStyleBox_Base::Select(bool bNonTravelSelect) |
997 | 0 | { |
998 | 0 | if (!bNonTravelSelect) |
999 | 0 | return; |
1000 | | |
1001 | 0 | OUString aSearchEntry(m_xWidget->get_active_text()); |
1002 | 0 | bool bDoIt = true, bClear = false; |
1003 | 0 | if( bInSpecialMode ) |
1004 | 0 | { |
1005 | 0 | if( aSearchEntry == aClearFormatKey && m_xWidget->get_active() == 0 ) |
1006 | 0 | { |
1007 | 0 | aSearchEntry = sDefaultStyle; |
1008 | 0 | bClear = true; |
1009 | | //not only apply default style but also call 'ClearFormatting' |
1010 | 0 | Sequence< PropertyValue > aEmptyVals; |
1011 | 0 | const Reference<XDispatchProvider> xProvider(m_xFrame, UNO_QUERY); |
1012 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:ResetAttributes"_ustr, aEmptyVals); |
1013 | 0 | } |
1014 | 0 | else if (aSearchEntry == aMoreKey && m_xWidget->get_active() == (m_xWidget->get_count() - 1)) |
1015 | 0 | { |
1016 | 0 | Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Base, ShowMoreHdl)); |
1017 | | //tdf#113214 change text back to previous entry |
1018 | 0 | set_active_or_entry_text(m_xWidget->get_saved_value()); |
1019 | 0 | bDoIt = false; |
1020 | 0 | } |
1021 | 0 | } |
1022 | | |
1023 | | //Do we need to create a new style? |
1024 | 0 | SfxObjectShell *pShell = SfxObjectShell::Current(); |
1025 | 0 | if (!pShell) |
1026 | 0 | return; |
1027 | | |
1028 | 0 | SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); |
1029 | 0 | SfxStyleSheetBase* pStyle = nullptr; |
1030 | |
|
1031 | 0 | bool bCreateNew = false; |
1032 | |
|
1033 | 0 | if ( pPool ) |
1034 | 0 | { |
1035 | 0 | pStyle = pPool->First(eStyleFamily); |
1036 | 0 | while ( pStyle && pStyle->GetName() != aSearchEntry ) |
1037 | 0 | pStyle = pPool->Next(); |
1038 | 0 | } |
1039 | |
|
1040 | 0 | if ( !pStyle ) |
1041 | 0 | { |
1042 | | // cannot find the style for whatever reason |
1043 | | // therefore create a new style |
1044 | 0 | bCreateNew = true; |
1045 | 0 | } |
1046 | | |
1047 | | /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. |
1048 | | This instance may be deleted in the meantime (i.e. when a dialog is opened |
1049 | | while in Dispatch()), accessing members will crash in this case. */ |
1050 | 0 | ReleaseFocus(); |
1051 | |
|
1052 | 0 | if( !bDoIt ) |
1053 | 0 | return; |
1054 | | |
1055 | 0 | if ( bClear ) |
1056 | 0 | set_active_or_entry_text(aSearchEntry); |
1057 | 0 | m_xWidget->save_value(); |
1058 | |
|
1059 | 0 | Sequence< PropertyValue > aArgs( 2 ); |
1060 | 0 | auto pArgs = aArgs.getArray(); |
1061 | 0 | pArgs[0].Value <<= aSearchEntry; |
1062 | 0 | pArgs[1].Name = "Family"; |
1063 | 0 | pArgs[1].Value <<= sal_Int16( eStyleFamily ); |
1064 | |
|
1065 | 0 | const Reference<XDispatchProvider> xProvider(m_xFrame, UNO_QUERY); |
1066 | 0 | if( bCreateNew ) |
1067 | 0 | { |
1068 | 0 | pArgs[0].Name = "Param"; |
1069 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:StyleNewByExample"_ustr, aArgs); |
1070 | 0 | } |
1071 | 0 | else |
1072 | 0 | { |
1073 | 0 | pArgs[0].Name = "Template"; |
1074 | 0 | SfxToolBoxControl::Dispatch(xProvider, m_aCommand, aArgs); |
1075 | 0 | } |
1076 | 0 | } |
1077 | | |
1078 | | void SvxStyleBox_Base::SetFamily( SfxStyleFamily eNewFamily ) |
1079 | 0 | { |
1080 | 0 | eStyleFamily = eNewFamily; |
1081 | 0 | } |
1082 | | |
1083 | | IMPL_LINK_NOARG(SvxStyleBox_Base, FocusOutHdl, weld::Widget&, void) |
1084 | 0 | { |
1085 | 0 | if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus |
1086 | 0 | set_active_or_entry_text(m_xWidget->get_saved_value()); |
1087 | 0 | } |
1088 | | |
1089 | | IMPL_LINK(SvxStyleBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) |
1090 | 0 | { |
1091 | 0 | return DoKeyInput(rKEvt); |
1092 | 0 | } |
1093 | | |
1094 | | bool SvxStyleBox_Base::DoKeyInput(const KeyEvent& rKEvt) |
1095 | 0 | { |
1096 | 0 | bool bHandled = false; |
1097 | |
|
1098 | 0 | sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); |
1099 | |
|
1100 | 0 | switch (nCode) |
1101 | 0 | { |
1102 | 0 | case KEY_TAB: |
1103 | 0 | bRelease = false; |
1104 | 0 | Select(true); |
1105 | 0 | break; |
1106 | 0 | case KEY_ESCAPE: |
1107 | 0 | set_active_or_entry_text(m_xWidget->get_saved_value()); |
1108 | 0 | if (!m_rCtrl.IsInSidebar()) |
1109 | 0 | { |
1110 | 0 | ReleaseFocus(); |
1111 | 0 | bHandled = true; |
1112 | 0 | } |
1113 | 0 | break; |
1114 | 0 | } |
1115 | | |
1116 | 0 | return bHandled; |
1117 | 0 | } |
1118 | | |
1119 | | bool SvxStyleBox_Impl::DoKeyInput(const KeyEvent& rKEvt) |
1120 | 0 | { |
1121 | 0 | return SvxStyleBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); |
1122 | 0 | } |
1123 | | |
1124 | | void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) |
1125 | 0 | { |
1126 | 0 | if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && |
1127 | 0 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) |
1128 | 0 | { |
1129 | 0 | SetOptimalSize(); |
1130 | 0 | } |
1131 | |
|
1132 | 0 | InterimItemWindow::DataChanged( rDCEvt ); |
1133 | 0 | } |
1134 | | |
1135 | | void SvxStyleBox_Impl::SetOptimalSize() |
1136 | 0 | { |
1137 | | // set width in chars low so the size request will not be overridden |
1138 | 0 | m_xWidget->set_entry_width_chars(1); |
1139 | | // tdf#132338 purely using this calculation to keep things their traditional width |
1140 | 0 | Size aSize(LogicToPixel(Size((COMBO_WIDTH_IN_CHARS + 3) * 4, 0), MapMode(MapUnit::MapAppFont))); |
1141 | 0 | m_xWidget->set_size_request(aSize.Width(), -1); |
1142 | |
|
1143 | 0 | SetSizePixel(get_preferred_size()); |
1144 | 0 | } |
1145 | | |
1146 | | namespace |
1147 | | { |
1148 | | std::vector<ScriptInfo> CheckScript(const OUString &rStyleName) |
1149 | 0 | { |
1150 | 0 | assert(!rStyleName.isEmpty()); // must have a preview text here! |
1151 | |
|
1152 | 0 | std::vector<ScriptInfo> aScriptChanges; |
1153 | |
|
1154 | 0 | auto aEditEngine = EditEngine(nullptr); |
1155 | 0 | aEditEngine.SetText(rStyleName); |
1156 | |
|
1157 | 0 | auto aScript = aEditEngine.GetScriptType({ 0, 0, 0, 0 }); |
1158 | 0 | for (sal_Int32 i = 1; i <= rStyleName.getLength(); i++) |
1159 | 0 | { |
1160 | 0 | auto aNextScript = aEditEngine.GetScriptType({ 0, i, 0, i }); |
1161 | 0 | if (aNextScript != aScript || i == rStyleName.getLength()) |
1162 | 0 | aScriptChanges.emplace_back(aScript, i); |
1163 | 0 | aScript = aNextScript; |
1164 | 0 | } |
1165 | |
|
1166 | 0 | return aScriptChanges; |
1167 | 0 | } |
1168 | | } |
1169 | | |
1170 | | tools::Rectangle SvxStyleBox_Base::CalcBoundRect(vcl::RenderContext& rRenderContext, const OUString &rStyleName, std::vector<ScriptInfo>& rScriptChanges, double fRatio) |
1171 | 0 | { |
1172 | 0 | tools::Rectangle aTextRect; |
1173 | |
|
1174 | 0 | SvtScriptType aScript; |
1175 | 0 | sal_uInt16 nIdx = 0; |
1176 | 0 | sal_Int32 nStart = 0; |
1177 | 0 | sal_Int32 nEnd; |
1178 | 0 | size_t nCnt = rScriptChanges.size(); |
1179 | |
|
1180 | 0 | if (nCnt) |
1181 | 0 | { |
1182 | 0 | nEnd = rScriptChanges[nIdx].changePos; |
1183 | 0 | aScript = rScriptChanges[nIdx].scriptType; |
1184 | 0 | } |
1185 | 0 | else |
1186 | 0 | { |
1187 | 0 | nEnd = rStyleName.getLength(); |
1188 | 0 | aScript = SvtScriptType::LATIN; |
1189 | 0 | } |
1190 | |
|
1191 | 0 | do |
1192 | 0 | { |
1193 | 0 | auto oFont = (aScript == SvtScriptType::ASIAN) ? |
1194 | 0 | m_oCJKFont : |
1195 | 0 | ((aScript == SvtScriptType::COMPLEX) ? |
1196 | 0 | m_oCTLFont : |
1197 | 0 | m_oFont); |
1198 | |
|
1199 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FONT); |
1200 | |
|
1201 | 0 | if (oFont) |
1202 | 0 | rRenderContext.SetFont(*oFont); |
1203 | |
|
1204 | 0 | if (fRatio != 1) |
1205 | 0 | { |
1206 | 0 | vcl::Font aFont(rRenderContext.GetFont()); |
1207 | 0 | Size aPixelSize(aFont.GetFontSize()); |
1208 | 0 | aPixelSize.setWidth(aPixelSize.Width() * fRatio); |
1209 | 0 | aPixelSize.setHeight(aPixelSize.Height() * fRatio); |
1210 | 0 | aFont.SetFontSize(aPixelSize); |
1211 | 0 | rRenderContext.SetFont(aFont); |
1212 | 0 | } |
1213 | |
|
1214 | 0 | tools::Rectangle aRect; |
1215 | 0 | rRenderContext.GetTextBoundRect(aRect, rStyleName, nStart, nStart, nEnd - nStart); |
1216 | 0 | aTextRect = aTextRect.Union(aRect); |
1217 | |
|
1218 | 0 | tools::Long nWidth = rRenderContext.GetTextWidth(rStyleName, nStart, nEnd - nStart); |
1219 | |
|
1220 | 0 | if (nIdx >= rScriptChanges.size()) |
1221 | 0 | break; |
1222 | | |
1223 | 0 | rScriptChanges[nIdx++].textWidth = nWidth; |
1224 | |
|
1225 | 0 | if (nEnd < rStyleName.getLength() && nIdx < nCnt) |
1226 | 0 | { |
1227 | 0 | nStart = nEnd; |
1228 | 0 | nEnd = rScriptChanges[nIdx].changePos; |
1229 | 0 | aScript = rScriptChanges[nIdx].scriptType; |
1230 | 0 | } |
1231 | 0 | else |
1232 | 0 | break; |
1233 | 0 | } |
1234 | 0 | while(true); |
1235 | |
|
1236 | 0 | return aTextRect; |
1237 | 0 | } |
1238 | | |
1239 | | void SvxStyleBox_Base::UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const tools::Rectangle& rTextRect, const OUString &rStyleName, const std::vector<ScriptInfo>& rScriptChanges) |
1240 | 0 | { |
1241 | | // IMG_TXT_DISTANCE in ilstbox.hxx is 6, then 1 is added as |
1242 | | // nBorder, and we are adding 1 in order to look better when |
1243 | | // italics is present |
1244 | 0 | const int nLeftDistance = 8; |
1245 | |
|
1246 | 0 | Point aPos(rRect.TopLeft()); |
1247 | 0 | aPos.AdjustX(nLeftDistance ); |
1248 | |
|
1249 | 0 | double fRatio = 1; |
1250 | 0 | if (rTextRect.Bottom() > rRect.GetHeight()) |
1251 | 0 | fRatio = static_cast<double>(rRect.GetHeight()) / rTextRect.Bottom(); |
1252 | 0 | else |
1253 | 0 | aPos.AdjustY((rRect.GetHeight() - rTextRect.Bottom()) / 2); |
1254 | |
|
1255 | 0 | SvtScriptType aScript; |
1256 | 0 | sal_uInt16 nIdx = 0; |
1257 | 0 | sal_Int32 nStart = 0; |
1258 | 0 | sal_Int32 nEnd; |
1259 | 0 | size_t nCnt = rScriptChanges.size(); |
1260 | |
|
1261 | 0 | if (nCnt) |
1262 | 0 | { |
1263 | 0 | nEnd = rScriptChanges[nIdx].changePos; |
1264 | 0 | aScript = rScriptChanges[nIdx].scriptType; |
1265 | 0 | } |
1266 | 0 | else |
1267 | 0 | { |
1268 | 0 | nEnd = rStyleName.getLength(); |
1269 | 0 | aScript = SvtScriptType::LATIN; |
1270 | 0 | } |
1271 | | |
1272 | |
|
1273 | 0 | do |
1274 | 0 | { |
1275 | 0 | auto oFont = (aScript == SvtScriptType::ASIAN) ? |
1276 | 0 | m_oCJKFont : |
1277 | 0 | ((aScript == SvtScriptType::COMPLEX) ? |
1278 | 0 | m_oCTLFont : |
1279 | 0 | m_oFont); |
1280 | |
|
1281 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FONT); |
1282 | |
|
1283 | 0 | if (oFont) |
1284 | 0 | rRenderContext.SetFont(*oFont); |
1285 | |
|
1286 | 0 | if (fRatio != 1) |
1287 | 0 | { |
1288 | 0 | vcl::Font aFont(rRenderContext.GetFont()); |
1289 | 0 | Size aPixelSize(aFont.GetFontSize()); |
1290 | 0 | aPixelSize.setWidth(aPixelSize.Width() * fRatio); |
1291 | 0 | aPixelSize.setHeight(aPixelSize.Height() * fRatio); |
1292 | 0 | aFont.SetFontSize(aPixelSize); |
1293 | 0 | rRenderContext.SetFont(aFont); |
1294 | 0 | } |
1295 | |
|
1296 | 0 | rRenderContext.DrawText(aPos, rStyleName, nStart, nEnd - nStart); |
1297 | |
|
1298 | 0 | aPos.AdjustX(rScriptChanges[nIdx++].textWidth * fRatio); |
1299 | 0 | if (nEnd < rStyleName.getLength() && nIdx < nCnt) |
1300 | 0 | { |
1301 | 0 | nStart = nEnd; |
1302 | 0 | nEnd = rScriptChanges[nIdx].changePos; |
1303 | 0 | aScript = rScriptChanges[nIdx].scriptType; |
1304 | 0 | } |
1305 | 0 | else |
1306 | 0 | break; |
1307 | 0 | } |
1308 | 0 | while(true); |
1309 | 0 | } |
1310 | | |
1311 | | static bool GetWhich(const SfxItemSet& rSet, sal_uInt16 nSlot, sal_uInt16& rWhich) |
1312 | 0 | { |
1313 | 0 | rWhich = rSet.GetPool()->GetWhichIDFromSlotID(nSlot); |
1314 | 0 | return rSet.GetItemState(rWhich) >= SfxItemState::DEFAULT; |
1315 | 0 | } |
1316 | | |
1317 | | static bool SetFont(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont) |
1318 | 0 | { |
1319 | 0 | sal_uInt16 nWhich; |
1320 | 0 | if (GetWhich(rSet, nSlot, nWhich)) |
1321 | 0 | { |
1322 | 0 | const auto& rFontItem = static_cast<const SvxFontItem&>(rSet.Get(nWhich)); |
1323 | 0 | rFont.SetFamilyName(rFontItem.GetFamilyName()); |
1324 | 0 | rFont.SetStyleName(rFontItem.GetStyleName()); |
1325 | 0 | return true; |
1326 | 0 | } |
1327 | 0 | return false; |
1328 | 0 | } |
1329 | | |
1330 | | static bool SetFontSize(const vcl::RenderContext& rRenderContext, const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont) |
1331 | 0 | { |
1332 | 0 | sal_uInt16 nWhich; |
1333 | 0 | if (GetWhich(rSet, nSlot, nWhich)) |
1334 | 0 | { |
1335 | 0 | const auto& rFontHeightItem = static_cast<const SvxFontHeightItem&>(rSet.Get(nWhich)); |
1336 | 0 | if (SfxObjectShell *pShell = SfxObjectShell::Current()) |
1337 | 0 | { |
1338 | 0 | Size aFontSize(0, rFontHeightItem.GetHeight()); |
1339 | 0 | Size aPixelSize(rRenderContext.LogicToPixel(aFontSize, MapMode(pShell->GetMapUnit()))); |
1340 | 0 | rFont.SetFontSize(aPixelSize); |
1341 | 0 | return true; |
1342 | 0 | } |
1343 | 0 | } |
1344 | 0 | return false; |
1345 | 0 | } |
1346 | | |
1347 | | static void SetFontStyle(const SfxItemSet& rSet, sal_uInt16 nPosture, sal_uInt16 nWeight, SvxFont& rFont) |
1348 | 0 | { |
1349 | 0 | sal_uInt16 nWhich; |
1350 | 0 | if (GetWhich(rSet, nPosture, nWhich)) |
1351 | 0 | { |
1352 | 0 | const auto& rItem = static_cast<const SvxPostureItem&>(rSet.Get(nWhich)); |
1353 | 0 | rFont.SetItalic(rItem.GetPosture()); |
1354 | 0 | } |
1355 | |
|
1356 | 0 | if (GetWhich(rSet, nWeight, nWhich)) |
1357 | 0 | { |
1358 | 0 | const auto& rItem = static_cast<const SvxWeightItem&>(rSet.Get(nWhich)); |
1359 | 0 | rFont.SetWeight(rItem.GetWeight()); |
1360 | 0 | } |
1361 | 0 | } |
1362 | | |
1363 | | void SvxStyleBox_Base::SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, std::u16string_view rStyleName, bool bIsNotSelected) |
1364 | 0 | { |
1365 | 0 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
1366 | 0 | if (!bIsNotSelected) |
1367 | 0 | rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); |
1368 | 0 | else |
1369 | 0 | rRenderContext.SetTextColor(rStyleSettings.GetWindowTextColor()); |
1370 | | |
1371 | | // handle the push-button |
1372 | 0 | if (!bIsNotSelected) |
1373 | 0 | { |
1374 | 0 | if (nItem == 0 || nItem == m_xWidget->get_count() - 1) |
1375 | 0 | m_xWidget->set_item_menu(OUString::number(nItem), nullptr); |
1376 | 0 | else |
1377 | 0 | { |
1378 | 0 | m_nLastItemWithMenu = nItem; |
1379 | 0 | m_xWidget->set_item_menu(OUString::number(nItem), m_xMenu.get()); |
1380 | 0 | } |
1381 | 0 | } |
1382 | |
|
1383 | 0 | SfxObjectShell *pShell = SfxObjectShell::Current(); |
1384 | 0 | if (!pShell) |
1385 | 0 | return; |
1386 | | |
1387 | 0 | SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); |
1388 | 0 | if (!pPool) |
1389 | 0 | return; |
1390 | | |
1391 | 0 | SfxStyleSheetBase* pStyle = pPool->First(eStyleFamily); |
1392 | 0 | SfxStyleSheetBase* pDefaultStyle = nullptr; |
1393 | 0 | while (pStyle) |
1394 | 0 | { |
1395 | 0 | if (pStyle->GetName() == rStyleName) |
1396 | 0 | break; |
1397 | 0 | if (pStyle->GetName() == sDefaultStyle) |
1398 | 0 | pDefaultStyle = pStyle; |
1399 | 0 | pStyle = pPool->Next(); |
1400 | 0 | } |
1401 | |
|
1402 | 0 | if (!pStyle) |
1403 | 0 | pStyle = pDefaultStyle; |
1404 | 0 | if (!pStyle ) |
1405 | 0 | return; |
1406 | | |
1407 | 0 | std::optional<SfxItemSet> const pItemSet(pStyle->GetItemSetForPreview()); |
1408 | 0 | if (!pItemSet) return; |
1409 | | |
1410 | 0 | SvxFont aFont; |
1411 | 0 | SvxFont aCJKFont; |
1412 | 0 | SvxFont aCTLFont; |
1413 | |
|
1414 | 0 | SetFontStyle(*pItemSet, SID_ATTR_CHAR_POSTURE, SID_ATTR_CHAR_WEIGHT, aFont); |
1415 | 0 | SetFontStyle(*pItemSet, SID_ATTR_CHAR_CJK_POSTURE, SID_ATTR_CHAR_CJK_WEIGHT, aCJKFont); |
1416 | 0 | SetFontStyle(*pItemSet, SID_ATTR_CHAR_CTL_POSTURE, SID_ATTR_CHAR_CTL_WEIGHT, aCTLFont); |
1417 | |
|
1418 | 0 | if (const SvxContourItem *pContourItem = pItemSet->GetItem( SID_ATTR_CHAR_CONTOUR )) |
1419 | 0 | { |
1420 | 0 | auto aVal = pContourItem->GetValue(); |
1421 | 0 | aFont.SetOutline(aVal); |
1422 | 0 | aCJKFont.SetOutline(aVal); |
1423 | 0 | aCTLFont.SetOutline(aVal); |
1424 | 0 | } |
1425 | |
|
1426 | 0 | if (const SvxShadowedItem* pShadowedItem = pItemSet->GetItem( SID_ATTR_CHAR_SHADOWED )) |
1427 | 0 | { |
1428 | 0 | auto aVal = pShadowedItem->GetValue(); |
1429 | 0 | aFont.SetShadow(aVal); |
1430 | 0 | aCJKFont.SetShadow(aVal); |
1431 | 0 | aCTLFont.SetShadow(aVal); |
1432 | 0 | } |
1433 | |
|
1434 | 0 | if (const SvxCharReliefItem* pCharReliefItem = pItemSet->GetItem( SID_ATTR_CHAR_RELIEF )) |
1435 | 0 | { |
1436 | 0 | auto aVal = pCharReliefItem->GetValue(); |
1437 | 0 | aFont.SetRelief(aVal); |
1438 | 0 | aCJKFont.SetRelief(aVal); |
1439 | 0 | aCTLFont.SetRelief(aVal); |
1440 | 0 | } |
1441 | |
|
1442 | 0 | if (const SvxUnderlineItem* pUnderlineItem = pItemSet->GetItem( SID_ATTR_CHAR_UNDERLINE )) |
1443 | 0 | { |
1444 | 0 | auto aVal = pUnderlineItem->GetLineStyle(); |
1445 | 0 | aFont.SetUnderline(aVal); |
1446 | 0 | aCJKFont.SetUnderline(aVal); |
1447 | 0 | aCTLFont.SetUnderline(aVal); |
1448 | 0 | } |
1449 | |
|
1450 | 0 | if (const SvxOverlineItem* pOverlineItem = pItemSet->GetItem( SID_ATTR_CHAR_OVERLINE )) |
1451 | 0 | { |
1452 | 0 | auto aVal = pOverlineItem->GetValue(); |
1453 | 0 | aFont.SetOverline(aVal); |
1454 | 0 | aCJKFont.SetOverline(aVal); |
1455 | 0 | aCTLFont.SetOverline(aVal); |
1456 | 0 | } |
1457 | |
|
1458 | 0 | if (const SvxCrossedOutItem* pCrossedOutItem = pItemSet->GetItem( SID_ATTR_CHAR_STRIKEOUT )) |
1459 | 0 | { |
1460 | 0 | auto aVal = pCrossedOutItem->GetStrikeout(); |
1461 | 0 | aFont.SetStrikeout(aVal); |
1462 | 0 | aCJKFont.SetStrikeout(aVal); |
1463 | 0 | aCTLFont.SetStrikeout(aVal); |
1464 | 0 | } |
1465 | |
|
1466 | 0 | if (const SvxCaseMapItem* pCaseMapItem = pItemSet->GetItem( SID_ATTR_CHAR_CASEMAP )) |
1467 | 0 | { |
1468 | 0 | auto aVal = pCaseMapItem->GetCaseMap(); |
1469 | 0 | aFont.SetCaseMap(aVal); |
1470 | 0 | aCJKFont.SetCaseMap(aVal); |
1471 | 0 | aCTLFont.SetCaseMap(aVal); |
1472 | 0 | } |
1473 | |
|
1474 | 0 | if (const SvxEmphasisMarkItem* pEmphasisMarkItem = pItemSet->GetItem( SID_ATTR_CHAR_EMPHASISMARK )) |
1475 | 0 | { |
1476 | 0 | auto aVal = pEmphasisMarkItem->GetEmphasisMark(); |
1477 | 0 | aFont.SetEmphasisMark(aVal); |
1478 | 0 | aCJKFont.SetEmphasisMark(aVal); |
1479 | 0 | aCTLFont.SetEmphasisMark(aVal); |
1480 | 0 | } |
1481 | | |
1482 | | // setup the device & draw |
1483 | 0 | Color aFontCol = COL_AUTO, aBackCol = COL_AUTO; |
1484 | |
|
1485 | 0 | const SvxColorItem* pColorItem = pItemSet->GetItem( SID_ATTR_CHAR_COLOR ); |
1486 | | // text color, when nothing is selected |
1487 | 0 | if ( pColorItem && bIsNotSelected) |
1488 | 0 | aFontCol = pColorItem->GetValue(); |
1489 | |
|
1490 | 0 | drawing::FillStyle style = drawing::FillStyle_NONE; |
1491 | | // which kind of Fill style is selected |
1492 | 0 | const XFillStyleItem* pFillStyleItem = pItemSet->GetItem( XATTR_FILLSTYLE ); |
1493 | | // only when ok and not selected |
1494 | 0 | if ( pFillStyleItem && bIsNotSelected) |
1495 | 0 | style = pFillStyleItem->GetValue(); |
1496 | |
|
1497 | 0 | switch(style) |
1498 | 0 | { |
1499 | 0 | case drawing::FillStyle_SOLID: |
1500 | 0 | { |
1501 | | // set background color |
1502 | 0 | if (const XFillColorItem* pFillColorItem = pItemSet->GetItem( XATTR_FILLCOLOR )) |
1503 | 0 | aBackCol = pFillColorItem->GetColorValue(); |
1504 | |
|
1505 | 0 | if ( aBackCol != COL_AUTO ) |
1506 | 0 | { |
1507 | 0 | rRenderContext.SetFillColor(aBackCol); |
1508 | 0 | rRenderContext.DrawRect(rRect); |
1509 | 0 | } |
1510 | 0 | } |
1511 | 0 | break; |
1512 | | |
1513 | 0 | default: break; |
1514 | | //TODO Draw the other background styles: gradient, hatching and bitmap |
1515 | 0 | } |
1516 | | |
1517 | | // when the font and background color are too similar, adjust the Font-Color |
1518 | 0 | if( (aFontCol != COL_AUTO) || (aBackCol != COL_AUTO) ) |
1519 | 0 | aFontCol = TestColorsVisible(aFontCol, (aBackCol != COL_AUTO) ? aBackCol : rRenderContext.GetBackground().GetColor()); |
1520 | | |
1521 | | // set text color |
1522 | 0 | if ( aFontCol != COL_AUTO ) |
1523 | 0 | rRenderContext.SetTextColor(aFontCol); |
1524 | |
|
1525 | 0 | if (SetFont(*pItemSet, SID_ATTR_CHAR_FONT, aFont) && |
1526 | 0 | SetFontSize(rRenderContext, *pItemSet, SID_ATTR_CHAR_FONTHEIGHT, aFont)) |
1527 | 0 | m_oFont = aFont; |
1528 | |
|
1529 | 0 | if (SetFont(*pItemSet, SID_ATTR_CHAR_CJK_FONT, aCJKFont) && |
1530 | 0 | SetFontSize(rRenderContext, *pItemSet, SID_ATTR_CHAR_CJK_FONTHEIGHT, aCJKFont)) |
1531 | 0 | m_oCJKFont = aCJKFont; |
1532 | |
|
1533 | 0 | if (SetFont(*pItemSet, SID_ATTR_CHAR_CTL_FONT, aCTLFont) && |
1534 | 0 | SetFontSize(rRenderContext, *pItemSet, SID_ATTR_CHAR_CTL_FONTHEIGHT, aCTLFont)) |
1535 | 0 | m_oCTLFont = aCTLFont; |
1536 | 0 | } |
1537 | | |
1538 | | IMPL_LINK(SvxStyleBox_Base, CustomRenderHdl, weld::ComboBox::render_args, aPayload, void) |
1539 | 0 | { |
1540 | 0 | vcl::RenderContext& rRenderContext = std::get<0>(aPayload); |
1541 | 0 | const ::tools::Rectangle& rRect = std::get<1>(aPayload); |
1542 | 0 | bool bSelected = std::get<2>(aPayload); |
1543 | 0 | const OUString& rId = std::get<3>(aPayload); |
1544 | |
|
1545 | 0 | sal_uInt32 nIndex = rId.toUInt32(); |
1546 | |
|
1547 | 0 | OUString aStyleName(m_xWidget->get_text(nIndex)); |
1548 | |
|
1549 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR); |
1550 | |
|
1551 | 0 | SetupEntry(rRenderContext, nIndex, rRect, aStyleName, !bSelected); |
1552 | 0 | auto aScriptChanges = CheckScript(aStyleName); |
1553 | 0 | auto aTextRect = CalcBoundRect(rRenderContext, aStyleName, aScriptChanges); |
1554 | 0 | UserDrawEntry(rRenderContext, rRect, aTextRect, aStyleName, aScriptChanges); |
1555 | 0 | } |
1556 | | |
1557 | | void SvxStyleBox_Base::CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext) |
1558 | 0 | { |
1559 | 0 | if (m_nMaxUserDrawFontWidth) |
1560 | 0 | return; |
1561 | | |
1562 | 0 | tools::Long nMaxNormalFontWidth = 0; |
1563 | 0 | sal_Int32 nEntryCount = m_xWidget->get_count(); |
1564 | 0 | for (sal_Int32 i = 0; i < nEntryCount; ++i) |
1565 | 0 | { |
1566 | 0 | OUString sStyleName(get_text(i)); |
1567 | 0 | tools::Rectangle aTextRectForDefaultFont; |
1568 | 0 | rRenderContext.GetTextBoundRect(aTextRectForDefaultFont, sStyleName); |
1569 | |
|
1570 | 0 | const tools::Long nWidth = aTextRectForDefaultFont.GetWidth(); |
1571 | |
|
1572 | 0 | nMaxNormalFontWidth = std::max(nWidth, nMaxNormalFontWidth); |
1573 | 0 | } |
1574 | |
|
1575 | 0 | m_nMaxUserDrawFontWidth = nMaxNormalFontWidth; |
1576 | 0 | for (sal_Int32 i = 1; i < nEntryCount-1; ++i) |
1577 | 0 | { |
1578 | 0 | OUString sStyleName(get_text(i)); |
1579 | |
|
1580 | 0 | if (sStyleName.isEmpty()) |
1581 | 0 | continue; |
1582 | | |
1583 | 0 | rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR); |
1584 | 0 | SetupEntry(rRenderContext, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true); |
1585 | 0 | auto aScriptChanges = CheckScript(sStyleName); |
1586 | 0 | tools::Rectangle aTextRectForActualFont = CalcBoundRect(rRenderContext, sStyleName, aScriptChanges); |
1587 | 0 | if (aTextRectForActualFont.Bottom() > ITEM_HEIGHT) |
1588 | 0 | { |
1589 | | //Font didn't fit, re-calculate with adjustment ratio. |
1590 | 0 | double fRatio = static_cast<double>(ITEM_HEIGHT) / aTextRectForActualFont.Bottom(); |
1591 | 0 | aTextRectForActualFont = CalcBoundRect(rRenderContext, sStyleName, aScriptChanges, fRatio); |
1592 | 0 | } |
1593 | 0 | rRenderContext.Pop(); |
1594 | |
|
1595 | 0 | const int nWidth = aTextRectForActualFont.GetWidth() + m_xWidget->get_menu_button_width() + BUTTON_PADDING; |
1596 | |
|
1597 | 0 | m_nMaxUserDrawFontWidth = std::max(nWidth, m_nMaxUserDrawFontWidth); |
1598 | 0 | } |
1599 | 0 | } |
1600 | | |
1601 | | // test is the color between Font- and background-color to be identify |
1602 | | // return is always the Font-Color |
1603 | | // when both light or dark, change the Contrast |
1604 | | // in other case do not change the origin color |
1605 | | // when the color is R=G=B=128 the DecreaseContrast make 128 the need an exception |
1606 | | Color SvxStyleBox_Base::TestColorsVisible(const Color &FontCol, const Color &BackCol) |
1607 | 0 | { |
1608 | 0 | constexpr sal_uInt8 ChgVal = 60; // increase/decrease the Contrast |
1609 | |
|
1610 | 0 | Color retCol = FontCol; |
1611 | 0 | if ((FontCol.IsDark() == BackCol.IsDark()) && (FontCol.IsBright() == BackCol.IsBright())) |
1612 | 0 | { |
1613 | 0 | sal_uInt8 lumi = retCol.GetLuminance(); |
1614 | |
|
1615 | 0 | if((lumi > 120) && (lumi < 140)) |
1616 | 0 | retCol.DecreaseLuminance(ChgVal / 2); |
1617 | 0 | else |
1618 | 0 | retCol.DecreaseContrast(ChgVal); |
1619 | 0 | } |
1620 | |
|
1621 | 0 | return retCol; |
1622 | 0 | } |
1623 | | |
1624 | | IMPL_LINK(SvxStyleBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void) |
1625 | 0 | { |
1626 | 0 | if (!m_xWidget) |
1627 | 0 | return; |
1628 | | |
1629 | 0 | { |
1630 | 0 | auto entriesNode = rJsonWriter.startNode("entries"); |
1631 | 0 | for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i) |
1632 | 0 | { |
1633 | 0 | auto entryNode = rJsonWriter.startNode(""); |
1634 | 0 | rJsonWriter.put("", m_xWidget->get_text(i)); |
1635 | 0 | } |
1636 | 0 | } |
1637 | |
|
1638 | 0 | int nActive = m_xWidget->get_active(); |
1639 | 0 | rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nActive == -1 ? 0 : 1)); |
1640 | |
|
1641 | 0 | { |
1642 | 0 | auto selectedNode = rJsonWriter.startNode("selectedEntries"); |
1643 | 0 | if (nActive != -1) |
1644 | 0 | { |
1645 | 0 | auto node = rJsonWriter.startNode(""); |
1646 | 0 | rJsonWriter.put("", static_cast<sal_Int32>(nActive)); |
1647 | 0 | } |
1648 | 0 | } |
1649 | |
|
1650 | 0 | rJsonWriter.put("command", ".uno:StyleApply"); |
1651 | 0 | } |
1652 | | |
1653 | | static bool lcl_GetDocFontList(const FontList** ppFontList, SvxFontNameBox_Base& rBox) |
1654 | 0 | { |
1655 | 0 | bool bChanged = false; |
1656 | 0 | const SfxObjectShell* pDocSh = SfxObjectShell::Current(); |
1657 | 0 | const SvxFontListItem* pFontListItem = nullptr; |
1658 | |
|
1659 | 0 | if ( pDocSh ) |
1660 | 0 | pFontListItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ); |
1661 | 0 | else |
1662 | 0 | { |
1663 | 0 | ::std::unique_ptr<FontList> aFontList(new FontList(Application::GetDefaultDevice())); |
1664 | 0 | *ppFontList = aFontList.get(); |
1665 | 0 | rBox.SetOwnFontList(std::move(aFontList)); |
1666 | 0 | bChanged = true; |
1667 | 0 | } |
1668 | |
|
1669 | 0 | if ( pFontListItem ) |
1670 | 0 | { |
1671 | 0 | const FontList* pNewFontList = pFontListItem->GetFontList(); |
1672 | 0 | DBG_ASSERT( pNewFontList, "Doc-FontList not available!" ); |
1673 | | |
1674 | | // No old list, but a new list |
1675 | 0 | if ( !*ppFontList && pNewFontList ) |
1676 | 0 | { |
1677 | | // => take over |
1678 | 0 | *ppFontList = pNewFontList; |
1679 | 0 | bChanged = true; |
1680 | 0 | } |
1681 | 0 | else |
1682 | 0 | { |
1683 | | // Comparing the font lists is not perfect. |
1684 | | // When you change the font list in the Doc, you can track |
1685 | | // changes here only on the Listbox, because ppFontList |
1686 | | // has already been updated. |
1687 | 0 | bChanged = !pNewFontList || |
1688 | 0 | *ppFontList != pNewFontList || |
1689 | 0 | rBox.GetListCount() != pNewFontList->GetFontNameCount(); |
1690 | | // HACK: Comparing is incomplete |
1691 | |
|
1692 | 0 | if ( bChanged ) |
1693 | 0 | *ppFontList = pNewFontList; |
1694 | 0 | } |
1695 | |
|
1696 | 0 | rBox.set_sensitive(true); |
1697 | 0 | } |
1698 | 0 | else if ( pDocSh || !ppFontList) |
1699 | 0 | { |
1700 | | // Disable box only when we have a SfxObjectShell and didn't get a font list OR |
1701 | | // we don't have a SfxObjectShell and no current font list. |
1702 | | // It's possible that we currently have no SfxObjectShell, but a current font list. |
1703 | | // See #i58471: When a user set the focus into the font name combo box and opens |
1704 | | // the help window with F1. After closing the help window, we disable the font name |
1705 | | // combo box. The SfxObjectShell::Current() method returns in that case zero. But the |
1706 | | // font list hasn't changed and therefore the combo box shouldn't be disabled! |
1707 | 0 | rBox.set_sensitive(false); |
1708 | 0 | } |
1709 | | |
1710 | | // Fill the FontBox, also the new list if necessary |
1711 | 0 | if ( bChanged ) |
1712 | 0 | { |
1713 | 0 | if (ppFontList && *ppFontList) |
1714 | 0 | rBox.Fill( *ppFontList ); |
1715 | 0 | else |
1716 | 0 | rBox.Clear(); |
1717 | 0 | } |
1718 | 0 | return bChanged; |
1719 | 0 | } |
1720 | | |
1721 | | SvxFontNameBox_Base::SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget, |
1722 | | const Reference<XFrame>& rFrame, |
1723 | | SvxFontNameToolBoxControl& rCtrl) |
1724 | 0 | : m_xListener(new comphelper::ConfigurationListener(u"/org.openoffice.Office.Common/Font/View"_ustr)) |
1725 | 0 | , m_aWYSIWYG(m_xListener, u"ShowFontBoxWYSIWYG"_ustr, *this) |
1726 | 0 | , m_aHistory(m_xListener, u"History"_ustr, *this) |
1727 | 0 | , m_rCtrl(rCtrl) |
1728 | 0 | , m_xWidget(new FontNameBox(std::move(xWidget))) |
1729 | 0 | , pFontList(nullptr) |
1730 | 0 | , nFtCount(0) |
1731 | 0 | , bRelease(true) |
1732 | 0 | , m_xFrame(rFrame) |
1733 | 0 | , mbCheckingUnknownFont(false) |
1734 | 0 | , mbDropDownActive(false) |
1735 | 0 | { |
1736 | 0 | EnableControls(); |
1737 | |
|
1738 | 0 | m_xWidget->connect_changed(LINK(this, SvxFontNameBox_Base, SelectHdl)); |
1739 | 0 | m_xWidget->connect_key_press(LINK(this, SvxFontNameBox_Base, KeyInputHdl)); |
1740 | 0 | m_xWidget->connect_entry_activate(LINK(this, SvxFontNameBox_Base, ActivateHdl)); |
1741 | 0 | m_xWidget->connect_focus_in(LINK(this, SvxFontNameBox_Base, FocusInHdl)); |
1742 | 0 | m_xWidget->connect_focus_out(LINK(this, SvxFontNameBox_Base, FocusOutHdl)); |
1743 | 0 | m_xWidget->connect_popup_toggled(LINK(this, SvxFontNameBox_Base, PopupToggledHdl)); |
1744 | 0 | m_xWidget->connect_live_preview(LINK(this, SvxFontNameBox_Base, LivePreviewHdl)); |
1745 | 0 | m_xWidget->connect_get_property_tree(LINK(this, SvxFontNameBox_Base, DumpAsPropertyTreeHdl)); |
1746 | |
|
1747 | 0 | m_xWidget->set_entry_width_chars(COMBO_WIDTH_IN_CHARS + 5); |
1748 | 0 | } |
1749 | | |
1750 | | SvxFontNameBox_Impl::SvxFontNameBox_Impl(vcl::Window* pParent, const Reference<XFrame>& rFrame, |
1751 | | SvxFontNameToolBoxControl& rCtrl) |
1752 | 0 | : InterimItemWindow(pParent, u"svx/ui/fontnamebox.ui"_ustr, u"FontNameBox"_ustr, true, reinterpret_cast<sal_uInt64>(SfxViewShell::Current())) |
1753 | 0 | , SvxFontNameBox_Base(m_xBuilder->weld_combo_box(u"fontnamecombobox"_ustr), rFrame, rCtrl) |
1754 | 0 | { |
1755 | 0 | set_id(u"fontnamecombobox"_ustr); |
1756 | 0 | SetOptimalSize(); |
1757 | 0 | } |
1758 | | |
1759 | | void SvxFontNameBox_Base::FillList() |
1760 | 0 | { |
1761 | 0 | if (!m_xWidget) // e.g. disposed |
1762 | 0 | return; |
1763 | | // Save old Selection, set back in the end |
1764 | 0 | int nStartPos, nEndPos; |
1765 | 0 | m_xWidget->get_entry_selection_bounds(nStartPos, nEndPos); |
1766 | | |
1767 | | // Did Doc-Fontlist change? |
1768 | 0 | lcl_GetDocFontList(&pFontList, *this); |
1769 | |
|
1770 | 0 | m_xWidget->select_entry_region(nStartPos, nEndPos); |
1771 | 0 | } |
1772 | | |
1773 | | bool SvxFontNameBox_Base::CheckFontIsAvailable(std::u16string_view fontname) |
1774 | 0 | { |
1775 | 0 | lcl_GetDocFontList(&pFontList, *this); |
1776 | 0 | return pFontList && pFontList->IsAvailable(fontname); |
1777 | 0 | } |
1778 | | |
1779 | | void SvxFontNameBox_Base::CheckAndMarkUnknownFont() |
1780 | 0 | { |
1781 | 0 | if (mbCheckingUnknownFont) //tdf#117537 block rentry |
1782 | 0 | return; |
1783 | 0 | mbCheckingUnknownFont = true; |
1784 | 0 | OUString fontname = m_xWidget->get_active_text(); |
1785 | | // tdf#154680 If a font is set and that font is unknown, show it in italic. |
1786 | 0 | vcl::Font font = m_xWidget->get_entry_font(); |
1787 | 0 | if (fontname.isEmpty() || CheckFontIsAvailable(fontname)) |
1788 | 0 | { |
1789 | 0 | if( font.GetItalicMaybeAskConfig() != ITALIC_NONE ) |
1790 | 0 | { |
1791 | 0 | font.SetItalic( ITALIC_NONE ); |
1792 | 0 | m_xWidget->set_entry_font(font); |
1793 | 0 | m_xWidget->set_entry_message_type(weld::EntryMessageType::Normal); |
1794 | 0 | m_xWidget->set_tooltip_text(SvxResId(RID_SVXSTR_CHARFONTNAME)); |
1795 | 0 | } |
1796 | 0 | } |
1797 | 0 | else |
1798 | 0 | { |
1799 | 0 | if( font.GetItalicMaybeAskConfig() != ITALIC_NORMAL ) |
1800 | 0 | { |
1801 | 0 | font.SetItalic( ITALIC_NORMAL ); |
1802 | 0 | m_xWidget->set_entry_font(font); |
1803 | 0 | m_xWidget->set_entry_message_type(weld::EntryMessageType::Warning); |
1804 | 0 | m_xWidget->set_tooltip_text(SvxResId(RID_SVXSTR_CHARFONTNAME_NOTAVAILABLE)); |
1805 | 0 | } |
1806 | 0 | } |
1807 | 0 | mbCheckingUnknownFont = false; |
1808 | 0 | } |
1809 | | |
1810 | | void SvxFontNameBox_Base::Update( const css::awt::FontDescriptor* pFontDesc ) |
1811 | 0 | { |
1812 | 0 | if ( pFontDesc ) |
1813 | 0 | { |
1814 | 0 | aCurFont.SetFamilyName ( pFontDesc->Name ); |
1815 | 0 | aCurFont.SetFamily ( FontFamily( pFontDesc->Family ) ); |
1816 | 0 | aCurFont.SetStyleName ( pFontDesc->StyleName ); |
1817 | 0 | aCurFont.SetPitch ( FontPitch( pFontDesc->Pitch ) ); |
1818 | 0 | aCurFont.SetCharSet ( rtl_TextEncoding( pFontDesc->CharSet ) ); |
1819 | 0 | } |
1820 | 0 | OUString aCurName = aCurFont.GetFamilyName(); |
1821 | 0 | OUString aText = m_xWidget->get_active_text(); |
1822 | 0 | if (aText != aCurName || comphelper::LibreOfficeKit::isActive()) |
1823 | 0 | set_active_or_entry_text(aCurName); |
1824 | 0 | } |
1825 | | |
1826 | | void SvxFontNameBox_Base::set_active_or_entry_text(const OUString& rText) |
1827 | 0 | { |
1828 | 0 | m_xWidget->set_active_or_entry_text(rText); |
1829 | 0 | CheckAndMarkUnknownFont(); |
1830 | 0 | } |
1831 | | |
1832 | | IMPL_LINK_NOARG(SvxFontNameBox_Base, FocusInHdl, weld::Widget&, void) |
1833 | 0 | { |
1834 | 0 | FillList(); |
1835 | 0 | } |
1836 | | |
1837 | | IMPL_LINK(SvxFontNameBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) |
1838 | 0 | { |
1839 | 0 | return DoKeyInput(rKEvt); |
1840 | 0 | } |
1841 | | |
1842 | | bool SvxFontNameBox_Base::DoKeyInput(const KeyEvent& rKEvt) |
1843 | 0 | { |
1844 | 0 | bool bHandled = false; |
1845 | |
|
1846 | 0 | sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); |
1847 | |
|
1848 | 0 | switch (nCode) |
1849 | 0 | { |
1850 | 0 | case KEY_TAB: |
1851 | 0 | bRelease = false; |
1852 | 0 | Select(true); |
1853 | 0 | break; |
1854 | | |
1855 | 0 | case KEY_ESCAPE: |
1856 | 0 | set_active_or_entry_text(m_xWidget->get_saved_value()); |
1857 | 0 | if (!m_rCtrl.IsInSidebar()) |
1858 | 0 | { |
1859 | 0 | ReleaseFocus_Impl(); |
1860 | 0 | bHandled = true; |
1861 | 0 | } |
1862 | 0 | break; |
1863 | 0 | } |
1864 | | |
1865 | 0 | return bHandled; |
1866 | 0 | } |
1867 | | |
1868 | | bool SvxFontNameBox_Impl::DoKeyInput(const KeyEvent& rKEvt) |
1869 | 0 | { |
1870 | 0 | return SvxFontNameBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); |
1871 | 0 | } |
1872 | | |
1873 | | IMPL_LINK_NOARG(SvxFontNameBox_Base, FocusOutHdl, weld::Widget&, void) |
1874 | 0 | { |
1875 | 0 | if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus |
1876 | 0 | { |
1877 | 0 | set_active_or_entry_text(m_xWidget->get_saved_value()); |
1878 | | // send EndPreview |
1879 | 0 | EndPreview(); |
1880 | 0 | } |
1881 | 0 | } |
1882 | | |
1883 | | IMPL_LINK(SvxFontNameBox_Base, LivePreviewHdl, const FontMetric&, rFontMetric, void) |
1884 | 0 | { |
1885 | 0 | Sequence<PropertyValue> aArgs(1); |
1886 | |
|
1887 | 0 | SvxFontItem aFontItem(rFontMetric.GetFamilyType(), |
1888 | 0 | rFontMetric.GetFamilyName(), |
1889 | 0 | rFontMetric.GetStyleName(), |
1890 | 0 | rFontMetric.GetPitch(), |
1891 | 0 | rFontMetric.GetCharSet(), |
1892 | 0 | SID_ATTR_CHAR_FONT); |
1893 | 0 | PropertyValue* pArgs = aArgs.getArray(); |
1894 | 0 | aFontItem.QueryValue(pArgs[0].Value); |
1895 | 0 | pArgs[0].Name = "CharPreviewFontName"; |
1896 | 0 | const Reference<XDispatchProvider> xProvider(m_xFrame, UNO_QUERY); |
1897 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:CharPreviewFontName"_ustr, aArgs); |
1898 | 0 | } |
1899 | | |
1900 | | IMPL_LINK_NOARG(SvxFontNameBox_Base, PopupToggledHdl, weld::ComboBox&, void) |
1901 | 0 | { |
1902 | 0 | mbDropDownActive = !mbDropDownActive; |
1903 | 0 | if (!mbDropDownActive) |
1904 | 0 | EndPreview(); |
1905 | 0 | } |
1906 | | |
1907 | | void SvxFontNameBox_Impl::SetOptimalSize() |
1908 | 0 | { |
1909 | | // set width in chars low so the size request will not be overridden |
1910 | 0 | m_xWidget->set_entry_width_chars(1); |
1911 | | // tdf#132338 purely using this calculation to keep things their traditional width |
1912 | 0 | Size aSize(LogicToPixel(Size((COMBO_WIDTH_IN_CHARS +5) * 4, 0), MapMode(MapUnit::MapAppFont))); |
1913 | 0 | m_xWidget->set_size_request(aSize.Width(), -1); |
1914 | |
|
1915 | 0 | SetSizePixel(get_preferred_size()); |
1916 | 0 | } |
1917 | | |
1918 | | void SvxFontNameBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) |
1919 | 0 | { |
1920 | 0 | if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && |
1921 | 0 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) |
1922 | 0 | { |
1923 | 0 | SetOptimalSize(); |
1924 | 0 | } |
1925 | 0 | else if ( ( rDCEvt.GetType() == DataChangedEventType::FONTS ) || |
1926 | 0 | ( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) |
1927 | 0 | { |
1928 | | // The old font list in shell has likely been destroyed at this point, so we need to get |
1929 | | // the new one before doing anything further. |
1930 | 0 | lcl_GetDocFontList( &pFontList, *this ); |
1931 | 0 | } |
1932 | 0 | } |
1933 | | |
1934 | | void SvxFontNameBox_Base::ReleaseFocus_Impl() |
1935 | 0 | { |
1936 | 0 | if ( !bRelease ) |
1937 | 0 | { |
1938 | 0 | bRelease = true; |
1939 | 0 | return; |
1940 | 0 | } |
1941 | 0 | if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) |
1942 | 0 | m_xFrame->getContainerWindow()->setFocus(); |
1943 | 0 | } |
1944 | | |
1945 | | void SvxFontNameBox_Base::EnableControls() |
1946 | 0 | { |
1947 | 0 | bool bEnableMRU = m_aHistory.get(); |
1948 | 0 | sal_uInt16 nEntries = bEnableMRU ? MAX_MRU_FONTNAME_ENTRIES : 0; |
1949 | |
|
1950 | 0 | bool bNewWYSIWYG = m_aWYSIWYG.get(); |
1951 | 0 | bool bOldWYSIWYG = m_xWidget->IsWYSIWYGEnabled(); |
1952 | |
|
1953 | 0 | if (m_xWidget->get_max_mru_count() != nEntries || bNewWYSIWYG != bOldWYSIWYG) |
1954 | 0 | { |
1955 | | // refill in the next GetFocus-Handler |
1956 | 0 | pFontList = nullptr; |
1957 | 0 | Clear(); |
1958 | 0 | m_xWidget->set_max_mru_count(nEntries); |
1959 | 0 | } |
1960 | |
|
1961 | 0 | if (bNewWYSIWYG != bOldWYSIWYG) |
1962 | 0 | m_xWidget->EnableWYSIWYG(bNewWYSIWYG); |
1963 | 0 | } |
1964 | | |
1965 | | IMPL_LINK(SvxFontNameBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) |
1966 | 0 | { |
1967 | 0 | Select(rCombo.changed_by_direct_pick()); // only when picked from the list |
1968 | 0 | } |
1969 | | |
1970 | | IMPL_LINK_NOARG(SvxFontNameBox_Base, ActivateHdl, weld::ComboBox&, bool) |
1971 | 0 | { |
1972 | 0 | Select(true); |
1973 | 0 | return true; |
1974 | 0 | } |
1975 | | |
1976 | | void SvxFontNameBox_Base::Select(bool bNonTravelSelect) |
1977 | 0 | { |
1978 | 0 | Sequence< PropertyValue > aArgs( 1 ); |
1979 | 0 | auto pArgs = aArgs.getArray(); |
1980 | 0 | std::unique_ptr<SvxFontItem> pFontItem; |
1981 | 0 | if ( pFontList ) |
1982 | 0 | { |
1983 | 0 | FontMetric aFontMetric( pFontList->Get(m_xWidget->get_active_text(), |
1984 | 0 | aCurFont.GetWeightMaybeAskConfig(), |
1985 | 0 | aCurFont.GetItalicMaybeAskConfig() ) ); |
1986 | 0 | aCurFont = aFontMetric; |
1987 | |
|
1988 | 0 | pFontItem.reset( new SvxFontItem( aFontMetric.GetFamilyTypeMaybeAskConfig(), |
1989 | 0 | aFontMetric.GetFamilyName(), |
1990 | 0 | aFontMetric.GetStyleName(), |
1991 | 0 | aFontMetric.GetPitchMaybeAskConfig(), |
1992 | 0 | aFontMetric.GetCharSet(), |
1993 | 0 | SID_ATTR_CHAR_FONT ) ); |
1994 | |
|
1995 | 0 | Any a; |
1996 | 0 | pFontItem->QueryValue( a ); |
1997 | 0 | pArgs[0].Value = std::move(a); |
1998 | 0 | } |
1999 | |
|
2000 | 0 | const Reference<XDispatchProvider> xProvider(m_xFrame, UNO_QUERY); |
2001 | 0 | if (bNonTravelSelect) |
2002 | 0 | { |
2003 | 0 | CheckAndMarkUnknownFont(); |
2004 | | // #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. |
2005 | | // This instance may be deleted in the meantime (i.e. when a dialog is opened |
2006 | | // while in Dispatch()), accessing members will crash in this case. |
2007 | 0 | ReleaseFocus_Impl(); |
2008 | 0 | EndPreview(); |
2009 | 0 | if (pFontItem) |
2010 | 0 | { |
2011 | 0 | pArgs[0].Name = "CharFontName"; |
2012 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:CharFontName"_ustr, aArgs); |
2013 | 0 | } |
2014 | 0 | } |
2015 | 0 | else |
2016 | 0 | { |
2017 | 0 | if (pFontItem) |
2018 | 0 | { |
2019 | 0 | pArgs[0].Name = "CharPreviewFontName"; |
2020 | 0 | SfxToolBoxControl::Dispatch(xProvider, u".uno:CharPreviewFontName"_ustr, aArgs); |
2021 | 0 | } |
2022 | 0 | } |
2023 | 0 | } |
2024 | | |
2025 | | IMPL_LINK(SvxFontNameBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void) |
2026 | 0 | { |
2027 | 0 | { |
2028 | 0 | auto entriesNode = rJsonWriter.startNode("entries"); |
2029 | 0 | for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i) |
2030 | 0 | { |
2031 | 0 | auto entryNode = rJsonWriter.startNode(""); |
2032 | 0 | rJsonWriter.put("", m_xWidget->get_text(i)); |
2033 | 0 | } |
2034 | 0 | } |
2035 | |
|
2036 | 0 | int nSelectedEntry = m_xWidget->get_active(); |
2037 | 0 | rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nSelectedEntry == -1 ? 0 : 1)); |
2038 | |
|
2039 | 0 | { |
2040 | 0 | auto selectedNode = rJsonWriter.startNode("selectedEntries"); |
2041 | 0 | if (nSelectedEntry != -1) |
2042 | 0 | { |
2043 | 0 | auto entryNode = rJsonWriter.startNode(""); |
2044 | 0 | rJsonWriter.put("", m_xWidget->get_text(nSelectedEntry)); |
2045 | 0 | } |
2046 | 0 | } |
2047 | |
|
2048 | 0 | rJsonWriter.put("command", ".uno:CharFontName"); |
2049 | 0 | } |
2050 | | |
2051 | | ColorWindow::ColorWindow(OUString rCommand, |
2052 | | std::shared_ptr<PaletteManager> xPaletteManager, |
2053 | | ColorStatus& rColorStatus, |
2054 | | sal_uInt16 nSlotId, |
2055 | | const Reference< XFrame >& rFrame, |
2056 | | const MenuOrToolMenuButton& rMenuButton, |
2057 | | TopLevelParentFunction aTopLevelParentFunction, |
2058 | | ColorSelectFunction aColorSelectFunction) |
2059 | 0 | : WeldToolbarPopup(rFrame, rMenuButton.get_widget(), u"svx/ui/colorwindow.ui"_ustr, u"palette_popup_window"_ustr) |
2060 | 0 | , mnSlotId(nSlotId) |
2061 | 0 | , maCommand(std::move(rCommand)) |
2062 | 0 | , maMenuButton(rMenuButton) |
2063 | 0 | , mxPaletteManager(std::move(xPaletteManager)) |
2064 | 0 | , mrColorStatus(rColorStatus) |
2065 | 0 | , maTopLevelParentFunction(std::move(aTopLevelParentFunction)) |
2066 | 0 | , maColorSelectFunction(std::move(aColorSelectFunction)) |
2067 | 0 | , mxColorSet(new SvxColorValueSet(m_xBuilder->weld_scrolled_window(u"colorsetwin"_ustr, true))) |
2068 | 0 | , mxRecentColorSet(new SvxColorValueSet(nullptr)) |
2069 | 0 | , mxPaletteListBox(m_xBuilder->weld_combo_box(u"palette_listbox"_ustr)) |
2070 | 0 | , mxButtonAutoColor(m_xBuilder->weld_button(u"auto_color_button"_ustr)) |
2071 | 0 | , mxButtonNoneColor(m_xBuilder->weld_button(u"none_color_button"_ustr)) |
2072 | 0 | , mxButtonPicker(m_xBuilder->weld_button(u"color_picker_button"_ustr)) |
2073 | 0 | , mxAutomaticSeparator(m_xBuilder->weld_widget(u"separator4"_ustr)) |
2074 | 0 | , mxColorSetWin(new weld::CustomWeld(*m_xBuilder, u"colorset"_ustr, *mxColorSet)) |
2075 | 0 | , mxRecentColorSetWin(new weld::CustomWeld(*m_xBuilder, u"recent_colorset"_ustr, *mxRecentColorSet)) |
2076 | 0 | , mpDefaultButton(nullptr) |
2077 | 0 | { |
2078 | 0 | mxColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); |
2079 | 0 | mxRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); |
2080 | |
|
2081 | 0 | switch ( mnSlotId ) |
2082 | 0 | { |
2083 | 0 | case SID_ATTR_CHAR_COLOR_BACKGROUND: |
2084 | 0 | case SID_BACKGROUND_COLOR: |
2085 | 0 | case SID_ATTR_CHAR_BACK_COLOR: |
2086 | 0 | case SID_TABLE_CELL_BACKGROUND_COLOR: |
2087 | 0 | { |
2088 | 0 | mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_NOFILL ) ); |
2089 | 0 | break; |
2090 | 0 | } |
2091 | 0 | case SID_AUTHOR_COLOR: |
2092 | 0 | { |
2093 | 0 | mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_BY_AUTHOR ) ); |
2094 | 0 | break; |
2095 | 0 | } |
2096 | 0 | case SID_BMPMASK_COLOR: |
2097 | 0 | { |
2098 | 0 | mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_TRANSPARENT ) ); |
2099 | 0 | break; |
2100 | 0 | } |
2101 | 0 | case SID_ATTR_CHAR_COLOR: |
2102 | 0 | case SID_ATTR_CHAR_COLOR2: |
2103 | 0 | case SID_EXTRUSION_3D_COLOR: |
2104 | 0 | { |
2105 | 0 | mxButtonAutoColor->set_label(EditResId(RID_SVXSTR_AUTOMATIC)); |
2106 | 0 | break; |
2107 | 0 | } |
2108 | 0 | case SID_FM_CTL_PROPERTIES: |
2109 | 0 | { |
2110 | 0 | mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_DEFAULT ) ); |
2111 | 0 | break; |
2112 | 0 | } |
2113 | 0 | default: |
2114 | 0 | { |
2115 | 0 | mxButtonAutoColor->hide(); |
2116 | 0 | mxAutomaticSeparator->hide(); |
2117 | 0 | break; |
2118 | 0 | } |
2119 | 0 | } |
2120 | | |
2121 | 0 | mxPaletteListBox->connect_changed(LINK(this, ColorWindow, SelectPaletteHdl)); |
2122 | 0 | std::vector<OUString> aPaletteList = mxPaletteManager->GetPaletteList(); |
2123 | 0 | mxPaletteListBox->freeze(); |
2124 | 0 | for (const auto& rPalette : aPaletteList) |
2125 | 0 | mxPaletteListBox->append_text(rPalette); |
2126 | 0 | mxPaletteListBox->thaw(); |
2127 | | |
2128 | | // tdf#162104 If the current palette does not exist, select the equivalent to the localized "Standard" palette |
2129 | | // This is required because the names are now localized and in Common.xcs the "Standard" (in English) |
2130 | | // palette is selected by default |
2131 | 0 | OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get()); |
2132 | 0 | auto it = std::find(aPaletteList.begin(), aPaletteList.end(), aPaletteName); |
2133 | 0 | if (it == aPaletteList.end()) |
2134 | 0 | aPaletteName = SvxResId(RID_SVXSTR_COLOR_PALETTE_STANDARD); |
2135 | |
|
2136 | 0 | mxPaletteListBox->set_active_text(aPaletteName); |
2137 | 0 | const int nSelectedEntry(mxPaletteListBox->get_active()); |
2138 | 0 | if (nSelectedEntry != -1) |
2139 | 0 | mxPaletteManager->SetPalette(nSelectedEntry); |
2140 | |
|
2141 | 0 | mxButtonAutoColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); |
2142 | 0 | mxButtonNoneColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); |
2143 | 0 | mxButtonPicker->connect_clicked(LINK(this, ColorWindow, OpenPickerClickHdl)); |
2144 | |
|
2145 | 0 | mxColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); |
2146 | 0 | mxRecentColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); |
2147 | 0 | m_xTopLevel->set_help_id(HID_POPUP_COLOR); |
2148 | 0 | mxColorSet->SetHelpId(HID_POPUP_COLOR_CTRL); |
2149 | |
|
2150 | 0 | mxPaletteManager->ReloadColorSet(*mxColorSet); |
2151 | 0 | const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount()); |
2152 | 0 | Size aSize = mxColorSet->layoutAllVisible(nMaxItems); |
2153 | 0 | mxColorSet->set_size_request(aSize.Width(), aSize.Height()); |
2154 | |
|
2155 | 0 | mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); |
2156 | 0 | aSize = mxRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount()); |
2157 | 0 | mxRecentColorSet->set_size_request(aSize.Width(), aSize.Height()); |
2158 | |
|
2159 | 0 | AddStatusListener( u".uno:ColorTableState"_ustr ); |
2160 | 0 | AddStatusListener( maCommand ); |
2161 | 0 | if ( maCommand == ".uno:FrameLineColor" ) |
2162 | 0 | { |
2163 | 0 | AddStatusListener( u".uno:BorderTLBR"_ustr ); |
2164 | 0 | AddStatusListener( u".uno:BorderBLTR"_ustr ); |
2165 | 0 | } |
2166 | 0 | } |
2167 | | |
2168 | | void ColorWindow::GrabFocus() |
2169 | 0 | { |
2170 | 0 | if (mxColorSet->IsNoSelection() && mpDefaultButton) |
2171 | 0 | mpDefaultButton->grab_focus(); |
2172 | 0 | else |
2173 | 0 | mxColorSet->GrabFocus(); |
2174 | 0 | } |
2175 | | |
2176 | | void ColorWindow::ShowNoneButton() |
2177 | 0 | { |
2178 | 0 | mxButtonNoneColor->show(); |
2179 | 0 | } |
2180 | | |
2181 | | ColorWindow::~ColorWindow() |
2182 | 0 | { |
2183 | 0 | } |
2184 | | |
2185 | | NamedColor ColorWindow::GetSelectEntryColor(ValueSet const * pColorSet) |
2186 | 0 | { |
2187 | 0 | Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId()); |
2188 | 0 | const OUString& sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId()); |
2189 | 0 | return { aColor, sColorName }; |
2190 | 0 | } |
2191 | | |
2192 | | namespace |
2193 | | { |
2194 | | NamedColor GetAutoColor(sal_uInt16 nSlotId) |
2195 | 0 | { |
2196 | 0 | Color aColor; |
2197 | 0 | OUString sColorName; |
2198 | 0 | switch (nSlotId) |
2199 | 0 | { |
2200 | 0 | case SID_ATTR_CHAR_COLOR_BACKGROUND: |
2201 | 0 | case SID_BACKGROUND_COLOR: |
2202 | 0 | case SID_ATTR_CHAR_BACK_COLOR: |
2203 | 0 | case SID_TABLE_CELL_BACKGROUND_COLOR: |
2204 | 0 | aColor = COL_TRANSPARENT; |
2205 | 0 | sColorName = SvxResId(RID_SVXSTR_NOFILL); |
2206 | 0 | break; |
2207 | 0 | case SID_AUTHOR_COLOR: |
2208 | 0 | aColor = COL_TRANSPARENT; |
2209 | 0 | sColorName = SvxResId(RID_SVXSTR_BY_AUTHOR); |
2210 | 0 | break; |
2211 | 0 | case SID_BMPMASK_COLOR: |
2212 | 0 | aColor = COL_TRANSPARENT; |
2213 | 0 | sColorName = SvxResId(RID_SVXSTR_TRANSPARENT); |
2214 | 0 | break; |
2215 | 0 | case SID_FM_CTL_PROPERTIES: |
2216 | 0 | aColor = COL_TRANSPARENT; |
2217 | 0 | sColorName = SvxResId(RID_SVXSTR_DEFAULT); |
2218 | 0 | break; |
2219 | 0 | case SID_ATTR_CHAR_COLOR: |
2220 | 0 | case SID_ATTR_CHAR_COLOR2: |
2221 | 0 | case SID_EXTRUSION_3D_COLOR: |
2222 | 0 | default: |
2223 | 0 | aColor = COL_AUTO; |
2224 | 0 | sColorName = EditResId(RID_SVXSTR_AUTOMATIC); |
2225 | 0 | break; |
2226 | 0 | } |
2227 | | |
2228 | 0 | return {aColor, sColorName}; |
2229 | 0 | } |
2230 | | |
2231 | | NamedColor GetNoneColor() |
2232 | 0 | { |
2233 | 0 | OUString aName = comphelper::LibreOfficeKit::isActive() |
2234 | 0 | ? SvxResId(RID_SVXSTR_INVISIBLE) |
2235 | 0 | : SvxResId(RID_SVXSTR_NONE); |
2236 | 0 | return { COL_NONE_COLOR, aName }; |
2237 | 0 | } |
2238 | | } |
2239 | | |
2240 | | NamedColor ColorWindow::GetSelectEntryColor() const |
2241 | 0 | { |
2242 | 0 | if (!mxColorSet->IsNoSelection()) |
2243 | 0 | return GetSelectEntryColor(mxColorSet.get()); |
2244 | 0 | if (!mxRecentColorSet->IsNoSelection()) |
2245 | 0 | return GetSelectEntryColor(mxRecentColorSet.get()); |
2246 | 0 | if (mxButtonNoneColor.get() == mpDefaultButton) |
2247 | 0 | return GetNoneColor(); |
2248 | 0 | return GetAutoColor(); |
2249 | 0 | } |
2250 | | |
2251 | | IMPL_LINK(ColorWindow, SelectHdl, ValueSet*, pColorSet, void) |
2252 | 0 | { |
2253 | 0 | NamedColor aNamedColor = GetSelectEntryColor(pColorSet); |
2254 | |
|
2255 | 0 | if (pColorSet != mxRecentColorSet.get()) |
2256 | 0 | { |
2257 | 0 | mxPaletteManager->AddRecentColor(aNamedColor.m_aColor, aNamedColor.m_aName); |
2258 | 0 | if (!maMenuButton.get_active()) |
2259 | 0 | mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); |
2260 | 0 | } |
2261 | |
|
2262 | 0 | mxPaletteManager->SetSplitButtonColor(aNamedColor); |
2263 | | |
2264 | | // deliberate take a copy here in case maMenuButton.set_inactive |
2265 | | // triggers a callback that destroys ourself |
2266 | 0 | ColorSelectFunction aColorSelectFunction(maColorSelectFunction); |
2267 | 0 | OUString sCommand(maCommand); |
2268 | | // Same for querying IsTheme early. |
2269 | 0 | bool bThemePaletteSelected = mxPaletteManager->IsThemePaletteSelected(); |
2270 | 0 | sal_uInt16 nSelectedItemId = pColorSet->GetSelectedItemId(); |
2271 | |
|
2272 | 0 | if (bThemePaletteSelected) |
2273 | 0 | { |
2274 | 0 | sal_uInt16 nThemeIndex; |
2275 | 0 | sal_uInt16 nEffectIndex; |
2276 | 0 | if (PaletteManager::GetThemeAndEffectIndex(nSelectedItemId, nThemeIndex, nEffectIndex)) |
2277 | 0 | { |
2278 | 0 | aNamedColor.m_nThemeIndex = nThemeIndex; |
2279 | 0 | mxPaletteManager->GetLumModOff(nThemeIndex, nEffectIndex, aNamedColor.m_nLumMod, aNamedColor.m_nLumOff); |
2280 | 0 | } |
2281 | 0 | } |
2282 | |
|
2283 | 0 | maMenuButton.set_inactive(); |
2284 | 0 | aColorSelectFunction(sCommand, aNamedColor); |
2285 | 0 | } |
2286 | | |
2287 | | IMPL_LINK_NOARG(ColorWindow, SelectPaletteHdl, weld::ComboBox&, void) |
2288 | 0 | { |
2289 | 0 | int nPos = mxPaletteListBox->get_active(); |
2290 | 0 | mxPaletteManager->SetPalette( nPos ); |
2291 | 0 | mxPaletteManager->ReloadColorSet(*mxColorSet); |
2292 | 0 | mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); |
2293 | 0 | } |
2294 | | |
2295 | | NamedColor ColorWindow::GetAutoColor() const |
2296 | 0 | { |
2297 | 0 | return ::GetAutoColor(mnSlotId); |
2298 | 0 | } |
2299 | | |
2300 | | IMPL_LINK(ColorWindow, AutoColorClickHdl, weld::Button&, rButton, void) |
2301 | 0 | { |
2302 | 0 | NamedColor aNamedColor = &rButton == mxButtonAutoColor.get() ? GetAutoColor() : GetNoneColor(); |
2303 | |
|
2304 | 0 | mxColorSet->SetNoSelection(); |
2305 | 0 | mxRecentColorSet->SetNoSelection(); |
2306 | 0 | mpDefaultButton = &rButton; |
2307 | |
|
2308 | 0 | mxPaletteManager->SetSplitButtonColor(aNamedColor); |
2309 | | |
2310 | | // deliberate take a copy here in case maMenuButton.set_inactive |
2311 | | // triggers a callback that destroys ourself |
2312 | 0 | ColorSelectFunction aColorSelectFunction(maColorSelectFunction); |
2313 | 0 | OUString sCommand(maCommand); |
2314 | |
|
2315 | 0 | maMenuButton.set_inactive(); |
2316 | |
|
2317 | 0 | aColorSelectFunction(sCommand, aNamedColor); |
2318 | 0 | } |
2319 | | |
2320 | | IMPL_LINK_NOARG(ColorWindow, OpenPickerClickHdl, weld::Button&, void) |
2321 | 0 | { |
2322 | | // copy before set_inactive |
2323 | 0 | auto nColor = GetSelectEntryColor().m_aColor; |
2324 | 0 | auto pParentWindow = maTopLevelParentFunction(); |
2325 | 0 | OUString sCommand = maCommand; |
2326 | 0 | std::shared_ptr<PaletteManager> xPaletteManager(mxPaletteManager); |
2327 | |
|
2328 | 0 | maMenuButton.set_inactive(); |
2329 | |
|
2330 | 0 | xPaletteManager->PopupColorPicker(pParentWindow, sCommand, nColor); |
2331 | 0 | } |
2332 | | |
2333 | | void ColorWindow::SetNoSelection() |
2334 | 0 | { |
2335 | 0 | mxColorSet->SetNoSelection(); |
2336 | 0 | mxRecentColorSet->SetNoSelection(); |
2337 | 0 | mpDefaultButton = nullptr; |
2338 | 0 | } |
2339 | | |
2340 | | bool ColorWindow::IsNoSelection() const |
2341 | 0 | { |
2342 | 0 | if (!mxColorSet->IsNoSelection()) |
2343 | 0 | return false; |
2344 | 0 | if (!mxRecentColorSet->IsNoSelection()) |
2345 | 0 | return false; |
2346 | 0 | return !mxButtonAutoColor->get_visible() && !mxButtonNoneColor->get_visible(); |
2347 | 0 | } |
2348 | | |
2349 | | void ColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
2350 | 0 | { |
2351 | 0 | if (rEvent.FeatureURL.Complete == ".uno:ColorTableState") |
2352 | 0 | { |
2353 | 0 | if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0) |
2354 | 0 | { |
2355 | 0 | mxPaletteManager->ReloadColorSet(*mxColorSet); |
2356 | 0 | mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); |
2357 | 0 | } |
2358 | 0 | } |
2359 | 0 | else |
2360 | 0 | { |
2361 | 0 | mrColorStatus.statusChanged(rEvent); |
2362 | 0 | SelectEntry(mrColorStatus.GetColor()); |
2363 | 0 | } |
2364 | 0 | } |
2365 | | |
2366 | | bool ColorWindow::SelectValueSetEntry(SvxColorValueSet* pColorSet, const Color& rColor) |
2367 | 0 | { |
2368 | 0 | for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i) |
2369 | 0 | { |
2370 | 0 | if (rColor == pColorSet->GetItemColor(i)) |
2371 | 0 | { |
2372 | 0 | pColorSet->SelectItem(i); |
2373 | 0 | return true; |
2374 | 0 | } |
2375 | 0 | } |
2376 | 0 | return false; |
2377 | 0 | } |
2378 | | |
2379 | | void ColorWindow::SelectEntry(const NamedColor& rNamedColor) |
2380 | 0 | { |
2381 | 0 | SetNoSelection(); |
2382 | |
|
2383 | 0 | const Color &rColor = rNamedColor.m_aColor; |
2384 | |
|
2385 | 0 | if (mxButtonAutoColor->get_visible() && rColor.IsFullyTransparent()) |
2386 | 0 | { |
2387 | 0 | mpDefaultButton = mxButtonAutoColor.get(); |
2388 | 0 | return; |
2389 | 0 | } |
2390 | | |
2391 | 0 | if (mxButtonNoneColor->get_visible() && rColor == COL_NONE_COLOR) |
2392 | 0 | { |
2393 | 0 | mpDefaultButton = mxButtonNoneColor.get(); |
2394 | 0 | return; |
2395 | 0 | } |
2396 | | |
2397 | | // try current palette |
2398 | 0 | bool bFoundColor = SelectValueSetEntry(mxColorSet.get(), rColor); |
2399 | | // try recently used |
2400 | 0 | if (!bFoundColor) |
2401 | 0 | bFoundColor = SelectValueSetEntry(mxRecentColorSet.get(), rColor); |
2402 | | // if it's not there, add it there now to the end of the recently used |
2403 | | // so its available somewhere handy, but not without trashing the |
2404 | | // whole recently used |
2405 | 0 | if (!bFoundColor) |
2406 | 0 | { |
2407 | 0 | const OUString& rColorName = rNamedColor.m_aName; |
2408 | 0 | mxPaletteManager->AddRecentColor(rColor, rColorName, false); |
2409 | 0 | mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); |
2410 | 0 | SelectValueSetEntry(mxRecentColorSet.get(), rColor); |
2411 | 0 | } |
2412 | 0 | } |
2413 | | |
2414 | | void ColorWindow::SelectEntry(const Color& rColor) |
2415 | 0 | { |
2416 | 0 | OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase(); |
2417 | 0 | ColorWindow::SelectEntry({rColor, sColorName}); |
2418 | 0 | } |
2419 | | |
2420 | | ColorStatus::ColorStatus() : |
2421 | 0 | maColor( COL_TRANSPARENT ), |
2422 | 0 | maTLBRColor( COL_TRANSPARENT ), |
2423 | 0 | maBLTRColor( COL_TRANSPARENT ) |
2424 | 0 | { |
2425 | 0 | } |
2426 | | |
2427 | | void ColorStatus::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
2428 | 0 | { |
2429 | 0 | Color aColor( COL_TRANSPARENT ); |
2430 | 0 | css::table::BorderLine2 aTable; |
2431 | |
|
2432 | 0 | if ( rEvent.State >>= aTable ) |
2433 | 0 | { |
2434 | 0 | SvxBorderLine aLine; |
2435 | 0 | (void)SvxBoxItem::LineToSvxLine( aTable, aLine, false ); |
2436 | 0 | if ( !aLine.isEmpty() ) |
2437 | 0 | aColor = aLine.GetColor(); |
2438 | 0 | } |
2439 | 0 | else |
2440 | 0 | rEvent.State >>= aColor; |
2441 | |
|
2442 | 0 | if ( rEvent.FeatureURL.Path == "BorderTLBR" ) |
2443 | 0 | maTLBRColor = aColor; |
2444 | 0 | else if ( rEvent.FeatureURL.Path == "BorderBLTR" ) |
2445 | 0 | maBLTRColor = aColor; |
2446 | 0 | else |
2447 | 0 | maColor = aColor; |
2448 | 0 | } |
2449 | | |
2450 | | Color ColorStatus::GetColor() |
2451 | 0 | { |
2452 | 0 | Color aColor( maColor ); |
2453 | |
|
2454 | 0 | if ( maTLBRColor != COL_TRANSPARENT ) |
2455 | 0 | { |
2456 | 0 | if ( aColor != maTLBRColor && aColor != COL_TRANSPARENT ) |
2457 | 0 | return COL_TRANSPARENT; |
2458 | 0 | aColor = maTLBRColor; |
2459 | 0 | } |
2460 | | |
2461 | 0 | if ( maBLTRColor != COL_TRANSPARENT ) |
2462 | 0 | { |
2463 | 0 | if ( aColor != maBLTRColor && aColor != COL_TRANSPARENT ) |
2464 | 0 | return COL_TRANSPARENT; |
2465 | 0 | return maBLTRColor; |
2466 | 0 | } |
2467 | | |
2468 | 0 | return aColor; |
2469 | 0 | } |
2470 | | |
2471 | | |
2472 | | SvxFrameWindow_Impl::SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent) |
2473 | 0 | : WeldToolbarPopup(pControl->getFrameInterface(), pParent, u"svx/ui/floatingframeborder.ui"_ustr, u"FloatingFrameBorder"_ustr) |
2474 | 0 | , mxControl(pControl) |
2475 | 0 | , mxFrameSet(new SvxFrmValueSet_Impl) |
2476 | 0 | , mxFrameSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *mxFrameSet)) |
2477 | 0 | , bParagraphMode(false) |
2478 | 0 | , m_bIsWriter(false) |
2479 | 0 | , m_bIsCalc(false) |
2480 | 0 | { |
2481 | | |
2482 | | // check whether the document is Writer or not |
2483 | | // check also if it's Calc or not |
2484 | 0 | if (Reference<lang::XServiceInfo> xSI{ m_xFrame->getController()->getModel(), UNO_QUERY }) |
2485 | 0 | { |
2486 | 0 | m_bIsWriter = xSI->supportsService(u"com.sun.star.text.TextDocument"_ustr); |
2487 | 0 | m_bIsCalc = xSI->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr); |
2488 | 0 | } |
2489 | |
|
2490 | 0 | mxFrameSet->SetStyle(WB_ITEMBORDER | WB_DOUBLEBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT); |
2491 | 0 | AddStatusListener(u".uno:BorderReducedMode"_ustr); |
2492 | 0 | InitImageList(); |
2493 | |
|
2494 | 0 | sal_uInt16 i = 0; |
2495 | | |
2496 | | // Writer and Calc uses 8 border types - for a single cell. |
2497 | 0 | for ( i=1; i < 9; i++ ) |
2498 | 0 | mxFrameSet->InsertItem(i, Image(aImgVec[i-1].first), aImgVec[i-1].second); |
2499 | | |
2500 | | //bParagraphMode should have been set in StateChanged |
2501 | 0 | if ( !bParagraphMode ) |
2502 | | // when multiple cell selected: |
2503 | | // Writer and Calc have 12 border types. |
2504 | 0 | for ( i = 9; i < 13; i++ ) |
2505 | 0 | mxFrameSet->InsertItem(i, Image(aImgVec[i-1].first), aImgVec[i-1].second); |
2506 | | |
2507 | | // adjust frame column for Writer and Calc |
2508 | 0 | sal_uInt16 colCount = 4; |
2509 | 0 | mxFrameSet->SetColCount( colCount ); |
2510 | 0 | mxFrameSet->SetSelectHdl( LINK( this, SvxFrameWindow_Impl, SelectHdl ) ); |
2511 | 0 | CalcSizeValueSet(); |
2512 | |
|
2513 | 0 | mxFrameSet->SetHelpId( HID_POPUP_FRAME ); |
2514 | 0 | mxFrameSet->SetAccessibleName( SvxResId(RID_SVXSTR_FRAME) ); |
2515 | 0 | } |
2516 | | |
2517 | | namespace { |
2518 | | |
2519 | | enum class FrmValidFlags { |
2520 | | NONE = 0x00, |
2521 | | Left = 0x01, |
2522 | | Right = 0x02, |
2523 | | Top = 0x04, |
2524 | | Bottom = 0x08, |
2525 | | HInner = 0x10, |
2526 | | VInner = 0x20, |
2527 | | AllMask = 0x3f, |
2528 | | }; |
2529 | | |
2530 | | } |
2531 | | |
2532 | | namespace o3tl { |
2533 | | template<> struct typed_flags<FrmValidFlags> : is_typed_flags<FrmValidFlags, 0x3f> {}; |
2534 | | } |
2535 | | |
2536 | | // By default unset lines remain unchanged. |
2537 | | // Via Shift unset lines are reset |
2538 | | |
2539 | | IMPL_LINK_NOARG(SvxFrameWindow_Impl, SelectHdl, ValueSet*, void) |
2540 | 0 | { |
2541 | 0 | SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER ); |
2542 | 0 | SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER ); |
2543 | 0 | SvxBorderLine theDefLine; |
2544 | | |
2545 | | // diagonal down border |
2546 | 0 | SvxBorderLine dDownBorderLine(nullptr, SvxBorderLineWidth::Hairline); |
2547 | 0 | SvxLineItem dDownLineItem(SID_ATTR_BORDER_DIAG_TLBR); |
2548 | | |
2549 | | // diagonal up border |
2550 | 0 | SvxBorderLine dUpBorderLine(nullptr, SvxBorderLineWidth::Hairline); |
2551 | 0 | SvxLineItem dUpLineItem(SID_ATTR_BORDER_DIAG_BLTR); |
2552 | |
|
2553 | 0 | bool bIsDiagonalBorder = false; |
2554 | |
|
2555 | 0 | SvxBorderLine *pLeft = nullptr, |
2556 | 0 | *pRight = nullptr, |
2557 | 0 | *pTop = nullptr, |
2558 | 0 | *pBottom = nullptr; |
2559 | 0 | sal_uInt16 nSel = mxFrameSet->GetSelectedItemId(); |
2560 | 0 | sal_uInt16 nModifier = mxFrameSet->GetModifier(); |
2561 | 0 | FrmValidFlags nValidFlags = FrmValidFlags::NONE; |
2562 | | |
2563 | | // tdf#48622, tdf#145828 use correct default to create intended 0.75pt |
2564 | | // cell border using the border formatting tool in the standard toolbar |
2565 | 0 | theDefLine.GuessLinesWidths(theDefLine.GetBorderLineStyle(), SvxBorderLineWidth::Thin); |
2566 | | |
2567 | | // nSel has 15 cases which means 12 (9 common with writer + 3 unique) unique border |
2568 | | // types for Calc. But Writer uses 12 (9 common with calc + 3 unique) |
2569 | | // of them - when diagonal borders excluded. |
2570 | 0 | if (m_bIsCalc) |
2571 | 0 | { |
2572 | | // This is a lookup table to map the new 1-12 order |
2573 | | // to the 'case' values of the switch statement. |
2574 | 0 | switch (nSel) |
2575 | 0 | { |
2576 | 0 | case 1: |
2577 | 0 | nSel = 1; |
2578 | 0 | break; // None |
2579 | 0 | case 2: |
2580 | 0 | nSel = 8; |
2581 | 0 | break; // Outside |
2582 | 0 | case 3: |
2583 | 0 | nSel = 12; |
2584 | 0 | break; // All |
2585 | 0 | case 4: |
2586 | 0 | nSel = 15; |
2587 | 0 | break; // Criss-cross |
2588 | 0 | case 5: |
2589 | 0 | nSel = 2; |
2590 | 0 | break; // Left |
2591 | 0 | case 6: |
2592 | 0 | nSel = 3; |
2593 | 0 | break; // Right |
2594 | 0 | case 7: |
2595 | 0 | nSel = 5; |
2596 | 0 | break; // Top |
2597 | 0 | case 8: |
2598 | 0 | nSel = 6; |
2599 | 0 | break; // Bottom |
2600 | 0 | case 9: |
2601 | 0 | nSel = 13; |
2602 | 0 | break; // Diagonal down |
2603 | 0 | case 10: |
2604 | 0 | nSel = 14; |
2605 | 0 | break; // Diagonal up |
2606 | 0 | case 11: |
2607 | 0 | nSel = 7; |
2608 | 0 | break; // Top-bottom |
2609 | 0 | case 12: |
2610 | 0 | nSel = 4; |
2611 | 0 | break; // Left-right |
2612 | 0 | } |
2613 | 0 | } |
2614 | | |
2615 | 0 | switch ( nSel ) |
2616 | 0 | { |
2617 | 0 | case 1: nValidFlags |= FrmValidFlags::AllMask; |
2618 | | // set nullptr to remove diagonal lines |
2619 | 0 | dDownLineItem.SetLine(nullptr); |
2620 | 0 | dUpLineItem.SetLine(nullptr); |
2621 | 0 | SetDiagonalDownBorder(dDownLineItem); |
2622 | 0 | SetDiagonalUpBorder(dUpLineItem); |
2623 | 0 | break; // NONE |
2624 | 0 | case 2: pLeft = &theDefLine; |
2625 | 0 | nValidFlags |= FrmValidFlags::Left; |
2626 | 0 | break; // LEFT |
2627 | 0 | case 3: pRight = &theDefLine; |
2628 | 0 | nValidFlags |= FrmValidFlags::Right; |
2629 | 0 | break; // RIGHT |
2630 | 0 | case 4: pLeft = pRight = &theDefLine; |
2631 | 0 | nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left; |
2632 | 0 | break; // LEFTRIGHT |
2633 | 0 | case 13: dDownLineItem.SetLine(&dDownBorderLine); |
2634 | 0 | SetDiagonalDownBorder(dDownLineItem); |
2635 | 0 | bIsDiagonalBorder = true; |
2636 | 0 | break; // DIAGONAL DOWN |
2637 | 0 | case 5: pTop = &theDefLine; |
2638 | 0 | nValidFlags |= FrmValidFlags::Top; |
2639 | 0 | break; // TOP |
2640 | 0 | case 6: pBottom = &theDefLine; |
2641 | 0 | nValidFlags |= FrmValidFlags::Bottom; |
2642 | 0 | break; // BOTTOM |
2643 | 0 | case 7: pTop = pBottom = &theDefLine; |
2644 | 0 | nValidFlags |= FrmValidFlags::Bottom|FrmValidFlags::Top; |
2645 | 0 | break; // TOPBOTTOM |
2646 | 0 | case 8: pLeft = pRight = pTop = pBottom = &theDefLine; |
2647 | 0 | nValidFlags |= FrmValidFlags::Left | FrmValidFlags::Right | FrmValidFlags::Top | FrmValidFlags::Bottom; |
2648 | 0 | break; // OUTER |
2649 | 0 | case 14: |
2650 | 0 | dUpLineItem.SetLine(&dUpBorderLine); |
2651 | 0 | SetDiagonalUpBorder(dUpLineItem); |
2652 | 0 | bIsDiagonalBorder = true; |
2653 | 0 | break; // DIAGONAL UP |
2654 | | |
2655 | | // Inner Table: |
2656 | 0 | case 9: // HOR |
2657 | 0 | pTop = pBottom = &theDefLine; |
2658 | 0 | aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); |
2659 | 0 | aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); |
2660 | 0 | nValidFlags |= FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; |
2661 | 0 | break; |
2662 | | |
2663 | 0 | case 10: // HORINNER |
2664 | 0 | pLeft = pRight = pTop = pBottom = &theDefLine; |
2665 | 0 | aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); |
2666 | 0 | aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); |
2667 | 0 | nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; |
2668 | 0 | break; |
2669 | | |
2670 | 0 | case 11: // VERINNER |
2671 | 0 | pLeft = pRight = pTop = pBottom = &theDefLine; |
2672 | 0 | aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::HORI ); |
2673 | 0 | aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); |
2674 | 0 | nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::VInner|FrmValidFlags::Top|FrmValidFlags::Bottom; |
2675 | 0 | break; |
2676 | | |
2677 | 0 | case 12: // ALL |
2678 | 0 | pLeft = pRight = pTop = pBottom = &theDefLine; |
2679 | 0 | aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); |
2680 | 0 | aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); |
2681 | 0 | nValidFlags |= FrmValidFlags::AllMask; |
2682 | 0 | break; |
2683 | | |
2684 | 0 | case 15: |
2685 | | // set both diagonal lines to draw criss-cross line |
2686 | 0 | dDownLineItem.SetLine(&dDownBorderLine); |
2687 | 0 | dUpLineItem.SetLine(&dUpBorderLine); |
2688 | |
|
2689 | 0 | SetDiagonalDownBorder(dDownLineItem); |
2690 | 0 | SetDiagonalUpBorder(dUpLineItem); |
2691 | 0 | bIsDiagonalBorder = true; |
2692 | 0 | break; // CRISS-CROSS |
2693 | | |
2694 | 0 | default: |
2695 | 0 | break; |
2696 | 0 | } |
2697 | | |
2698 | | // if diagonal borders selected, |
2699 | | // no need to execute this block |
2700 | 0 | if (!bIsDiagonalBorder) |
2701 | 0 | { |
2702 | 0 | aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT ); |
2703 | 0 | aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT ); |
2704 | 0 | aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP ); |
2705 | 0 | aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM ); |
2706 | |
|
2707 | 0 | if(nModifier == KEY_SHIFT) |
2708 | 0 | nValidFlags |= FrmValidFlags::AllMask; |
2709 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, bool(nValidFlags&FrmValidFlags::Top )); |
2710 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, bool(nValidFlags&FrmValidFlags::Bottom )); |
2711 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, bool(nValidFlags&FrmValidFlags::Left)); |
2712 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, bool(nValidFlags&FrmValidFlags::Right )); |
2713 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, bool(nValidFlags&FrmValidFlags::HInner )); |
2714 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, bool(nValidFlags&FrmValidFlags::VInner)); |
2715 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); |
2716 | 0 | aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false ); |
2717 | |
|
2718 | 0 | Any a1, a2; |
2719 | 0 | aBorderOuter.QueryValue( a1 ); |
2720 | 0 | aBorderInner.QueryValue( a2 ); |
2721 | 0 | Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(u"OuterBorder"_ustr, a1), |
2722 | 0 | comphelper::makePropertyValue(u"InnerBorder"_ustr, a2) }; |
2723 | |
|
2724 | 0 | mxControl->dispatchCommand( u".uno:SetBorderStyle"_ustr, aArgs ); |
2725 | 0 | } |
2726 | | |
2727 | | // coverity[ check_after_deref : FALSE] |
2728 | 0 | if (mxFrameSet) |
2729 | 0 | { |
2730 | | /* #i33380# Moved the following line above the Dispatch() call. |
2731 | | This instance may be deleted in the meantime (i.e. when a dialog is opened |
2732 | | while in Dispatch()), accessing members will crash in this case. */ |
2733 | 0 | mxFrameSet->SetNoSelection(); |
2734 | 0 | } |
2735 | |
|
2736 | 0 | mxControl->EndPopupMode(); |
2737 | 0 | } |
2738 | | |
2739 | | void SvxFrameWindow_Impl::SetDiagonalDownBorder(const SvxLineItem& dDownLineItem) |
2740 | 0 | { |
2741 | | // apply diagonal down border |
2742 | 0 | Any a; |
2743 | 0 | dDownLineItem.QueryValue(a); |
2744 | 0 | Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue(u"BorderTLBR"_ustr, a) }; |
2745 | |
|
2746 | 0 | mxControl->dispatchCommand(u".uno:BorderTLBR"_ustr, aArgs); |
2747 | 0 | } |
2748 | | |
2749 | | void SvxFrameWindow_Impl::SetDiagonalUpBorder(const SvxLineItem& dUpLineItem) |
2750 | 0 | { |
2751 | | // apply diagonal up border |
2752 | 0 | Any a; |
2753 | 0 | dUpLineItem.QueryValue(a); |
2754 | 0 | Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue(u"BorderBLTR"_ustr, a) }; |
2755 | |
|
2756 | 0 | mxControl->dispatchCommand(u".uno:BorderBLTR"_ustr, aArgs); |
2757 | 0 | } |
2758 | | |
2759 | | void SvxFrameWindow_Impl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
2760 | 0 | { |
2761 | 0 | if ( rEvent.FeatureURL.Complete != ".uno:BorderReducedMode" ) |
2762 | 0 | return; |
2763 | | |
2764 | 0 | bool bValue; |
2765 | 0 | if ( !(rEvent.State >>= bValue) ) |
2766 | 0 | return; |
2767 | | |
2768 | 0 | bParagraphMode = bValue; |
2769 | | //initial calls mustn't insert or remove elements |
2770 | 0 | if(!mxFrameSet->GetItemCount()) |
2771 | 0 | return; |
2772 | | |
2773 | | // set 12 border types for Writer and Calc. |
2774 | 0 | bool bTableMode = ( mxFrameSet->GetItemCount() == static_cast<size_t>(12) ); |
2775 | 0 | bool bResize = false; |
2776 | |
|
2777 | 0 | if ( bTableMode && bParagraphMode ) |
2778 | 0 | { |
2779 | 0 | for ( sal_uInt16 i = 9; i < 13; i++ ) |
2780 | 0 | mxFrameSet->RemoveItem(i); |
2781 | 0 | bResize = true; |
2782 | 0 | } |
2783 | 0 | else if ( !bTableMode && !bParagraphMode ) |
2784 | 0 | { |
2785 | 0 | for ( sal_uInt16 i = 9; i < 13; i++ ) |
2786 | 0 | mxFrameSet->InsertItem(i, Image(aImgVec[i-1].first), aImgVec[i-1].second); |
2787 | 0 | bResize = true; |
2788 | 0 | } |
2789 | |
|
2790 | 0 | if ( bResize ) |
2791 | 0 | { |
2792 | 0 | CalcSizeValueSet(); |
2793 | 0 | } |
2794 | 0 | } |
2795 | | |
2796 | | void SvxFrameWindow_Impl::CalcSizeValueSet() |
2797 | 0 | { |
2798 | 0 | weld::DrawingArea* pDrawingArea = mxFrameSet->GetDrawingArea(); |
2799 | 0 | const OutputDevice& rDevice = pDrawingArea->get_ref_device(); |
2800 | 0 | Size aItemSize( 20 * rDevice.GetDPIScaleFactor(), 20 * rDevice.GetDPIScaleFactor() ); |
2801 | 0 | Size aSize = mxFrameSet->CalcWindowSizePixel( aItemSize ); |
2802 | 0 | pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); |
2803 | 0 | mxFrameSet->SetOutputSizePixel(aSize); |
2804 | 0 | } |
2805 | | |
2806 | | void SvxFrameWindow_Impl::InitImageList() |
2807 | 0 | { |
2808 | 0 | if (!m_bIsCalc) |
2809 | 0 | { |
2810 | | // not Writer/Impress/Draw-specific aImgVec. |
2811 | | // Since they don't have diagonal borders, |
2812 | | // we have to use 12 border types here. |
2813 | 0 | aImgVec = { |
2814 | 0 | {Bitmap(RID_SVXBMP_FRAME1), SvxResId(RID_SVXSTR_TABLE_PRESET_NONE)}, |
2815 | 0 | {Bitmap(RID_SVXBMP_FRAME2), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYLEFT)}, |
2816 | 0 | {Bitmap(RID_SVXBMP_FRAME3), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYRIGHT)}, |
2817 | 0 | {Bitmap(RID_SVXBMP_FRAME4), SvxResId(RID_SVXSTR_PARA_PRESET_LEFTRIGHT)}, |
2818 | |
|
2819 | 0 | {Bitmap(RID_SVXBMP_FRAME5), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYTOP)}, |
2820 | 0 | {Bitmap(RID_SVXBMP_FRAME6), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYBOTTOM)}, |
2821 | 0 | {Bitmap(RID_SVXBMP_FRAME7), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOM)}, |
2822 | 0 | {Bitmap(RID_SVXBMP_FRAME8), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTER)}, |
2823 | |
|
2824 | 0 | {Bitmap(RID_SVXBMP_FRAME9), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOMHORI)}, |
2825 | 0 | {Bitmap(RID_SVXBMP_FRAME10), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERHORI)}, |
2826 | 0 | {Bitmap(RID_SVXBMP_FRAME11), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERVERI)}, |
2827 | 0 | {Bitmap(RID_SVXBMP_FRAME12), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERALL)} |
2828 | 0 | }; |
2829 | 0 | } |
2830 | 0 | else |
2831 | 0 | { |
2832 | | // Calc has diagonal borders feature. |
2833 | | // Therefore use additional 3 diagonal border types, |
2834 | | // which make border types for Calc 12 in total. |
2835 | 0 | aImgVec = { |
2836 | 0 | {Bitmap(RID_SVXBMP_FRAME1), SvxResId(RID_SVXSTR_TABLE_PRESET_NONE)}, |
2837 | 0 | {Bitmap(RID_SVXBMP_FRAME8), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTER)}, |
2838 | 0 | {Bitmap(RID_SVXBMP_FRAME12), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERALL)}, |
2839 | 0 | {Bitmap(RID_SVXBMP_FRAME15), SvxResId(RID_SVXSTR_PARA_PRESET_CRISSCROSS)}, // criss-cross border |
2840 | |
|
2841 | 0 | {Bitmap(RID_SVXBMP_FRAME2), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYLEFT)}, |
2842 | 0 | {Bitmap(RID_SVXBMP_FRAME3), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYRIGHT)}, |
2843 | 0 | {Bitmap(RID_SVXBMP_FRAME5), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYTOP)}, |
2844 | 0 | {Bitmap(RID_SVXBMP_FRAME6), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYBOTTOM)}, |
2845 | |
|
2846 | 0 | {Bitmap(RID_SVXBMP_FRAME14), SvxResId(RID_SVXSTR_PARA_PRESET_DIAGONALDOWN)}, // diagonal down border |
2847 | 0 | {Bitmap(RID_SVXBMP_FRAME13), SvxResId(RID_SVXSTR_PARA_PRESET_DIAGONALUP)}, // diagonal up border |
2848 | 0 | {Bitmap(RID_SVXBMP_FRAME7), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOM)}, |
2849 | 0 | {Bitmap(RID_SVXBMP_FRAME4), SvxResId(RID_SVXSTR_PARA_PRESET_LEFTRIGHT)} |
2850 | 0 | }; |
2851 | 0 | } |
2852 | 0 | } |
2853 | | |
2854 | | static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ ) |
2855 | 0 | { |
2856 | 0 | return SvxBorderLine::threeDMediumColor( aMain ); |
2857 | 0 | } |
2858 | | |
2859 | | SvxLineWindow_Impl::SvxLineWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent) |
2860 | 0 | : WeldToolbarPopup(pControl->getFrameInterface(), pParent, u"svx/ui/floatingframeborder.ui"_ustr, u"FloatingFrameBorder"_ustr) |
2861 | 0 | , m_xControl(pControl) |
2862 | 0 | , m_xLineStyleLb(new LineListBox) |
2863 | 0 | , m_xLineStyleLbWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_xLineStyleLb)) |
2864 | 0 | , m_bIsWriter(false) |
2865 | 0 | { |
2866 | 0 | try |
2867 | 0 | { |
2868 | 0 | Reference< lang::XServiceInfo > xServices(m_xFrame->getController()->getModel(), UNO_QUERY); |
2869 | 0 | if (xServices) |
2870 | 0 | m_bIsWriter = xServices->supportsService(u"com.sun.star.text.TextDocument"_ustr); |
2871 | 0 | } |
2872 | 0 | catch(const uno::Exception& ) |
2873 | 0 | { |
2874 | 0 | } |
2875 | |
|
2876 | 0 | m_xLineStyleLb->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); |
2877 | |
|
2878 | 0 | m_xLineStyleLb->SetSourceUnit( FieldUnit::TWIP ); |
2879 | 0 | m_xLineStyleLb->SetNone( comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) |
2880 | 0 | :SvxResId(RID_SVXSTR_NONE) ); |
2881 | |
|
2882 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::SOLID ), SvxBorderLineStyle::SOLID ); |
2883 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOTTED ), SvxBorderLineStyle::DOTTED ); |
2884 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DASHED ), SvxBorderLineStyle::DASHED ); |
2885 | | |
2886 | | // Double lines |
2887 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOUBLE ), SvxBorderLineStyle::DOUBLE ); |
2888 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_SMALLGAP ), SvxBorderLineStyle::THINTHICK_SMALLGAP, 20 ); |
2889 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_MEDIUMGAP ), SvxBorderLineStyle::THINTHICK_MEDIUMGAP ); |
2890 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_LARGEGAP ), SvxBorderLineStyle::THINTHICK_LARGEGAP ); |
2891 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_SMALLGAP ), SvxBorderLineStyle::THICKTHIN_SMALLGAP, 20 ); |
2892 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ), SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ); |
2893 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_LARGEGAP ), SvxBorderLineStyle::THICKTHIN_LARGEGAP ); |
2894 | | |
2895 | | // Engraved / Embossed |
2896 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::EMBOSSED ), SvxBorderLineStyle::EMBOSSED, 15, |
2897 | 0 | &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, |
2898 | 0 | &lcl_mediumColor ); |
2899 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::ENGRAVED ), SvxBorderLineStyle::ENGRAVED, 15, |
2900 | 0 | &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, |
2901 | 0 | &lcl_mediumColor ); |
2902 | | |
2903 | | // Inset / Outset |
2904 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::OUTSET ), SvxBorderLineStyle::OUTSET, 10, |
2905 | 0 | &SvxBorderLine::lightColor, &SvxBorderLine::darkColor ); |
2906 | 0 | m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::INSET ), SvxBorderLineStyle::INSET, 10, |
2907 | 0 | &SvxBorderLine::darkColor, &SvxBorderLine::lightColor ); |
2908 | 0 | Size aSize = m_xLineStyleLb->SetWidth( 20 ); // 1pt by default |
2909 | |
|
2910 | 0 | m_xLineStyleLb->SetSelectHdl( LINK( this, SvxLineWindow_Impl, SelectHdl ) ); |
2911 | |
|
2912 | 0 | m_xContainer->set_help_id(HID_POPUP_LINE); |
2913 | |
|
2914 | 0 | aSize.AdjustWidth(6); |
2915 | 0 | aSize.AdjustHeight(6); |
2916 | 0 | aSize = m_xLineStyleLb->CalcWindowSizePixel(aSize); |
2917 | 0 | m_xLineStyleLb->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); |
2918 | 0 | m_xLineStyleLb->SetOutputSizePixel(aSize); |
2919 | 0 | } |
2920 | | |
2921 | | IMPL_LINK_NOARG(SvxLineWindow_Impl, SelectHdl, ValueSet*, void) |
2922 | 0 | { |
2923 | 0 | SvxLineItem aLineItem( SID_FRAME_LINESTYLE ); |
2924 | 0 | SvxBorderLineStyle nStyle = m_xLineStyleLb->GetSelectEntryStyle(); |
2925 | |
|
2926 | 0 | if ( m_xLineStyleLb->GetSelectItemPos( ) > 0 ) |
2927 | 0 | { |
2928 | 0 | SvxBorderLine aTmp; |
2929 | 0 | aTmp.SetBorderLineStyle( nStyle ); |
2930 | 0 | aTmp.SetWidth( SvxBorderLineWidth::Thin ); // TODO Make it depend on a width field |
2931 | 0 | aLineItem.SetLine( &aTmp ); |
2932 | 0 | } |
2933 | 0 | else |
2934 | 0 | aLineItem.SetLine( nullptr ); |
2935 | |
|
2936 | 0 | Any a; |
2937 | 0 | aLineItem.QueryValue( a, m_bIsWriter ? CONVERT_TWIPS : 0 ); |
2938 | 0 | Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(u"LineStyle"_ustr, a) }; |
2939 | |
|
2940 | 0 | m_xControl->dispatchCommand( u".uno:LineStyle"_ustr, aArgs ); |
2941 | |
|
2942 | 0 | m_xControl->EndPopupMode(); |
2943 | 0 | } |
2944 | | |
2945 | | SfxStyleControllerItem_Impl::SfxStyleControllerItem_Impl( |
2946 | | const Reference< XDispatchProvider >& rDispatchProvider, |
2947 | | sal_uInt16 nSlotId, // Family-ID |
2948 | | const OUString& rCommand, // .uno: command bound to this item |
2949 | | SvxStyleToolBoxControl& rTbxCtl ) // controller instance, which the item is assigned to. |
2950 | 0 | : SfxStatusListener( rDispatchProvider, nSlotId, rCommand ), |
2951 | 0 | rControl( rTbxCtl ) |
2952 | 0 | { |
2953 | 0 | } |
2954 | | |
2955 | | void SfxStyleControllerItem_Impl::StateChangedAtStatusListener( |
2956 | | SfxItemState eState, const SfxPoolItem* pState ) |
2957 | 0 | { |
2958 | 0 | switch ( GetId() ) |
2959 | 0 | { |
2960 | 0 | case SID_STYLE_FAMILY1: |
2961 | 0 | case SID_STYLE_FAMILY2: |
2962 | 0 | case SID_STYLE_FAMILY3: |
2963 | 0 | case SID_STYLE_FAMILY4: |
2964 | 0 | case SID_STYLE_FAMILY5: |
2965 | 0 | { |
2966 | 0 | const sal_uInt16 nIdx = GetId() - SID_STYLE_FAMILY_START; |
2967 | |
|
2968 | 0 | if ( SfxItemState::DEFAULT == eState ) |
2969 | 0 | { |
2970 | 0 | const SfxTemplateItem* pStateItem = |
2971 | 0 | dynamic_cast<const SfxTemplateItem*>( pState ); |
2972 | 0 | DBG_ASSERT( pStateItem != nullptr, "SfxTemplateItem expected" ); |
2973 | 0 | rControl.SetFamilyState( nIdx, pStateItem ); |
2974 | 0 | } |
2975 | 0 | else |
2976 | 0 | rControl.SetFamilyState( nIdx, nullptr ); |
2977 | 0 | break; |
2978 | 0 | } |
2979 | 0 | } |
2980 | 0 | } |
2981 | | |
2982 | | struct SvxStyleToolBoxControl::Impl |
2983 | | { |
2984 | | OUString aClearForm; |
2985 | | OUString aMore; |
2986 | | ::std::vector< std::pair< OUString, OUString > > aDefaultStyles; |
2987 | | bool bSpecModeWriter; |
2988 | | bool bSpecModeCalc; |
2989 | | |
2990 | | VclPtr<SvxStyleBox_Impl> m_xVclBox; |
2991 | | std::unique_ptr<SvxStyleBox_Base> m_xWeldBox; |
2992 | | SvxStyleBox_Base* m_pBox; |
2993 | | |
2994 | | Impl() |
2995 | 0 | :aClearForm ( SvxResId( RID_SVXSTR_CLEARFORM ) ) |
2996 | 0 | ,aMore ( SvxResId( RID_SVXSTR_MORE_STYLES ) ) |
2997 | 0 | ,bSpecModeWriter ( false ) |
2998 | 0 | ,bSpecModeCalc ( false ) |
2999 | 0 | ,m_pBox ( nullptr ) |
3000 | 0 | { |
3001 | | |
3002 | |
|
3003 | 0 | } |
3004 | | void InitializeStyles(const Reference < frame::XModel >& xModel) |
3005 | 0 | { |
3006 | 0 | aDefaultStyles.clear(); |
3007 | | |
3008 | | //now convert the default style names to the localized names |
3009 | 0 | try |
3010 | 0 | { |
3011 | 0 | Reference< style::XStyleFamiliesSupplier > xStylesSupplier( xModel, UNO_QUERY_THROW ); |
3012 | 0 | Reference< lang::XServiceInfo > xServices( xModel, UNO_QUERY_THROW ); |
3013 | 0 | bSpecModeWriter = xServices->supportsService(u"com.sun.star.text.TextDocument"_ustr); |
3014 | 0 | if(bSpecModeWriter) |
3015 | 0 | { |
3016 | 0 | Reference<container::XNameAccess> xParaStyles; |
3017 | 0 | xStylesSupplier->getStyleFamilies()->getByName(u"ParagraphStyles"_ustr) >>= |
3018 | 0 | xParaStyles; |
3019 | 0 | static constexpr OUString aWriterStyles[] |
3020 | 0 | { |
3021 | 0 | u"Standard"_ustr, |
3022 | 0 | u"Text body"_ustr, |
3023 | 0 | u"Title"_ustr, |
3024 | 0 | u"Subtitle"_ustr, |
3025 | 0 | u"Heading 1"_ustr, |
3026 | 0 | u"Heading 2"_ustr, |
3027 | 0 | u"Heading 3"_ustr, |
3028 | 0 | u"Heading 4"_ustr, |
3029 | 0 | u"Quotations"_ustr, |
3030 | 0 | u"Preformatted Text"_ustr |
3031 | 0 | }; |
3032 | 0 | for( const OUString& aStyle: aWriterStyles ) |
3033 | 0 | { |
3034 | 0 | try |
3035 | 0 | { |
3036 | 0 | Reference< beans::XPropertySet > xStyle; |
3037 | 0 | xParaStyles->getByName( aStyle ) >>= xStyle; |
3038 | 0 | OUString sName; |
3039 | 0 | xStyle->getPropertyValue(u"DisplayName"_ustr) >>= sName; |
3040 | 0 | if( !sName.isEmpty() ) |
3041 | 0 | aDefaultStyles.push_back( |
3042 | 0 | std::pair<OUString, OUString>(aStyle, sName) ); |
3043 | 0 | } |
3044 | 0 | catch( const uno::Exception& ) |
3045 | 0 | {} |
3046 | 0 | } |
3047 | |
|
3048 | 0 | } |
3049 | 0 | else if( ( |
3050 | 0 | bSpecModeCalc = xServices->supportsService( |
3051 | 0 | u"com.sun.star.sheet.SpreadsheetDocument"_ustr))) |
3052 | 0 | { |
3053 | 0 | static constexpr OUString aCalcStyles[] |
3054 | 0 | { |
3055 | 0 | u"Default"_ustr, |
3056 | 0 | u"Accent 1"_ustr, |
3057 | 0 | u"Accent 2"_ustr, |
3058 | 0 | u"Accent 3"_ustr, |
3059 | 0 | u"Heading 1"_ustr, |
3060 | 0 | u"Heading 2"_ustr, |
3061 | 0 | u"Result"_ustr |
3062 | 0 | }; |
3063 | 0 | Reference<container::XNameAccess> xCellStyles; |
3064 | 0 | xStylesSupplier->getStyleFamilies()->getByName(u"CellStyles"_ustr) >>= xCellStyles; |
3065 | 0 | for(const OUString & sStyleName : aCalcStyles) |
3066 | 0 | { |
3067 | 0 | try |
3068 | 0 | { |
3069 | 0 | if( xCellStyles->hasByName( sStyleName ) ) |
3070 | 0 | { |
3071 | 0 | Reference< beans::XPropertySet > xStyle( xCellStyles->getByName( sStyleName), UNO_QUERY_THROW ); |
3072 | 0 | OUString sName; |
3073 | 0 | xStyle->getPropertyValue(u"DisplayName"_ustr) >>= sName; |
3074 | 0 | if( !sName.isEmpty() ) |
3075 | 0 | aDefaultStyles.push_back( |
3076 | 0 | std::pair<OUString, OUString>(sStyleName, sName) ); |
3077 | 0 | } |
3078 | 0 | } |
3079 | 0 | catch( const uno::Exception& ) |
3080 | 0 | {} |
3081 | 0 | } |
3082 | 0 | } |
3083 | 0 | } |
3084 | 0 | catch(const uno::Exception& ) |
3085 | 0 | { |
3086 | 0 | OSL_FAIL("error while initializing style names"); |
3087 | 0 | } |
3088 | 0 | } |
3089 | | }; |
3090 | | |
3091 | | // mapping table from bound items. BE CAREFUL this table must be in the |
3092 | | // same order as the uno commands bound to the slots SID_STYLE_FAMILY1..n |
3093 | | // MAX_FAMILIES must also be correctly set! |
3094 | | constexpr OUString StyleSlotToStyleCommand[MAX_FAMILIES] = |
3095 | | { |
3096 | | u".uno:CharStyle"_ustr, |
3097 | | u".uno:ParaStyle"_ustr, |
3098 | | u".uno:FrameStyle"_ustr, |
3099 | | u".uno:PageStyle"_ustr, |
3100 | | u".uno:TemplateFamily5"_ustr |
3101 | | }; |
3102 | | |
3103 | | SvxStyleToolBoxControl::SvxStyleToolBoxControl() |
3104 | 0 | : m_pImpl(new Impl) |
3105 | 0 | , m_pStyleSheetPool(nullptr) |
3106 | 0 | , m_nActFamily(0xffff) |
3107 | 0 | { |
3108 | 0 | for (sal_uInt16 i = 0; i < MAX_FAMILIES; ++i) |
3109 | 0 | { |
3110 | 0 | m_xBoundItems[i].clear(); |
3111 | 0 | m_pFamilyState[i] = nullptr; |
3112 | 0 | } |
3113 | 0 | } |
3114 | | |
3115 | | SvxStyleToolBoxControl::~SvxStyleToolBoxControl() |
3116 | 0 | { |
3117 | 0 | } |
3118 | | |
3119 | | void SAL_CALL SvxStyleToolBoxControl::initialize(const Sequence<Any>& rArguments) |
3120 | 0 | { |
3121 | 0 | svt::ToolboxController::initialize(rArguments); |
3122 | | |
3123 | | // After initialize we should have a valid frame member where we can retrieve our |
3124 | | // dispatch provider. |
3125 | 0 | if ( !m_xFrame.is() ) |
3126 | 0 | return; |
3127 | | |
3128 | 0 | m_pImpl->InitializeStyles(m_xFrame->getController()->getModel()); |
3129 | 0 | Reference< XDispatchProvider > xDispatchProvider( m_xFrame->getController(), UNO_QUERY ); |
3130 | 0 | for ( sal_uInt16 i=0; i<MAX_FAMILIES; i++ ) |
3131 | 0 | { |
3132 | 0 | m_xBoundItems[i] = new SfxStyleControllerItem_Impl( xDispatchProvider, |
3133 | 0 | SID_STYLE_FAMILY_START + i, |
3134 | 0 | StyleSlotToStyleCommand[i], |
3135 | 0 | *this ); |
3136 | 0 | m_pFamilyState[i] = nullptr; |
3137 | 0 | } |
3138 | 0 | } |
3139 | | |
3140 | | // XComponent |
3141 | | void SAL_CALL SvxStyleToolBoxControl::dispose() |
3142 | 0 | { |
3143 | 0 | svt::ToolboxController::dispose(); |
3144 | |
|
3145 | 0 | SolarMutexGuard aSolarMutexGuard; |
3146 | 0 | m_pImpl->m_xVclBox.disposeAndClear(); |
3147 | 0 | m_pImpl->m_xWeldBox.reset(); |
3148 | 0 | m_pImpl->m_pBox = nullptr; |
3149 | |
|
3150 | 0 | for (rtl::Reference<SfxStyleControllerItem_Impl>& pBoundItem : m_xBoundItems) |
3151 | 0 | { |
3152 | 0 | if (!pBoundItem) |
3153 | 0 | continue; |
3154 | 0 | pBoundItem->UnBind(); |
3155 | 0 | } |
3156 | 0 | unbindListener(); |
3157 | |
|
3158 | 0 | for( sal_uInt16 i=0; i<MAX_FAMILIES; i++ ) |
3159 | 0 | { |
3160 | 0 | if ( m_xBoundItems[i].is() ) |
3161 | 0 | { |
3162 | 0 | try |
3163 | 0 | { |
3164 | 0 | m_xBoundItems[i]->dispose(); |
3165 | 0 | } |
3166 | 0 | catch ( Exception& ) |
3167 | 0 | { |
3168 | 0 | } |
3169 | |
|
3170 | 0 | m_xBoundItems[i].clear(); |
3171 | 0 | } |
3172 | 0 | m_pFamilyState[i].reset(); |
3173 | 0 | } |
3174 | 0 | m_pStyleSheetPool = nullptr; |
3175 | 0 | m_pImpl.reset(); |
3176 | 0 | } |
3177 | | |
3178 | | OUString SvxStyleToolBoxControl::getImplementationName() |
3179 | 0 | { |
3180 | 0 | return u"com.sun.star.comp.svx.StyleToolBoxControl"_ustr; |
3181 | 0 | } |
3182 | | |
3183 | | sal_Bool SvxStyleToolBoxControl::supportsService( const OUString& rServiceName ) |
3184 | 0 | { |
3185 | 0 | return cppu::supportsService( this, rServiceName ); |
3186 | 0 | } |
3187 | | |
3188 | | css::uno::Sequence< OUString > SvxStyleToolBoxControl::getSupportedServiceNames() |
3189 | 0 | { |
3190 | 0 | return { u"com.sun.star.frame.ToolbarController"_ustr }; |
3191 | 0 | } |
3192 | | |
3193 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
3194 | | com_sun_star_comp_svx_StyleToolBoxControl_get_implementation( |
3195 | | css::uno::XComponentContext*, |
3196 | | css::uno::Sequence<css::uno::Any> const & ) |
3197 | 0 | { |
3198 | 0 | return cppu::acquire( new SvxStyleToolBoxControl() ); |
3199 | 0 | } |
3200 | | |
3201 | | void SAL_CALL SvxStyleToolBoxControl::update() |
3202 | 0 | { |
3203 | 0 | for (rtl::Reference<SfxStyleControllerItem_Impl>& pBoundItem : m_xBoundItems) |
3204 | 0 | pBoundItem->ReBind(); |
3205 | 0 | bindListener(); |
3206 | 0 | } |
3207 | | |
3208 | | SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const |
3209 | 0 | { |
3210 | 0 | switch ( m_nActFamily-1 + SID_STYLE_FAMILY_START ) |
3211 | 0 | { |
3212 | 0 | case SID_STYLE_FAMILY1: return SfxStyleFamily::Char; |
3213 | 0 | case SID_STYLE_FAMILY2: return SfxStyleFamily::Para; |
3214 | 0 | case SID_STYLE_FAMILY3: return SfxStyleFamily::Frame; |
3215 | 0 | case SID_STYLE_FAMILY4: return SfxStyleFamily::Page; |
3216 | 0 | case SID_STYLE_FAMILY5: return SfxStyleFamily::Pseudo; |
3217 | 0 | default: |
3218 | 0 | OSL_FAIL( "unknown style family" ); |
3219 | 0 | break; |
3220 | 0 | } |
3221 | 0 | return SfxStyleFamily::Para; |
3222 | 0 | } |
3223 | | |
3224 | | void SvxStyleToolBoxControl::FillStyleBox() |
3225 | 0 | { |
3226 | 0 | SvxStyleBox_Base* pBox = m_pImpl->m_pBox; |
3227 | |
|
3228 | 0 | DBG_ASSERT( m_pStyleSheetPool, "StyleSheetPool not found!" ); |
3229 | 0 | DBG_ASSERT( pBox, "Control not found!" ); |
3230 | |
|
3231 | 0 | if ( !(m_pStyleSheetPool && pBox && m_nActFamily!=0xffff) ) |
3232 | 0 | return; |
3233 | | |
3234 | 0 | const SfxStyleFamily eFamily = GetActFamily(); |
3235 | | |
3236 | | // TODO: Check whether fill is necessary |
3237 | |
|
3238 | 0 | OUString aStrSel(pBox->get_active_text()); |
3239 | 0 | pBox->freeze(); |
3240 | 0 | pBox->clear(); |
3241 | | |
3242 | | // Insert Clear button |
3243 | |
|
3244 | 0 | if (m_pImpl->bSpecModeWriter || m_pImpl->bSpecModeCalc) |
3245 | 0 | { |
3246 | 0 | pBox->append_text(m_pImpl->aClearForm); |
3247 | 0 | pBox->insert_separator(1, u"separator"_ustr); |
3248 | 0 | } |
3249 | | |
3250 | | // Add used, favourite and user defined |
3251 | |
|
3252 | 0 | std::vector<OUString> aStyles; |
3253 | | // use a set to avoid O(n^2) performance problem in insert loop |
3254 | 0 | std::unordered_set<OUString> aStylesSet; |
3255 | |
|
3256 | 0 | AppendStyles(aStyles, eFamily, SfxStyleSearchBits::Favourite); |
3257 | 0 | AppendStyles(aStyles, eFamily, SfxStyleSearchBits::UserDefined); |
3258 | 0 | AppendStyles(aStyles, eFamily, SfxStyleSearchBits::Used); |
3259 | | |
3260 | | // Add default styles on top first |
3261 | 0 | if (m_pImpl->bSpecModeWriter || m_pImpl->bSpecModeCalc) |
3262 | 0 | { |
3263 | 0 | for( const auto &rStyle : m_pImpl->aDefaultStyles ) |
3264 | 0 | { |
3265 | 0 | pBox->append_text(rStyle.second); |
3266 | 0 | aStylesSet.insert(rStyle.second); |
3267 | 0 | } |
3268 | 0 | } |
3269 | | |
3270 | | // Insert styles |
3271 | 0 | for (const auto& rStyle : aStyles) |
3272 | 0 | { |
3273 | | // do not duplicate default styles |
3274 | 0 | if (aStylesSet.insert(rStyle).second) |
3275 | 0 | pBox->append_text(rStyle); |
3276 | 0 | } |
3277 | | |
3278 | | // Insert More button |
3279 | 0 | if ((m_pImpl->bSpecModeWriter || m_pImpl->bSpecModeCalc) && !comphelper::LibreOfficeKit::isActive()) |
3280 | 0 | pBox->append_text(m_pImpl->aMore); |
3281 | |
|
3282 | 0 | pBox->thaw(); |
3283 | 0 | pBox->set_active_or_entry_text(aStrSel); |
3284 | 0 | pBox->SetFamily( eFamily ); |
3285 | 0 | } |
3286 | | |
3287 | | void SvxStyleToolBoxControl::AppendStyles(std::vector<OUString>& rStyles, SfxStyleFamily eFamily, |
3288 | | SfxStyleSearchBits eBits) |
3289 | 0 | { |
3290 | 0 | auto xIter = m_pStyleSheetPool->CreateIterator(eFamily, eBits); |
3291 | 0 | SfxStyleSheetBase* pStyle = xIter->First(); |
3292 | |
|
3293 | 0 | pStyle = xIter->Next(); |
3294 | 0 | while ( pStyle ) |
3295 | 0 | { |
3296 | 0 | rStyles.push_back(pStyle->GetName()); |
3297 | 0 | pStyle = xIter->Next(); |
3298 | 0 | } |
3299 | 0 | } |
3300 | | |
3301 | | void SvxStyleToolBoxControl::SelectStyle( const OUString& rStyleName ) |
3302 | 0 | { |
3303 | 0 | SvxStyleBox_Base* pBox = m_pImpl->m_pBox; |
3304 | 0 | DBG_ASSERT( pBox, "Control not found!" ); |
3305 | |
|
3306 | 0 | if ( !pBox ) |
3307 | 0 | return; |
3308 | | |
3309 | 0 | OUString aStrSel(pBox->get_active_text()); |
3310 | |
|
3311 | 0 | if ( !rStyleName.isEmpty() ) |
3312 | 0 | { |
3313 | 0 | OUString aNewStyle = rStyleName; |
3314 | |
|
3315 | 0 | auto aFound = std::find_if(m_pImpl->aDefaultStyles.begin(), m_pImpl->aDefaultStyles.end(), |
3316 | 0 | [rStyleName] (auto it) { return it.first == rStyleName || it.second == rStyleName; } |
3317 | 0 | ); |
3318 | |
|
3319 | 0 | if (aFound != m_pImpl->aDefaultStyles.end()) |
3320 | 0 | aNewStyle = aFound->second; |
3321 | |
|
3322 | 0 | if ( aNewStyle != aStrSel ) |
3323 | 0 | pBox->set_active_or_entry_text( aNewStyle ); |
3324 | 0 | } |
3325 | 0 | else |
3326 | 0 | pBox->set_active(-1); |
3327 | 0 | pBox->save_value(); |
3328 | 0 | } |
3329 | | |
3330 | | void SvxStyleToolBoxControl::Update() |
3331 | 0 | { |
3332 | 0 | SfxStyleSheetBasePool* pPool = nullptr; |
3333 | 0 | SfxObjectShell* pDocShell = SfxObjectShell::Current(); |
3334 | |
|
3335 | 0 | if ( pDocShell ) |
3336 | 0 | pPool = pDocShell->GetStyleSheetPool(); |
3337 | |
|
3338 | 0 | sal_uInt16 i; |
3339 | 0 | for ( i=0; i<MAX_FAMILIES; i++ ) |
3340 | 0 | if( m_pFamilyState[i] ) |
3341 | 0 | break; |
3342 | |
|
3343 | 0 | if ( i==MAX_FAMILIES || !pPool ) |
3344 | 0 | { |
3345 | 0 | m_pStyleSheetPool = pPool; |
3346 | 0 | return; |
3347 | 0 | } |
3348 | | |
3349 | | |
3350 | 0 | const SfxTemplateItem* pItem = nullptr; |
3351 | |
|
3352 | 0 | if ( m_nActFamily == 0xffff || nullptr == (pItem = m_pFamilyState[m_nActFamily-1].get()) ) |
3353 | | // Current range not within allowed ranges or default |
3354 | 0 | { |
3355 | 0 | m_pStyleSheetPool = pPool; |
3356 | 0 | m_nActFamily = 2; |
3357 | |
|
3358 | 0 | pItem = m_pFamilyState[m_nActFamily-1].get(); |
3359 | 0 | if ( !pItem ) |
3360 | 0 | { |
3361 | 0 | m_nActFamily++; |
3362 | 0 | pItem = m_pFamilyState[m_nActFamily-1].get(); |
3363 | 0 | } |
3364 | 0 | } |
3365 | 0 | else if ( pPool != m_pStyleSheetPool ) |
3366 | 0 | m_pStyleSheetPool = pPool; |
3367 | |
|
3368 | 0 | FillStyleBox(); // Decides by itself whether Fill is needed |
3369 | |
|
3370 | 0 | if ( pItem ) |
3371 | 0 | SelectStyle( pItem->GetStyleName() ); |
3372 | 0 | } |
3373 | | |
3374 | | void SvxStyleToolBoxControl::SetFamilyState( sal_uInt16 nIdx, |
3375 | | const SfxTemplateItem* pItem ) |
3376 | 0 | { |
3377 | 0 | m_pFamilyState[nIdx].reset( pItem == nullptr ? nullptr : new SfxTemplateItem( *pItem ) ); |
3378 | 0 | Update(); |
3379 | 0 | } |
3380 | | |
3381 | | void SvxStyleToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
3382 | 0 | { |
3383 | 0 | SolarMutexGuard aGuard; |
3384 | |
|
3385 | 0 | if (m_pToolbar) |
3386 | 0 | m_pToolbar->set_item_sensitive(m_aCommandURL, rEvent.IsEnabled); |
3387 | 0 | else |
3388 | 0 | { |
3389 | 0 | ToolBox* pToolBox = nullptr; |
3390 | 0 | ToolBoxItemId nId; |
3391 | 0 | if (!getToolboxId( nId, &pToolBox ) ) |
3392 | 0 | return; |
3393 | 0 | pToolBox->EnableItem( nId, rEvent.IsEnabled ); |
3394 | 0 | } |
3395 | | |
3396 | 0 | if (rEvent.IsEnabled) |
3397 | 0 | Update(); |
3398 | 0 | } |
3399 | | |
3400 | | css::uno::Reference<css::awt::XWindow> SvxStyleToolBoxControl::createItemWindow(const css::uno::Reference< css::awt::XWindow>& rParent) |
3401 | 0 | { |
3402 | 0 | uno::Reference< awt::XWindow > xItemWindow; |
3403 | |
|
3404 | 0 | if (m_pBuilder) |
3405 | 0 | { |
3406 | 0 | SolarMutexGuard aSolarMutexGuard; |
3407 | |
|
3408 | 0 | std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box(u"applystyle"_ustr)); |
3409 | |
|
3410 | 0 | xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); |
3411 | |
|
3412 | 0 | m_pImpl->m_xWeldBox.reset(new SvxStyleBox_Base(std::move(xWidget), |
3413 | 0 | u".uno:StyleApply"_ustr, |
3414 | 0 | SfxStyleFamily::Para, |
3415 | 0 | m_xFrame, |
3416 | 0 | m_pImpl->aClearForm, |
3417 | 0 | m_pImpl->aMore, |
3418 | 0 | m_pImpl->bSpecModeWriter || m_pImpl->bSpecModeCalc, *this)); |
3419 | 0 | m_pImpl->m_pBox = m_pImpl->m_xWeldBox.get(); |
3420 | 0 | } |
3421 | 0 | else |
3422 | 0 | { |
3423 | 0 | VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent); |
3424 | 0 | if ( pParent ) |
3425 | 0 | { |
3426 | 0 | SolarMutexGuard aSolarMutexGuard; |
3427 | |
|
3428 | 0 | m_pImpl->m_xVclBox = VclPtr<SvxStyleBox_Impl>::Create(pParent, |
3429 | 0 | ".uno:StyleApply", |
3430 | 0 | SfxStyleFamily::Para, |
3431 | 0 | m_xFrame, |
3432 | 0 | m_pImpl->aClearForm, |
3433 | 0 | m_pImpl->aMore, |
3434 | 0 | m_pImpl->bSpecModeWriter || m_pImpl->bSpecModeCalc, *this); |
3435 | 0 | m_pImpl->m_pBox = m_pImpl->m_xVclBox.get(); |
3436 | 0 | xItemWindow = VCLUnoHelper::GetInterface(m_pImpl->m_xVclBox); |
3437 | 0 | } |
3438 | 0 | } |
3439 | |
|
3440 | 0 | if (m_pImpl->m_pBox && !m_pImpl->aDefaultStyles.empty()) |
3441 | 0 | m_pImpl->m_pBox->SetDefaultStyle(m_pImpl->aDefaultStyles[0].second); |
3442 | |
|
3443 | 0 | return xItemWindow; |
3444 | 0 | } |
3445 | | |
3446 | | SvxFontNameToolBoxControl::SvxFontNameToolBoxControl() |
3447 | 0 | : m_pBox(nullptr) |
3448 | 0 | { |
3449 | 0 | } |
3450 | | |
3451 | | void SvxFontNameBox_Base::statusChanged_Impl( const css::frame::FeatureStateEvent& rEvent ) |
3452 | 0 | { |
3453 | 0 | if ( !rEvent.IsEnabled ) |
3454 | 0 | { |
3455 | 0 | set_sensitive(false); |
3456 | 0 | Update( nullptr ); |
3457 | 0 | } |
3458 | 0 | else |
3459 | 0 | { |
3460 | 0 | set_sensitive(true); |
3461 | |
|
3462 | 0 | css::awt::FontDescriptor aFontDesc; |
3463 | 0 | if ( rEvent.State >>= aFontDesc ) |
3464 | 0 | Update(&aFontDesc); |
3465 | 0 | else { |
3466 | | // no active element; delete value in the display |
3467 | 0 | m_xWidget->set_active(-1); |
3468 | 0 | set_active_or_entry_text(u""_ustr); |
3469 | 0 | } |
3470 | 0 | m_xWidget->save_value(); |
3471 | 0 | } |
3472 | 0 | } |
3473 | | |
3474 | | void SvxFontNameToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
3475 | 0 | { |
3476 | 0 | SolarMutexGuard aGuard; |
3477 | 0 | m_pBox->statusChanged_Impl(rEvent); |
3478 | |
|
3479 | 0 | if (m_pToolbar) |
3480 | 0 | m_pToolbar->set_item_sensitive(m_aCommandURL, rEvent.IsEnabled); |
3481 | 0 | else |
3482 | 0 | { |
3483 | 0 | ToolBox* pToolBox = nullptr; |
3484 | 0 | ToolBoxItemId nId; |
3485 | 0 | if (!getToolboxId( nId, &pToolBox ) ) |
3486 | 0 | return; |
3487 | 0 | pToolBox->EnableItem( nId, rEvent.IsEnabled ); |
3488 | 0 | } |
3489 | 0 | } |
3490 | | |
3491 | | css::uno::Reference<css::awt::XWindow> SvxFontNameToolBoxControl::createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) |
3492 | 0 | { |
3493 | 0 | uno::Reference< awt::XWindow > xItemWindow; |
3494 | |
|
3495 | 0 | if (m_pBuilder) |
3496 | 0 | { |
3497 | 0 | SolarMutexGuard aSolarMutexGuard; |
3498 | |
|
3499 | 0 | std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box(u"fontnamecombobox"_ustr)); |
3500 | |
|
3501 | 0 | xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); |
3502 | |
|
3503 | 0 | m_xWeldBox.reset(new SvxFontNameBox_Base(std::move(xWidget), m_xFrame, *this)); |
3504 | 0 | m_pBox = m_xWeldBox.get(); |
3505 | 0 | } |
3506 | 0 | else |
3507 | 0 | { |
3508 | 0 | VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent); |
3509 | 0 | if ( pParent ) |
3510 | 0 | { |
3511 | 0 | SolarMutexGuard aSolarMutexGuard; |
3512 | 0 | m_xVclBox = VclPtr<SvxFontNameBox_Impl>::Create(pParent, m_xFrame, *this); |
3513 | 0 | m_pBox = m_xVclBox.get(); |
3514 | 0 | xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox); |
3515 | 0 | } |
3516 | 0 | } |
3517 | |
|
3518 | 0 | return xItemWindow; |
3519 | 0 | } |
3520 | | |
3521 | | void SvxFontNameToolBoxControl::dispose() |
3522 | 0 | { |
3523 | 0 | ToolboxController::dispose(); |
3524 | |
|
3525 | 0 | SolarMutexGuard aSolarMutexGuard; |
3526 | 0 | m_xVclBox.disposeAndClear(); |
3527 | 0 | m_xWeldBox.reset(); |
3528 | 0 | m_pBox = nullptr; |
3529 | 0 | } |
3530 | | |
3531 | | OUString SvxFontNameToolBoxControl::getImplementationName() |
3532 | 0 | { |
3533 | 0 | return u"com.sun.star.comp.svx.FontNameToolBoxControl"_ustr; |
3534 | 0 | } |
3535 | | |
3536 | | sal_Bool SvxFontNameToolBoxControl::supportsService( const OUString& rServiceName ) |
3537 | 0 | { |
3538 | 0 | return cppu::supportsService( this, rServiceName ); |
3539 | 0 | } |
3540 | | |
3541 | | css::uno::Sequence< OUString > SvxFontNameToolBoxControl::getSupportedServiceNames() |
3542 | 0 | { |
3543 | 0 | return { u"com.sun.star.frame.ToolbarController"_ustr }; |
3544 | 0 | } |
3545 | | |
3546 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
3547 | | com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation( |
3548 | | css::uno::XComponentContext*, |
3549 | | css::uno::Sequence<css::uno::Any> const & ) |
3550 | 0 | { |
3551 | 0 | return cppu::acquire( new SvxFontNameToolBoxControl() ); |
3552 | 0 | } |
3553 | | |
3554 | | SvxColorToolBoxControl::SvxColorToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) : |
3555 | 0 | ImplInheritanceHelper( rContext, nullptr, OUString() ), |
3556 | 0 | m_bSplitButton(true), |
3557 | 0 | m_nSlotId(0), |
3558 | 0 | m_aColorSelectFunction(PaletteManager::DispatchColorCommand) |
3559 | 0 | { |
3560 | 0 | } |
3561 | | |
3562 | | namespace { |
3563 | | |
3564 | | sal_uInt16 MapCommandToSlotId(const OUString& rCommand) |
3565 | 0 | { |
3566 | 0 | if (rCommand == ".uno:Color") |
3567 | 0 | return SID_ATTR_CHAR_COLOR; |
3568 | 0 | else if (rCommand == ".uno:FontColor") |
3569 | 0 | return SID_ATTR_CHAR_COLOR2; |
3570 | 0 | else if (rCommand == ".uno:BackColor") // deprecated - use CharBackColor |
3571 | 0 | return SID_ATTR_CHAR_COLOR_BACKGROUND; |
3572 | 0 | else if (rCommand == ".uno:CharBackColor") |
3573 | 0 | return SID_ATTR_CHAR_BACK_COLOR; |
3574 | 0 | else if (rCommand == ".uno:BackgroundColor") |
3575 | 0 | return SID_BACKGROUND_COLOR; |
3576 | 0 | else if (rCommand == ".uno:TableCellBackgroundColor") |
3577 | 0 | return SID_TABLE_CELL_BACKGROUND_COLOR; |
3578 | 0 | else if (rCommand == ".uno:Extrusion3DColor") |
3579 | 0 | return SID_EXTRUSION_3D_COLOR; |
3580 | 0 | else if (rCommand == ".uno:XLineColor") |
3581 | 0 | return SID_ATTR_LINE_COLOR; |
3582 | 0 | else if (rCommand == ".uno:FillColor") |
3583 | 0 | return SID_ATTR_FILL_COLOR; |
3584 | 0 | else if (rCommand == ".uno:FrameLineColor") |
3585 | 0 | return SID_FRAME_LINECOLOR; |
3586 | | |
3587 | 0 | SAL_WARN("svx.tbxcrtls", "Unknown color command: " << rCommand); |
3588 | 0 | return 0; |
3589 | 0 | } |
3590 | | |
3591 | | } |
3592 | | |
3593 | | void SvxColorToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) |
3594 | 0 | { |
3595 | 0 | PopupWindowController::initialize( rArguments ); |
3596 | |
|
3597 | 0 | m_nSlotId = MapCommandToSlotId( m_aCommandURL ); |
3598 | |
|
3599 | 0 | if ( m_nSlotId == SID_ATTR_LINE_COLOR || m_nSlotId == SID_ATTR_FILL_COLOR || |
3600 | 0 | m_nSlotId == SID_FRAME_LINECOLOR || m_nSlotId == SID_BACKGROUND_COLOR ) |
3601 | 0 | { |
3602 | | // Sidebar uses wide buttons for those. |
3603 | 0 | m_bSplitButton = !m_bSidebar; |
3604 | 0 | } |
3605 | |
|
3606 | 0 | auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(getCommandURL(), getModuleName()); |
3607 | 0 | OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); |
3608 | |
|
3609 | 0 | if (m_pToolbar) |
3610 | 0 | { |
3611 | 0 | mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); |
3612 | 0 | m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); |
3613 | 0 | m_xBtnUpdater.reset(new svx::ToolboxButtonColorUpdater(m_nSlotId, m_aCommandURL, m_pToolbar, !m_bSplitButton, aCommandLabel, m_xFrame)); |
3614 | 0 | return; |
3615 | 0 | } |
3616 | | |
3617 | 0 | ToolBox* pToolBox = nullptr; |
3618 | 0 | ToolBoxItemId nId; |
3619 | 0 | if (getToolboxId(nId, &pToolBox)) |
3620 | 0 | { |
3621 | 0 | m_xBtnUpdater.reset( new svx::VclToolboxButtonColorUpdater( m_nSlotId, nId, pToolBox, !m_bSplitButton, aCommandLabel, m_aCommandURL, m_xFrame ) ); |
3622 | 0 | pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ( m_bSplitButton ? ToolBoxItemBits::DROPDOWN : ToolBoxItemBits::DROPDOWNONLY ) ); |
3623 | 0 | } |
3624 | 0 | } |
3625 | | |
3626 | | void SvxColorToolBoxControl::update() |
3627 | 0 | { |
3628 | 0 | PopupWindowController::update(); |
3629 | |
|
3630 | 0 | switch( m_nSlotId ) |
3631 | 0 | { |
3632 | 0 | case SID_ATTR_CHAR_COLOR2: |
3633 | 0 | addStatusListener( u".uno:CharColorExt"_ustr); |
3634 | 0 | break; |
3635 | | |
3636 | 0 | case SID_ATTR_CHAR_BACK_COLOR: |
3637 | 0 | case SID_ATTR_CHAR_COLOR_BACKGROUND: |
3638 | 0 | addStatusListener( u".uno:CharBackgroundExt"_ustr); |
3639 | 0 | break; |
3640 | | |
3641 | 0 | case SID_FRAME_LINECOLOR: |
3642 | 0 | addStatusListener( u".uno:BorderTLBR"_ustr); |
3643 | 0 | addStatusListener( u".uno:BorderBLTR"_ustr); |
3644 | 0 | break; |
3645 | 0 | } |
3646 | 0 | } |
3647 | | |
3648 | | void SvxColorToolBoxControl::EnsurePaletteManager() |
3649 | 0 | { |
3650 | 0 | if (!m_xPaletteManager) |
3651 | 0 | { |
3652 | 0 | m_xPaletteManager = std::make_shared<PaletteManager>(); |
3653 | 0 | m_xPaletteManager->SetBtnUpdater(m_xBtnUpdater.get()); |
3654 | 0 | } |
3655 | 0 | } |
3656 | | |
3657 | | SvxColorToolBoxControl::~SvxColorToolBoxControl() |
3658 | 0 | { |
3659 | 0 | if (m_xPaletteManager) |
3660 | 0 | m_xPaletteManager->SetBtnUpdater(nullptr); |
3661 | 0 | } |
3662 | | |
3663 | | void SvxColorToolBoxControl::setColorSelectFunction(const ColorSelectFunction& aColorSelectFunction) |
3664 | 0 | { |
3665 | 0 | m_aColorSelectFunction = aColorSelectFunction; |
3666 | 0 | if (m_xPaletteManager) |
3667 | 0 | m_xPaletteManager->SetColorSelectFunction(aColorSelectFunction); |
3668 | 0 | } |
3669 | | |
3670 | | weld::Window* SvxColorToolBoxControl::GetParentFrame() const |
3671 | 0 | { |
3672 | 0 | const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow(); |
3673 | 0 | return Application::GetFrameWeld(xParent); |
3674 | 0 | } |
3675 | | |
3676 | | std::unique_ptr<WeldToolbarPopup> SvxColorToolBoxControl::weldPopupWindow() |
3677 | 0 | { |
3678 | 0 | EnsurePaletteManager(); |
3679 | |
|
3680 | 0 | auto xPopover = std::make_unique<ColorWindow>( |
3681 | 0 | m_aCommandURL, |
3682 | 0 | m_xPaletteManager, |
3683 | 0 | m_aColorStatus, |
3684 | 0 | m_nSlotId, |
3685 | 0 | m_xFrame, |
3686 | 0 | MenuOrToolMenuButton(m_pToolbar, m_aCommandURL), |
3687 | 0 | [this] { return GetParentFrame(); }, |
3688 | 0 | m_aColorSelectFunction); |
3689 | |
|
3690 | 0 | return xPopover; |
3691 | 0 | } |
3692 | | |
3693 | | VclPtr<vcl::Window> SvxColorToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) |
3694 | 0 | { |
3695 | 0 | ToolBox* pToolBox = nullptr; |
3696 | 0 | ToolBoxItemId nId; |
3697 | 0 | if (!getToolboxId(nId, &pToolBox)) |
3698 | 0 | return nullptr; |
3699 | | |
3700 | 0 | EnsurePaletteManager(); |
3701 | |
|
3702 | 0 | auto xPopover = std::make_unique<ColorWindow>( |
3703 | 0 | m_aCommandURL, |
3704 | 0 | m_xPaletteManager, |
3705 | 0 | m_aColorStatus, |
3706 | 0 | m_nSlotId, |
3707 | 0 | m_xFrame, |
3708 | 0 | MenuOrToolMenuButton(this, pToolBox, nId), |
3709 | 0 | [this] { return GetParentFrame(); }, |
3710 | 0 | m_aColorSelectFunction); |
3711 | |
|
3712 | 0 | mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, |
3713 | 0 | std::move(xPopover), true); |
3714 | |
|
3715 | 0 | auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(m_aCommandURL, m_sModuleName); |
3716 | 0 | OUString aWindowTitle = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); |
3717 | 0 | mxInterimPopover->SetText(aWindowTitle); |
3718 | |
|
3719 | 0 | mxInterimPopover->Show(); |
3720 | |
|
3721 | 0 | return mxInterimPopover; |
3722 | 0 | } |
3723 | | |
3724 | | void SvxColorToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) |
3725 | 0 | { |
3726 | 0 | ToolBox* pToolBox = nullptr; |
3727 | 0 | ToolBoxItemId nId; |
3728 | 0 | if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) |
3729 | 0 | return; |
3730 | | |
3731 | 0 | if ( rEvent.FeatureURL.Complete == m_aCommandURL ) |
3732 | 0 | { |
3733 | 0 | if (m_pToolbar) |
3734 | 0 | m_pToolbar->set_item_sensitive(m_aCommandURL, rEvent.IsEnabled); |
3735 | 0 | else |
3736 | 0 | pToolBox->EnableItem( nId, rEvent.IsEnabled ); |
3737 | 0 | } |
3738 | |
|
3739 | 0 | bool bValue; |
3740 | 0 | if ( !m_bSplitButton ) |
3741 | 0 | { |
3742 | 0 | SolarMutexGuard aSolarMutexGuard; |
3743 | 0 | m_aColorStatus.statusChanged( rEvent ); |
3744 | 0 | m_xBtnUpdater->Update( m_aColorStatus.GetColor() ); |
3745 | 0 | } |
3746 | 0 | else if ( rEvent.State >>= bValue ) |
3747 | 0 | { |
3748 | 0 | if (m_pToolbar) |
3749 | 0 | m_pToolbar->set_item_active(m_aCommandURL, bValue); |
3750 | 0 | else if (pToolBox) |
3751 | 0 | pToolBox->CheckItem( nId, bValue ); |
3752 | 0 | } |
3753 | 0 | } |
3754 | | |
3755 | | void SvxColorToolBoxControl::execute(sal_Int16 /*nSelectModifier*/) |
3756 | 0 | { |
3757 | 0 | if ( !m_bSplitButton ) |
3758 | 0 | { |
3759 | 0 | if (m_pToolbar) |
3760 | 0 | { |
3761 | | // Toggle the popup also when toolbutton is activated |
3762 | 0 | m_pToolbar->set_menu_item_active(m_aCommandURL, !m_pToolbar->get_menu_item_active(m_aCommandURL)); |
3763 | 0 | } |
3764 | 0 | else |
3765 | 0 | { |
3766 | | // Open the popup also when Enter key is pressed. |
3767 | 0 | createPopupWindow(); |
3768 | 0 | } |
3769 | 0 | return; |
3770 | 0 | } |
3771 | | |
3772 | 0 | OUString aCommand = m_aCommandURL; |
3773 | 0 | Color aColor = m_xBtnUpdater->GetCurrentColor(); |
3774 | |
|
3775 | 0 | switch( m_nSlotId ) |
3776 | 0 | { |
3777 | 0 | case SID_ATTR_CHAR_COLOR2 : |
3778 | 0 | aCommand = ".uno:CharColorExt"; |
3779 | 0 | break; |
3780 | 0 | } |
3781 | | |
3782 | 0 | auto aArgs( comphelper::InitPropertySequence( { |
3783 | 0 | { m_aCommandURL.copy(5), css::uno::Any(aColor) } |
3784 | 0 | } ) ); |
3785 | 0 | dispatchCommand( aCommand, aArgs ); |
3786 | |
|
3787 | 0 | EnsurePaletteManager(); |
3788 | 0 | OUString sColorName = m_xBtnUpdater->GetCurrentColorName(); |
3789 | 0 | m_xPaletteManager->AddRecentColor(aColor, sColorName); |
3790 | 0 | } |
3791 | | |
3792 | | sal_Bool SvxColorToolBoxControl::opensSubToolbar() |
3793 | 0 | { |
3794 | | // We mark this controller as a sub-toolbar controller, so we get notified |
3795 | | // (through updateImage method) on button image changes, and could redraw |
3796 | | // the last used color on top of it. |
3797 | 0 | return true; |
3798 | 0 | } |
3799 | | |
3800 | | void SvxColorToolBoxControl::updateImage() |
3801 | 0 | { |
3802 | 0 | m_xBtnUpdater->Update(m_xBtnUpdater->GetCurrentColor(), true); |
3803 | 0 | } |
3804 | | |
3805 | | OUString SvxColorToolBoxControl::getSubToolbarName() |
3806 | 0 | { |
3807 | 0 | return OUString(); |
3808 | 0 | } |
3809 | | |
3810 | | void SvxColorToolBoxControl::functionSelected( const OUString& /*rCommand*/ ) |
3811 | 0 | { |
3812 | 0 | } |
3813 | | |
3814 | | OUString SvxColorToolBoxControl::getImplementationName() |
3815 | 0 | { |
3816 | 0 | return u"com.sun.star.comp.svx.ColorToolBoxControl"_ustr; |
3817 | 0 | } |
3818 | | |
3819 | | css::uno::Sequence<OUString> SvxColorToolBoxControl::getSupportedServiceNames() |
3820 | 0 | { |
3821 | 0 | return { u"com.sun.star.frame.ToolbarController"_ustr }; |
3822 | 0 | } |
3823 | | |
3824 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
3825 | | com_sun_star_comp_svx_ColorToolBoxControl_get_implementation( |
3826 | | css::uno::XComponentContext* rContext, |
3827 | | css::uno::Sequence<css::uno::Any> const & ) |
3828 | 0 | { |
3829 | 0 | return cppu::acquire( new SvxColorToolBoxControl( rContext ) ); |
3830 | 0 | } |
3831 | | |
3832 | | SvxFrameToolBoxControl::SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ) |
3833 | 0 | : svt::PopupWindowController( rContext, nullptr, OUString() ) |
3834 | 0 | { |
3835 | 0 | } |
3836 | | |
3837 | | void SAL_CALL SvxFrameToolBoxControl::execute(sal_Int16 /*KeyModifier*/) |
3838 | 0 | { |
3839 | 0 | if (m_pToolbar) |
3840 | 0 | { |
3841 | | // Toggle the popup also when toolbutton is activated |
3842 | 0 | m_pToolbar->set_menu_item_active(m_aCommandURL, !m_pToolbar->get_menu_item_active(m_aCommandURL)); |
3843 | 0 | } |
3844 | 0 | else |
3845 | 0 | { |
3846 | | // Open the popup also when Enter key is pressed. |
3847 | 0 | createPopupWindow(); |
3848 | 0 | } |
3849 | 0 | } |
3850 | | |
3851 | | void SvxFrameToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) |
3852 | 0 | { |
3853 | 0 | svt::PopupWindowController::initialize( rArguments ); |
3854 | |
|
3855 | 0 | if (m_pToolbar) |
3856 | 0 | { |
3857 | 0 | mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); |
3858 | 0 | m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); |
3859 | 0 | } |
3860 | |
|
3861 | 0 | ToolBox* pToolBox = nullptr; |
3862 | 0 | ToolBoxItemId nId; |
3863 | 0 | if (getToolboxId(nId, &pToolBox)) |
3864 | 0 | pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); |
3865 | 0 | } |
3866 | | |
3867 | | std::unique_ptr<WeldToolbarPopup> SvxFrameToolBoxControl::weldPopupWindow() |
3868 | 0 | { |
3869 | 0 | if ( m_aCommandURL == ".uno:LineStyle" ) |
3870 | 0 | return std::make_unique<SvxLineWindow_Impl>(this, m_pToolbar); |
3871 | 0 | return std::make_unique<SvxFrameWindow_Impl>(this, m_pToolbar); |
3872 | 0 | } |
3873 | | |
3874 | | VclPtr<vcl::Window> SvxFrameToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) |
3875 | 0 | { |
3876 | 0 | if ( m_aCommandURL == ".uno:LineStyle" ) |
3877 | 0 | { |
3878 | 0 | mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, |
3879 | 0 | std::make_unique<SvxLineWindow_Impl>(this, pParent->GetFrameWeld()), true); |
3880 | |
|
3881 | 0 | mxInterimPopover->Show(); |
3882 | |
|
3883 | 0 | mxInterimPopover->SetText(SvxResId(RID_SVXSTR_FRAME_STYLE)); |
3884 | |
|
3885 | 0 | return mxInterimPopover; |
3886 | 0 | } |
3887 | | |
3888 | 0 | mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, |
3889 | 0 | std::make_unique<SvxFrameWindow_Impl>(this, pParent->GetFrameWeld()), true); |
3890 | |
|
3891 | 0 | mxInterimPopover->Show(); |
3892 | |
|
3893 | 0 | mxInterimPopover->SetText(SvxResId(RID_SVXSTR_FRAME)); |
3894 | |
|
3895 | 0 | return mxInterimPopover; |
3896 | 0 | } |
3897 | | |
3898 | | OUString SvxFrameToolBoxControl::getImplementationName() |
3899 | 0 | { |
3900 | 0 | return u"com.sun.star.comp.svx.FrameToolBoxControl"_ustr; |
3901 | 0 | } |
3902 | | |
3903 | | css::uno::Sequence< OUString > SvxFrameToolBoxControl::getSupportedServiceNames() |
3904 | 0 | { |
3905 | 0 | return { u"com.sun.star.frame.ToolbarController"_ustr }; |
3906 | 0 | } |
3907 | | |
3908 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
3909 | | com_sun_star_comp_svx_FrameToolBoxControl_get_implementation( |
3910 | | css::uno::XComponentContext* rContext, |
3911 | | css::uno::Sequence<css::uno::Any> const & ) |
3912 | 0 | { |
3913 | 0 | return cppu::acquire( new SvxFrameToolBoxControl( rContext ) ); |
3914 | 0 | } |
3915 | | |
3916 | | SvxCurrencyToolBoxControl::SvxCurrencyToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) : |
3917 | 0 | PopupWindowController( rContext, nullptr, OUString() ), |
3918 | 0 | m_eLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ), |
3919 | 0 | m_nFormatKey( NUMBERFORMAT_ENTRY_NOT_FOUND ) |
3920 | 0 | { |
3921 | 0 | } |
3922 | | |
3923 | 0 | SvxCurrencyToolBoxControl::~SvxCurrencyToolBoxControl() {} |
3924 | | |
3925 | | namespace |
3926 | | { |
3927 | | /** Implementation of the currency combo widget **/ |
3928 | | class SvxCurrencyList_Impl : public WeldToolbarPopup |
3929 | | { |
3930 | | private: |
3931 | | rtl::Reference<SvxCurrencyToolBoxControl> m_xControl; |
3932 | | std::unique_ptr<weld::TreeView> m_xCurrencyLb; |
3933 | | OUString& m_rSelectedFormat; |
3934 | | LanguageType& m_eSelectedLanguage; |
3935 | | |
3936 | | std::vector<OUString> m_aFormatEntries; |
3937 | | LanguageType m_eFormatLanguage; |
3938 | | DECL_LINK(RowActivatedHdl, weld::TreeView&, bool); |
3939 | | |
3940 | | virtual void GrabFocus() override; |
3941 | | |
3942 | | public: |
3943 | | SvxCurrencyList_Impl(SvxCurrencyToolBoxControl* pControl, weld::Widget* pParent, OUString& rSelectedFormat, LanguageType& eSelectedLanguage) |
3944 | 0 | : WeldToolbarPopup(pControl->getFrameInterface(), pParent, u"svx/ui/currencywindow.ui"_ustr, u"CurrencyWindow"_ustr) |
3945 | 0 | , m_xControl(pControl) |
3946 | 0 | , m_xCurrencyLb(m_xBuilder->weld_tree_view(u"currency"_ustr)) |
3947 | 0 | , m_rSelectedFormat(rSelectedFormat) |
3948 | 0 | , m_eSelectedLanguage(eSelectedLanguage) |
3949 | 0 | { |
3950 | 0 | std::vector< OUString > aList; |
3951 | 0 | std::vector< sal_uInt16 > aCurrencyList; |
3952 | 0 | const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); |
3953 | 0 | sal_uInt16 nLen = rCurrencyTable.size(); |
3954 | |
|
3955 | 0 | SvNumberFormatter aFormatter( m_xControl->getContext(), LANGUAGE_SYSTEM ); |
3956 | 0 | m_eFormatLanguage = aFormatter.GetLanguage(); |
3957 | |
|
3958 | 0 | std::vector<sfx::CurrencyID> aCurrencyIDs; |
3959 | |
|
3960 | 0 | if (SfxObjectShell* pDocShell = SfxObjectShell::Current()) |
3961 | 0 | if (auto pModelAccessor = pDocShell->GetDocumentModelAccessor()) |
3962 | 0 | aCurrencyIDs = pModelAccessor->getDocumentCurrencies(); |
3963 | |
|
3964 | 0 | SvxCurrencyToolBoxControl::GetCurrencySymbols(aList, true, aCurrencyList, aCurrencyIDs); |
3965 | |
|
3966 | 0 | sal_uInt16 nPos = 0, nCount = 0; |
3967 | 0 | sal_Int32 nSelectedPos = -1; |
3968 | 0 | bool bIsSymbol; |
3969 | 0 | NfWSStringsDtor aStringsDtor; |
3970 | |
|
3971 | 0 | OUString sLongestString; |
3972 | |
|
3973 | 0 | m_xCurrencyLb->freeze(); |
3974 | 0 | for( const auto& rItem : aList ) |
3975 | 0 | { |
3976 | 0 | sal_uInt16& rCurrencyIndex = aCurrencyList[ nCount ]; |
3977 | 0 | if ( rCurrencyIndex < nLen ) |
3978 | 0 | { |
3979 | 0 | m_xCurrencyLb->append_text(rItem); |
3980 | |
|
3981 | 0 | if (rItem.getLength() > sLongestString.getLength()) |
3982 | 0 | sLongestString = rItem; |
3983 | |
|
3984 | 0 | bIsSymbol = nPos >= nLen; |
3985 | |
|
3986 | 0 | sal_uInt16 nDefaultFormat; |
3987 | 0 | const NfCurrencyEntry& rCurrencyEntry = rCurrencyTable[ rCurrencyIndex ]; |
3988 | 0 | if (rCurrencyIndex == 0) |
3989 | 0 | { |
3990 | | // Stored with system locale, but we want the resolved |
3991 | | // full LCID format string. For example |
3992 | | // "[$$-409]#,##0.00" instead of "[$$]#,##0.00". |
3993 | 0 | NfCurrencyEntry aCurrencyEntry( rCurrencyEntry); |
3994 | 0 | aCurrencyEntry.SetLanguage( LanguageTag( aCurrencyEntry.GetLanguage()).getLanguageType()); |
3995 | 0 | nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, aCurrencyEntry, bIsSymbol); |
3996 | 0 | } |
3997 | 0 | else |
3998 | 0 | { |
3999 | 0 | nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, rCurrencyEntry, bIsSymbol); |
4000 | 0 | } |
4001 | 0 | const OUString& rFormatStr = aStringsDtor[ nDefaultFormat ]; |
4002 | 0 | m_aFormatEntries.push_back( rFormatStr ); |
4003 | 0 | if( rFormatStr == m_rSelectedFormat ) |
4004 | 0 | nSelectedPos = nPos; |
4005 | 0 | ++nPos; |
4006 | 0 | } |
4007 | 0 | ++nCount; |
4008 | 0 | } |
4009 | 0 | m_xCurrencyLb->thaw(); |
4010 | | // enable multiple selection enabled so we can start with nothing selected |
4011 | 0 | m_xCurrencyLb->set_selection_mode(SelectionMode::Multiple); |
4012 | 0 | m_xCurrencyLb->connect_row_activated( LINK( this, SvxCurrencyList_Impl, RowActivatedHdl ) ); |
4013 | 0 | m_xCurrencyLb->select( nSelectedPos ); |
4014 | | |
4015 | | // gtk will initially make a best guess depending on the first few entries, so copy the probable |
4016 | | // longest entry to the start temporarily and force in the width at this point |
4017 | 0 | m_xCurrencyLb->insert_text(0, sLongestString); |
4018 | 0 | m_xCurrencyLb->set_size_request(m_xCurrencyLb->get_preferred_size().Width(), m_xCurrencyLb->get_height_rows(12)); |
4019 | 0 | m_xCurrencyLb->remove(0); |
4020 | 0 | } |
4021 | | }; |
4022 | | |
4023 | | void SvxCurrencyList_Impl::GrabFocus() |
4024 | 0 | { |
4025 | 0 | m_xCurrencyLb->grab_focus(); |
4026 | 0 | } |
4027 | | |
4028 | | IMPL_LINK_NOARG(SvxCurrencyList_Impl, RowActivatedHdl, weld::TreeView&, bool) |
4029 | 0 | { |
4030 | 0 | if (!m_xControl.is()) |
4031 | 0 | return true; |
4032 | | |
4033 | | // multiple selection enabled so we can start with nothing selected, |
4034 | | // so force single selection after something is picked |
4035 | 0 | int nSelected = m_xCurrencyLb->get_selected_index(); |
4036 | 0 | if (nSelected == -1) |
4037 | 0 | return true; |
4038 | | |
4039 | 0 | m_xCurrencyLb->set_selection_mode(SelectionMode::Single); |
4040 | |
|
4041 | 0 | m_rSelectedFormat = m_aFormatEntries[nSelected]; |
4042 | 0 | m_eSelectedLanguage = m_eFormatLanguage; |
4043 | |
|
4044 | 0 | m_xControl->execute(nSelected + 1); |
4045 | |
|
4046 | 0 | m_xControl->EndPopupMode(); |
4047 | |
|
4048 | 0 | return true; |
4049 | 0 | } |
4050 | | } |
4051 | | |
4052 | | void SvxCurrencyToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) |
4053 | 0 | { |
4054 | 0 | PopupWindowController::initialize(rArguments); |
4055 | |
|
4056 | 0 | if (m_pToolbar) |
4057 | 0 | { |
4058 | 0 | mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); |
4059 | 0 | m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); |
4060 | 0 | return; |
4061 | 0 | } |
4062 | | |
4063 | 0 | ToolBox* pToolBox = nullptr; |
4064 | 0 | ToolBoxItemId nId; |
4065 | 0 | if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) |
4066 | 0 | pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId)); |
4067 | 0 | } |
4068 | | |
4069 | | std::unique_ptr<WeldToolbarPopup> SvxCurrencyToolBoxControl::weldPopupWindow() |
4070 | 0 | { |
4071 | 0 | return std::make_unique<SvxCurrencyList_Impl>(this, m_pToolbar, m_aFormatString, m_eLanguage); |
4072 | 0 | } |
4073 | | |
4074 | | VclPtr<vcl::Window> SvxCurrencyToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) |
4075 | 0 | { |
4076 | 0 | mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, |
4077 | 0 | std::make_unique<SvxCurrencyList_Impl>(this, pParent->GetFrameWeld(), m_aFormatString, m_eLanguage)); |
4078 | |
|
4079 | 0 | mxInterimPopover->Show(); |
4080 | |
|
4081 | 0 | return mxInterimPopover; |
4082 | 0 | } |
4083 | | |
4084 | | void SvxCurrencyToolBoxControl::execute( sal_Int16 nSelectModifier ) |
4085 | 0 | { |
4086 | 0 | sal_uInt32 nFormatKey; |
4087 | 0 | if (m_aFormatString.isEmpty()) |
4088 | 0 | nFormatKey = NUMBERFORMAT_ENTRY_NOT_FOUND; |
4089 | 0 | else |
4090 | 0 | { |
4091 | 0 | if ( nSelectModifier > 0 ) |
4092 | 0 | { |
4093 | 0 | try |
4094 | 0 | { |
4095 | 0 | uno::Reference< util::XNumberFormatsSupplier > xRef( m_xFrame->getController()->getModel(), uno::UNO_QUERY ); |
4096 | 0 | uno::Reference< util::XNumberFormats > rxNumberFormats( xRef->getNumberFormats(), uno::UNO_SET_THROW ); |
4097 | 0 | css::lang::Locale aLocale = LanguageTag::convertToLocale( m_eLanguage ); |
4098 | 0 | nFormatKey = rxNumberFormats->queryKey( m_aFormatString, aLocale, false ); |
4099 | 0 | if ( nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
4100 | 0 | nFormatKey = rxNumberFormats->addNew( m_aFormatString, aLocale ); |
4101 | 0 | } |
4102 | 0 | catch( const uno::Exception& ) |
4103 | 0 | { |
4104 | 0 | nFormatKey = m_nFormatKey; |
4105 | 0 | } |
4106 | 0 | } |
4107 | 0 | else |
4108 | 0 | nFormatKey = m_nFormatKey; |
4109 | 0 | } |
4110 | |
|
4111 | 0 | if( nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) |
4112 | 0 | { |
4113 | 0 | Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(u"NumberFormatCurrency"_ustr, |
4114 | 0 | nFormatKey) }; |
4115 | 0 | dispatchCommand( m_aCommandURL, aArgs ); |
4116 | 0 | m_nFormatKey = nFormatKey; |
4117 | 0 | } |
4118 | 0 | else |
4119 | 0 | PopupWindowController::execute( nSelectModifier ); |
4120 | 0 | } |
4121 | | |
4122 | | OUString SvxCurrencyToolBoxControl::getImplementationName() |
4123 | 0 | { |
4124 | 0 | return u"com.sun.star.comp.svx.CurrencyToolBoxControl"_ustr; |
4125 | 0 | } |
4126 | | |
4127 | | css::uno::Sequence<OUString> SvxCurrencyToolBoxControl::getSupportedServiceNames() |
4128 | 0 | { |
4129 | 0 | return { u"com.sun.star.frame.ToolbarController"_ustr }; |
4130 | 0 | } |
4131 | | |
4132 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
4133 | | com_sun_star_comp_svx_CurrencyToolBoxControl_get_implementation( |
4134 | | css::uno::XComponentContext* rContext, |
4135 | | css::uno::Sequence<css::uno::Any> const & ) |
4136 | 0 | { |
4137 | 0 | return cppu::acquire( new SvxCurrencyToolBoxControl( rContext ) ); |
4138 | 0 | } |
4139 | | |
4140 | | rtl::Reference<comphelper::OAccessible> SvxFontNameBox_Impl::CreateAccessible() |
4141 | 0 | { |
4142 | 0 | FillList(); |
4143 | 0 | return InterimItemWindow::CreateAccessible(); |
4144 | 0 | } |
4145 | | |
4146 | | //static |
4147 | | void SvxCurrencyToolBoxControl::GetCurrencySymbols(std::vector<OUString>& rList, bool bFlag, |
4148 | | std::vector<sal_uInt16>& rCurrencyList, |
4149 | | std::vector<sfx::CurrencyID> const& rDocumentCurrencyIDs) |
4150 | 0 | { |
4151 | 0 | rCurrencyList.clear(); |
4152 | |
|
4153 | 0 | static constexpr OUString aTwoSpace = u" "_ustr; |
4154 | 0 | const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); |
4155 | 0 | sal_uInt16 nCount = rCurrencyTable.size(); |
4156 | |
|
4157 | 0 | sal_uInt16 nStart = 1; |
4158 | |
|
4159 | 0 | LanguageTag eLangTag = Application::GetSettings().GetLanguageTag(); |
4160 | 0 | OUString aString(ApplyLreOrRleEmbedding(rCurrencyTable[0].GetBankSymbol())); |
4161 | 0 | aString += aTwoSpace; |
4162 | 0 | aString += ApplyLreOrRleEmbedding(rCurrencyTable[0].GetSymbol()); |
4163 | 0 | aString += aTwoSpace; |
4164 | 0 | aString += ApplyLreOrRleEmbedding(SvtLanguageTable::GetLanguageString(eLangTag.getLanguageType())); |
4165 | 0 | aString += aTwoSpace; |
4166 | 0 | aString += ApplyLreOrRleEmbedding(SvtLanguageTable::GetLanguageString(rCurrencyTable[0].GetLanguage())); |
4167 | |
|
4168 | 0 | rList.push_back( aString ); |
4169 | 0 | rCurrencyList.push_back( sal_uInt16(-1) ); // nAuto |
4170 | |
|
4171 | 0 | if( bFlag ) |
4172 | 0 | { |
4173 | 0 | rList.push_back( aString ); |
4174 | 0 | rCurrencyList.push_back( 0 ); |
4175 | 0 | ++nStart; |
4176 | 0 | } |
4177 | |
|
4178 | 0 | CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() ); |
4179 | 0 | aCollator.loadDefaultCollator(eLangTag.getLocale(), 0); |
4180 | |
|
4181 | 0 | for( sal_uInt16 i = 1; i < nCount; ++i ) |
4182 | 0 | { |
4183 | 0 | auto& rCurrencyEntry = rCurrencyTable[i]; |
4184 | |
|
4185 | 0 | OUString aStr( ApplyLreOrRleEmbedding(rCurrencyEntry.GetBankSymbol())); |
4186 | 0 | aStr += aTwoSpace; |
4187 | 0 | aStr += ApplyLreOrRleEmbedding(rCurrencyEntry.GetSymbol()); |
4188 | 0 | aStr += aTwoSpace; |
4189 | 0 | aStr += ApplyLreOrRleEmbedding(SvtLanguageTable::GetLanguageString(rCurrencyEntry.GetLanguage())); |
4190 | |
|
4191 | 0 | std::vector<OUString>::size_type j = nStart; |
4192 | | |
4193 | | // Search if the currency is present in the document |
4194 | 0 | auto iter = std::find_if(rDocumentCurrencyIDs.begin(), rDocumentCurrencyIDs.end(), [rCurrencyEntry](sfx::CurrencyID const& rCurrency) |
4195 | 0 | { |
4196 | 0 | const NfCurrencyEntry* pEntry = SvNumberFormatter::GetCurrencyEntry(o3tl::temporary(bool()), rCurrency.aSymbol, rCurrency.aExtension, rCurrency.eLanguage); |
4197 | |
|
4198 | 0 | if (pEntry) |
4199 | 0 | return rCurrencyEntry.GetLanguage() == pEntry->GetLanguage() && rCurrencyEntry.GetSymbol() == pEntry->GetSymbol(); |
4200 | | |
4201 | 0 | return false; |
4202 | 0 | }); |
4203 | | |
4204 | | // If currency is in document, insert it on top |
4205 | 0 | if (iter != rDocumentCurrencyIDs.end()) |
4206 | 0 | { |
4207 | 0 | nStart++; |
4208 | 0 | } |
4209 | 0 | else |
4210 | 0 | { |
4211 | 0 | for( ; j < rList.size(); ++j ) |
4212 | 0 | { |
4213 | 0 | if ( aCollator.compareString( aStr, rList[j] ) < 0 ) |
4214 | 0 | break; // insert before first greater than |
4215 | 0 | } |
4216 | 0 | } |
4217 | |
|
4218 | 0 | rList.insert( rList.begin() + j, aStr ); |
4219 | 0 | rCurrencyList.insert( rCurrencyList.begin() + j, i ); |
4220 | 0 | } |
4221 | | |
4222 | | // Append ISO codes to symbol list. |
4223 | | // XXX If this is to be changed, various other places would had to be |
4224 | | // adapted that assume this order! |
4225 | 0 | std::vector<OUString>::size_type nCont = rList.size(); |
4226 | |
|
4227 | 0 | for ( sal_uInt16 i = 1; i < nCount; ++i ) |
4228 | 0 | { |
4229 | 0 | bool bInsert = true; |
4230 | 0 | auto& rCurrencyEntry = rCurrencyTable[i]; |
4231 | 0 | OUString aStr( ApplyLreOrRleEmbedding(rCurrencyEntry.GetBankSymbol())); |
4232 | |
|
4233 | 0 | std::vector<OUString>::size_type j = nCont; |
4234 | 0 | for ( ; j < rList.size() && bInsert; ++j ) |
4235 | 0 | { |
4236 | 0 | if( rList[j] == aStr ) |
4237 | 0 | bInsert = false; |
4238 | 0 | else if ( aCollator.compareString( aStr, rList[j] ) < 0 ) |
4239 | 0 | break; // insert before first greater than |
4240 | 0 | } |
4241 | 0 | if ( bInsert ) |
4242 | 0 | { |
4243 | 0 | rList.insert( rList.begin() + j, aStr ); |
4244 | 0 | rCurrencyList.insert( rCurrencyList.begin() + j, i ); |
4245 | 0 | } |
4246 | 0 | } |
4247 | 0 | } |
4248 | | |
4249 | | ListBoxColorWrapper::ListBoxColorWrapper(ColorListBox* pControl) |
4250 | 0 | : mpControl(pControl) |
4251 | 0 | { |
4252 | 0 | } |
4253 | | |
4254 | | void ListBoxColorWrapper::operator()( |
4255 | | [[maybe_unused]] const OUString& /*rCommand*/, const NamedColor& rColor) |
4256 | 0 | { |
4257 | 0 | mpControl->Selected(rColor); |
4258 | 0 | } |
4259 | | |
4260 | | void ColorListBox::EnsurePaletteManager() |
4261 | 0 | { |
4262 | 0 | if (!m_xPaletteManager) |
4263 | 0 | { |
4264 | 0 | m_xPaletteManager = std::make_shared<PaletteManager>(); |
4265 | 0 | m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper)); |
4266 | 0 | } |
4267 | 0 | } |
4268 | | |
4269 | | void ColorListBox::SetSlotId(sal_uInt16 nSlotId, bool bShowNoneButton) |
4270 | 0 | { |
4271 | 0 | m_nSlotId = nSlotId; |
4272 | 0 | m_bShowNoneButton = bShowNoneButton; |
4273 | 0 | m_xButton->set_popover(nullptr); |
4274 | 0 | m_xColorWindow.reset(); |
4275 | 0 | m_aSelectedColor = bShowNoneButton ? GetNoneColor() : GetAutoColor(m_nSlotId); |
4276 | 0 | ShowPreview(m_aSelectedColor); |
4277 | 0 | createColorWindow(); |
4278 | 0 | } |
4279 | | |
4280 | | ColorListBox::ColorListBox(std::unique_ptr<weld::MenuButton> pControl, |
4281 | | TopLevelParentFunction aTopLevelParentFunction) |
4282 | 0 | : m_xButton(std::move(pControl)) |
4283 | 0 | , m_aColorWrapper(this) |
4284 | 0 | , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor()) |
4285 | 0 | , m_nSlotId(0) |
4286 | 0 | , m_bShowNoneButton(false) |
4287 | 0 | , m_aTopLevelParentFunction(std::move(aTopLevelParentFunction)) |
4288 | 0 | { |
4289 | 0 | m_xButton->connect_toggled(LINK(this, ColorListBox, ToggleHdl)); |
4290 | 0 | m_aSelectedColor = GetAutoColor(m_nSlotId); |
4291 | 0 | LockWidthRequest(CalcBestWidthRequest()); |
4292 | 0 | ShowPreview(m_aSelectedColor); |
4293 | 0 | } |
4294 | | |
4295 | | IMPL_LINK(ColorListBox, ToggleHdl, weld::Toggleable&, rButton, void) |
4296 | 0 | { |
4297 | 0 | if (rButton.get_active()) |
4298 | 0 | { |
4299 | 0 | ColorWindow* pColorWindow = getColorWindow(); |
4300 | 0 | if (pColorWindow && !comphelper::LibreOfficeKit::isActive()) |
4301 | 0 | pColorWindow->GrabFocus(); |
4302 | 0 | } |
4303 | 0 | } |
4304 | | |
4305 | | ColorListBox::~ColorListBox() |
4306 | 0 | { |
4307 | 0 | } |
4308 | | |
4309 | | ColorWindow* ColorListBox::getColorWindow() const |
4310 | 0 | { |
4311 | 0 | if (!m_xColorWindow) |
4312 | 0 | const_cast<ColorListBox*>(this)->createColorWindow(); |
4313 | 0 | return m_xColorWindow.get(); |
4314 | 0 | } |
4315 | | |
4316 | | void ColorListBox::createColorWindow() |
4317 | 0 | { |
4318 | 0 | const SfxViewFrame* pViewFrame = SfxViewFrame::Current(); |
4319 | 0 | const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; |
4320 | 0 | css::uno::Reference<css::frame::XFrame> xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference<css::frame::XFrame>()); |
4321 | |
|
4322 | 0 | EnsurePaletteManager(); |
4323 | |
|
4324 | 0 | m_xColorWindow.reset(new ColorWindow( |
4325 | 0 | OUString() /*m_aCommandURL*/, |
4326 | 0 | m_xPaletteManager, |
4327 | 0 | m_aColorStatus, |
4328 | 0 | m_nSlotId, |
4329 | 0 | xFrame, |
4330 | 0 | m_xButton.get(), |
4331 | 0 | m_aTopLevelParentFunction, |
4332 | 0 | m_aColorWrapper)); |
4333 | |
|
4334 | 0 | SetNoSelection(); |
4335 | 0 | m_xButton->set_popover(m_xColorWindow->getTopLevel()); |
4336 | 0 | if (m_bShowNoneButton) |
4337 | 0 | m_xColorWindow->ShowNoneButton(); |
4338 | 0 | m_xColorWindow->SelectEntry(m_aSelectedColor); |
4339 | 0 | } |
4340 | | |
4341 | | void ColorListBox::SelectEntry(const NamedColor& rColor) |
4342 | 0 | { |
4343 | 0 | if (o3tl::trim(rColor.m_aName).empty()) |
4344 | 0 | { |
4345 | 0 | SelectEntry(rColor.m_aColor); |
4346 | 0 | return; |
4347 | 0 | } |
4348 | 0 | ColorWindow* pColorWindow = getColorWindow(); |
4349 | 0 | pColorWindow->SelectEntry(rColor); |
4350 | 0 | m_aSelectedColor = pColorWindow->GetSelectEntryColor(); |
4351 | 0 | ShowPreview(m_aSelectedColor); |
4352 | 0 | } |
4353 | | |
4354 | | void ColorListBox::SelectEntry(const Color& rColor) |
4355 | 0 | { |
4356 | 0 | ColorWindow* pColorWindow = getColorWindow(); |
4357 | 0 | pColorWindow->SelectEntry(rColor); |
4358 | 0 | m_aSelectedColor = pColorWindow->GetSelectEntryColor(); |
4359 | 0 | ShowPreview(m_aSelectedColor); |
4360 | 0 | } |
4361 | | |
4362 | | void ColorListBox::Selected(const NamedColor& rColor) |
4363 | 0 | { |
4364 | 0 | ShowPreview(rColor); |
4365 | 0 | m_aSelectedColor = rColor; |
4366 | 0 | if (m_aSelectedLink.IsSet()) |
4367 | 0 | m_aSelectedLink.Call(*this); |
4368 | 0 | } |
4369 | | |
4370 | | //to avoid the box resizing every time the color is changed to |
4371 | | //the optimal size of the individual color, get the longest |
4372 | | //standard color and stick with that as the size for all |
4373 | | int ColorListBox::CalcBestWidthRequest() |
4374 | 0 | { |
4375 | 0 | NamedColor aLongestColor; |
4376 | 0 | tools::Long nMaxStandardColorTextWidth = 0; |
4377 | 0 | XColorListRef const xColorTable = XColorList::CreateStdColorList(); |
4378 | 0 | for (tools::Long i = 0; i != xColorTable->Count(); ++i) |
4379 | 0 | { |
4380 | 0 | XColorEntry& rEntry = *xColorTable->GetColor(i); |
4381 | 0 | auto nColorTextWidth = m_xButton->get_pixel_size(rEntry.GetName()).Width(); |
4382 | 0 | if (nColorTextWidth > nMaxStandardColorTextWidth) |
4383 | 0 | { |
4384 | 0 | nMaxStandardColorTextWidth = nColorTextWidth; |
4385 | 0 | aLongestColor.m_aName = rEntry.GetName(); |
4386 | 0 | } |
4387 | 0 | } |
4388 | 0 | ShowPreview(aLongestColor); |
4389 | 0 | return m_xButton->get_preferred_size().Width(); |
4390 | 0 | } |
4391 | | |
4392 | | void ColorListBox::LockWidthRequest(int nWidth) |
4393 | 0 | { |
4394 | 0 | m_xButton->set_size_request(nWidth, -1); |
4395 | 0 | } |
4396 | | |
4397 | | void ColorListBox::ShowPreview(const NamedColor &rColor) |
4398 | 0 | { |
4399 | | // ScGridWindow::UpdateAutoFilterFromMenu is similar |
4400 | 0 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
4401 | 0 | Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); |
4402 | |
|
4403 | 0 | ScopedVclPtrInstance<VirtualDevice> xDevice; |
4404 | 0 | xDevice->SetOutputSize(aImageSize); |
4405 | 0 | const tools::Rectangle aRect(Point(0, 0), aImageSize); |
4406 | 0 | if (m_bShowNoneButton && rColor.m_aColor == COL_NONE_COLOR) |
4407 | 0 | { |
4408 | 0 | const Color aW(COL_WHITE); |
4409 | 0 | const Color aG(0xef, 0xef, 0xef); |
4410 | 0 | int nMinDim = std::min(aImageSize.Width(), aImageSize.Height()) + 1; |
4411 | 0 | int nCheckSize = nMinDim / 3; |
4412 | 0 | xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), std::min(nCheckSize, 8), aW, aG); |
4413 | 0 | xDevice->SetFillColor(); |
4414 | 0 | } |
4415 | 0 | else |
4416 | 0 | { |
4417 | 0 | if (rColor.m_aColor == COL_AUTO) |
4418 | 0 | xDevice->SetFillColor(m_aAutoDisplayColor); |
4419 | 0 | else |
4420 | 0 | xDevice->SetFillColor(rColor.m_aColor); |
4421 | 0 | } |
4422 | |
|
4423 | 0 | xDevice->SetLineColor(rStyleSettings.GetDisableColor()); |
4424 | 0 | xDevice->DrawRect(aRect); |
4425 | |
|
4426 | 0 | m_xButton->set_image(xDevice.get()); |
4427 | 0 | m_xButton->set_label(rColor.m_aName); |
4428 | 0 | } |
4429 | | |
4430 | | MenuOrToolMenuButton::MenuOrToolMenuButton(weld::MenuButton* pMenuButton) |
4431 | 0 | : m_pMenuButton(pMenuButton) |
4432 | 0 | , m_pToolbar(nullptr) |
4433 | 0 | , m_pControl(nullptr) |
4434 | 0 | , m_nId(0) |
4435 | 0 | { |
4436 | 0 | } |
4437 | | |
4438 | | MenuOrToolMenuButton::MenuOrToolMenuButton(weld::Toolbar* pToolbar, OUString aIdent) |
4439 | 0 | : m_pMenuButton(nullptr) |
4440 | 0 | , m_pToolbar(pToolbar) |
4441 | 0 | , m_aIdent(std::move(aIdent)) |
4442 | 0 | , m_pControl(nullptr) |
4443 | 0 | , m_nId(0) |
4444 | 0 | { |
4445 | 0 | } |
4446 | | |
4447 | | MenuOrToolMenuButton::MenuOrToolMenuButton(SvxColorToolBoxControl* pControl, ToolBox* pToolbar, ToolBoxItemId nId) |
4448 | 0 | : m_pMenuButton(nullptr) |
4449 | 0 | , m_pToolbar(nullptr) |
4450 | 0 | , m_pControl(pControl) |
4451 | 0 | , m_xToolBox(pToolbar) |
4452 | 0 | , m_nId(nId) |
4453 | 0 | { |
4454 | 0 | } |
4455 | | |
4456 | | MenuOrToolMenuButton::~MenuOrToolMenuButton() |
4457 | 0 | { |
4458 | 0 | } |
4459 | | |
4460 | | bool MenuOrToolMenuButton::get_active() const |
4461 | 0 | { |
4462 | 0 | if (m_pMenuButton) |
4463 | 0 | return m_pMenuButton->get_active(); |
4464 | 0 | if (m_pToolbar) |
4465 | 0 | return m_pToolbar->get_menu_item_active(m_aIdent); |
4466 | 0 | return m_xToolBox->GetDownItemId() == m_nId; |
4467 | 0 | } |
4468 | | |
4469 | | void MenuOrToolMenuButton::set_inactive() const |
4470 | 0 | { |
4471 | 0 | if (m_pMenuButton) |
4472 | 0 | { |
4473 | 0 | if (m_pMenuButton->get_active()) |
4474 | 0 | m_pMenuButton->set_active(false); |
4475 | 0 | return; |
4476 | 0 | } |
4477 | 0 | if (m_pToolbar) |
4478 | 0 | { |
4479 | 0 | if (m_pToolbar->get_menu_item_active(m_aIdent)) |
4480 | 0 | m_pToolbar->set_menu_item_active(m_aIdent, false); |
4481 | 0 | return; |
4482 | 0 | } |
4483 | 0 | m_pControl->EndPopupMode(); |
4484 | 0 | } |
4485 | | |
4486 | | weld::Widget* MenuOrToolMenuButton::get_widget() const |
4487 | 0 | { |
4488 | 0 | if (m_pMenuButton) |
4489 | 0 | return m_pMenuButton; |
4490 | 0 | if (m_pToolbar) |
4491 | 0 | return m_pToolbar; |
4492 | 0 | return m_xToolBox->GetFrameWeld(); |
4493 | 0 | } |
4494 | | |
4495 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |