xref: /core/sfx2/source/dialog/StyleList.cxx (revision ef862ba4)
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 <memory>
21 #include <unordered_map>
22 
23 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/container/XNameAccess.hpp>
26 #include <utility>
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 <comphelper/processfactory.hxx>
37 #include <officecfg/Office/Common.hxx>
38 
39 #include <osl/diagnose.h>
40 #include <sfx2/dispatch.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <templdgi.hxx>
43 #include <tplcitem.hxx>
44 #include <sfx2/styfitem.hxx>
45 #include <sfx2/objsh.hxx>
46 #include <sfx2/viewsh.hxx>
47 #include <sfx2/newstyle.hxx>
48 #include <sfx2/tplpitem.hxx>
49 #include <sfx2/sfxresid.hxx>
50 
51 #include <sfx2/sfxsids.hrc>
52 #include <sfx2/strings.hrc>
53 #include <sfx2/docfac.hxx>
54 #include <sfx2/module.hxx>
55 #include <helpids.h>
56 #include <sfx2/viewfrm.hxx>
57 
58 #include <comphelper/string.hxx>
59 
60 #include <sfx2/StyleManager.hxx>
61 #include <sfx2/StylePreviewRenderer.hxx>
62 
63 #include <StyleList.hxx>
64 
65 using namespace css;
66 using namespace css::beans;
67 using namespace css::frame;
68 using namespace css::uno;
69 
70 class TreeViewDropTarget final : public DropTargetHelper
71 {
72 private:
73     StyleList& m_rParent;
74 
75 public:
76     TreeViewDropTarget(StyleList& rStyleList, weld::TreeView& rTreeView)
77         : DropTargetHelper(rTreeView.get_drop_target())
78         , m_rParent(rStyleList)
79     {
80     }
81 
82     virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override
83     {
84         return m_rParent.AcceptDrop(rEvt, *this);
85     }
86 
87     virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
88     {
89         return m_rParent.ExecuteDrop(rEvt);
90     }
91 };
92 
93 // Constructor
94 
95 StyleList::StyleList(weld::Builder* pBuilder, SfxBindings* pBindings,
96                      SfxCommonTemplateDialog_Impl* Parent, weld::Container* pC,
97                      OString treeviewname, OString flatviewname)
98     : m_bHierarchical(false)
99     , m_bAllowReParentDrop(false)
100     , m_bNewByExampleDisabled(false)
101     , m_bDontUpdate(false)
102     , m_bTreeDrag(true)
103     , m_bCanEdit(false)
104     , m_bCanHide(true)
105     , m_bCanShow(false)
106     , m_bCanNew(true)
107     , m_bUpdateFamily(false)
108     , m_bCanDel(false)
109     , m_bBindingUpdate(true)
110     , m_pStyleSheetPool(nullptr)
111     , m_nActFilter(0)
112     , m_xFmtLb(pBuilder->weld_tree_view(flatviewname))
113     , m_xTreeBox(pBuilder->weld_tree_view(treeviewname))
114     , m_pCurObjShell(nullptr)
115     , m_nActFamily(0xffff)
116     , m_nAppFilter(SfxStyleSearchBits::Auto)
117     , m_pParentDialog(Parent)
118     , m_pBindings(pBindings)
119     , m_Module(nullptr)
120     , m_nModifier(0)
121     , m_pContainer(pC)
122 {
123     m_xFmtLb->set_help_id(HID_TEMPLATE_FMT);
124 }
125 
126 // Destructor
127 
128 StyleList::~StyleList() {}
129 
130 // Called in the destructor of Dialog
131 // Cleans up the StyleList individual components while closing the application
132 IMPL_LINK_NOARG(StyleList, Cleanup, void*, void)
133 {
134     if (m_pStyleSheetPool)
135         EndListening(*m_pStyleSheetPool);
136     m_pStyleSheetPool = nullptr;
137     m_xTreeView1DropTargetHelper.reset();
138     m_xTreeView2DropTargetHelper.reset();
139     m_xTreeBox.reset();
140     m_xFmtLb.reset();
141     pIdle.reset();
142 }
143 
144 void StyleList::CreateContextMenu()
145 {
146     if (m_bBindingUpdate)
147     {
148         m_pBindings->Invalidate(SID_STYLE_NEW, true);
149         m_pBindings->Update(SID_STYLE_NEW);
150         m_bBindingUpdate = false;
151     }
152     mxMenu.reset();
153     mxMenuBuilder = Application::CreateBuilder(nullptr, "sfx/ui/stylecontextmenu.ui");
154     mxMenu = mxMenuBuilder->weld_menu("menu");
155     mxMenu->set_sensitive("edit", m_bCanEdit);
156     mxMenu->set_sensitive("delete", m_bCanDel);
157     mxMenu->set_sensitive("new", m_bCanNew);
158     mxMenu->set_sensitive("hide", m_bCanHide);
159     mxMenu->set_sensitive("show", m_bCanShow);
160 
161     const SfxStyleFamilyItem* pItem = GetFamilyItem();
162     if (pItem && pItem->GetFamily() == SfxStyleFamily::Table) //tdf#101648, no ui for this yet
163     {
164         mxMenu->set_sensitive("edit", false);
165         mxMenu->set_sensitive("new", false);
166     }
167     if (pItem && pItem->GetFamily() == SfxStyleFamily::Pseudo)
168     {
169         const OUString aTemplName(GetSelectedEntry());
170         if (aTemplName == "No List")
171         {
172             mxMenu->set_sensitive("edit", false);
173             mxMenu->set_sensitive("new", false);
174             mxMenu->set_sensitive("hide", false);
175         }
176     }
177 }
178 
179 IMPL_LINK_NOARG(StyleList, ReadResource, void*, size_t)
180 {
181     // Read global user resource
182     for (auto& i : m_pFamilyState)
183         i.reset();
184 
185     SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame();
186     m_pCurObjShell = pViewFrame->GetObjectShell();
187     m_Module = m_pCurObjShell ? m_pCurObjShell->GetModule() : nullptr;
188     if (m_Module)
189         m_xStyleFamilies = m_Module->CreateStyleFamilies();
190     if (!m_xStyleFamilies)
191         m_xStyleFamilies.emplace();
192 
193     m_nActFilter = 0xffff;
194 
195     if (m_pCurObjShell)
196     {
197         m_nActFilter = static_cast<sal_uInt16>(m_aLoadFactoryStyleFilter.Call(m_pCurObjShell));
198         if (0xffff == m_nActFilter)
199         {
200             m_nActFilter = m_pCurObjShell->GetAutoStyleFilterIndex();
201         }
202     }
203     size_t nCount = m_xStyleFamilies->size();
204     m_pBindings->ENTERREGISTRATIONS();
205 
206     size_t i;
207     for (i = 0; i < nCount; ++i)
208     {
209         sal_uInt16 nSlot = 0;
210         switch (m_xStyleFamilies->at(i).GetFamily())
211         {
212             case SfxStyleFamily::Char:
213                 nSlot = SID_STYLE_FAMILY1;
214                 break;
215             case SfxStyleFamily::Para:
216                 nSlot = SID_STYLE_FAMILY2;
217                 break;
218             case SfxStyleFamily::Frame:
219                 nSlot = SID_STYLE_FAMILY3;
220                 break;
221             case SfxStyleFamily::Page:
222                 nSlot = SID_STYLE_FAMILY4;
223                 break;
224             case SfxStyleFamily::Pseudo:
225                 nSlot = SID_STYLE_FAMILY5;
226                 break;
227             case SfxStyleFamily::Table:
228                 nSlot = SID_STYLE_FAMILY6;
229                 break;
230             default:
231                 OSL_FAIL("unknown StyleFamily");
232                 break;
233         }
234         pBoundItems[i].reset(new SfxTemplateControllerItem(nSlot, *m_pParentDialog, *m_pBindings));
235     }
236     pBoundItems[i++].reset(
237         new SfxTemplateControllerItem(SID_STYLE_WATERCAN, *m_pParentDialog, *m_pBindings));
238     pBoundItems[i++].reset(
239         new SfxTemplateControllerItem(SID_STYLE_NEW_BY_EXAMPLE, *m_pParentDialog, *m_pBindings));
240     pBoundItems[i++].reset(
241         new SfxTemplateControllerItem(SID_STYLE_UPDATE_BY_EXAMPLE, *m_pParentDialog, *m_pBindings));
242     pBoundItems[i++].reset(
243         new SfxTemplateControllerItem(SID_STYLE_NEW, *m_pParentDialog, *m_pBindings));
244     pBoundItems[i++].reset(
245         new SfxTemplateControllerItem(SID_STYLE_DRAGHIERARCHIE, *m_pParentDialog, *m_pBindings));
246     pBoundItems[i++].reset(
247         new SfxTemplateControllerItem(SID_STYLE_EDIT, *m_pParentDialog, *m_pBindings));
248     pBoundItems[i++].reset(
249         new SfxTemplateControllerItem(SID_STYLE_DELETE, *m_pParentDialog, *m_pBindings));
250     pBoundItems[i++].reset(
251         new SfxTemplateControllerItem(SID_STYLE_FAMILY, *m_pParentDialog, *m_pBindings));
252     m_pBindings->LEAVEREGISTRATIONS();
253 
254     for (; i < COUNT_BOUND_FUNC; ++i)
255         pBoundItems[i] = nullptr;
256 
257     StartListening(*m_pBindings);
258 
259     for (i = SID_STYLE_FAMILY1; i <= SID_STYLE_FAMILY4; i++)
260         m_pBindings->Update(i);
261 
262     return nCount;
263 }
264 
265 void StyleList::EnableNewByExample(bool newByExampleDisabled)
266 {
267     m_bNewByExampleDisabled = newByExampleDisabled;
268 }
269 
270 void StyleList::FilterSelect(sal_uInt16 nActFilter, bool bsetFilter)
271 {
272     m_nActFilter = nActFilter;
273     if (bsetFilter)
274     {
275         SfxObjectShell* const pDocShell = m_aSaveSelection.Call(*this);
276         SfxStyleSheetBasePool* pOldStyleSheetPool = m_pStyleSheetPool;
277         m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr;
278         if (pOldStyleSheetPool != m_pStyleSheetPool)
279         {
280             if (pOldStyleSheetPool)
281                 EndListening(*pOldStyleSheetPool);
282             if (m_pStyleSheetPool)
283                 StartListening(*m_pStyleSheetPool);
284         }
285     }
286     UpdateStyles(StyleFlags::UpdateFamilyList);
287 }
288 
289 IMPL_LINK(StyleList, SetFamily, sal_uInt16, nId, void)
290 {
291     if (m_nActFamily != 0xFFFF)
292         m_pParentDialog->CheckItem(OString::number(m_nActFamily), false);
293     m_nActFamily = nId;
294     if (nId != 0xFFFF)
295     {
296         m_bUpdateFamily = true;
297     }
298 }
299 
300 void StyleList::InvalidateBindings()
301 {
302     m_pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, true);
303     m_pBindings->Update(SID_STYLE_NEW_BY_EXAMPLE);
304     m_pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, true);
305     m_pBindings->Update(SID_STYLE_UPDATE_BY_EXAMPLE);
306     m_pBindings->Invalidate(SID_STYLE_WATERCAN, true);
307     m_pBindings->Update(SID_STYLE_WATERCAN);
308     m_pBindings->Invalidate(SID_STYLE_NEW, true);
309     m_pBindings->Update(SID_STYLE_NEW);
310     m_pBindings->Invalidate(SID_STYLE_DRAGHIERARCHIE, true);
311     m_pBindings->Update(SID_STYLE_DRAGHIERARCHIE);
312 }
313 
314 void StyleList::Initialize()
315 {
316     m_pBindings->Invalidate(SID_STYLE_FAMILY);
317     m_pBindings->Update(SID_STYLE_FAMILY);
318 
319     m_xFmtLb->connect_row_activated(LINK(this, StyleList, TreeListApplyHdl));
320     m_xFmtLb->connect_mouse_press(LINK(this, StyleList, MousePressHdl));
321     m_xFmtLb->connect_query_tooltip(LINK(this, StyleList, QueryTooltipHdl));
322     m_xFmtLb->connect_changed(LINK(this, StyleList, FmtSelectHdl));
323     m_xFmtLb->connect_popup_menu(LINK(this, StyleList, PopupFlatMenuHdl));
324     m_xFmtLb->connect_key_press(LINK(this, StyleList, KeyInputHdl));
325     m_xFmtLb->set_selection_mode(SelectionMode::Multiple);
326     m_xTreeBox->connect_changed(LINK(this, StyleList, FmtSelectHdl));
327     m_xTreeBox->connect_row_activated(LINK(this, StyleList, TreeListApplyHdl));
328     m_xTreeBox->connect_mouse_press(LINK(this, StyleList, MousePressHdl));
329     m_xTreeBox->connect_query_tooltip(LINK(this, StyleList, QueryTooltipHdl));
330     m_xTreeBox->connect_popup_menu(LINK(this, StyleList, PopupTreeMenuHdl));
331     m_xTreeBox->connect_key_press(LINK(this, StyleList, KeyInputHdl));
332     m_xTreeBox->connect_drag_begin(LINK(this, StyleList, DragBeginHdl));
333     m_xTreeView1DropTargetHelper.reset(new TreeViewDropTarget(*this, *m_xFmtLb));
334     m_xTreeView2DropTargetHelper.reset(new TreeViewDropTarget(*this, *m_xTreeBox));
335 
336     m_pParentDialog->connect_stylelist_read_resource(LINK(this, StyleList, ReadResource));
337     m_pParentDialog->connect_stylelist_clear(LINK(this, StyleList, Clear));
338     m_pParentDialog->connect_stylelist_cleanup(LINK(this, StyleList, Cleanup));
339     m_pParentDialog->connect_stylelist_execute_drop(LINK(this, StyleList, ExecuteDrop));
340     m_pParentDialog->connect_stylelist_execute_new_menu(
341         LINK(this, StyleList, NewMenuExecuteAction));
342     m_pParentDialog->connect_stylelist_for_watercan(LINK(this, StyleList, IsSafeForWaterCan));
343     m_pParentDialog->connect_stylelist_has_selected_style(LINK(this, StyleList, HasSelectedStyle));
344     m_pParentDialog->connect_stylelist_update_style_dependents(
345         LINK(this, StyleList, UpdateStyleDependents));
346     m_pParentDialog->connect_stylelist_enable_tree_drag(LINK(this, StyleList, EnableTreeDrag));
347     m_pParentDialog->connect_stylelist_enable_delete(LINK(this, StyleList, EnableDelete));
348     m_pParentDialog->connect_stylelist_set_water_can_state(LINK(this, StyleList, SetWaterCanState));
349     m_pParentDialog->connect_set_family(LINK(this, StyleList, SetFamily));
350 
351     int nTreeHeight = m_xFmtLb->get_height_rows(8);
352     m_xFmtLb->set_size_request(-1, nTreeHeight);
353     m_xTreeBox->set_size_request(-1, nTreeHeight);
354 
355     m_xFmtLb->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl));
356     m_xFmtLb->connect_custom_render(LINK(this, StyleList, CustomRenderHdl));
357     m_xTreeBox->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl));
358     m_xTreeBox->connect_custom_render(LINK(this, StyleList, CustomRenderHdl));
359     bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get();
360     m_xFmtLb->set_column_custom_renderer(0, bCustomPreview);
361     m_xTreeBox->set_column_custom_renderer(0, bCustomPreview);
362 
363     m_xFmtLb->set_visible(!m_bHierarchical);
364     m_xTreeBox->set_visible(m_bHierarchical);
365     Update();
366 }
367 
368 void StyleList::UpdateFamily()
369 {
370     m_bUpdateFamily = false;
371 
372     SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl();
373     SfxViewFrame* pViewFrame = pDispat->GetFrame();
374     SfxObjectShell* pDocShell = pViewFrame->GetObjectShell();
375 
376     SfxStyleSheetBasePool* pOldStyleSheetPool = m_pStyleSheetPool;
377     m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr;
378     if (pOldStyleSheetPool != m_pStyleSheetPool)
379     {
380         if (pOldStyleSheetPool)
381             EndListening(*pOldStyleSheetPool);
382         if (m_pStyleSheetPool)
383             StartListening(*m_pStyleSheetPool);
384     }
385 
386     m_bTreeDrag = true;
387     m_bCanNew = m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1;
388     m_pParentDialog->EnableNew(m_bCanNew, this);
389     m_bTreeDrag = true;
390     if (m_pStyleSheetPool)
391     {
392         if (!m_xTreeBox->get_visible())
393             UpdateStyles(StyleFlags::UpdateFamily | StyleFlags::UpdateFamilyList);
394         else
395         {
396             UpdateStyles(StyleFlags::UpdateFamily);
397             FillTreeBox(GetActualFamily());
398         }
399     }
400 
401     InvalidateBindings();
402 }
403 
404 bool StyleList::EnableExecute()
405 {
406     return m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1;
407 }
408 
409 void StyleList::connect_LoadFactoryStyleFilter(const Link<SfxObjectShell const*, sal_Int32>& rLink)
410 {
411     m_aLoadFactoryStyleFilter = rLink;
412 }
413 
414 void StyleList::connect_SaveSelection(const Link<StyleList&, SfxObjectShell*> rLink)
415 {
416     m_aSaveSelection = rLink;
417 }
418 
419 /** Drop is enabled as long as it is allowed to create a new style by example, i.e. to
420     create a style out of the current selection.
421 */
422 sal_Int8 StyleList::AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper)
423 {
424     if (rHelper.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR))
425     {
426         // special case: page styles are allowed to create new styles by example
427         // but not allowed to be created by drag and drop
428         if (GetActualFamily() == SfxStyleFamily::Page || m_bNewByExampleDisabled)
429             return DND_ACTION_NONE;
430         else
431             return DND_ACTION_COPY;
432     }
433     // to enable the autoscroll when we're close to the edges
434     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
435     pTreeView->get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
436     return DND_ACTION_MOVE;
437 }
438 
439 // handles drop of content in treeview when creating a new style
440 IMPL_LINK(StyleList, ExecuteDrop, const ExecuteDropEvent&, rEvt, sal_Int8)
441 {
442     SfxObjectShell* pDocShell = m_pCurObjShell;
443     if (pDocShell)
444     {
445         TransferableDataHelper aHelper(rEvt.maDropEvent.Transferable);
446         sal_uInt32 nFormatCount = aHelper.GetFormatCount();
447 
448         sal_Int8 nRet = DND_ACTION_NONE;
449 
450         bool bFormatFound = false;
451 
452         for (sal_uInt32 i = 0; i < nFormatCount; ++i)
453         {
454             SotClipboardFormatId nId = aHelper.GetFormat(i);
455             TransferableObjectDescriptor aDesc;
456 
457             if (aHelper.GetTransferableObjectDescriptor(nId, aDesc))
458             {
459                 if (aDesc.maClassName == pDocShell->GetFactory().GetClassId())
460                 {
461                     Application::PostUserEvent(
462                         LINK(m_pParentDialog, SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop),
463                         this);
464 
465                     bFormatFound = true;
466                     nRet = rEvt.mnAction;
467                     break;
468                 }
469             }
470         }
471 
472         if (bFormatFound)
473             return nRet;
474     }
475 
476     if (!m_xTreeBox->get_visible())
477         return DND_ACTION_NONE;
478 
479     if (!m_bAllowReParentDrop)
480         return DND_ACTION_NONE;
481 
482     // otherwise if we're dragging with the treeview to set a new parent of the dragged style
483     weld::TreeView* pSource = m_xTreeBox->get_drag_source();
484     // only dragging within the same widget allowed
485     if (!pSource || pSource != m_xTreeBox.get())
486         return DND_ACTION_NONE;
487 
488     std::unique_ptr<weld::TreeIter> xSource(m_xTreeBox->make_iterator());
489     if (!m_xTreeBox->get_selected(xSource.get()))
490         return DND_ACTION_NONE;
491 
492     std::unique_ptr<weld::TreeIter> xTarget(m_xTreeBox->make_iterator());
493     if (!m_xTreeBox->get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), true))
494     {
495         // if nothing under the mouse, use the last row
496         int nChildren = m_xTreeBox->n_children();
497         if (!nChildren)
498             return DND_ACTION_NONE;
499         if (!m_xTreeBox->get_iter_first(*xTarget)
500             || !m_xTreeBox->iter_nth_sibling(*xTarget, nChildren - 1))
501             return DND_ACTION_NONE;
502         while (m_xTreeBox->get_row_expanded(*xTarget))
503         {
504             nChildren = m_xTreeBox->iter_n_children(*xTarget);
505             if (!m_xTreeBox->iter_children(*xTarget)
506                 || !m_xTreeBox->iter_nth_sibling(*xTarget, nChildren - 1))
507                 return DND_ACTION_NONE;
508         }
509     }
510     OUString aTargetStyle = m_xTreeBox->get_text(*xTarget);
511     DropHdl(m_xTreeBox->get_text(*xSource), aTargetStyle);
512     m_xTreeBox->unset_drag_dest_row();
513     FillTreeBox(GetActualFamily());
514     m_pParentDialog->SelectStyle(aTargetStyle, false, *this);
515     return DND_ACTION_NONE;
516 }
517 
518 IMPL_LINK_NOARG(StyleList, NewMenuExecuteAction, void*, void)
519 {
520     if (!m_pStyleSheetPool || m_nActFamily == 0xffff)
521         return;
522 
523     const SfxStyleFamily eFam = GetFamilyItem()->GetFamily();
524     const SfxStyleFamilyItem* pItem = GetFamilyItem();
525     SfxStyleSearchBits nFilter(SfxStyleSearchBits::Auto);
526     if (pItem && m_nActFilter != 0xffff)
527         nFilter = pItem->GetFilterList()[m_nActFilter].nFlags;
528     if (nFilter == SfxStyleSearchBits::Auto) // automatic
529         nFilter = m_nAppFilter;
530 
531     // why? : FloatingWindow must not be parent of a modal dialog
532     SfxNewStyleDlg aDlg(m_pContainer, *m_pStyleSheetPool, eFam);
533     auto nResult = aDlg.run();
534     if (nResult == RET_OK)
535     {
536         const OUString aTemplName(aDlg.GetName());
537         m_pParentDialog->Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE, aTemplName, "",
538                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this,
539                                       nFilter);
540         UpdateFamily();
541         m_aUpdateFamily.Call(*this);
542     }
543 }
544 
545 void StyleList::DropHdl(const OUString& rStyle, const OUString& rParent)
546 {
547     m_bDontUpdate = true;
548     const SfxStyleFamilyItem* pItem = GetFamilyItem();
549     const SfxStyleFamily eFam = pItem->GetFamily();
550     m_pStyleSheetPool->SetParent(eFam, rStyle, rParent);
551     m_bDontUpdate = false;
552 }
553 
554 void StyleList::PrepareMenu(const Point& rPos)
555 {
556     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
557     std::unique_ptr<weld::TreeIter> xIter(pTreeView->make_iterator());
558     if (pTreeView->get_dest_row_at_pos(rPos, xIter.get(), false) && !pTreeView->is_selected(*xIter))
559     {
560         pTreeView->unselect_all();
561         pTreeView->set_cursor(*xIter);
562         pTreeView->select(*xIter);
563     }
564     FmtSelectHdl(*pTreeView);
565 }
566 
567 /** Internal structure for the establishment of the hierarchical view */
568 namespace
569 {
570 class StyleTree_Impl;
571 }
572 
573 typedef std::vector<std::unique_ptr<StyleTree_Impl>> StyleTreeArr_Impl;
574 
575 namespace
576 {
577 class StyleTree_Impl
578 {
579 private:
580     OUString aName;
581     OUString aParent;
582     StyleTreeArr_Impl pChildren;
583 
584 public:
585     bool HasParent() const { return !aParent.isEmpty(); }
586 
587     StyleTree_Impl(OUString _aName, OUString _aParent)
588         : aName(std::move(_aName))
589         , aParent(std::move(_aParent))
590         , pChildren(0)
591     {
592     }
593 
594     const OUString& getName() const { return aName; }
595     const OUString& getParent() const { return aParent; }
596     StyleTreeArr_Impl& getChildren() { return pChildren; }
597 };
598 }
599 
600 static void MakeTree_Impl(StyleTreeArr_Impl& rArr, const OUString& aUIName)
601 {
602     const comphelper::string::NaturalStringSorter aSorter(
603         ::comphelper::getProcessComponentContext(),
604         Application::GetSettings().GetLanguageTag().getLocale());
605 
606     std::unordered_map<OUString, StyleTree_Impl*> styleFinder;
607     styleFinder.reserve(rArr.size());
608     for (const auto& pEntry : rArr)
609     {
610         styleFinder.emplace(pEntry->getName(), pEntry.get());
611     }
612 
613     // Arrange all under their Parents
614     for (auto& pEntry : rArr)
615     {
616         if (!pEntry->HasParent())
617             continue;
618         auto it = styleFinder.find(pEntry->getParent());
619         if (it != styleFinder.end())
620         {
621             StyleTree_Impl* pCmp = it->second;
622             // Insert child entries sorted
623             auto iPos = std::lower_bound(
624                 pCmp->getChildren().begin(), pCmp->getChildren().end(), pEntry,
625                 [&aSorter](std::unique_ptr<StyleTree_Impl> const& pEntry1,
626                            std::unique_ptr<StyleTree_Impl> const& pEntry2) {
627                     return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0;
628                 });
629             pCmp->getChildren().insert(iPos, std::move(pEntry));
630         }
631     }
632 
633     // Only keep tree roots in rArr, child elements can be accessed through the hierarchy
634     rArr.erase(
635         std::remove_if(rArr.begin(), rArr.end(),
636                        [](std::unique_ptr<StyleTree_Impl> const& pEntry) { return !pEntry; }),
637         rArr.end());
638 
639     // tdf#91106 sort top level styles
640     std::sort(rArr.begin(), rArr.end());
641     std::sort(rArr.begin(), rArr.end(),
642               [&aSorter, &aUIName](std::unique_ptr<StyleTree_Impl> const& pEntry1,
643                                    std::unique_ptr<StyleTree_Impl> const& pEntry2) {
644                   if (pEntry2->getName() == aUIName)
645                       return false;
646                   if (pEntry1->getName() == aUIName)
647                       return true; // default always first
648                   return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0;
649               });
650 }
651 
652 static bool IsExpanded_Impl(const std::vector<OUString>& rEntries, std::u16string_view rStr)
653 {
654     for (const auto& rEntry : rEntries)
655     {
656         if (rEntry == rStr)
657             return true;
658     }
659     return false;
660 }
661 
662 static void FillBox_Impl(weld::TreeView& rBox, StyleTree_Impl* pEntry,
663                          const std::vector<OUString>& rEntries, SfxStyleFamily eStyleFamily,
664                          const weld::TreeIter* pParent)
665 {
666     std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator();
667     const OUString& rName = pEntry->getName();
668     rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get());
669 
670     for (size_t i = 0; i < pEntry->getChildren().size(); ++i)
671         FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get());
672 }
673 
674 namespace SfxTemplate
675 {
676 // converts from SFX_STYLE_FAMILY Ids to 1-6
677 static sal_uInt16 SfxFamilyIdToNId(SfxStyleFamily nFamily)
678 {
679     switch (nFamily)
680     {
681         case SfxStyleFamily::Char:
682             return 1;
683         case SfxStyleFamily::Para:
684             return 2;
685         case SfxStyleFamily::Frame:
686             return 3;
687         case SfxStyleFamily::Page:
688             return 4;
689         case SfxStyleFamily::Pseudo:
690             return 5;
691         case SfxStyleFamily::Table:
692             return 6;
693         default:
694             return 0xffff;
695     }
696 }
697 // converts from 1-6 to SFX_STYLE_FAMILY Ids
698 static SfxStyleFamily NIdToSfxFamilyId(sal_uInt16 nId)
699 {
700     switch (nId)
701     {
702         case 1:
703             return SfxStyleFamily::Char;
704         case 2:
705             return SfxStyleFamily::Para;
706         case 3:
707             return SfxStyleFamily::Frame;
708         case 4:
709             return SfxStyleFamily::Page;
710         case 5:
711             return SfxStyleFamily::Pseudo;
712         case 6:
713             return SfxStyleFamily::Table;
714         default:
715             return SfxStyleFamily::All;
716     }
717 }
718 }
719 
720 sal_uInt16 StyleList::StyleNrToInfoOffset(sal_uInt16 nId)
721 {
722     const SfxStyleFamilyItem& rItem = m_xStyleFamilies->at(nId);
723     return SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()) - 1;
724 }
725 
726 // Helper function: Access to the current family item
727 const SfxStyleFamilyItem* StyleList::GetFamilyItem() const
728 {
729     const size_t nCount = m_xStyleFamilies->size();
730     for (size_t i = 0; i < nCount; ++i)
731     {
732         const SfxStyleFamilyItem& rItem = m_xStyleFamilies->at(i);
733         sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily());
734         if (nId == m_nActFamily)
735             return &rItem;
736     }
737     return nullptr;
738 }
739 
740 void StyleList::GetSelectedStyle() const
741 {
742     const OUString aTemplName(GetSelectedEntry());
743     const SfxStyleFamilyItem* pItem = GetFamilyItem();
744     m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily());
745 }
746 
747 // Used to get the current selected entry in visible treeview
748 OUString StyleList::GetSelectedEntry() const
749 {
750     OUString aRet;
751     if (m_xTreeBox->get_visible())
752         aRet = m_xTreeBox->get_selected_text();
753     else
754         aRet = m_xFmtLb->get_selected_text();
755     return aRet;
756 }
757 
758 /**
759  * Is it safe to show the water-can / fill icon. If we've a
760  * hierarchical widget - we have only single select, otherwise
761  * we need to check if we have a multi-selection. We either have
762  * a m_xTreeBox showing or an m_xFmtLb (which we hide when not shown)
763  */
764 IMPL_LINK_NOARG(StyleList, IsSafeForWaterCan, void*, bool)
765 {
766     if (m_xTreeBox->get_visible())
767         return m_xTreeBox->get_selected_index() != -1;
768     else
769         return m_xFmtLb->count_selected_rows() == 1;
770 }
771 
772 IMPL_LINK(StyleList, SetWaterCanState, const SfxBoolItem*, pItem, void)
773 {
774     size_t nCount = m_xStyleFamilies->size();
775     m_pBindings->EnterRegistrations();
776     for (size_t n = 0; n < nCount; n++)
777     {
778         SfxControllerItem* pCItem = pBoundItems[n].get();
779         bool bChecked = pItem && pItem->GetValue();
780         if (pCItem->IsBound() == bChecked)
781         {
782             if (!bChecked)
783                 pCItem->ReBind();
784             else
785                 pCItem->UnBind();
786         }
787     }
788     m_pBindings->LeaveRegistrations();
789 }
790 
791 void StyleList::FamilySelect(sal_uInt16 nEntry)
792 {
793     m_nActFamily = nEntry;
794     SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl();
795     SfxUInt16Item const aItem(SID_STYLE_FAMILY,
796                               static_cast<sal_uInt16>(SfxTemplate::NIdToSfxFamilyId(nEntry)));
797     pDispat->ExecuteList(SID_STYLE_FAMILY, SfxCallMode::SYNCHRON, { &aItem });
798     m_pBindings->Invalidate(SID_STYLE_FAMILY);
799     m_pBindings->Update(SID_STYLE_FAMILY);
800     UpdateFamily();
801     m_aUpdateFamily.Call(*this);
802 }
803 
804 // It selects the style in treeview
805 // bIsCallBack is true for the selected style. For eg. if "Addressee" is selected in
806 // styles, bIsCallBack will be true for it.
807 void StyleList::SelectStyle(const OUString& rStr, bool bIsCallback)
808 {
809     const SfxStyleFamilyItem* pItem = GetFamilyItem();
810     if (!pItem)
811         return;
812     const SfxStyleFamily eFam = pItem->GetFamily();
813     SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(rStr, eFam);
814     if (pStyle)
815     {
816         bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly);
817         m_pParentDialog->EnableEdit(bReadWrite, this);
818         m_pParentDialog->EnableHide(bReadWrite && !pStyle->IsHidden() && !pStyle->IsUsed(), this);
819         m_pParentDialog->EnableShow(bReadWrite && pStyle->IsHidden(), this);
820     }
821     else
822     {
823         m_pParentDialog->EnableEdit(false, this);
824         m_pParentDialog->EnableHide(false, this);
825         m_pParentDialog->EnableShow(false, this);
826     }
827 
828     if (bIsCallback)
829         return;
830 
831     if (m_xTreeBox->get_visible())
832     {
833         if (!rStr.isEmpty())
834         {
835             std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator();
836             bool bEntry = m_xTreeBox->get_iter_first(*xEntry);
837             while (bEntry)
838             {
839                 if (m_xTreeBox->get_text(*xEntry) == rStr)
840                 {
841                     m_xTreeBox->scroll_to_row(*xEntry);
842                     m_xTreeBox->select(*xEntry);
843                     break;
844                 }
845                 bEntry = m_xTreeBox->iter_next(*xEntry);
846             }
847         }
848         else if (eFam == SfxStyleFamily::Pseudo)
849         {
850             std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator();
851             if (m_xTreeBox->get_iter_first(*xEntry))
852             {
853                 m_xTreeBox->scroll_to_row(*xEntry);
854                 m_xTreeBox->select(*xEntry);
855             }
856         }
857         else
858             m_xTreeBox->unselect_all();
859     }
860     else
861     {
862         bool bSelect = !rStr.isEmpty();
863         if (bSelect)
864         {
865             std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator();
866             bool bEntry = m_xFmtLb->get_iter_first(*xEntry);
867             while (bEntry && m_xFmtLb->get_text(*xEntry) != rStr)
868                 bEntry = m_xFmtLb->iter_next(*xEntry);
869             if (!bEntry)
870                 bSelect = false;
871             else
872             {
873                 if (!m_xFmtLb->is_selected(*xEntry))
874                 {
875                     m_xFmtLb->unselect_all();
876                     m_xFmtLb->scroll_to_row(*xEntry);
877                     m_xFmtLb->select(*xEntry);
878                 }
879             }
880         }
881 
882         if (!bSelect)
883         {
884             m_xFmtLb->unselect_all();
885             m_pParentDialog->EnableEdit(false, this);
886             m_pParentDialog->EnableHide(false, this);
887             m_pParentDialog->EnableShow(false, this);
888         }
889     }
890 }
891 
892 static void MakeExpanded_Impl(const weld::TreeView& rBox, std::vector<OUString>& rEntries)
893 {
894     std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator();
895     if (rBox.get_iter_first(*xEntry))
896     {
897         do
898         {
899             if (rBox.get_row_expanded(*xEntry))
900                 rEntries.push_back(rBox.get_text(*xEntry));
901         } while (rBox.iter_next(*xEntry));
902     }
903 }
904 
905 IMPL_LINK(StyleList, EnableTreeDrag, bool, m_bEnable, void)
906 {
907     if (m_pStyleSheetPool)
908     {
909         const SfxStyleFamilyItem* pItem = GetFamilyItem();
910         SfxStyleSheetBase* pStyle = pItem ? m_pStyleSheetPool->First(pItem->GetFamily()) : nullptr;
911         m_bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && m_bEnable;
912     }
913     m_bTreeDrag = m_bEnable;
914 }
915 
916 // Fill the treeview
917 
918 void StyleList::FillTreeBox(SfxStyleFamily eFam)
919 {
920     assert(m_xTreeBox && "FillTreeBox() without treebox");
921     if (!m_pStyleSheetPool || m_nActFamily == 0xffff)
922         return;
923 
924     const SfxStyleFamilyItem* pItem = GetFamilyItem();
925     if (!pItem)
926         return;
927 
928     StyleTreeArr_Impl aArr;
929     SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, SfxStyleSearchBits::AllVisible);
930 
931     m_bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && m_bTreeDrag;
932 
933     while (pStyle)
934     {
935         StyleTree_Impl* pNew = new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent());
936         aArr.emplace_back(pNew);
937         pStyle = m_pStyleSheetPool->Next();
938     }
939     OUString aUIName = getDefaultStyleName(eFam);
940     MakeTree_Impl(aArr, aUIName);
941     std::vector<OUString> aEntries;
942     MakeExpanded_Impl(*m_xTreeBox, aEntries);
943     m_xTreeBox->freeze();
944     m_xTreeBox->clear();
945     const sal_uInt16 nCount = aArr.size();
946 
947     for (sal_uInt16 i = 0; i < nCount; ++i)
948     {
949         FillBox_Impl(*m_xTreeBox, aArr[i].get(), aEntries, eFam, nullptr);
950         aArr[i].reset();
951     }
952 
953     m_pParentDialog->EnableItem("watercan", false);
954 
955     SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get();
956 
957     m_xTreeBox->thaw();
958 
959     std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator();
960     bool bEntry = m_xTreeBox->get_iter_first(*xEntry);
961     if (bEntry && nCount)
962         m_xTreeBox->expand_row(*xEntry);
963 
964     while (bEntry)
965     {
966         if (IsExpanded_Impl(aEntries, m_xTreeBox->get_text(*xEntry)))
967             m_xTreeBox->expand_row(*xEntry);
968         bEntry = m_xTreeBox->iter_next(*xEntry);
969     }
970 
971     OUString aStyle;
972     if (pState) // Select current entry
973         aStyle = pState->GetStyleName();
974     m_pParentDialog->SelectStyle(aStyle, false, *this);
975     EnableDelete(nullptr);
976 }
977 
978 static OUString lcl_GetStyleFamilyName(SfxStyleFamily nFamily)
979 {
980     if (nFamily == SfxStyleFamily::Char)
981         return "CharacterStyles";
982     if (nFamily == SfxStyleFamily::Para)
983         return "ParagraphStyles";
984     if (nFamily == SfxStyleFamily::Page)
985         return "PageStyles";
986     if (nFamily == SfxStyleFamily::Table)
987         return "TableStyles";
988     if (nFamily == SfxStyleFamily::Pseudo)
989         return "NumberingStyles";
990     return OUString();
991 }
992 
993 OUString StyleList::getDefaultStyleName(const SfxStyleFamily eFam)
994 {
995     OUString sDefaultStyle;
996     OUString aFamilyName = lcl_GetStyleFamilyName(eFam);
997     if (aFamilyName == "TableStyles")
998         sDefaultStyle = "Default Style";
999     else if (aFamilyName == "NumberingStyles")
1000         sDefaultStyle = "No List";
1001     else
1002         sDefaultStyle = "Standard";
1003     uno::Reference<style::XStyleFamiliesSupplier> xModel(m_pCurObjShell->GetModel(),
1004                                                          uno::UNO_QUERY);
1005     OUString aUIName;
1006     try
1007     {
1008         uno::Reference<container::XNameAccess> xStyles;
1009         uno::Reference<container::XNameAccess> xCont = xModel->getStyleFamilies();
1010         xCont->getByName(aFamilyName) >>= xStyles;
1011         uno::Reference<beans::XPropertySet> xInfo;
1012         xStyles->getByName(sDefaultStyle) >>= xInfo;
1013         xInfo->getPropertyValue("DisplayName") >>= aUIName;
1014     }
1015     catch (const uno::Exception&)
1016     {
1017     }
1018     return aUIName;
1019 }
1020 
1021 SfxStyleFamily StyleList::GetActualFamily() const
1022 {
1023     const SfxStyleFamilyItem* pFamilyItem = GetFamilyItem();
1024     if (!pFamilyItem || m_nActFamily == 0xffff)
1025         return SfxStyleFamily::Para;
1026     else
1027         return pFamilyItem->GetFamily();
1028 }
1029 
1030 IMPL_LINK_NOARG(StyleList, HasSelectedStyle, void*, bool)
1031 {
1032     return m_xTreeBox->get_visible() ? m_xTreeBox->get_selected_index() != -1
1033                                      : m_xFmtLb->count_selected_rows() != 0;
1034 }
1035 
1036 IMPL_LINK_NOARG(StyleList, UpdateStyleDependents, void*, void)
1037 {
1038     // Trigger Help PI. Only when the watercan is on
1039     if (m_nActFamily != 0xffff && m_pParentDialog->IsCheckedItem("watercan") &&
1040         // only if that region is allowed
1041         nullptr != m_pFamilyState[m_nActFamily - 1] && IsSafeForWaterCan(nullptr))
1042     {
1043         m_pParentDialog->Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, *this);
1044         m_pParentDialog->Execute_Impl(SID_STYLE_WATERCAN, GetSelectedEntry(), "",
1045                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this);
1046     }
1047 }
1048 
1049 // Comes into action when the current style is changed
1050 void StyleList::UpdateStyles(StyleFlags nFlags)
1051 {
1052     OSL_ENSURE(nFlags != StyleFlags::NONE, "nothing to do");
1053     const SfxStyleFamilyItem* pItem = GetFamilyItem();
1054     if (!pItem)
1055     {
1056         // Is the case for the template catalog
1057         const size_t nFamilyCount = m_xStyleFamilies->size();
1058         size_t n;
1059         for (n = 0; n < nFamilyCount; n++)
1060             if (m_pFamilyState[StyleNrToInfoOffset(n)])
1061                 break;
1062         if (n == nFamilyCount)
1063             // It happens sometimes, God knows why
1064             return;
1065         m_nAppFilter = m_pFamilyState[StyleNrToInfoOffset(n)]->GetValue();
1066         m_pParentDialog->FamilySelect(StyleNrToInfoOffset(n) + 1, *this);
1067         pItem = GetFamilyItem();
1068     }
1069 
1070     const SfxStyleFamily eFam = pItem->GetFamily();
1071 
1072     SfxStyleSearchBits nFilter(m_nActFilter < pItem->GetFilterList().size()
1073                                    ? pItem->GetFilterList()[m_nActFilter].nFlags
1074                                    : SfxStyleSearchBits::Auto);
1075     if (nFilter == SfxStyleSearchBits::Auto) // automatic
1076         nFilter = m_nAppFilter;
1077 
1078     OSL_ENSURE(m_pStyleSheetPool, "no StyleSheetPool");
1079     if (!m_pStyleSheetPool)
1080         return;
1081 
1082     pItem = GetFamilyItem();
1083 
1084     m_aUpdateStyles.Call(nFlags);
1085 
1086     SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, nFilter);
1087 
1088     std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator();
1089     bool bEntry = m_xFmtLb->get_iter_first(*xEntry);
1090     std::vector<OUString> aStrings;
1091 
1092     comphelper::string::NaturalStringSorter aSorter(
1093         ::comphelper::getProcessComponentContext(),
1094         Application::GetSettings().GetLanguageTag().getLocale());
1095 
1096     while (pStyle)
1097     {
1098         aStrings.push_back(pStyle->GetName());
1099         pStyle = m_pStyleSheetPool->Next();
1100     }
1101     OUString aUIName = getDefaultStyleName(eFam);
1102 
1103     // Paradoxically, with a list and non-Latin style names,
1104     // sorting twice is faster than sorting once.
1105     // The first sort has a cheap comparator, and gets the list into mostly-sorted order.
1106     // Then the second sort needs to call its (much more expensive) comparator less often.
1107     std::sort(aStrings.begin(), aStrings.end());
1108     std::sort(aStrings.begin(), aStrings.end(),
1109               [&aSorter, &aUIName](const OUString& rLHS, const OUString& rRHS) {
1110                   if (rRHS == aUIName)
1111                       return false;
1112                   if (rLHS == aUIName)
1113                       return true; // default always first
1114                   return aSorter.compare(rLHS, rRHS) < 0;
1115               });
1116 
1117     size_t nCount = aStrings.size();
1118     size_t nPos = 0;
1119     while (nPos < nCount && bEntry && aStrings[nPos] == m_xFmtLb->get_text(*xEntry))
1120     {
1121         ++nPos;
1122         bEntry = m_xFmtLb->iter_next(*xEntry);
1123     }
1124 
1125     if (nPos < nCount || bEntry)
1126     {
1127         // Fills the display box
1128         m_xFmtLb->freeze();
1129         m_xFmtLb->clear();
1130 
1131         for (nPos = 0; nPos < nCount; ++nPos)
1132             m_xFmtLb->append(aStrings[nPos], aStrings[nPos]);
1133 
1134         m_xFmtLb->thaw();
1135     }
1136     // Selects the current style if any
1137     SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get();
1138     OUString aStyle;
1139     if (pState)
1140         aStyle = pState->GetStyleName();
1141     m_pParentDialog->SelectStyle(aStyle, false, *this);
1142     EnableDelete(nullptr);
1143 }
1144 
1145 void StyleList::SetFamilyState(sal_uInt16 nSlotId, const SfxTemplateItem* pItem)
1146 {
1147     sal_uInt16 nIdx = nSlotId - SID_STYLE_FAMILY_START;
1148     m_pFamilyState[nIdx].reset();
1149     if (pItem)
1150         m_pFamilyState[nIdx].reset(new SfxTemplateItem(*pItem));
1151     m_bUpdateFamily = true;
1152 }
1153 
1154 void StyleList::SetHierarchical()
1155 {
1156     m_bHierarchical = true;
1157     const OUString aSelectEntry(GetSelectedEntry());
1158     m_xFmtLb->hide();
1159     FillTreeBox(GetActualFamily());
1160     m_pParentDialog->SelectStyle(aSelectEntry, false, *this);
1161     m_xTreeBox->show();
1162 }
1163 
1164 void StyleList::SetFilterControlsHandle()
1165 {
1166     m_xTreeBox->hide();
1167     m_xFmtLb->show();
1168     m_bHierarchical = false;
1169 }
1170 
1171 // Handler for the New-Buttons
1172 void StyleList::NewHdl()
1173 {
1174     if (m_nActFamily == 0xffff
1175         || !(m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1))
1176         return;
1177 
1178     const SfxStyleFamilyItem* pItem = GetFamilyItem();
1179     const SfxStyleFamily eFam = pItem->GetFamily();
1180     SfxStyleSearchBits nMask(SfxStyleSearchBits::Auto);
1181     if (m_nActFilter != 0xffff)
1182         nMask = pItem->GetFilterList()[m_nActFilter].nFlags;
1183     if (nMask == SfxStyleSearchBits::Auto) // automatic
1184         nMask = m_nAppFilter;
1185 
1186     m_pParentDialog->Execute_Impl(SID_STYLE_NEW, "", GetSelectedEntry(),
1187                                   static_cast<sal_uInt16>(eFam), *this, nMask);
1188 }
1189 
1190 // Handler for the edit-Buttons
1191 void StyleList::EditHdl()
1192 {
1193     if (m_nActFamily != 0xffff && HasSelectedStyle(nullptr))
1194     {
1195         sal_uInt16 nFilter = m_nActFilter;
1196         OUString aTemplName(GetSelectedEntry());
1197         GetSelectedStyle(); // -Wall required??
1198         m_pParentDialog->Execute_Impl(SID_STYLE_EDIT, aTemplName, OUString(),
1199                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this,
1200                                       SfxStyleSearchBits::Auto, &nFilter);
1201     }
1202 }
1203 
1204 // Handler for the Delete-Buttons
1205 void StyleList::DeleteHdl()
1206 {
1207     if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr))
1208         return;
1209 
1210     bool bUsedStyle = false; // one of the selected styles are used in the document?
1211 
1212     std::vector<std::unique_ptr<weld::TreeIter>> aList;
1213     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
1214     const SfxStyleFamilyItem* pItem = GetFamilyItem();
1215 
1216     OUStringBuffer aMsg;
1217     aMsg.append(SfxResId(STR_DELETE_STYLE_USED) + SfxResId(STR_DELETE_STYLE));
1218 
1219     pTreeView->selected_foreach(
1220         [this, pTreeView, pItem, &aList, &bUsedStyle, &aMsg](weld::TreeIter& rEntry) {
1221             aList.emplace_back(pTreeView->make_iterator(&rEntry));
1222             // check the style is used or not
1223             const OUString aTemplName(pTreeView->get_text(rEntry));
1224 
1225             SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily());
1226 
1227             if (pStyle->IsUsed()) // pStyle is in use in the document?
1228             {
1229                 if (bUsedStyle) // add a separator for the second and later styles
1230                     aMsg.append(", ");
1231                 aMsg.append(aTemplName);
1232                 bUsedStyle = true;
1233             }
1234 
1235             return false;
1236         });
1237 
1238     bool aApproved = false;
1239 
1240     // we only want to show the dialog once and if we want to delete a style in use (UX-advice)
1241     if (bUsedStyle)
1242     {
1243         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
1244             pTreeView, VclMessageType::Question, VclButtonsType::YesNo, aMsg.makeStringAndClear()));
1245         aApproved = xBox->run() == RET_YES;
1246     }
1247 
1248     // if there are no used styles selected or the user approved the changes
1249     if (bUsedStyle && !aApproved)
1250         return;
1251 
1252     for (auto const& elem : aList)
1253     {
1254         const OUString aTemplName(pTreeView->get_text(*elem));
1255         m_bDontUpdate = true; // To prevent the Treelistbox to shut down while deleting
1256         m_pParentDialog->Execute_Impl(SID_STYLE_DELETE, aTemplName, OUString(),
1257                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this);
1258 
1259         if (m_xTreeBox->get_visible())
1260         {
1261             weld::RemoveParentKeepChildren(*m_xTreeBox, *elem);
1262             m_bDontUpdate = false;
1263         }
1264     }
1265     m_bDontUpdate = false; // if everything is deleted set m_bDontUpdate back to false
1266     UpdateStyles(StyleFlags::UpdateFamilyList); // and force-update the list
1267 }
1268 
1269 void StyleList::HideHdl()
1270 {
1271     if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr))
1272         return;
1273 
1274     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
1275     pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry) {
1276         OUString aTemplName = pTreeView->get_text(rEntry);
1277 
1278         m_pParentDialog->Execute_Impl(SID_STYLE_HIDE, aTemplName, OUString(),
1279                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this);
1280 
1281         return false;
1282     });
1283 }
1284 
1285 void StyleList::ShowHdl()
1286 {
1287     if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr))
1288         return;
1289 
1290     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
1291     pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry) {
1292         OUString aTemplName = pTreeView->get_text(rEntry);
1293 
1294         m_pParentDialog->Execute_Impl(SID_STYLE_SHOW, aTemplName, OUString(),
1295                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this);
1296 
1297         return false;
1298     });
1299 }
1300 
1301 IMPL_LINK_NOARG(StyleList, EnableDelete, void*, void)
1302 {
1303     bool bEnableDelete(false);
1304     if (m_nActFamily != 0xffff && HasSelectedStyle(nullptr))
1305     {
1306         OSL_ENSURE(m_pStyleSheetPool, "No StyleSheetPool");
1307         const OUString aTemplName(GetSelectedEntry());
1308         const SfxStyleFamilyItem* pItem = GetFamilyItem();
1309         const SfxStyleFamily eFam = pItem->GetFamily();
1310         SfxStyleSearchBits nFilter = SfxStyleSearchBits::Auto;
1311         if (pItem->GetFilterList().size() > m_nActFilter)
1312             nFilter = pItem->GetFilterList()[m_nActFilter].nFlags;
1313         if (nFilter == SfxStyleSearchBits::Auto) // automatic
1314             nFilter = m_nAppFilter;
1315         const SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(
1316             aTemplName, eFam, m_xTreeBox->get_visible() ? SfxStyleSearchBits::All : nFilter);
1317 
1318         OSL_ENSURE(pStyle, "Style not found");
1319         if (pStyle && pStyle->IsUserDefined())
1320         {
1321             if (pStyle->HasClearParentSupport() || !pStyle->IsUsed())
1322             {
1323                 bEnableDelete = true;
1324             }
1325         }
1326     }
1327     m_pParentDialog->EnableDel(bEnableDelete, this);
1328 }
1329 
1330 IMPL_LINK_NOARG(StyleList, Clear, void*, void)
1331 {
1332     m_xStyleFamilies.reset();
1333     for (auto& i : m_pFamilyState)
1334         i.reset();
1335     m_pCurObjShell = nullptr;
1336     for (auto& i : pBoundItems)
1337         i.reset();
1338 }
1339 
1340 void StyleList::ShowMenu(const CommandEvent& rCEvt)
1341 {
1342     CreateContextMenu();
1343     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
1344     OString sCommand(
1345         mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1))));
1346     MenuSelect(sCommand);
1347 }
1348 
1349 void StyleList::MenuSelect(const OString& rIdent)
1350 {
1351     sLastItemIdent = rIdent;
1352     if (sLastItemIdent.isEmpty())
1353         return;
1354     Application::PostUserEvent(LINK(this, StyleList, MenuSelectAsyncHdl)); /***check this****/
1355 }
1356 
1357 void StyleList::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
1358 {
1359     const SfxHintId nId = rHint.GetId();
1360 
1361     switch (nId)
1362     {
1363         case SfxHintId::UpdateDone:
1364         {
1365             SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame();
1366             SfxObjectShell* pDocShell = pViewFrame->GetObjectShell();
1367             if (m_pParentDialog->GetNotifyUpdate()
1368                 && (!m_pParentDialog->IsCheckedItem("watercan")
1369                     || (pDocShell && pDocShell->GetStyleSheetPool() != m_pStyleSheetPool)))
1370             {
1371                 m_pParentDialog->SetNotifyupdate(false);
1372                 Update();
1373             }
1374             else if (m_bUpdateFamily)
1375             {
1376                 UpdateFamily();
1377                 m_aUpdateFamily.Call(*this);
1378             }
1379 
1380             if (m_pStyleSheetPool)
1381             {
1382                 OUString aStr = GetSelectedEntry();
1383                 if (!aStr.isEmpty())
1384                 {
1385                     const SfxStyleFamilyItem* pItem = GetFamilyItem();
1386                     if (!pItem)
1387                         break;
1388                     const SfxStyleFamily eFam = pItem->GetFamily();
1389                     SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aStr, eFam);
1390                     if (pStyle)
1391                     {
1392                         bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly);
1393                         m_pParentDialog->EnableEdit(bReadWrite, this);
1394                         m_pParentDialog->EnableHide(
1395                             bReadWrite && !pStyle->IsUsed() && !pStyle->IsHidden(), this);
1396                         m_pParentDialog->EnableShow(bReadWrite && pStyle->IsHidden(), this);
1397                     }
1398                     else
1399                     {
1400                         m_pParentDialog->EnableEdit(false, this);
1401                         m_pParentDialog->EnableHide(false, this);
1402                         m_pParentDialog->EnableShow(false, this);
1403                     }
1404                 }
1405             }
1406             break;
1407         }
1408 
1409         // Necessary if switching between documents and in both documents
1410         // the same template is used. Do not immediately call Update_Impl,
1411         // for the case that one of the documents is an internal InPlaceObject!
1412         case SfxHintId::DocChanged:
1413             m_pParentDialog->SetNotifyupdate(true);
1414             break;
1415         case SfxHintId::Dying:
1416         {
1417             EndListening(*m_pStyleSheetPool);
1418             m_pStyleSheetPool = nullptr;
1419             break;
1420         }
1421         default:
1422             break;
1423     }
1424 
1425     // Do not set timer when the stylesheet pool is in the box, because it is
1426     // possible that a new one is registered after the timer is up -
1427     // works bad in UpdateStyles_Impl ()!
1428 
1429     if (!m_bDontUpdate && nId != SfxHintId::Dying
1430         && (dynamic_cast<const SfxStyleSheetPoolHint*>(&rHint)
1431             || dynamic_cast<const SfxStyleSheetHint*>(&rHint)
1432             || dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint)
1433             || nId == SfxHintId::StyleSheetModified))
1434     {
1435         if (!pIdle)
1436         {
1437             pIdle.reset(new Idle("SfxCommonTemplate"));
1438             pIdle->SetPriority(TaskPriority::LOWEST);
1439             pIdle->SetInvokeHandler(LINK(this, StyleList, TimeOut));
1440         }
1441         pIdle->Start();
1442     }
1443 }
1444 
1445 IMPL_LINK_NOARG(StyleList, TimeOut, Timer*, void)
1446 {
1447     if (!m_bDontUpdate)
1448     {
1449         m_bDontUpdate = true;
1450         if (!m_xTreeBox->get_visible())
1451             UpdateStyles(StyleFlags::UpdateFamilyList);
1452         else
1453         {
1454             FillTreeBox(GetActualFamily());
1455             SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get();
1456             if (pState)
1457             {
1458                 m_pParentDialog->SelectStyle(pState->GetStyleName(), false, *this);
1459                 EnableDelete(nullptr);
1460             }
1461         }
1462         m_bDontUpdate = false;
1463         pIdle.reset();
1464     }
1465     else
1466         pIdle->Start();
1467 }
1468 
1469 IMPL_LINK_NOARG(StyleList, MenuSelectAsyncHdl, void*, void)
1470 {
1471     if (sLastItemIdent == "new")
1472         NewHdl();
1473     else if (sLastItemIdent == "edit")
1474         EditHdl();
1475     else if (sLastItemIdent == "delete")
1476         DeleteHdl();
1477     else if (sLastItemIdent == "hide")
1478         HideHdl();
1479     else if (sLastItemIdent == "show")
1480         ShowHdl();
1481 }
1482 
1483 // Double-click on a style sheet in the ListBox is applied.
1484 IMPL_LINK(StyleList, DragBeginHdl, bool&, rUnsetDragIcon, bool)
1485 {
1486     rUnsetDragIcon = false;
1487     // Allow normal processing. only if bAllowReParentDrop is true
1488     return !m_bAllowReParentDrop;
1489 }
1490 
1491 IMPL_LINK(StyleList, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
1492 {
1493     bool bRet = false;
1494     const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode();
1495     if (m_bCanDel && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_DELETE)
1496     {
1497         DeleteHdl();
1498         bRet = true;
1499     }
1500     return bRet;
1501 }
1502 
1503 IMPL_LINK(StyleList, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString)
1504 {
1505     weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get();
1506     const OUString aTemplName(pTreeView->get_text(rEntry));
1507     OUString sQuickHelpText(aTemplName);
1508 
1509     const SfxStyleFamilyItem* pItem = GetFamilyItem();
1510     if (!pItem)
1511         return sQuickHelpText;
1512     SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily());
1513 
1514     if (pStyle && pStyle->IsUsed()) // pStyle is in use in the document?
1515     {
1516         OUString sUsedBy;
1517         if (pStyle->GetFamily() == SfxStyleFamily::Pseudo)
1518             sUsedBy = pStyle->GetUsedBy();
1519 
1520         if (!sUsedBy.isEmpty())
1521         {
1522             const sal_Int32 nMaxLen = 80;
1523             if (sUsedBy.getLength() > nMaxLen)
1524             {
1525                 sUsedBy = OUString::Concat(sUsedBy.subView(0, nMaxLen)) + "...";
1526             }
1527 
1528             OUString aMessage = SfxResId(STR_STYLEUSEDBY);
1529             aMessage = aMessage.replaceFirst("%STYLELIST", sUsedBy);
1530             sQuickHelpText = aTemplName + " " + aMessage;
1531         }
1532     }
1533 
1534     return sQuickHelpText;
1535 }
1536 
1537 IMPL_LINK(StyleList, CustomRenderHdl, weld::TreeView::render_args, aPayload, void)
1538 {
1539     vcl::RenderContext& rRenderContext = std::get<0>(aPayload);
1540     const ::tools::Rectangle& rRect = std::get<1>(aPayload);
1541     ::tools::Rectangle aRect(
1542         rRect.TopLeft(),
1543         Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), rRect.GetHeight()));
1544     bool bSelected = std::get<2>(aPayload);
1545     const OUString& rId = std::get<3>(aPayload);
1546 
1547     rRenderContext.Push(vcl::PushFlags::TEXTCOLOR);
1548     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1549     if (bSelected)
1550         rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
1551     else
1552         rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor());
1553 
1554     bool bSuccess = false;
1555 
1556     SfxObjectShell* pShell = SfxObjectShell::Current();
1557     sfx2::StyleManager* pStyleManager = pShell ? pShell->GetStyleManager() : nullptr;
1558 
1559     if (pStyleManager)
1560     {
1561         const SfxStyleFamilyItem* pItem = GetFamilyItem();
1562         SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(rId, pItem->GetFamily());
1563 
1564         if (pStyleSheet)
1565         {
1566             rRenderContext.Push(vcl::PushFlags::ALL);
1567             sal_Int32 nSize = aRect.GetHeight();
1568             std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer(
1569                 pStyleManager->CreateStylePreviewRenderer(rRenderContext, pStyleSheet, nSize));
1570             bSuccess = pStylePreviewRenderer->recalculate() && pStylePreviewRenderer->render(aRect);
1571             rRenderContext.Pop();
1572         }
1573     }
1574 
1575     if (!bSuccess)
1576         rRenderContext.DrawText(aRect, rId, DrawTextFlags::Left | DrawTextFlags::VCenter);
1577 
1578     rRenderContext.Pop();
1579 }
1580 
1581 // Selection of a template during the Watercan-Status
1582 IMPL_LINK(StyleList, FmtSelectHdl, weld::TreeView&, rListBox, void)
1583 {
1584     std::unique_ptr<weld::TreeIter> xHdlEntry = rListBox.make_iterator();
1585     if (!rListBox.get_cursor(xHdlEntry.get()))
1586         return;
1587 
1588     m_pParentDialog->SelectStyle(rListBox.get_text(*xHdlEntry), true, *this);
1589 }
1590 
1591 IMPL_LINK_NOARG(StyleList, TreeListApplyHdl, weld::TreeView&, bool)
1592 {
1593     // only if that region is allowed
1594     if (m_nActFamily != 0xffff && nullptr != m_pFamilyState[m_nActFamily - 1]
1595         && !GetSelectedEntry().isEmpty())
1596     {
1597         m_pParentDialog->Execute_Impl(SID_STYLE_APPLY, GetSelectedEntry(), OUString(),
1598                                       static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this,
1599                                       SfxStyleSearchBits::Auto, nullptr, &m_nModifier);
1600     }
1601     // After selecting a focused item if possible again on the app window
1602     if (dynamic_cast<const SfxTemplateDialog_Impl*>(m_pParentDialog) != nullptr)
1603     {
1604         SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame();
1605         SfxViewShell* pVu = pViewFrame->GetViewShell();
1606         vcl::Window* pAppWin = pVu ? pVu->GetWindow() : nullptr;
1607         if (pAppWin)
1608             pAppWin->GrabFocus();
1609     }
1610 
1611     return true;
1612 }
1613 
1614 IMPL_LINK(StyleList, MousePressHdl, const MouseEvent&, rMEvt, bool)
1615 {
1616     m_nModifier = rMEvt.GetModifier();
1617     return false;
1618 }
1619 
1620 // Notice from SfxBindings that the update is completed. Pushes out the update
1621 // of the display.
1622 void StyleList::Update()
1623 {
1624     bool bDocChanged = false;
1625     SfxStyleSheetBasePool* pNewPool = nullptr;
1626     SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame();
1627     SfxObjectShell* pDocShell = pViewFrame->GetObjectShell();
1628     if (pDocShell)
1629         pNewPool = pDocShell->GetStyleSheetPool();
1630 
1631     if (pNewPool != m_pStyleSheetPool && pDocShell)
1632     {
1633         SfxModule* pNewModule = pDocShell->GetModule();
1634         if (pNewModule && pNewModule != m_Module)
1635         {
1636             m_aClearResource.Call(nullptr);
1637             m_aReadResource.Call(*this);
1638         }
1639         if (m_pStyleSheetPool)
1640         {
1641             EndListening(*m_pStyleSheetPool);
1642             m_pStyleSheetPool = nullptr;
1643         }
1644 
1645         if (pNewPool)
1646         {
1647             StartListening(*pNewPool);
1648             m_pStyleSheetPool = pNewPool;
1649             bDocChanged = true;
1650         }
1651     }
1652 
1653     if (m_bUpdateFamily)
1654     {
1655         UpdateFamily();
1656         m_aUpdateFamily.Call(*this);
1657     }
1658 
1659     sal_uInt16 i;
1660     for (i = 0; i < MAX_FAMILIES; ++i)
1661         if (m_pFamilyState[i])
1662             break;
1663     if (i == MAX_FAMILIES || !pNewPool)
1664         // nothing is allowed
1665         return;
1666 
1667     SfxTemplateItem* pItem = nullptr;
1668     // current region not within the allowed region or default
1669     if (m_nActFamily == 0xffff || nullptr == (pItem = m_pFamilyState[m_nActFamily - 1].get()))
1670     {
1671         m_pParentDialog->CheckItem(OString::number(m_nActFamily), false);
1672         const size_t nFamilyCount = m_xStyleFamilies->size();
1673         size_t n;
1674         for (n = 0; n < nFamilyCount; n++)
1675             if (m_pFamilyState[StyleNrToInfoOffset(n)])
1676                 break;
1677 
1678         std::unique_ptr<SfxTemplateItem>& pNewItem = m_pFamilyState[StyleNrToInfoOffset(n)];
1679         m_nAppFilter = pNewItem->GetValue();
1680         m_pParentDialog->FamilySelect(StyleNrToInfoOffset(n) + 1, *this);
1681         pItem = pNewItem.get();
1682     }
1683     else if (bDocChanged)
1684     {
1685         // other DocShell -> all new
1686         m_pParentDialog->CheckItem(OString::number(m_nActFamily));
1687         m_nActFilter = static_cast<sal_uInt16>(m_aLoadFactoryStyleFilter.Call(pDocShell));
1688         m_pParentDialog->IsUpdate(*this);
1689         if (0xffff == m_nActFilter)
1690         {
1691             m_nActFilter = pDocShell->GetAutoStyleFilterIndex();
1692         }
1693 
1694         m_nAppFilter = pItem->GetValue();
1695         if (!m_xTreeBox->get_visible())
1696         {
1697             UpdateStyles(StyleFlags::UpdateFamilyList);
1698         }
1699         else
1700             FillTreeBox(GetActualFamily());
1701     }
1702     else
1703     {
1704         // other filters for automatic
1705         m_pParentDialog->CheckItem(OString::number(m_nActFamily));
1706         const SfxStyleFamilyItem* pStyleItem = GetFamilyItem();
1707         if (pStyleItem
1708             && SfxStyleSearchBits::Auto == pStyleItem->GetFilterList()[m_nActFilter].nFlags
1709             && m_nAppFilter != pItem->GetValue())
1710         {
1711             m_nAppFilter = pItem->GetValue();
1712             if (!m_xTreeBox->get_visible())
1713                 UpdateStyles(StyleFlags::UpdateFamilyList);
1714             else
1715                 FillTreeBox(GetActualFamily());
1716         }
1717         else
1718         {
1719             m_nAppFilter = pItem->GetValue();
1720         }
1721     }
1722     const OUString aStyle(pItem->GetStyleName());
1723     m_pParentDialog->SelectStyle(aStyle, false, *this);
1724     EnableDelete(nullptr);
1725     m_pParentDialog->EnableNew(m_bCanNew, this);
1726 }
1727 
1728 void StyleList::EnablePreview(bool bCustomPreview)
1729 {
1730     m_xFmtLb->clear();
1731     m_xFmtLb->set_column_custom_renderer(0, bCustomPreview);
1732     m_xTreeBox->clear();
1733     m_xTreeBox->set_column_custom_renderer(0, bCustomPreview);
1734 }
1735 
1736 const SfxStyleFamilyItem& StyleList::GetFamilyItemByIndex(size_t i) const
1737 {
1738     return m_xStyleFamilies->at(i);
1739 }
1740 
1741 IMPL_STATIC_LINK(StyleList, CustomGetSizeHdl, weld::TreeView::get_size_args, aPayload, Size)
1742 {
1743     vcl::RenderContext& rRenderContext = aPayload.first;
1744     return Size(42, 32 * rRenderContext.GetDPIScaleFactor());
1745 }
1746 
1747 IMPL_LINK(StyleList, PopupFlatMenuHdl, const CommandEvent&, rCEvt, bool)
1748 {
1749     if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
1750         return false;
1751 
1752     PrepareMenu(rCEvt.GetMousePosPixel());
1753 
1754     if (m_xFmtLb->count_selected_rows() <= 0)
1755     {
1756         m_pParentDialog->EnableEdit(false, this);
1757         m_pParentDialog->EnableDel(false, this);
1758     }
1759 
1760     ShowMenu(rCEvt);
1761 
1762     return true;
1763 }
1764 
1765 IMPL_LINK(StyleList, PopupTreeMenuHdl, const CommandEvent&, rCEvt, bool)
1766 {
1767     if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
1768         return false;
1769 
1770     PrepareMenu(rCEvt.GetMousePosPixel());
1771 
1772     ShowMenu(rCEvt);
1773 
1774     return true;
1775 }
1776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1777