1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <unordered_map>
23 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/container/XNameAccess.hpp>
27 #include <vcl/commandevent.hxx>
28 #include <vcl/commandinfoprovider.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/settings.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/weldutils.hxx>
33 #include <vcl/window.hxx>
34 #include <svl/intitem.hxx>
35 #include <svl/style.hxx>
36 #include <svl/itemset.hxx>
37 #include <comphelper/processfactory.hxx>
38 #include <officecfg/Office/Common.hxx>
40 #include <osl/diagnose.h>
41 #include <sfx2/dispatch.hxx>
42 #include <sfx2/bindings.hxx>
43 #include <templdgi.hxx>
44 #include <tplcitem.hxx>
45 #include <sfx2/styfitem.hxx>
46 #include <sfx2/objsh.hxx>
47 #include <sfx2/viewsh.hxx>
48 #include <sfx2/newstyle.hxx>
49 #include <sfx2/tplpitem.hxx>
50 #include <sfx2/sfxresid.hxx>
52 #include <sfx2/sfxsids.hrc>
53 #include <sfx2/strings.hrc>
54 #include <sfx2/docfac.hxx>
55 #include <sfx2/module.hxx>
57 #include <sfx2/viewfrm.hxx>
59 #include <comphelper/string.hxx>
61 #include <sfx2/StyleManager.hxx>
62 #include <sfx2/StylePreviewRenderer.hxx>
64 #include <StyleList.hxx>
66 #include <vcl/virdev.hxx>
67 #include <basegfx/color/bcolortools.hxx>
71 using namespace css::beans
;
72 using namespace css::frame
;
73 using namespace css::uno
;
75 class TreeViewDropTarget final
: public DropTargetHelper
81 TreeViewDropTarget(StyleList
& rStyleList
, weld::TreeView
& rTreeView
)
82 : DropTargetHelper(rTreeView
.get_drop_target())
83 , m_rParent(rStyleList
)
87 virtual sal_Int8
AcceptDrop(const AcceptDropEvent
& rEvt
) override
89 return m_rParent
.AcceptDrop(rEvt
, *this);
92 virtual sal_Int8
ExecuteDrop(const ExecuteDropEvent
& rEvt
) override
94 return m_rParent
.ExecuteDrop(rEvt
);
100 Color
ColorHash(std::u16string_view rString
)
102 static constexpr auto aSaturationArray
= std::to_array
<sal_uInt16
>({ 90, 75, 60 });
103 static constexpr auto aBrightnessArray
= std::to_array
<sal_uInt16
>({ 100, 80, 60 });
104 static constexpr auto aTintOrShadeArray
105 = std::to_array
<sal_Int16
>({ 1'500, 3'000, 4'500, 6'500, 7'500 });
107 sal_uInt32 nStringHash
= rtl_ustr_hashCode_WithLength(rString
.data(), rString
.length());
109 // Twist the hash number with a RNG twister so we can get very different number even when the string hash
110 // differs only slightly. For example "Heading 1" and "Heading 2" are very close, so we would get a color
111 // that is very similar and with number quantization could result in the same color.
112 std::mt19937 twister
;
113 twister
.seed(nStringHash
); // setting the hash for
114 nStringHash
= twister();
116 double fHue
= (nStringHash
% 60) * 6;
117 nStringHash
= nStringHash
/ 60;
119 double fSaturation
= aSaturationArray
[nStringHash
% aSaturationArray
.size()];
120 nStringHash
= nStringHash
/ aSaturationArray
.size();
122 double fBrightness
= aBrightnessArray
[nStringHash
% aBrightnessArray
.size()];
123 nStringHash
= nStringHash
/ aBrightnessArray
.size();
125 auto aColor
= Color::HSBtoRGB(fHue
, fSaturation
, fBrightness
);
126 double fTintOrShade
= aTintOrShadeArray
[nStringHash
% aTintOrShadeArray
.size()];
127 aColor
.ApplyTintOrShade(fTintOrShade
);
132 // used to disallow the default character style in the styles highlighter character styles color map
133 std::optional
<OUString
> sDefaultCharStyleUIName
;
138 StyleList::StyleList(weld::Builder
* pBuilder
, SfxBindings
* pBindings
,
139 SfxCommonTemplateDialog_Impl
* Parent
, weld::Container
* pC
,
140 const OUString
& treeviewname
, const OUString
& flatviewname
)
141 : m_bHierarchical(false)
142 , m_bAllowReParentDrop(false)
143 , m_bNewByExampleDisabled(false)
144 , m_bDontUpdate(false)
150 , m_bUpdateFamily(false)
152 , m_bBindingUpdate(true)
153 , m_pStyleSheetPool(nullptr)
155 , m_xFmtLb(pBuilder
->weld_tree_view(flatviewname
))
156 , m_xTreeBox(pBuilder
->weld_tree_view(treeviewname
))
157 , m_pCurObjShell(nullptr)
158 , m_nActFamily(0xffff)
159 , m_nAppFilter(SfxStyleSearchBits::Auto
)
160 , m_pParentDialog(Parent
)
161 , m_pBindings(pBindings
)
166 m_xFmtLb
->set_help_id(HID_TEMPLATE_FMT
);
168 uno::Reference
<frame::XFrame
> xFrame
169 = m_pBindings
->GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface();
170 m_bModuleHasStylesHighlighterFeature
171 = vcl::CommandInfoProvider::GetModuleIdentifier(xFrame
) == "com.sun.star.text.TextDocument";
176 StyleList::~StyleList() {}
178 // Called in the destructor of Dialog
179 // Cleans up the StyleList individual components while closing the application
180 IMPL_LINK_NOARG(StyleList
, Cleanup
, void*, void)
182 if (m_pStyleSheetPool
)
183 EndListening(*m_pStyleSheetPool
);
184 m_pStyleSheetPool
= nullptr;
185 m_xTreeView1DropTargetHelper
.reset();
186 m_xTreeView2DropTargetHelper
.reset();
192 void StyleList::CreateContextMenu()
194 if (m_bBindingUpdate
)
196 m_pBindings
->Invalidate(SID_STYLE_NEW
, true);
197 m_pBindings
->Update(SID_STYLE_NEW
);
198 m_bBindingUpdate
= false;
201 mxMenuBuilder
= Application::CreateBuilder(m_pContainer
, u
"sfx/ui/stylecontextmenu.ui"_ustr
);
202 mxMenu
= mxMenuBuilder
->weld_menu(u
"menu"_ustr
);
203 mxMenu
->set_sensitive(u
"edit"_ustr
, m_bCanEdit
);
204 mxMenu
->set_sensitive(u
"delete"_ustr
, m_bCanDel
);
205 mxMenu
->set_sensitive(u
"new"_ustr
, m_bCanNew
);
206 mxMenu
->set_sensitive(u
"hide"_ustr
, m_bCanHide
);
207 mxMenu
->set_sensitive(u
"show"_ustr
, m_bCanShow
);
209 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
210 if (pItem
&& pItem
->GetFamily() == SfxStyleFamily::Table
) //tdf#101648, no ui for this yet
212 mxMenu
->set_sensitive(u
"edit"_ustr
, false);
213 mxMenu
->set_sensitive(u
"new"_ustr
, false);
215 if (pItem
&& pItem
->GetFamily() == SfxStyleFamily::Pseudo
)
217 const OUString
aTemplName(GetSelectedEntry());
218 if (aTemplName
== "No List")
220 mxMenu
->set_sensitive(u
"edit"_ustr
, false);
221 mxMenu
->set_sensitive(u
"new"_ustr
, false);
222 mxMenu
->set_sensitive(u
"hide"_ustr
, false);
227 IMPL_LINK_NOARG(StyleList
, ReadResource
, void*, size_t)
229 // Read global user resource
230 for (auto& i
: m_pFamilyState
)
233 SfxViewFrame
* pViewFrame
= m_pBindings
->GetDispatcher_Impl()->GetFrame();
234 m_pCurObjShell
= pViewFrame
->GetObjectShell();
235 m_Module
= m_pCurObjShell
? m_pCurObjShell
->GetModule() : nullptr;
237 m_xStyleFamilies
= m_Module
->CreateStyleFamilies();
238 if (!m_xStyleFamilies
)
239 m_xStyleFamilies
.emplace();
241 m_nActFilter
= 0xffff;
245 m_nActFilter
= static_cast<sal_uInt16
>(m_aLoadFactoryStyleFilter
.Call(m_pCurObjShell
));
246 if (0xffff == m_nActFilter
)
248 m_nActFilter
= m_pCurObjShell
->GetAutoStyleFilterIndex();
250 if (m_bModuleHasStylesHighlighterFeature
)
251 sDefaultCharStyleUIName
= getDefaultStyleName(SfxStyleFamily::Char
);
253 size_t nCount
= m_xStyleFamilies
->size();
254 m_pBindings
->ENTERREGISTRATIONS();
257 for (i
= 0; i
< nCount
; ++i
)
259 sal_uInt16 nSlot
= 0;
260 switch (m_xStyleFamilies
->at(i
).GetFamily())
262 case SfxStyleFamily::Char
:
263 nSlot
= SID_STYLE_FAMILY1
;
265 case SfxStyleFamily::Para
:
266 nSlot
= SID_STYLE_FAMILY2
;
268 case SfxStyleFamily::Frame
:
269 nSlot
= SID_STYLE_FAMILY3
;
271 case SfxStyleFamily::Page
:
272 nSlot
= SID_STYLE_FAMILY4
;
274 case SfxStyleFamily::Pseudo
:
275 nSlot
= SID_STYLE_FAMILY5
;
277 case SfxStyleFamily::Table
:
278 nSlot
= SID_STYLE_FAMILY6
;
281 OSL_FAIL("unknown StyleFamily");
284 pBoundItems
[i
].reset(new SfxTemplateControllerItem(nSlot
, *m_pParentDialog
, *m_pBindings
));
286 pBoundItems
[i
++].reset(
287 new SfxTemplateControllerItem(SID_STYLE_WATERCAN
, *m_pParentDialog
, *m_pBindings
));
288 pBoundItems
[i
++].reset(
289 new SfxTemplateControllerItem(SID_STYLE_NEW_BY_EXAMPLE
, *m_pParentDialog
, *m_pBindings
));
290 pBoundItems
[i
++].reset(
291 new SfxTemplateControllerItem(SID_STYLE_UPDATE_BY_EXAMPLE
, *m_pParentDialog
, *m_pBindings
));
292 pBoundItems
[i
++].reset(
293 new SfxTemplateControllerItem(SID_STYLE_NEW
, *m_pParentDialog
, *m_pBindings
));
294 pBoundItems
[i
++].reset(
295 new SfxTemplateControllerItem(SID_STYLE_DRAGHIERARCHIE
, *m_pParentDialog
, *m_pBindings
));
296 pBoundItems
[i
++].reset(
297 new SfxTemplateControllerItem(SID_STYLE_EDIT
, *m_pParentDialog
, *m_pBindings
));
298 pBoundItems
[i
++].reset(
299 new SfxTemplateControllerItem(SID_STYLE_DELETE
, *m_pParentDialog
, *m_pBindings
));
300 pBoundItems
[i
++].reset(
301 new SfxTemplateControllerItem(SID_STYLE_FAMILY
, *m_pParentDialog
, *m_pBindings
));
302 m_pBindings
->LEAVEREGISTRATIONS();
304 for (; i
< COUNT_BOUND_FUNC
; ++i
)
305 pBoundItems
[i
] = nullptr;
307 StartListening(*m_pBindings
);
309 for (i
= SID_STYLE_FAMILY1
; i
<= SID_STYLE_FAMILY4
; i
++)
310 m_pBindings
->Update(i
);
315 void StyleList::EnableNewByExample(bool newByExampleDisabled
)
317 m_bNewByExampleDisabled
= newByExampleDisabled
;
320 void StyleList::FilterSelect(sal_uInt16 nActFilter
, bool bsetFilter
)
322 m_nActFilter
= nActFilter
;
325 SfxObjectShell
* const pDocShell
= m_aSaveSelection
.Call(*this);
326 SfxStyleSheetBasePool
* pOldStyleSheetPool
= m_pStyleSheetPool
;
327 m_pStyleSheetPool
= pDocShell
? pDocShell
->GetStyleSheetPool() : nullptr;
328 if (pOldStyleSheetPool
!= m_pStyleSheetPool
)
330 if (pOldStyleSheetPool
)
331 EndListening(*pOldStyleSheetPool
);
332 if (m_pStyleSheetPool
)
333 StartListening(*m_pStyleSheetPool
);
336 UpdateStyles(StyleFlags::UpdateFamilyList
);
339 IMPL_LINK(StyleList
, SetFamily
, sal_uInt16
, nId
, void)
341 if (m_nActFamily
!= 0xFFFF)
342 m_pParentDialog
->CheckItem(OUString::number(m_nActFamily
), false);
346 m_bUpdateFamily
= true;
350 void StyleList::InvalidateBindings()
352 m_pBindings
->Invalidate(SID_STYLE_NEW_BY_EXAMPLE
, true);
353 m_pBindings
->Update(SID_STYLE_NEW_BY_EXAMPLE
);
354 m_pBindings
->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE
, true);
355 m_pBindings
->Update(SID_STYLE_UPDATE_BY_EXAMPLE
);
356 m_pBindings
->Invalidate(SID_STYLE_WATERCAN
, true);
357 m_pBindings
->Update(SID_STYLE_WATERCAN
);
358 m_pBindings
->Invalidate(SID_STYLE_NEW
, true);
359 m_pBindings
->Update(SID_STYLE_NEW
);
360 m_pBindings
->Invalidate(SID_STYLE_DRAGHIERARCHIE
, true);
361 m_pBindings
->Update(SID_STYLE_DRAGHIERARCHIE
);
364 void StyleList::Initialize()
366 m_pBindings
->Invalidate(SID_STYLE_FAMILY
);
367 m_pBindings
->Update(SID_STYLE_FAMILY
);
369 m_xFmtLb
->connect_row_activated(LINK(this, StyleList
, TreeListApplyHdl
));
370 m_xFmtLb
->connect_mouse_press(LINK(this, StyleList
, MousePressHdl
));
371 m_xFmtLb
->connect_query_tooltip(LINK(this, StyleList
, QueryTooltipHdl
));
372 m_xFmtLb
->connect_selection_changed(LINK(this, StyleList
, FmtSelectHdl
));
373 m_xFmtLb
->connect_popup_menu(LINK(this, StyleList
, PopupFlatMenuHdl
));
374 m_xFmtLb
->connect_key_press(LINK(this, StyleList
, KeyInputHdl
));
375 m_xFmtLb
->set_selection_mode(SelectionMode::Multiple
);
376 m_xTreeBox
->connect_selection_changed(LINK(this, StyleList
, FmtSelectHdl
));
377 m_xTreeBox
->connect_row_activated(LINK(this, StyleList
, TreeListApplyHdl
));
378 m_xTreeBox
->connect_mouse_press(LINK(this, StyleList
, MousePressHdl
));
379 m_xTreeBox
->connect_query_tooltip(LINK(this, StyleList
, QueryTooltipHdl
));
380 m_xTreeBox
->connect_popup_menu(LINK(this, StyleList
, PopupTreeMenuHdl
));
381 m_xTreeBox
->connect_key_press(LINK(this, StyleList
, KeyInputHdl
));
382 m_xTreeBox
->connect_drag_begin(LINK(this, StyleList
, DragBeginHdl
));
383 m_xTreeView1DropTargetHelper
.reset(new TreeViewDropTarget(*this, *m_xFmtLb
));
384 m_xTreeView2DropTargetHelper
.reset(new TreeViewDropTarget(*this, *m_xTreeBox
));
386 m_pParentDialog
->connect_stylelist_read_resource(LINK(this, StyleList
, ReadResource
));
387 m_pParentDialog
->connect_stylelist_clear(LINK(this, StyleList
, Clear
));
388 m_pParentDialog
->connect_stylelist_cleanup(LINK(this, StyleList
, Cleanup
));
389 m_pParentDialog
->connect_stylelist_execute_drop(LINK(this, StyleList
, ExecuteDrop
));
390 m_pParentDialog
->connect_stylelist_execute_new_menu(
391 LINK(this, StyleList
, NewMenuExecuteAction
));
392 m_pParentDialog
->connect_stylelist_for_watercan(LINK(this, StyleList
, IsSafeForWaterCan
));
393 m_pParentDialog
->connect_stylelist_has_selected_style(LINK(this, StyleList
, HasSelectedStyle
));
394 m_pParentDialog
->connect_stylelist_update_style_dependents(
395 LINK(this, StyleList
, UpdateStyleDependents
));
396 m_pParentDialog
->connect_stylelist_enable_tree_drag(LINK(this, StyleList
, EnableTreeDrag
));
397 m_pParentDialog
->connect_stylelist_enable_delete(LINK(this, StyleList
, EnableDelete
));
398 m_pParentDialog
->connect_stylelist_set_water_can_state(LINK(this, StyleList
, SetWaterCanState
));
399 m_pParentDialog
->connect_set_family(LINK(this, StyleList
, SetFamily
));
401 int nTreeHeight
= m_xFmtLb
->get_height_rows(8);
402 m_xFmtLb
->set_size_request(-1, nTreeHeight
);
403 m_xTreeBox
->set_size_request(-1, nTreeHeight
);
405 m_xFmtLb
->connect_custom_get_size(LINK(this, StyleList
, CustomGetSizeHdl
));
406 m_xFmtLb
->connect_custom_render(LINK(this, StyleList
, CustomRenderHdl
));
407 m_xTreeBox
->connect_custom_get_size(LINK(this, StyleList
, CustomGetSizeHdl
));
408 m_xTreeBox
->connect_custom_render(LINK(this, StyleList
, CustomRenderHdl
));
409 bool bCustomPreview
= officecfg::Office::Common::StylesAndFormatting::Preview::get();
410 m_xFmtLb
->set_column_custom_renderer(1, bCustomPreview
);
411 m_xTreeBox
->set_column_custom_renderer(1, bCustomPreview
);
413 m_xFmtLb
->set_visible(!m_bHierarchical
);
414 m_xTreeBox
->set_visible(m_bHierarchical
);
418 void StyleList::UpdateFamily()
420 m_bUpdateFamily
= false;
422 SfxDispatcher
* pDispat
= m_pBindings
->GetDispatcher_Impl();
423 SfxViewFrame
* pViewFrame
= pDispat
->GetFrame();
424 SfxObjectShell
* pDocShell
= pViewFrame
->GetObjectShell();
426 SfxStyleSheetBasePool
* pOldStyleSheetPool
= m_pStyleSheetPool
;
427 m_pStyleSheetPool
= pDocShell
? pDocShell
->GetStyleSheetPool() : nullptr;
428 if (pOldStyleSheetPool
!= m_pStyleSheetPool
)
430 if (pOldStyleSheetPool
)
431 EndListening(*pOldStyleSheetPool
);
432 if (m_pStyleSheetPool
)
433 StartListening(*m_pStyleSheetPool
);
437 m_bCanNew
= m_xTreeBox
->get_visible() || m_xFmtLb
->count_selected_rows() <= 1;
438 m_pParentDialog
->EnableNew(m_bCanNew
, this);
440 if (m_pStyleSheetPool
)
442 if (!m_xTreeBox
->get_visible())
443 UpdateStyles(StyleFlags::UpdateFamily
| StyleFlags::UpdateFamilyList
);
446 UpdateStyles(StyleFlags::UpdateFamily
);
447 FillTreeBox(GetActualFamily());
451 InvalidateBindings();
454 bool StyleList::EnableExecute()
456 return m_xTreeBox
->get_visible() || m_xFmtLb
->count_selected_rows() <= 1;
459 void StyleList::connect_LoadFactoryStyleFilter(const Link
<SfxObjectShell
const*, sal_Int32
>& rLink
)
461 m_aLoadFactoryStyleFilter
= rLink
;
464 void StyleList::connect_SaveSelection(const Link
<StyleList
&, SfxObjectShell
*> rLink
)
466 m_aSaveSelection
= rLink
;
469 /** Drop is enabled as long as it is allowed to create a new style by example, i.e. to
470 create a style out of the current selection.
472 sal_Int8
StyleList::AcceptDrop(const AcceptDropEvent
& rEvt
, const DropTargetHelper
& rHelper
)
474 if (rHelper
.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR
))
476 // special case: page styles are allowed to create new styles by example
477 // but not allowed to be created by drag and drop
478 if (GetActualFamily() == SfxStyleFamily::Page
|| m_bNewByExampleDisabled
)
479 return DND_ACTION_NONE
;
481 return DND_ACTION_COPY
;
483 // to enable the autoscroll when we're close to the edges
484 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
485 pTreeView
->get_dest_row_at_pos(rEvt
.maPosPixel
, nullptr, true);
486 return DND_ACTION_MOVE
;
489 // handles drop of content in treeview when creating a new style
490 IMPL_LINK(StyleList
, ExecuteDrop
, const ExecuteDropEvent
&, rEvt
, sal_Int8
)
492 SfxObjectShell
* pDocShell
= m_pCurObjShell
;
495 TransferableDataHelper
aHelper(rEvt
.maDropEvent
.Transferable
);
496 sal_uInt32 nFormatCount
= aHelper
.GetFormatCount();
498 sal_Int8 nRet
= DND_ACTION_NONE
;
500 bool bFormatFound
= false;
502 for (sal_uInt32 i
= 0; i
< nFormatCount
; ++i
)
504 SotClipboardFormatId nId
= aHelper
.GetFormat(i
);
505 TransferableObjectDescriptor aDesc
;
507 if (aHelper
.GetTransferableObjectDescriptor(nId
, aDesc
))
509 if (aDesc
.maClassName
== pDocShell
->GetFactory().GetClassId())
511 Application::PostUserEvent(
512 LINK(m_pParentDialog
, SfxCommonTemplateDialog_Impl
, OnAsyncExecuteDrop
),
516 nRet
= rEvt
.mnAction
;
526 if (!m_xTreeBox
->get_visible())
527 return DND_ACTION_NONE
;
529 if (!m_bAllowReParentDrop
)
530 return DND_ACTION_NONE
;
532 // otherwise if we're dragging with the treeview to set a new parent of the dragged style
533 weld::TreeView
* pSource
= m_xTreeBox
->get_drag_source();
534 // only dragging within the same widget allowed
535 if (!pSource
|| pSource
!= m_xTreeBox
.get())
536 return DND_ACTION_NONE
;
538 std::unique_ptr
<weld::TreeIter
> xSource(m_xTreeBox
->make_iterator());
539 if (!m_xTreeBox
->get_selected(xSource
.get()))
540 return DND_ACTION_NONE
;
542 std::unique_ptr
<weld::TreeIter
> xTarget(m_xTreeBox
->make_iterator());
543 if (!m_xTreeBox
->get_dest_row_at_pos(rEvt
.maPosPixel
, xTarget
.get(), true))
545 // if nothing under the mouse, use the last row
546 int nChildren
= m_xTreeBox
->n_children();
548 return DND_ACTION_NONE
;
549 if (!m_xTreeBox
->get_iter_first(*xTarget
)
550 || !m_xTreeBox
->iter_nth_sibling(*xTarget
, nChildren
- 1))
551 return DND_ACTION_NONE
;
552 while (m_xTreeBox
->get_row_expanded(*xTarget
))
554 nChildren
= m_xTreeBox
->iter_n_children(*xTarget
);
555 if (!m_xTreeBox
->iter_children(*xTarget
)
556 || !m_xTreeBox
->iter_nth_sibling(*xTarget
, nChildren
- 1))
557 return DND_ACTION_NONE
;
560 OUString aTargetStyle
= m_xTreeBox
->get_text(*xTarget
);
561 DropHdl(m_xTreeBox
->get_text(*xSource
), aTargetStyle
);
562 m_xTreeBox
->unset_drag_dest_row();
563 FillTreeBox(GetActualFamily());
564 m_pParentDialog
->SelectStyle(aTargetStyle
, false, *this);
565 return DND_ACTION_NONE
;
568 IMPL_LINK_NOARG(StyleList
, NewMenuExecuteAction
, void*, void)
570 if (!m_pStyleSheetPool
|| m_nActFamily
== 0xffff)
573 const SfxStyleFamily eFam
= GetFamilyItem()->GetFamily();
574 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
575 SfxStyleSearchBits
nFilter(SfxStyleSearchBits::Auto
);
576 if (pItem
&& m_nActFilter
!= 0xffff)
577 nFilter
= pItem
->GetFilterList()[m_nActFilter
].nFlags
;
578 if (nFilter
== SfxStyleSearchBits::Auto
) // automatic
579 nFilter
= m_nAppFilter
;
581 // why? : FloatingWindow must not be parent of a modal dialog
582 SfxNewStyleDlg
aDlg(m_pContainer
, *m_pStyleSheetPool
, eFam
);
583 auto nResult
= aDlg
.run();
584 if (nResult
== RET_OK
)
586 const OUString
aTemplName(aDlg
.GetName());
587 m_pParentDialog
->Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE
, aTemplName
, u
""_ustr
,
588 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this,
591 m_aUpdateFamily
.Call(*this);
595 void StyleList::DropHdl(const OUString
& rStyle
, const OUString
& rParent
)
597 m_bDontUpdate
= true;
598 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
599 const SfxStyleFamily eFam
= pItem
->GetFamily();
600 if (auto pStyle
= m_pStyleSheetPool
->Find(rStyle
, eFam
))
601 pStyle
->SetParent(rParent
);
602 m_bDontUpdate
= false;
605 void StyleList::PrepareMenu(const Point
& rPos
)
607 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
608 std::unique_ptr
<weld::TreeIter
> xIter(pTreeView
->make_iterator());
609 if (pTreeView
->get_dest_row_at_pos(rPos
, xIter
.get(), false) && !pTreeView
->is_selected(*xIter
))
611 pTreeView
->unselect_all();
612 pTreeView
->set_cursor(*xIter
);
613 pTreeView
->select(*xIter
);
615 FmtSelectHdl(*pTreeView
);
618 /** Internal structure for the establishment of the hierarchical view */
621 class StyleTree_Impl
;
624 typedef std::vector
<std::unique_ptr
<StyleTree_Impl
>> StyleTreeArr_Impl
;
633 StyleTreeArr_Impl pChildren
;
636 bool HasParent() const { return !aParent
.isEmpty(); }
638 StyleTree_Impl(OUString _aName
, OUString _aParent
)
639 : aName(std::move(_aName
))
640 , aParent(std::move(_aParent
))
645 const OUString
& getName() const { return aName
; }
646 const OUString
& getParent() const { return aParent
; }
647 StyleTreeArr_Impl
& getChildren() { return pChildren
; }
651 static void MakeTree_Impl(StyleTreeArr_Impl
& rArr
, const OUString
& aUIName
)
653 const comphelper::string::NaturalStringSorter
aSorter(
654 ::comphelper::getProcessComponentContext(),
655 Application::GetSettings().GetLanguageTag().getLocale());
657 std::unordered_map
<OUString
, StyleTree_Impl
*> styleFinder
;
658 styleFinder
.reserve(rArr
.size());
659 for (const auto& pEntry
: rArr
)
661 styleFinder
.emplace(pEntry
->getName(), pEntry
.get());
664 // Arrange all under their Parents
665 for (auto& pEntry
: rArr
)
667 if (!pEntry
->HasParent())
669 auto it
= styleFinder
.find(pEntry
->getParent());
670 if (it
!= styleFinder
.end())
672 StyleTree_Impl
* pCmp
= it
->second
;
673 // Insert child entries sorted
674 auto iPos
= std::lower_bound(
675 pCmp
->getChildren().begin(), pCmp
->getChildren().end(), pEntry
,
676 [&aSorter
](std::unique_ptr
<StyleTree_Impl
> const& pEntry1
,
677 std::unique_ptr
<StyleTree_Impl
> const& pEntry2
) {
678 return aSorter
.compare(pEntry1
->getName(), pEntry2
->getName()) < 0;
680 pCmp
->getChildren().insert(iPos
, std::move(pEntry
));
684 // Only keep tree roots in rArr, child elements can be accessed through the hierarchy
685 std::erase_if(rArr
, [](std::unique_ptr
<StyleTree_Impl
> const& pEntry
) { return !pEntry
; });
687 // tdf#91106 sort top level styles
688 std::sort(rArr
.begin(), rArr
.end());
689 std::sort(rArr
.begin(), rArr
.end(),
690 [&aSorter
, &aUIName
](std::unique_ptr
<StyleTree_Impl
> const& pEntry1
,
691 std::unique_ptr
<StyleTree_Impl
> const& pEntry2
) {
692 if (pEntry2
->getName() == aUIName
)
694 if (pEntry1
->getName() == aUIName
)
695 return true; // default always first
696 return aSorter
.compare(pEntry1
->getName(), pEntry2
->getName()) < 0;
700 static bool IsExpanded_Impl(const std::vector
<OUString
>& rEntries
, std::u16string_view rStr
)
702 for (const auto& rEntry
: rEntries
)
710 static void lcl_Update(weld::TreeView
& rTreeView
, weld::TreeIter
& rIter
, const OUString
& rName
,
711 SfxStyleFamily eFam
, SfxViewShell
* pViewSh
)
713 Color aColor
= ColorHash(rName
);
716 if (eFam
== SfxStyleFamily::Para
)
718 StylesHighlighterColorMap
& rParaStylesColorMap
719 = pViewSh
->GetStylesHighlighterParaColorMap();
720 nColor
= rParaStylesColorMap
.size();
721 rParaStylesColorMap
[rName
] = std::pair(aColor
, nColor
);
725 StylesHighlighterColorMap
& rCharStylesColorMap
726 = pViewSh
->GetStylesHighlighterCharColorMap();
727 nColor
= rCharStylesColorMap
.size();
728 rCharStylesColorMap
[rName
] = std::pair(aColor
, nColor
);
729 // don't show a color or number for default character style 'No Character Style' entry
730 if (rName
== sDefaultCharStyleUIName
.value() /*"No Character Style"*/)
732 rTreeView
.set_id(rIter
, rName
);
733 rTreeView
.set_text(rIter
, rName
);
738 // draw the color rectangle and number image
739 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
740 Size aImageSize
= rStyleSettings
.GetListBoxPreviewDefaultPixelSize();
741 ScopedVclPtrInstance
<VirtualDevice
> xDevice
;
742 xDevice
->SetOutputSize(aImageSize
);
743 xDevice
->SetFillColor(aColor
);
744 const tools::Rectangle
aRect(Point(0, 0), aImageSize
);
745 xDevice
->DrawRect(aRect
);
746 xDevice
->SetTextColor(COL_BLACK
);
747 xDevice
->DrawText(aRect
, OUString::number(nColor
),
748 DrawTextFlags::Center
| DrawTextFlags::VCenter
);
750 rTreeView
.set_id(rIter
, rName
);
751 rTreeView
.set_text(rIter
, rName
);
752 rTreeView
.set_image(rIter
, *xDevice
);
755 static void FillBox_Impl(weld::TreeView
& rBox
, StyleTreeArr_Impl
& rTreeArray
,
756 SfxStyleFamily eStyleFamily
, const weld::TreeIter
* pParent
,
757 bool blcl_insert
, SfxViewShell
* pViewShell
,
758 SfxStyleSheetBasePool
* pStyleSheetPool
)
760 if (rTreeArray
.empty())
762 rBox
.bulk_insert_for_each(rTreeArray
.size(),
763 [&rTreeArray
, blcl_insert
, pStyleSheetPool
, eStyleFamily
, &rBox
,
764 pViewShell
](weld::TreeIter
& rIter
, int i
) {
765 StyleTree_Impl
* pChildEntry
= rTreeArray
[i
].get();
766 const OUString
& rChildName
= pChildEntry
->getName();
769 const SfxStyleSheetBase
* pStyle
= nullptr;
771 pStyle
= pStyleSheetPool
->Find(rChildName
, eStyleFamily
);
772 if (pStyle
&& pStyle
->IsUsed())
773 lcl_Update(rBox
, rIter
, rChildName
, eStyleFamily
,
777 rBox
.set_id(rIter
, rChildName
);
778 rBox
.set_text(rIter
, rChildName
);
783 rBox
.set_id(rIter
, rChildName
);
784 rBox
.set_text(rIter
, rChildName
);
787 pParent
, nullptr, /*bGoingToSetText*/ true);
789 std::unique_ptr
<weld::TreeIter
> xChildParentIter
= rBox
.make_iterator(pParent
);
791 (void)rBox
.get_iter_first(*xChildParentIter
);
793 (void)rBox
.iter_children(*xChildParentIter
);
794 for (size_t i
= 0; i
< rTreeArray
.size(); ++i
)
796 FillBox_Impl(rBox
, rTreeArray
[i
]->getChildren(), eStyleFamily
, xChildParentIter
.get(),
797 blcl_insert
, pViewShell
, pStyleSheetPool
);
798 (void)rBox
.iter_next_sibling(*xChildParentIter
);
802 namespace SfxTemplate
804 // converts from SFX_STYLE_FAMILY Ids to 1-6
805 static sal_uInt16
SfxFamilyIdToNId(SfxStyleFamily nFamily
)
809 case SfxStyleFamily::Char
:
811 case SfxStyleFamily::Para
:
813 case SfxStyleFamily::Frame
:
815 case SfxStyleFamily::Page
:
817 case SfxStyleFamily::Pseudo
:
819 case SfxStyleFamily::Table
:
825 // converts from 1-6 to SFX_STYLE_FAMILY Ids
826 static SfxStyleFamily
NIdToSfxFamilyId(sal_uInt16 nId
)
831 return SfxStyleFamily::Char
;
833 return SfxStyleFamily::Para
;
835 return SfxStyleFamily::Frame
;
837 return SfxStyleFamily::Page
;
839 return SfxStyleFamily::Pseudo
;
841 return SfxStyleFamily::Table
;
843 return SfxStyleFamily::All
;
848 sal_uInt16
StyleList::StyleNrToInfoOffset(sal_uInt16 nId
)
850 const SfxStyleFamilyItem
& rItem
= m_xStyleFamilies
->at(nId
);
851 return SfxTemplate::SfxFamilyIdToNId(rItem
.GetFamily()) - 1;
854 // Helper function: Access to the current family item
855 const SfxStyleFamilyItem
* StyleList::GetFamilyItem() const
857 const size_t nCount
= m_xStyleFamilies
->size();
858 for (size_t i
= 0; i
< nCount
; ++i
)
860 const SfxStyleFamilyItem
& rItem
= m_xStyleFamilies
->at(i
);
861 sal_uInt16 nId
= SfxTemplate::SfxFamilyIdToNId(rItem
.GetFamily());
862 if (nId
== m_nActFamily
)
868 void StyleList::GetSelectedStyle() const
870 const OUString
aTemplName(GetSelectedEntry());
871 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
872 m_pStyleSheetPool
->Find(aTemplName
, pItem
->GetFamily());
875 // Used to get the current selected entry in visible treeview
876 OUString
StyleList::GetSelectedEntry() const
879 if (m_xTreeBox
->get_visible())
880 aRet
= m_xTreeBox
->get_selected_text();
882 aRet
= m_xFmtLb
->get_selected_text();
887 * Is it safe to show the water-can / fill icon. If we've a
888 * hierarchical widget - we have only single select, otherwise
889 * we need to check if we have a multi-selection. We either have
890 * a m_xTreeBox showing or an m_xFmtLb (which we hide when not shown)
892 IMPL_LINK_NOARG(StyleList
, IsSafeForWaterCan
, void*, bool)
894 if (m_xTreeBox
->get_visible())
895 return m_xTreeBox
->get_selected_index() != -1;
897 return m_xFmtLb
->count_selected_rows() == 1;
900 IMPL_LINK(StyleList
, SetWaterCanState
, const SfxBoolItem
*, pItem
, void)
902 size_t nCount
= m_xStyleFamilies
->size();
903 m_pBindings
->EnterRegistrations();
904 for (size_t n
= 0; n
< nCount
; n
++)
906 SfxControllerItem
* pCItem
= pBoundItems
[n
].get();
907 bool bChecked
= pItem
&& pItem
->GetValue();
908 if (pCItem
->IsBound() == bChecked
)
916 m_pBindings
->LeaveRegistrations();
919 void StyleList::FamilySelect(sal_uInt16 nEntry
, bool bRefresh
)
923 bool bCustomPreview
= officecfg::Office::Common::StylesAndFormatting::Preview::get();
925 m_xFmtLb
->set_column_custom_renderer(1, bCustomPreview
);
927 m_xTreeBox
->set_column_custom_renderer(1, bCustomPreview
);
929 m_nActFamily
= nEntry
;
930 SfxDispatcher
* pDispat
= m_pBindings
->GetDispatcher_Impl();
931 SfxUInt16Item
const aItem(SID_STYLE_FAMILY
,
932 static_cast<sal_uInt16
>(SfxTemplate::NIdToSfxFamilyId(nEntry
)));
933 pDispat
->ExecuteList(SID_STYLE_FAMILY
, SfxCallMode::SYNCHRON
, { &aItem
});
934 m_pBindings
->Invalidate(SID_STYLE_FAMILY
);
935 m_pBindings
->Update(SID_STYLE_FAMILY
);
937 m_aUpdateFamily
.Call(*this);
940 // It selects the style in treeview
941 // bIsCallBack is true for the selected style. For eg. if "Addressee" is selected in
942 // styles, bIsCallBack will be true for it.
943 void StyleList::SelectStyle(const OUString
& rStr
, bool bIsCallback
)
945 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
948 const SfxStyleFamily eFam
= pItem
->GetFamily();
949 SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->Find(rStr
, eFam
);
952 bool bReadWrite
= !(pStyle
->GetMask() & SfxStyleSearchBits::ReadOnly
);
953 m_pParentDialog
->EnableEdit(bReadWrite
, this);
954 m_pParentDialog
->EnableHide(bReadWrite
&& !pStyle
->IsHidden() && !pStyle
->IsUsed(), this);
955 m_pParentDialog
->EnableShow(bReadWrite
&& pStyle
->IsHidden(), this);
959 m_pParentDialog
->EnableEdit(false, this);
960 m_pParentDialog
->EnableHide(false, this);
961 m_pParentDialog
->EnableShow(false, this);
967 if (m_xTreeBox
->get_visible())
971 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xTreeBox
->make_iterator();
972 bool bEntry
= m_xTreeBox
->get_iter_first(*xEntry
);
975 if (m_xTreeBox
->get_text(*xEntry
) == rStr
)
977 m_xTreeBox
->scroll_to_row(*xEntry
);
978 m_xTreeBox
->select(*xEntry
);
981 bEntry
= m_xTreeBox
->iter_next(*xEntry
);
984 else if (eFam
== SfxStyleFamily::Pseudo
)
986 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xTreeBox
->make_iterator();
987 if (m_xTreeBox
->get_iter_first(*xEntry
))
989 m_xTreeBox
->scroll_to_row(*xEntry
);
990 m_xTreeBox
->select(*xEntry
);
994 m_xTreeBox
->unselect_all();
998 bool bSelect
= !rStr
.isEmpty();
1001 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xFmtLb
->make_iterator();
1002 bool bEntry
= m_xFmtLb
->get_iter_first(*xEntry
);
1003 while (bEntry
&& m_xFmtLb
->get_text(*xEntry
) != rStr
)
1004 bEntry
= m_xFmtLb
->iter_next(*xEntry
);
1009 if (!m_xFmtLb
->is_selected(*xEntry
))
1011 m_xFmtLb
->unselect_all();
1012 m_xFmtLb
->scroll_to_row(*xEntry
);
1013 m_xFmtLb
->select(*xEntry
);
1020 m_xFmtLb
->unselect_all();
1021 m_pParentDialog
->EnableEdit(false, this);
1022 m_pParentDialog
->EnableHide(false, this);
1023 m_pParentDialog
->EnableShow(false, this);
1028 static void MakeExpanded_Impl(const weld::TreeView
& rBox
, std::vector
<OUString
>& rEntries
)
1030 std::unique_ptr
<weld::TreeIter
> xEntry
= rBox
.make_iterator();
1031 if (rBox
.get_iter_first(*xEntry
))
1035 if (rBox
.get_row_expanded(*xEntry
))
1036 rEntries
.push_back(rBox
.get_text(*xEntry
));
1037 } while (rBox
.iter_next(*xEntry
));
1041 IMPL_LINK(StyleList
, EnableTreeDrag
, bool, m_bEnable
, void)
1043 if (m_pStyleSheetPool
)
1045 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1046 SfxStyleSheetBase
* pStyle
= pItem
? m_pStyleSheetPool
->First(pItem
->GetFamily()) : nullptr;
1047 m_bAllowReParentDrop
= pStyle
&& pStyle
->HasParentSupport() && m_bEnable
;
1049 m_bTreeDrag
= m_bEnable
;
1052 // Fill the treeview
1054 void StyleList::FillTreeBox(SfxStyleFamily eFam
)
1056 assert(m_xTreeBox
&& "FillTreeBox() without treebox");
1057 if (!m_pStyleSheetPool
|| m_nActFamily
== 0xffff)
1060 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1064 StyleTreeArr_Impl aArr
;
1065 SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->First(eFam
, SfxStyleSearchBits::All
);
1067 m_bAllowReParentDrop
= pStyle
&& pStyle
->HasParentSupport() && m_bTreeDrag
;
1071 if (pStyle
->IsHidden()
1072 && (pStyle
->GetFamily() == SfxStyleFamily::Page
1073 || pStyle
->GetFamily() == SfxStyleFamily::Pseudo
1074 || pStyle
->GetFamily() == SfxStyleFamily::Table
))
1078 StyleTree_Impl
* pNew
= new StyleTree_Impl(pStyle
->GetName(), pStyle
->GetParent());
1079 aArr
.emplace_back(pNew
);
1081 pStyle
= m_pStyleSheetPool
->Next();
1083 OUString aUIName
= getDefaultStyleName(eFam
);
1084 MakeTree_Impl(aArr
, aUIName
);
1085 std::vector
<OUString
> aEntries
;
1086 MakeExpanded_Impl(*m_xTreeBox
, aEntries
);
1087 m_xTreeBox
->freeze();
1088 m_xTreeBox
->clear();
1089 const sal_uInt16 nCount
= aArr
.size();
1091 SfxViewShell
* pViewShell
= m_pCurObjShell
->GetViewShell();
1092 StylesHighlighterColorMap
* pHighlighterColorMap
= nullptr;
1093 bool bOrigMapHasEntries
= false;
1094 if (pViewShell
&& m_bModuleHasStylesHighlighterFeature
)
1096 if (eFam
== SfxStyleFamily::Para
)
1097 pHighlighterColorMap
= &pViewShell
->GetStylesHighlighterParaColorMap();
1098 else if (eFam
== SfxStyleFamily::Char
)
1099 pHighlighterColorMap
= &pViewShell
->GetStylesHighlighterCharColorMap();
1102 if (pHighlighterColorMap
&& !pHighlighterColorMap
->empty())
1104 bOrigMapHasEntries
= true;
1105 pHighlighterColorMap
->clear();
1108 bool blcl_insert
= pViewShell
&& m_bModuleHasStylesHighlighterFeature
1109 && ((eFam
== SfxStyleFamily::Para
&& m_bHighlightParaStyles
)
1110 || (eFam
== SfxStyleFamily::Char
&& m_bHighlightCharStyles
));
1112 FillBox_Impl(*m_xTreeBox
, aArr
, eFam
, nullptr, blcl_insert
, pViewShell
, m_pStyleSheetPool
);
1113 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
1116 m_xTreeBox
->columns_autosize();
1118 m_pParentDialog
->EnableItem(u
"watercan"_ustr
, false);
1120 SfxTemplateItem
* pState
= m_pFamilyState
[m_nActFamily
- 1].get();
1125 if (pViewShell
&& pHighlighterColorMap
1126 && (!pHighlighterColorMap
->empty() || bOrigMapHasEntries
))
1127 static_cast<SfxListener
*>(pViewShell
)
1128 ->Notify(*m_pStyleSheetPool
, SfxHint(SfxHintId::StylesHighlighterModified
));
1130 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xTreeBox
->make_iterator();
1131 bool bEntry
= m_xTreeBox
->get_iter_first(*xEntry
);
1132 if (bEntry
&& nCount
)
1133 m_xTreeBox
->expand_row(*xEntry
);
1137 if (IsExpanded_Impl(aEntries
, m_xTreeBox
->get_text(*xEntry
)))
1138 m_xTreeBox
->expand_row(*xEntry
);
1139 bEntry
= m_xTreeBox
->iter_next(*xEntry
);
1143 if (pState
) // Select current entry
1144 aStyle
= pState
->GetStyleName();
1145 m_pParentDialog
->SelectStyle(aStyle
, false, *this);
1146 EnableDelete(nullptr);
1149 static OUString
lcl_GetStyleFamilyName(SfxStyleFamily nFamily
)
1151 if (nFamily
== SfxStyleFamily::Char
)
1152 return u
"CharacterStyles"_ustr
;
1153 if (nFamily
== SfxStyleFamily::Para
)
1154 return u
"ParagraphStyles"_ustr
;
1155 if (nFamily
== SfxStyleFamily::Page
)
1156 return u
"PageStyles"_ustr
;
1157 if (nFamily
== SfxStyleFamily::Table
)
1158 return u
"TableStyles"_ustr
;
1159 if (nFamily
== SfxStyleFamily::Pseudo
)
1160 return u
"NumberingStyles"_ustr
;
1164 OUString
StyleList::getDefaultStyleName(const SfxStyleFamily eFam
)
1166 OUString sDefaultStyle
;
1167 OUString aFamilyName
= lcl_GetStyleFamilyName(eFam
);
1168 if (aFamilyName
== "TableStyles")
1169 sDefaultStyle
= "Default Style";
1170 else if (aFamilyName
== "NumberingStyles")
1171 sDefaultStyle
= "No List";
1173 sDefaultStyle
= "Standard";
1174 uno::Reference
<style::XStyleFamiliesSupplier
> xModel(m_pCurObjShell
->GetModel(),
1179 uno::Reference
<container::XNameAccess
> xStyles
;
1180 uno::Reference
<container::XNameAccess
> xCont
= xModel
->getStyleFamilies();
1181 xCont
->getByName(aFamilyName
) >>= xStyles
;
1182 uno::Reference
<beans::XPropertySet
> xInfo
;
1183 xStyles
->getByName(sDefaultStyle
) >>= xInfo
;
1184 xInfo
->getPropertyValue(u
"DisplayName"_ustr
) >>= aUIName
;
1186 catch (const uno::Exception
&)
1192 SfxStyleFamily
StyleList::GetActualFamily() const
1194 const SfxStyleFamilyItem
* pFamilyItem
= GetFamilyItem();
1195 if (!pFamilyItem
|| m_nActFamily
== 0xffff)
1196 return SfxStyleFamily::Para
;
1198 return pFamilyItem
->GetFamily();
1201 IMPL_LINK_NOARG(StyleList
, HasSelectedStyle
, void*, bool)
1203 return m_xTreeBox
->get_visible() ? m_xTreeBox
->get_selected_index() != -1
1204 : m_xFmtLb
->count_selected_rows() != 0;
1207 IMPL_LINK_NOARG(StyleList
, UpdateStyleDependents
, void*, void)
1209 // Trigger Help PI. Only when the watercan is on
1210 if (m_nActFamily
!= 0xffff && m_pParentDialog
->IsCheckedItem(u
"watercan"_ustr
) &&
1211 // only if that region is allowed
1212 nullptr != m_pFamilyState
[m_nActFamily
- 1] && IsSafeForWaterCan(nullptr))
1214 m_pParentDialog
->Execute_Impl(SID_STYLE_WATERCAN
, u
""_ustr
, u
""_ustr
, 0, *this);
1215 m_pParentDialog
->Execute_Impl(SID_STYLE_WATERCAN
, GetSelectedEntry(), u
""_ustr
,
1216 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this);
1220 // Comes into action when the current style is changed
1221 void StyleList::UpdateStyles(StyleFlags nFlags
)
1223 OSL_ENSURE(nFlags
!= StyleFlags::NONE
, "nothing to do");
1224 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1227 // Is the case for the template catalog
1228 const size_t nFamilyCount
= m_xStyleFamilies
->size();
1230 for (n
= 0; n
< nFamilyCount
; n
++)
1231 if (m_pFamilyState
[StyleNrToInfoOffset(n
)])
1233 if (n
== nFamilyCount
)
1234 // It happens sometimes, God knows why
1236 m_nAppFilter
= m_pFamilyState
[StyleNrToInfoOffset(n
)]->GetValue();
1237 m_pParentDialog
->FamilySelect(StyleNrToInfoOffset(n
) + 1, *this);
1238 pItem
= GetFamilyItem();
1241 const SfxStyleFamily eFam
= pItem
->GetFamily();
1243 SfxStyleSearchBits
nFilter(m_nActFilter
< pItem
->GetFilterList().size()
1244 ? pItem
->GetFilterList()[m_nActFilter
].nFlags
1245 : SfxStyleSearchBits::Auto
);
1246 if (nFilter
== SfxStyleSearchBits::Auto
) // automatic
1247 nFilter
= m_nAppFilter
;
1249 OSL_ENSURE(m_pStyleSheetPool
, "no StyleSheetPool");
1250 if (!m_pStyleSheetPool
)
1253 m_aUpdateStyles
.Call(nFlags
);
1255 SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->First(eFam
, nFilter
);
1257 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xFmtLb
->make_iterator();
1258 std::vector
<OUString
> aStrings
;
1260 comphelper::string::NaturalStringSorter
aSorter(
1261 ::comphelper::getProcessComponentContext(),
1262 Application::GetSettings().GetLanguageTag().getLocale());
1266 aStrings
.push_back(pStyle
->GetName());
1267 pStyle
= m_pStyleSheetPool
->Next();
1269 OUString aUIName
= getDefaultStyleName(eFam
);
1271 // Paradoxically, with a list and non-Latin style names,
1272 // sorting twice is faster than sorting once.
1273 // The first sort has a cheap comparator, and gets the list into mostly-sorted order.
1274 // Then the second sort needs to call its (much more expensive) comparator less often.
1275 std::sort(aStrings
.begin(), aStrings
.end());
1276 std::sort(aStrings
.begin(), aStrings
.end(),
1277 [&aSorter
, &aUIName
](const OUString
& rLHS
, const OUString
& rRHS
) {
1278 if (rRHS
== aUIName
)
1280 if (rLHS
== aUIName
)
1281 return true; // default always first
1282 return aSorter
.compare(rLHS
, rRHS
) < 0;
1285 // Fill the display box
1289 SfxViewShell
* pViewShell
= m_pCurObjShell
->GetViewShell();
1290 StylesHighlighterColorMap
* pHighlighterColorMap
= nullptr;
1291 bool bOrigMapHasEntries
= false;
1292 if (pViewShell
&& m_bModuleHasStylesHighlighterFeature
)
1294 if (eFam
== SfxStyleFamily::Para
)
1295 pHighlighterColorMap
= &pViewShell
->GetStylesHighlighterParaColorMap();
1296 else if (eFam
== SfxStyleFamily::Char
)
1297 pHighlighterColorMap
= &pViewShell
->GetStylesHighlighterCharColorMap();
1300 if (pHighlighterColorMap
&& !pHighlighterColorMap
->empty())
1302 bOrigMapHasEntries
= true;
1303 pHighlighterColorMap
->clear();
1306 size_t nCount
= aStrings
.size();
1308 if (pViewShell
&& m_bModuleHasStylesHighlighterFeature
1309 && ((eFam
== SfxStyleFamily::Para
&& m_bHighlightParaStyles
)
1310 || (eFam
== SfxStyleFamily::Char
&& m_bHighlightCharStyles
)))
1312 m_xFmtLb
->bulk_insert_for_each(
1314 [this, &aStrings
, eFam
, pViewShell
](weld::TreeIter
& rIter
, int nIdx
) {
1315 auto pChildStyle
= m_pStyleSheetPool
->Find(aStrings
[nIdx
], eFam
);
1316 if (pChildStyle
&& pChildStyle
->IsUsed())
1317 lcl_Update(*m_xFmtLb
, rIter
, aStrings
[nIdx
], eFam
, pViewShell
);
1320 m_xFmtLb
->set_id(rIter
, aStrings
[nIdx
]);
1321 m_xFmtLb
->set_text(rIter
, aStrings
[nIdx
]);
1324 nullptr, nullptr, /*bGoingToSetText*/ true);
1328 m_xFmtLb
->bulk_insert_for_each(nCount
,
1329 [this, &aStrings
](weld::TreeIter
& rIter
, int nIdx
) {
1330 m_xFmtLb
->set_id(rIter
, aStrings
[nIdx
]);
1331 m_xFmtLb
->set_text(rIter
, aStrings
[nIdx
]);
1333 nullptr, nullptr, /*bGoingToSetText*/ true);
1336 m_xFmtLb
->columns_autosize();
1341 if (pViewShell
&& pHighlighterColorMap
1342 && (!pHighlighterColorMap
->empty() || bOrigMapHasEntries
))
1343 static_cast<SfxListener
*>(pViewShell
)
1344 ->Notify(*m_pStyleSheetPool
, SfxHint(SfxHintId::StylesHighlighterModified
));
1346 // Selects the current style if any
1347 SfxTemplateItem
* pState
= m_pFamilyState
[m_nActFamily
- 1].get();
1350 aStyle
= pState
->GetStyleName();
1351 m_pParentDialog
->SelectStyle(aStyle
, false, *this);
1352 EnableDelete(nullptr);
1355 void StyleList::SetFamilyState(sal_uInt16 nSlotId
, const SfxTemplateItem
* pItem
)
1357 sal_uInt16 nIdx
= nSlotId
- SID_STYLE_FAMILY_START
;
1358 m_pFamilyState
[nIdx
].reset();
1360 m_pFamilyState
[nIdx
].reset(new SfxTemplateItem(*pItem
));
1361 m_bUpdateFamily
= true;
1364 void StyleList::SetHierarchical()
1366 m_bHierarchical
= true;
1367 const OUString
aSelectEntry(GetSelectedEntry());
1369 FillTreeBox(GetActualFamily());
1370 m_pParentDialog
->SelectStyle(aSelectEntry
, false, *this);
1374 void StyleList::SetFilterControlsHandle()
1378 m_bHierarchical
= false;
1381 // Handler for the New-Buttons
1382 void StyleList::NewHdl()
1384 if (m_nActFamily
== 0xffff
1385 || !(m_xTreeBox
->get_visible() || m_xFmtLb
->count_selected_rows() <= 1))
1388 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1389 const SfxStyleFamily eFam
= pItem
->GetFamily();
1390 SfxStyleSearchBits
nMask(SfxStyleSearchBits::Auto
);
1391 if (m_nActFilter
!= 0xffff)
1392 nMask
= pItem
->GetFilterList()[m_nActFilter
].nFlags
;
1393 if (nMask
== SfxStyleSearchBits::Auto
) // automatic
1394 nMask
= m_nAppFilter
;
1396 m_pParentDialog
->Execute_Impl(SID_STYLE_NEW
, u
""_ustr
, GetSelectedEntry(),
1397 static_cast<sal_uInt16
>(eFam
), *this, nMask
);
1400 // Handler for the edit-Buttons
1401 void StyleList::EditHdl()
1403 if (m_nActFamily
!= 0xffff && HasSelectedStyle(nullptr))
1405 sal_uInt16 nFilter
= m_nActFilter
;
1406 OUString
aTemplName(GetSelectedEntry());
1407 GetSelectedStyle(); // -Wall required??
1408 m_pParentDialog
->Execute_Impl(SID_STYLE_EDIT
, aTemplName
, OUString(),
1409 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this,
1410 SfxStyleSearchBits::Auto
, &nFilter
);
1414 // Handler for the Delete-Buttons
1415 void StyleList::DeleteHdl()
1417 if (m_nActFamily
== 0xffff || !HasSelectedStyle(nullptr))
1420 bool bUsedStyle
= false; // one of the selected styles are used in the document?
1422 std::vector
<std::unique_ptr
<weld::TreeIter
>> aList
;
1423 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
1424 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1426 OUStringBuffer
aMsg(SfxResId(STR_DELETE_STYLE_USED
) + SfxResId(STR_DELETE_STYLE
));
1428 pTreeView
->selected_foreach(
1429 [this, pTreeView
, pItem
, &aList
, &bUsedStyle
, &aMsg
](weld::TreeIter
& rEntry
) {
1430 aList
.emplace_back(pTreeView
->make_iterator(&rEntry
));
1431 // check the style is used or not
1432 const OUString
aTemplName(pTreeView
->get_text(rEntry
));
1434 SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->Find(aTemplName
, pItem
->GetFamily());
1436 if (pStyle
->IsUsed()) // pStyle is in use in the document?
1438 if (bUsedStyle
) // add a separator for the second and later styles
1440 aMsg
.append(aTemplName
);
1447 bool aApproved
= false;
1449 // we only want to show the dialog once and if we want to delete a style in use (UX-advice)
1452 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(
1453 pTreeView
, VclMessageType::Question
, VclButtonsType::YesNo
, aMsg
.makeStringAndClear()));
1454 aApproved
= xBox
->run() == RET_YES
;
1457 // if there are no used styles selected or the user approved the changes
1458 if (bUsedStyle
&& !aApproved
)
1461 for (auto const& elem
: aList
)
1463 const OUString
aTemplName(pTreeView
->get_text(*elem
));
1464 m_bDontUpdate
= true; // To prevent the Treelistbox to shut down while deleting
1465 m_pParentDialog
->Execute_Impl(SID_STYLE_DELETE
, aTemplName
, OUString(),
1466 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this);
1468 if (m_xTreeBox
->get_visible())
1470 weld::RemoveParentKeepChildren(*m_xTreeBox
, *elem
);
1471 m_bDontUpdate
= false;
1474 m_bDontUpdate
= false; // if everything is deleted set m_bDontUpdate back to false
1475 UpdateStyles(StyleFlags::UpdateFamilyList
); // and force-update the list
1478 void StyleList::HideHdl()
1480 if (m_nActFamily
== 0xffff || !HasSelectedStyle(nullptr))
1483 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
1484 pTreeView
->selected_foreach([this, pTreeView
](weld::TreeIter
& rEntry
) {
1485 OUString aTemplName
= pTreeView
->get_text(rEntry
);
1487 m_pParentDialog
->Execute_Impl(SID_STYLE_HIDE
, aTemplName
, OUString(),
1488 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this);
1494 void StyleList::ShowHdl()
1496 if (m_nActFamily
== 0xffff || !HasSelectedStyle(nullptr))
1499 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
1500 pTreeView
->selected_foreach([this, pTreeView
](weld::TreeIter
& rEntry
) {
1501 OUString aTemplName
= pTreeView
->get_text(rEntry
);
1503 m_pParentDialog
->Execute_Impl(SID_STYLE_SHOW
, aTemplName
, OUString(),
1504 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this);
1510 IMPL_LINK_NOARG(StyleList
, EnableDelete
, void*, void)
1512 bool bEnableDelete(false);
1513 if (m_nActFamily
!= 0xffff && HasSelectedStyle(nullptr))
1515 OSL_ENSURE(m_pStyleSheetPool
, "No StyleSheetPool");
1516 const OUString
aTemplName(GetSelectedEntry());
1517 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1518 const SfxStyleFamily eFam
= pItem
->GetFamily();
1519 SfxStyleSearchBits nFilter
= SfxStyleSearchBits::Auto
;
1520 if (pItem
->GetFilterList().size() > m_nActFilter
)
1521 nFilter
= pItem
->GetFilterList()[m_nActFilter
].nFlags
;
1522 if (nFilter
== SfxStyleSearchBits::Auto
) // automatic
1523 nFilter
= m_nAppFilter
;
1524 const SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->Find(
1525 aTemplName
, eFam
, m_xTreeBox
->get_visible() ? SfxStyleSearchBits::All
: nFilter
);
1527 OSL_ENSURE(pStyle
, "Style not found");
1528 if (pStyle
&& pStyle
->IsUserDefined())
1530 if (pStyle
->HasClearParentSupport() || !pStyle
->IsUsed())
1532 bEnableDelete
= true;
1536 m_pParentDialog
->EnableDel(bEnableDelete
, this);
1539 IMPL_LINK_NOARG(StyleList
, Clear
, void*, void)
1541 if (m_pCurObjShell
&& m_bModuleHasStylesHighlighterFeature
)
1543 SfxViewShell
* pViewShell
= m_pCurObjShell
->GetViewShell();
1546 pViewShell
->GetStylesHighlighterParaColorMap().clear();
1547 pViewShell
->GetStylesHighlighterCharColorMap().clear();
1550 m_xStyleFamilies
.reset();
1551 for (auto& i
: m_pFamilyState
)
1553 m_pCurObjShell
= nullptr;
1554 for (auto& i
: pBoundItems
)
1558 IMPL_LINK(StyleList
, OnPopupEnd
, const OUString
&, sCommand
, void) { MenuSelect(sCommand
); }
1560 void StyleList::ShowMenu(const CommandEvent
& rCEvt
)
1562 CreateContextMenu();
1563 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
1564 mxMenu
->connect_activate(LINK(this, StyleList
, OnPopupEnd
));
1565 mxMenu
->popup_at_rect(pTreeView
, tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1, 1)));
1568 void StyleList::MenuSelect(const OUString
& rIdent
)
1570 sLastItemIdent
= rIdent
;
1571 if (sLastItemIdent
.isEmpty())
1573 Application::PostUserEvent(LINK(this, StyleList
, MenuSelectAsyncHdl
)); /***check this****/
1576 void StyleList::Notify(SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
1578 const SfxHintId nId
= rHint
.GetId();
1582 case SfxHintId::UpdateDone
:
1584 SfxViewFrame
* pViewFrame
= m_pBindings
->GetDispatcher_Impl()->GetFrame();
1585 SfxObjectShell
* pDocShell
= pViewFrame
->GetObjectShell();
1586 if (m_pParentDialog
->GetNotifyUpdate()
1587 && (!m_pParentDialog
->IsCheckedItem(u
"watercan"_ustr
)
1588 || (pDocShell
&& pDocShell
->GetStyleSheetPool() != m_pStyleSheetPool
)))
1590 m_pParentDialog
->SetNotifyupdate(false);
1593 else if (m_bUpdateFamily
)
1596 m_aUpdateFamily
.Call(*this);
1599 if (m_pStyleSheetPool
)
1601 OUString aStr
= GetSelectedEntry();
1602 if (!aStr
.isEmpty())
1604 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1607 const SfxStyleFamily eFam
= pItem
->GetFamily();
1608 SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->Find(aStr
, eFam
);
1611 bool bReadWrite
= !(pStyle
->GetMask() & SfxStyleSearchBits::ReadOnly
);
1612 m_pParentDialog
->EnableEdit(bReadWrite
, this);
1613 m_pParentDialog
->EnableHide(
1614 bReadWrite
&& !pStyle
->IsUsed() && !pStyle
->IsHidden(), this);
1615 m_pParentDialog
->EnableShow(bReadWrite
&& pStyle
->IsHidden(), this);
1619 m_pParentDialog
->EnableEdit(false, this);
1620 m_pParentDialog
->EnableHide(false, this);
1621 m_pParentDialog
->EnableShow(false, this);
1628 // Necessary if switching between documents and in both documents
1629 // the same template is used. Do not immediately call Update_Impl,
1630 // for the case that one of the documents is an internal InPlaceObject!
1631 case SfxHintId::DocChanged
:
1632 m_pParentDialog
->SetNotifyupdate(true);
1634 case SfxHintId::Dying
:
1636 EndListening(*m_pStyleSheetPool
);
1637 m_pStyleSheetPool
= nullptr;
1644 // Do not set timer when the stylesheet pool is in the box, because it is
1645 // possible that a new one is registered after the timer is up -
1646 // works bad in UpdateStyles_Impl ()!
1648 if (!m_bDontUpdate
&& nId
!= SfxHintId::Dying
1649 && (nId
== SfxHintId::SfxStyleSheetPool
|| dynamic_cast<const SfxStyleSheetHint
*>(&rHint
)
1650 || nId
== SfxHintId::StyleSheetModifiedExtended
)) // ie. SfxStyleSheetModifiedHint
1654 pIdle
.reset(new Idle("SfxCommonTemplate"));
1655 pIdle
->SetPriority(TaskPriority::LOWEST
);
1656 pIdle
->SetInvokeHandler(LINK(this, StyleList
, TimeOut
));
1662 IMPL_LINK_NOARG(StyleList
, TimeOut
, Timer
*, void)
1666 m_bDontUpdate
= true;
1667 if (!m_xTreeBox
->get_visible())
1668 UpdateStyles(StyleFlags::UpdateFamilyList
);
1671 FillTreeBox(GetActualFamily());
1672 SfxTemplateItem
* pState
= m_pFamilyState
[m_nActFamily
- 1].get();
1675 m_pParentDialog
->SelectStyle(pState
->GetStyleName(), false, *this);
1676 EnableDelete(nullptr);
1679 m_bDontUpdate
= false;
1686 IMPL_LINK_NOARG(StyleList
, MenuSelectAsyncHdl
, void*, void)
1688 if (sLastItemIdent
== "new")
1690 else if (sLastItemIdent
== "edit")
1692 else if (sLastItemIdent
== "delete")
1694 else if (sLastItemIdent
== "hide")
1696 else if (sLastItemIdent
== "show")
1700 mxMenuBuilder
.reset();
1703 // Double-click on a style sheet in the ListBox is applied.
1704 IMPL_LINK(StyleList
, DragBeginHdl
, bool&, rUnsetDragIcon
, bool)
1706 rUnsetDragIcon
= false;
1707 // Allow normal processing. only if bAllowReParentDrop is true
1708 return !m_bAllowReParentDrop
;
1711 IMPL_LINK(StyleList
, KeyInputHdl
, const KeyEvent
&, rKeyEvent
, bool)
1714 const vcl::KeyCode
& rKeyCode
= rKeyEvent
.GetKeyCode();
1715 if (m_bCanDel
&& !rKeyCode
.GetModifier() && rKeyCode
.GetCode() == KEY_DELETE
)
1723 IMPL_LINK(StyleList
, QueryTooltipHdl
, const weld::TreeIter
&, rEntry
, OUString
)
1725 weld::TreeView
* pTreeView
= m_xTreeBox
->get_visible() ? m_xTreeBox
.get() : m_xFmtLb
.get();
1726 const OUString
aTemplName(pTreeView
->get_text(rEntry
));
1727 OUString
sQuickHelpText(aTemplName
);
1729 const SfxStyleFamilyItem
* pItem
= GetFamilyItem();
1731 return sQuickHelpText
;
1732 SfxStyleSheetBase
* pStyle
= m_pStyleSheetPool
->Find(aTemplName
, pItem
->GetFamily());
1733 if (pStyle
&& pStyle
->IsUsed()) // pStyle is in use in the document?
1736 if (pStyle
->GetFamily() == SfxStyleFamily::Pseudo
)
1737 sUsedBy
= pStyle
->GetUsedBy();
1739 if (!sUsedBy
.isEmpty())
1741 const sal_Int32 nMaxLen
= 80;
1742 if (sUsedBy
.getLength() > nMaxLen
)
1744 sUsedBy
= OUString::Concat(sUsedBy
.subView(0, nMaxLen
)) + "...";
1747 OUString aMessage
= SfxResId(STR_STYLEUSEDBY
);
1748 aMessage
= aMessage
.replaceFirst("%STYLELIST", sUsedBy
);
1749 sQuickHelpText
= aTemplName
+ " " + aMessage
;
1753 return sQuickHelpText
;
1756 IMPL_LINK(StyleList
, CustomRenderHdl
, weld::TreeView::render_args
, aPayload
, void)
1758 vcl::RenderContext
& rRenderContext
= std::get
<0>(aPayload
);
1759 const ::tools::Rectangle
& rRect
= std::get
<1>(aPayload
);
1760 ::tools::Rectangle
aRect(
1762 Size(rRenderContext
.GetOutputSize().Width() - rRect
.Left(), rRect
.GetHeight()));
1763 bool bSelected
= std::get
<2>(aPayload
);
1764 const OUString
& rId
= std::get
<3>(aPayload
);
1766 rRenderContext
.Push(vcl::PushFlags::TEXTCOLOR
);
1767 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1769 rRenderContext
.SetTextColor(rStyleSettings
.GetHighlightTextColor());
1771 rRenderContext
.SetTextColor(rStyleSettings
.GetDialogTextColor());
1773 bool bSuccess
= false;
1775 SfxObjectShell
* pShell
= SfxObjectShell::Current();
1776 sfx2::StyleManager
* pStyleManager
= pShell
? pShell
->GetStyleManager() : nullptr;
1780 if (const SfxStyleFamilyItem
* pItem
= GetFamilyItem())
1782 SfxStyleSheetBase
* pStyleSheet
= pStyleManager
->Search(rId
, pItem
->GetFamily());
1786 rRenderContext
.Push(vcl::PushFlags::ALL
);
1787 // tdf#119919 - show "hidden" styles as disabled to not move children onto root node
1788 if (pStyleSheet
->IsHidden() && m_bHierarchical
)
1789 rRenderContext
.SetTextColor(rStyleSettings
.GetDisableColor());
1791 sal_Int32 nSize
= aRect
.GetHeight();
1792 std::unique_ptr
<sfx2::StylePreviewRenderer
> pStylePreviewRenderer(
1793 pStyleManager
->CreateStylePreviewRenderer(rRenderContext
, pStyleSheet
, nSize
));
1795 = pStylePreviewRenderer
->recalculate() && pStylePreviewRenderer
->render(aRect
);
1796 rRenderContext
.Pop();
1802 rRenderContext
.DrawText(aRect
, rId
, DrawTextFlags::Left
| DrawTextFlags::VCenter
);
1804 rRenderContext
.Pop();
1807 // Selection of a template during the Watercan-Status
1808 IMPL_LINK(StyleList
, FmtSelectHdl
, weld::TreeView
&, rListBox
, void)
1810 std::unique_ptr
<weld::TreeIter
> xHdlEntry
= rListBox
.make_iterator();
1811 if (!rListBox
.get_cursor(xHdlEntry
.get()))
1814 m_pParentDialog
->SelectStyle(rListBox
.get_text(*xHdlEntry
), true, *this);
1817 IMPL_LINK_NOARG(StyleList
, TreeListApplyHdl
, weld::TreeView
&, bool)
1819 // only if that region is allowed
1820 if (m_nActFamily
!= 0xffff && nullptr != m_pFamilyState
[m_nActFamily
- 1]
1821 && !GetSelectedEntry().isEmpty())
1823 m_pParentDialog
->Execute_Impl(SID_STYLE_APPLY
, GetSelectedEntry(), OUString(),
1824 static_cast<sal_uInt16
>(GetFamilyItem()->GetFamily()), *this,
1825 SfxStyleSearchBits::Auto
, nullptr, &m_nModifier
);
1827 // After selecting a focused item if possible again on the app window
1828 if (dynamic_cast<const SfxTemplateDialog_Impl
*>(m_pParentDialog
) != nullptr)
1830 SfxViewFrame
* pViewFrame
= m_pBindings
->GetDispatcher_Impl()->GetFrame();
1831 SfxViewShell
* pVu
= pViewFrame
->GetViewShell();
1832 vcl::Window
* pAppWin
= pVu
? pVu
->GetWindow() : nullptr;
1834 pAppWin
->GrabFocus();
1840 IMPL_LINK(StyleList
, MousePressHdl
, const MouseEvent
&, rMEvt
, bool)
1842 m_nModifier
= rMEvt
.GetModifier();
1846 // Notice from SfxBindings that the update is completed. Pushes out the update
1848 void StyleList::Update()
1850 bool bDocChanged
= false;
1851 SfxStyleSheetBasePool
* pNewPool
= nullptr;
1852 SfxViewFrame
* pViewFrame
= m_pBindings
->GetDispatcher_Impl()->GetFrame();
1853 SfxObjectShell
* pDocShell
= pViewFrame
->GetObjectShell();
1855 pNewPool
= pDocShell
->GetStyleSheetPool();
1857 if (pNewPool
!= m_pStyleSheetPool
&& pDocShell
)
1859 SfxModule
* pNewModule
= pDocShell
->GetModule();
1860 if (pNewModule
&& pNewModule
!= m_Module
)
1862 m_aClearResource
.Call(nullptr);
1863 m_aReadResource
.Call(*this);
1865 if (m_pStyleSheetPool
)
1867 EndListening(*m_pStyleSheetPool
);
1868 m_pStyleSheetPool
= nullptr;
1873 StartListening(*pNewPool
);
1874 m_pStyleSheetPool
= pNewPool
;
1879 if (m_bUpdateFamily
)
1882 m_aUpdateFamily
.Call(*this);
1886 for (i
= 0; i
< MAX_FAMILIES
; ++i
)
1887 if (m_pFamilyState
[i
])
1889 if (i
== MAX_FAMILIES
|| !pNewPool
)
1890 // nothing is allowed
1893 SfxTemplateItem
* pItem
= nullptr;
1894 // current region not within the allowed region or default
1895 if (m_nActFamily
== 0xffff || nullptr == (pItem
= m_pFamilyState
[m_nActFamily
- 1].get()))
1897 m_pParentDialog
->CheckItem(OUString::number(m_nActFamily
), false);
1898 const size_t nFamilyCount
= m_xStyleFamilies
->size();
1900 for (n
= 0; n
< nFamilyCount
; n
++)
1901 if (m_pFamilyState
[StyleNrToInfoOffset(n
)])
1904 std::unique_ptr
<SfxTemplateItem
>& pNewItem
= m_pFamilyState
[StyleNrToInfoOffset(n
)];
1905 m_nAppFilter
= pNewItem
->GetValue();
1906 m_pParentDialog
->FamilySelect(StyleNrToInfoOffset(n
) + 1, *this);
1907 pItem
= pNewItem
.get();
1909 else if (bDocChanged
)
1911 // other DocShell -> all new
1912 m_pParentDialog
->CheckItem(OUString::number(m_nActFamily
));
1913 m_nActFilter
= static_cast<sal_uInt16
>(m_aLoadFactoryStyleFilter
.Call(pDocShell
));
1914 m_pParentDialog
->IsUpdate(*this);
1915 if (0xffff == m_nActFilter
)
1917 m_nActFilter
= pDocShell
->GetAutoStyleFilterIndex();
1920 m_nAppFilter
= pItem
->GetValue();
1921 if (!m_xTreeBox
->get_visible())
1923 UpdateStyles(StyleFlags::UpdateFamilyList
);
1926 FillTreeBox(GetActualFamily());
1930 // other filters for automatic
1931 m_pParentDialog
->CheckItem(OUString::number(m_nActFamily
));
1932 const SfxStyleFamilyItem
* pStyleItem
= GetFamilyItem();
1934 && SfxStyleSearchBits::Auto
== pStyleItem
->GetFilterList()[m_nActFilter
].nFlags
1935 && m_nAppFilter
!= pItem
->GetValue())
1937 m_nAppFilter
= pItem
->GetValue();
1938 if (!m_xTreeBox
->get_visible())
1939 UpdateStyles(StyleFlags::UpdateFamilyList
);
1941 FillTreeBox(GetActualFamily());
1945 m_nAppFilter
= pItem
->GetValue();
1948 const OUString
aStyle(pItem
->GetStyleName());
1949 m_pParentDialog
->SelectStyle(aStyle
, false, *this);
1950 EnableDelete(nullptr);
1951 m_pParentDialog
->EnableNew(m_bCanNew
, this);
1954 const SfxStyleFamilyItem
& StyleList::GetFamilyItemByIndex(size_t i
) const
1956 return m_xStyleFamilies
->at(i
);
1959 IMPL_STATIC_LINK(StyleList
, CustomGetSizeHdl
, weld::TreeView::get_size_args
, aPayload
, Size
)
1961 vcl::RenderContext
& rRenderContext
= aPayload
.first
;
1962 return Size(42, 32 * rRenderContext
.GetDPIScaleFactor());
1965 IMPL_LINK(StyleList
, PopupFlatMenuHdl
, const CommandEvent
&, rCEvt
, bool)
1967 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1970 PrepareMenu(rCEvt
.GetMousePosPixel());
1972 if (m_xFmtLb
->count_selected_rows() <= 0)
1974 m_pParentDialog
->EnableEdit(false, this);
1975 m_pParentDialog
->EnableDel(false, this);
1983 IMPL_LINK(StyleList
, PopupTreeMenuHdl
, const CommandEvent
&, rCEvt
, bool)
1985 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1988 PrepareMenu(rCEvt
.GetMousePosPixel());
1994 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */