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 .
22 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/container/XNameAccess.hpp>
25 #include <vcl/commandevent.hxx>
26 #include <vcl/commandinfoprovider.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/weldutils.hxx>
31 #include <svl/intitem.hxx>
32 #include <svl/stritem.hxx>
33 #include <svl/style.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/propertyvalue.hxx>
36 #include <comphelper/sequenceashashmap.hxx>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/frame/ModuleManager.hpp>
39 #include <com/sun/star/frame/UnknownModuleException.hpp>
40 #include <officecfg/Office/Common.hxx>
42 #include <sal/log.hxx>
43 #include <osl/diagnose.h>
44 #include <tools/diagnose_ex.h>
45 #include <sfx2/app.hxx>
46 #include <sfx2/dispatch.hxx>
47 #include <sfx2/bindings.hxx>
48 #include <sfx2/templdlg.hxx>
49 #include <templdgi.hxx>
50 #include <tplcitem.hxx>
51 #include <sfx2/styfitem.hxx>
52 #include <sfx2/objsh.hxx>
53 #include <sfx2/viewsh.hxx>
54 #include <sfx2/newstyle.hxx>
55 #include <sfx2/tplpitem.hxx>
56 #include <sfx2/sfxresid.hxx>
58 #include <sfx2/sfxsids.hrc>
59 #include <sfx2/strings.hrc>
60 #include <sfx2/docfac.hxx>
61 #include <sfx2/module.hxx>
63 #include <sfx2/viewfrm.hxx>
65 #include <comphelper/string.hxx>
67 #include <sfx2/StyleManager.hxx>
68 #include <sfx2/StylePreviewRenderer.hxx>
71 using namespace css::beans
;
72 using namespace css::frame
;
73 using namespace css::uno
;
75 class SfxCommonTemplateDialog_Impl::DeletionWatcher
77 typedef void (DeletionWatcher::* bool_type
)();
80 explicit DeletionWatcher(SfxCommonTemplateDialog_Impl
& rDialog
)
82 , m_pPrevious(m_pDialog
->impl_setDeletionWatcher(this))
89 m_pDialog
->impl_setDeletionWatcher(m_pPrevious
);
92 DeletionWatcher(const DeletionWatcher
&) = delete;
93 DeletionWatcher
& operator=(const DeletionWatcher
&) = delete;
95 // Signal that the dialog was deleted
100 m_pPrevious
->signal();
103 // Return true if the dialog was deleted
104 operator bool_type() const
106 return m_pDialog
? nullptr : &DeletionWatcher::signal
;
110 SfxCommonTemplateDialog_Impl
* m_pDialog
;
111 DeletionWatcher
*const m_pPrevious
; /// let's add more epicycles!
114 sal_Int8
SfxCommonTemplateDialog_Impl::ExecuteDrop(const ExecuteDropEvent
& rEvt
)
116 // handle drop of content into the treeview to create a new style
117 m_aStyleListExecuteDrop
.Call(rEvt
);
118 return DND_ACTION_NONE
;
121 IMPL_LINK(SfxCommonTemplateDialog_Impl
, OnAsyncExecuteDrop
, void*, pStyleList
, void)
123 StyleList
* pStyle
= static_cast<StyleList
*>(pStyleList
);
124 if (pStyle
== &m_aStyleList
)
125 ActionSelect("new", m_aStyleList
);
128 SfxTemplatePanelControl::SfxTemplatePanelControl(SfxBindings
* pBindings
, weld::Widget
* pParent
)
129 : PanelLayout(pParent
, "TemplatePanel", "sfx/ui/templatepanel.ui")
130 , pImpl(new SfxTemplateDialog_Impl(pBindings
, this))
132 OSL_ASSERT(pBindings
!=nullptr);
135 SfxTemplatePanelControl::~SfxTemplatePanelControl()
139 namespace SfxTemplate
141 // converts from SFX_STYLE_FAMILY Ids to 1-6
142 static sal_uInt16
SfxFamilyIdToNId(SfxStyleFamily nFamily
)
146 case SfxStyleFamily::Char
: return 1;
147 case SfxStyleFamily::Para
: return 2;
148 case SfxStyleFamily::Frame
: return 3;
149 case SfxStyleFamily::Page
: return 4;
150 case SfxStyleFamily::Pseudo
: return 5;
151 case SfxStyleFamily::Table
: return 6;
152 default: return 0xffff;
157 void SfxCommonTemplateDialog_Impl::connect_stylelist_execute_drop(
158 const Link
<const ExecuteDropEvent
&, sal_Int8
>& rLink
)
160 m_aStyleListExecuteDrop
= rLink
;
163 void SfxCommonTemplateDialog_Impl::connect_stylelist_has_selected_style(const Link
<void*, bool>& rLink
)
165 m_aStyleListHasSelectedStyle
= rLink
;
168 void SfxCommonTemplateDialog_Impl::connect_stylelist_update_style_dependents(const Link
<void*, void>& rLink
)
170 m_aStyleListUpdateStyleDependents
= rLink
;
173 void SfxCommonTemplateDialog_Impl::connect_stylelist_enable_tree_drag(const Link
<bool, void> rLink
)
175 m_aStyleListEnableTreeDrag
= rLink
;
178 void SfxCommonTemplateDialog_Impl::connect_stylelist_enable_delete(const Link
<void*, void> rLink
)
180 m_aStyleListEnableDelete
= rLink
;
183 void SfxCommonTemplateDialog_Impl::connect_stylelist_set_water_can_state(
184 const Link
<const SfxBoolItem
*, void> rLink
)
186 m_aStyleListSetWaterCanState
= rLink
;
191 SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl(SfxBindings
* pB
, weld::Container
* pC
, weld::Builder
* pBuilder
)
194 , xModuleManager(frame::ModuleManager::create(::comphelper::getProcessComponentContext()))
195 , m_pDeletionWatcher(nullptr)
196 , m_aStyleList(pBuilder
, pB
, this, pC
, "treeview", "flatview")
197 , mxPreviewCheckbox(pBuilder
->weld_check_button("showpreview"))
198 , mxFilterLb(pBuilder
->weld_combo_box("filter"))
203 , bWaterDisabled(false)
204 , bNewByExampleDisabled(false)
205 , bUpdateByExampleDisabled(false)
206 , m_bWantHierarchical(false)
208 mxFilterLb
->set_help_id(HID_TEMPLATE_FILTER
);
209 mxPreviewCheckbox
->set_active(officecfg::Office::Common::StylesAndFormatting::Preview::get());
212 void SfxTemplateDialog_Impl::EnableEdit(bool bEnable
, StyleList
* rStyleList
)
214 if(rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
215 SfxCommonTemplateDialog_Impl::EnableEdit( bEnable
, &m_aStyleList
);
216 if( !bEnable
|| !bUpdateByExampleDisabled
)
217 EnableItem("update", bEnable
);
220 IMPL_LINK(SfxCommonTemplateDialog_Impl
, ReadResource_Hdl
, StyleList
&, rStyleList
, void)
224 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
225 SfxObjectShell
* pCurObjShell
= pViewFrame
->GetObjectShell();
228 nActFilter
= static_cast<sal_uInt16
>(LoadFactoryStyleFilter_Hdl(pCurObjShell
));
229 if (0xffff == nActFilter
)
231 nActFilter
= pCurObjShell
->GetAutoStyleFilterIndex();
235 size_t nCount
= m_aStyleListReadResource
.Call(nullptr);
237 // Insert in the reverse order of occurrence in the Style Families. This is for
238 // the toolbar of the designer. The list box of the catalog respects the
239 // correct order by itself.
241 // Sequences: the order of Resource = the order of Toolbar for example list box.
242 // Order of ascending SIDs: Low SIDs are displayed first when templates of
243 // several families are active.
245 // in the Writer the UpdateStyleByExample Toolbox button is removed and
246 // the NewStyle button gets a PopupMenu
248 ReplaceUpdateButtonByMenu();
252 const SfxStyleFamilyItem
&rItem
= rStyleList
.GetFamilyItemByIndex( nCount
);
253 sal_uInt16 nId
= SfxTemplate::SfxFamilyIdToNId( rItem
.GetFamily() );
254 InsertFamilyItem(nId
, rItem
);
258 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, ClearResource_Hdl
, void*, void)
261 m_aStyleListClear
.Call(nullptr);
264 SfxCommonTemplateDialog_Impl::DeletionWatcher
*
265 SfxCommonTemplateDialog_Impl::impl_setDeletionWatcher(
266 DeletionWatcher
*const pNewWatcher
)
268 DeletionWatcher
*const pRet(m_pDeletionWatcher
);
269 m_pDeletionWatcher
= pNewWatcher
;
273 void SfxCommonTemplateDialog_Impl::Initialize()
275 m_aStyleList
.connect_ReadResource(LINK(this, SfxCommonTemplateDialog_Impl
, ReadResource_Hdl
));
276 m_aStyleList
.connect_ClearResource(LINK(this, SfxCommonTemplateDialog_Impl
, ClearResource_Hdl
));
277 m_aStyleList
.connect_LoadFactoryStyleFilter(LINK(this, SfxCommonTemplateDialog_Impl
, LoadFactoryStyleFilter_Hdl
));
278 m_aStyleList
.connect_SaveSelection(LINK(this, SfxCommonTemplateDialog_Impl
, SaveSelection_Hdl
));
279 m_aStyleList
.connect_UpdateStyleDependents(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateStyleDependents_Hdl
));
280 m_aStyleList
.connect_UpdateFamily(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateFamily_Hdl
));
281 m_aStyleList
.connect_UpdateStyles(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateStyles_Hdl
));
283 mxFilterLb
->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl
, FilterSelectHdl
));
284 mxPreviewCheckbox
->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl
, PreviewHdl
));
285 m_aStyleList
.Initialize();
288 IMPL_LINK(SfxCommonTemplateDialog_Impl
, UpdateStyles_Hdl
, StyleFlags
, nFlags
, void)
290 const SfxStyleFamilyItem
* pItem
= m_aStyleList
.GetFamilyItem();
292 if (nFlags
& StyleFlags::UpdateFamily
) // Update view type list (Hierarchical, All, etc.
294 CheckItem(OString::number(nActFamily
)); // check Button in Toolbox
296 mxFilterLb
->freeze();
299 //insert hierarchical at the beginning
300 mxFilterLb
->append(OUString::number(static_cast<int>(SfxStyleSearchBits::All
)),
301 SfxResId(STR_STYLE_FILTER_HIERARCHICAL
));
302 const SfxStyleFilter
& rFilter
= pItem
->GetFilterList();
303 for (const SfxFilterTuple
& i
: rFilter
)
304 mxFilterLb
->append(OUString::number(static_cast<int>(i
.nFlags
)), i
.aName
);
307 if (nActFilter
< mxFilterLb
->get_count() - 1)
308 mxFilterLb
->set_active(nActFilter
+ 1);
312 m_aStyleList
.FilterSelect(nActFilter
, false);
313 mxFilterLb
->set_active(1);
316 // if the tree view again, select family hierarchy
317 if (m_aStyleList
.IsTreeView() || m_bWantHierarchical
)
319 mxFilterLb
->set_active_text(SfxResId(STR_STYLE_FILTER_HIERARCHICAL
));
320 EnableHierarchical(true, m_aStyleList
);
325 if (nActFilter
< mxFilterLb
->get_count() - 1)
326 mxFilterLb
->set_active(nActFilter
+ 1);
330 m_aStyleList
.FilterSelect(nActFilter
, false);
331 mxFilterLb
->set_active(1);
335 if (!(nFlags
& StyleFlags::UpdateFamilyList
))
338 EnableItem("watercan", false);
341 SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl()
344 Execute_Impl(SID_STYLE_WATERCAN
, "", "", 0, m_aStyleList
);
345 m_aStyleListClear
.Call(nullptr);
346 m_aStyleListCleanup
.Call(nullptr);
347 if ( m_pDeletionWatcher
)
348 m_pDeletionWatcher
->signal();
349 mxPreviewCheckbox
.reset();
354 * Is it safe to show the water-can / fill icon. If we've a
355 * hierarchical widget - we have only single select, otherwise
356 * we need to check if we have a multi-selection. We either have
357 * a mxTreeBox showing or an mxFmtLb (which we hide when not shown)
359 bool SfxCommonTemplateDialog_Impl::IsSafeForWaterCan() const
361 return m_aStyleListWaterCan
.Call(nullptr);
364 void SfxCommonTemplateDialog_Impl::SelectStyle(const OUString
&rStr
, bool bIsCallback
, StyleList
& rStyleList
)
366 rStyleList
.SelectStyle(rStr
, bIsCallback
);
368 bWaterDisabled
= !IsSafeForWaterCan();
370 // tdf#134598 call UpdateStyleDependents to update watercan
371 UpdateStyleDependents_Hdl(nullptr);
374 void SfxCommonTemplateDialog_Impl::EnableTreeDrag(bool bEnable
)
376 m_aStyleListEnableTreeDrag
.Call(bEnable
);
379 // Updated display: Watering the house
380 void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem
*pItem
)
382 bWaterDisabled
= (pItem
== nullptr);
385 //make sure the watercan is only activated when there is (only) one selection
386 bWaterDisabled
= !IsSafeForWaterCan();
388 if(pItem
&& !bWaterDisabled
)
390 CheckItem("watercan", pItem
->GetValue());
391 EnableItem("watercan");
396 EnableItem("watercan");
398 EnableItem("watercan", false);
401 // Ignore while in watercan mode statusupdates
403 m_aStyleListSetWaterCanState
.Call(pItem
);
406 // Item with the status of a Family is copied and noted
407 // (is updated when all states have also been updated.)
408 // See also: <SfxBindings::AddDoneHdl(const Link &)>
409 void SfxCommonTemplateDialog_Impl::SetFamilyState( sal_uInt16 nSlotId
, const SfxTemplateItem
* pItem
)
411 m_aStyleList
.SetFamilyState(nSlotId
, pItem
);
415 // Internal: Perform functions through the Dispatcher
416 bool SfxCommonTemplateDialog_Impl::Execute_Impl(
417 sal_uInt16 nId
, const OUString
&rStr
, const OUString
& rRefStr
, sal_uInt16 nFamily
, StyleList
& rStyleList
,
418 SfxStyleSearchBits nMask
, sal_uInt16
*pIdx
, const sal_uInt16
* pModifier
)
420 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
421 SfxStringItem
aItem(nId
, rStr
);
422 SfxUInt16Item
aFamily(SID_STYLE_FAMILY
, nFamily
);
423 SfxUInt16Item
aMask( SID_STYLE_MASK
, static_cast<sal_uInt16
>(nMask
) );
424 SfxStringItem
aUpdName(SID_STYLE_UPD_BY_EX_NAME
, rStr
);
425 SfxStringItem
aRefName( SID_STYLE_REFERENCE
, rRefStr
);
426 const SfxPoolItem
* pItems
[ 6 ];
427 sal_uInt16 nCount
= 0;
428 if( !rStr
.isEmpty() )
429 pItems
[ nCount
++ ] = &aItem
;
430 pItems
[ nCount
++ ] = &aFamily
;
431 if( nMask
!= SfxStyleSearchBits::Auto
)
432 pItems
[ nCount
++ ] = &aMask
;
433 if(SID_STYLE_UPDATE_BY_EXAMPLE
== nId
)
435 // Special solution for Numbering update in Writer
436 const OUString
aTemplName(rStyleList
.GetSelectedEntry());
437 aUpdName
.SetValue(aTemplName
);
438 pItems
[ nCount
++ ] = &aUpdName
;
441 if ( !rRefStr
.isEmpty() )
442 pItems
[ nCount
++ ] = &aRefName
;
444 pItems
[ nCount
++ ] = nullptr;
446 DeletionWatcher
aDeleted(*this);
447 sal_uInt16 nModi
= pModifier
? *pModifier
: 0;
448 const SfxPoolItem
* pItem
= rDispatcher
.Execute(
449 nId
, SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
452 // Dialog can be destroyed while in Execute() because started
453 // subdialogs are not modal to it (#i97888#).
454 if ( !pItem
|| aDeleted
)
457 if ((nId
== SID_STYLE_NEW
|| SID_STYLE_EDIT
== nId
)
458 && rStyleList
.EnableExecute())
460 const SfxUInt16Item
*pFilterItem
= dynamic_cast< const SfxUInt16Item
* >(pItem
);
462 SfxStyleSearchBits nFilterFlags
= static_cast<SfxStyleSearchBits
>(pFilterItem
->GetValue()) & ~SfxStyleSearchBits::UserDefined
;
463 if(nFilterFlags
== SfxStyleSearchBits::Auto
) // User Template?
464 nFilterFlags
= static_cast<SfxStyleSearchBits
>(pFilterItem
->GetValue());
465 const SfxStyleFamilyItem
*pFamilyItem
= rStyleList
.GetFamilyItem();
466 const size_t nFilterCount
= pFamilyItem
->GetFilterList().size();
468 for ( size_t i
= 0; i
< nFilterCount
; ++i
)
470 const SfxFilterTuple
&rTupel
= pFamilyItem
->GetFilterList()[ i
];
472 if ( ( rTupel
.nFlags
& nFilterFlags
) == nFilterFlags
&& pIdx
)
480 // Handler Listbox of Filter
481 void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable
, StyleList
& rStyleList
)
485 if (!rStyleList
.IsHierarchical())
488 m_bWantHierarchical
= true;
489 SaveSelection_Hdl(rStyleList
); // fdo#61429 store "hierarchical"
490 m_aStyleList
.SetHierarchical();
495 m_aStyleList
.SetFilterControlsHandle();
496 // If bHierarchical, then the family can have changed
497 // minus one since hierarchical is inserted at the start
498 m_bWantHierarchical
= false; // before FilterSelect
499 FilterSelect(mxFilterLb
->get_active() - 1, rStyleList
.IsHierarchical() );
503 // Other filters; can be switched by the users or as a result of new or
504 // editing, if the current document has been assigned a different filter.
505 void SfxCommonTemplateDialog_Impl::FilterSelect(
506 sal_uInt16 nEntry
, // Idx of the new Filters
507 bool bForce
) // Force update, even if the new filter is equal to the current
509 if (nEntry
== nActFilter
&& !bForce
)
513 m_aStyleList
.FilterSelect(nActFilter
, true);
516 void SfxCommonTemplateDialog_Impl::IsUpdate(bool bDoUpdate
, StyleList
&)
518 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
519 SfxObjectShell
* pDocShell
= pViewFrame
->GetObjectShell();
522 nActFilter
= static_cast<sal_uInt16
>(LoadFactoryStyleFilter_Hdl(pDocShell
));
523 if (0xffff == nActFilter
)
525 nActFilter
= pDocShell
->GetAutoStyleFilterIndex();
530 IMPL_LINK(SfxCommonTemplateDialog_Impl
, FilterSelectHdl
, weld::ComboBox
&, rBox
, void)
532 if (SfxResId(STR_STYLE_FILTER_HIERARCHICAL
) == rBox
.get_active_text())
534 EnableHierarchical(true, m_aStyleList
);
538 EnableHierarchical(false, m_aStyleList
);
542 // Select-Handler for the Toolbox
543 void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry
, StyleList
&, bool bPreviewRefresh
)
545 assert((0 < nEntry
&& nEntry
<= MAX_FAMILIES
) || 0xffff == nEntry
);
546 if( nEntry
!= nActFamily
|| bPreviewRefresh
)
548 CheckItem(OString::number(nActFamily
), false);
550 m_aStyleList
.FamilySelect(nEntry
);
554 void SfxCommonTemplateDialog_Impl::ActionSelect(const OString
& rEntry
, StyleList
& rStyleList
)
556 if (rEntry
== "watercan")
558 const bool bOldState
= !IsCheckedItem(rEntry
);
561 // when a template is chosen.
562 if (!bOldState
&& m_aStyleListHasSelectedStyle
.Call(nullptr))
564 const OUString
aTemplName(rStyleList
.GetSelectedEntry());
565 Execute_Impl(SID_STYLE_WATERCAN
, aTemplName
, "",
566 static_cast<sal_uInt16
>(m_aStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
571 Execute_Impl(SID_STYLE_WATERCAN
, "", "", 0, rStyleList
);
574 CheckItem(rEntry
, bCheck
);
575 aBool
.SetValue(bCheck
);
576 SetWaterCanState(&aBool
);
578 else if (rEntry
== "new" || rEntry
== "newmenu")
580 m_aStyleListNewMenu
.Call(nullptr);
582 else if (rEntry
== "update")
584 Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE
,
586 static_cast<sal_uInt16
>(m_aStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
588 else if (rEntry
== "load")
589 SfxGetpApp()->GetDispatcher_Impl()->Execute(SID_TEMPLATE_LOAD
);
591 SAL_WARN("sfx", "not implemented: " << rEntry
);
594 static OUString
getModuleIdentifier( const Reference
< XModuleManager2
>& i_xModMgr
, SfxObjectShell
const * i_pObjSh
)
596 OSL_ENSURE( i_xModMgr
.is(), "getModuleIdentifier(): no XModuleManager" );
597 OSL_ENSURE( i_pObjSh
, "getModuleIdentifier(): no ObjectShell" );
599 OUString sIdentifier
;
603 sIdentifier
= i_xModMgr
->identify( i_pObjSh
->GetModel() );
605 catch ( css::frame::UnknownModuleException
& )
607 SAL_WARN("sfx", "getModuleIdentifier(): unknown module" );
611 TOOLS_WARN_EXCEPTION( "sfx", "getModuleIdentifier(): exception of XModuleManager::identify()" );
617 IMPL_LINK(SfxCommonTemplateDialog_Impl
, LoadFactoryStyleFilter_Hdl
, SfxObjectShell
const*, i_pObjSh
, sal_Int32
)
619 OSL_ENSURE( i_pObjSh
, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" );
621 ::comphelper::SequenceAsHashMap
aFactoryProps(
622 xModuleManager
->getByName( getModuleIdentifier( xModuleManager
, i_pObjSh
) ) );
623 sal_Int32 nFilter
= aFactoryProps
.getUnpackedValueOrDefault( "ooSetupFactoryStyleFilter", sal_Int32(-1) );
625 m_bWantHierarchical
= (nFilter
& 0x1000) != 0;
626 nFilter
&= ~0x1000; // clear it
631 void SfxCommonTemplateDialog_Impl::SaveFactoryStyleFilter( SfxObjectShell
const * i_pObjSh
, sal_Int32 i_nFilter
)
633 OSL_ENSURE( i_pObjSh
, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" );
634 Sequence
< PropertyValue
> lProps
{ comphelper::makePropertyValue(
635 "ooSetupFactoryStyleFilter", i_nFilter
| (m_bWantHierarchical
? 0x1000 : 0)) };
636 xModuleManager
->replaceByName( getModuleIdentifier( xModuleManager
, i_pObjSh
), makeAny( lProps
) );
639 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, SaveSelection_Hdl
, StyleList
&, SfxObjectShell
*)
641 SfxViewFrame
*const pViewFrame(pBindings
->GetDispatcher_Impl()->GetFrame());
642 SfxObjectShell
*const pDocShell(pViewFrame
->GetObjectShell());
645 pDocShell
->SetAutoStyleFilterIndex(nActFilter
);
646 SaveFactoryStyleFilter( pDocShell
, nActFilter
);
651 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, PreviewHdl
, weld::Toggleable
&, void)
653 std::shared_ptr
<comphelper::ConfigurationChanges
> batch( comphelper::ConfigurationChanges::create() );
654 bool bCustomPreview
= mxPreviewCheckbox
->get_active();
655 officecfg::Office::Common::StylesAndFormatting::Preview::set(bCustomPreview
, batch
);
658 m_aStyleList
.EnablePreview(bCustomPreview
);
660 FamilySelect(nActFamily
, m_aStyleList
, true);
663 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, UpdateStyleDependents_Hdl
, void*, void)
665 m_aStyleListUpdateStyleDependents
.Call(nullptr);
666 EnableItem("watercan", !bWaterDisabled
);
667 m_aStyleListEnableDelete
.Call(nullptr);
670 void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId
, bool bEnable
)
672 bool bDisable
= !bEnable
|| !IsSafeForWaterCan();
673 if (nId
== SID_STYLE_NEW_BY_EXAMPLE
)
675 bNewByExampleDisabled
= bDisable
;
676 m_aStyleList
.EnableNewByExample(bNewByExampleDisabled
);
677 EnableItem("new", bEnable
);
678 EnableItem("newmenu", bEnable
);
680 else if( nId
== SID_STYLE_UPDATE_BY_EXAMPLE
)
682 bUpdateByExampleDisabled
= bDisable
;
683 EnableItem("update", bEnable
);
687 SfxTemplateDialog_Impl::SfxTemplateDialog_Impl(SfxBindings
* pB
, SfxTemplatePanelControl
* pDlgWindow
)
688 : SfxCommonTemplateDialog_Impl(pB
, pDlgWindow
->get_container(), pDlgWindow
->get_builder())
689 , m_xActionTbL(pDlgWindow
->get_builder()->weld_toolbar("left"))
690 , m_xActionTbR(pDlgWindow
->get_builder()->weld_toolbar("right"))
691 , m_xToolMenu(pDlgWindow
->get_builder()->weld_menu("toolmenu"))
692 , m_nActionTbLVisible(0)
694 m_xActionTbR
->set_item_help_id("watercan", HID_TEMPLDLG_WATERCAN
);
695 // shown/hidden in SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
696 m_xActionTbR
->set_item_help_id("new", HID_TEMPLDLG_NEWBYEXAMPLE
);
697 m_xActionTbR
->set_item_help_id("newmenu", HID_TEMPLDLG_NEWBYEXAMPLE
);
698 m_xActionTbR
->set_item_menu("newmenu", m_xToolMenu
.get());
699 m_xToolMenu
->connect_activate(LINK(this, SfxTemplateDialog_Impl
, ToolMenuSelectHdl
));
700 m_xActionTbR
->set_item_help_id("update", HID_TEMPLDLG_UPDATEBYEXAMPLE
);
705 class ToolbarDropTarget final
: public DropTargetHelper
708 SfxTemplateDialog_Impl
& m_rParent
;
711 ToolbarDropTarget(SfxTemplateDialog_Impl
& rDialog
, weld::Toolbar
& rToolbar
)
712 : DropTargetHelper(rToolbar
.get_drop_target())
717 virtual sal_Int8
AcceptDrop(const AcceptDropEvent
& rEvt
) override
719 return m_rParent
.AcceptToolbarDrop(rEvt
, *this);
722 virtual sal_Int8
ExecuteDrop(const ExecuteDropEvent
& rEvt
) override
724 return m_rParent
.ExecuteDrop(rEvt
);
728 void SfxTemplateDialog_Impl::Initialize()
730 SfxCommonTemplateDialog_Impl::Initialize();
732 m_xActionTbL
->connect_clicked(LINK(this, SfxTemplateDialog_Impl
, ToolBoxLSelect
));
733 m_xActionTbR
->connect_clicked(LINK(this, SfxTemplateDialog_Impl
, ToolBoxRSelect
));
734 m_xActionTbL
->set_help_id(HID_TEMPLDLG_TOOLBOX_LEFT
);
736 m_xToolbarDropTargetHelper
.reset(new ToolbarDropTarget(*this, *m_xActionTbL
));
739 void SfxTemplateDialog_Impl::EnableFamilyItem(sal_uInt16 nId
, bool bEnable
)
741 m_xActionTbL
->set_item_sensitive(OString::number(nId
), bEnable
);
744 // Insert element into dropdown filter "Frame Styles", "List Styles", etc.
745 void SfxTemplateDialog_Impl::InsertFamilyItem(sal_uInt16 nId
, const SfxStyleFamilyItem
&rItem
)
748 switch( rItem
.GetFamily() )
750 case SfxStyleFamily::Char
: sHelpId
= ".uno:CharStyle"; break;
751 case SfxStyleFamily::Para
: sHelpId
= ".uno:ParaStyle"; break;
752 case SfxStyleFamily::Frame
: sHelpId
= ".uno:FrameStyle"; break;
753 case SfxStyleFamily::Page
: sHelpId
= ".uno:PageStyle"; break;
754 case SfxStyleFamily::Pseudo
: sHelpId
= ".uno:ListStyle"; break;
755 case SfxStyleFamily::Table
: sHelpId
= ".uno:TableStyle"; break;
756 default: OSL_FAIL("unknown StyleFamily"); break;
759 OString
sId(OString::number(nId
));
760 m_xActionTbL
->set_item_visible(sId
, true);
761 m_xActionTbL
->set_item_icon_name(sId
, rItem
.GetImage());
762 m_xActionTbL
->set_item_tooltip_text(sId
, rItem
.GetText());
763 m_xActionTbL
->set_item_help_id(sId
, sHelpId
);
764 ++m_nActionTbLVisible
;
767 void SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
769 m_xActionTbR
->set_item_visible("update", false);
770 m_xActionTbR
->set_item_visible("new", false);
771 m_xActionTbR
->set_item_visible("newmenu", true);
775 void SfxTemplateDialog_Impl::ClearFamilyList()
777 for (int i
= 0, nCount
= m_xActionTbL
->get_n_items(); i
< nCount
; ++i
)
778 m_xActionTbL
->set_item_visible(m_xActionTbL
->get_item_ident(i
), false);
782 SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl()
784 m_xToolbarDropTargetHelper
.reset();
785 m_xActionTbL
.reset();
786 m_xActionTbR
.reset();
789 void SfxTemplateDialog_Impl::EnableItem(const OString
& rMesId
, bool bCheck
)
791 if (rMesId
== "watercan" && !bCheck
&& IsCheckedItem("watercan"))
792 Execute_Impl(SID_STYLE_WATERCAN
, "", "", 0, m_aStyleList
);
793 m_xActionTbR
->set_item_sensitive(rMesId
, bCheck
);
796 void SfxTemplateDialog_Impl::CheckItem(const OString
&rMesId
, bool bCheck
)
798 if (rMesId
== "watercan")
801 m_xActionTbR
->set_item_active("watercan", bCheck
);
804 m_xActionTbL
->set_item_active(rMesId
, bCheck
);
807 bool SfxTemplateDialog_Impl::IsCheckedItem(const OString
& rMesId
)
809 if (rMesId
== "watercan")
810 return m_xActionTbR
->get_item_active("watercan");
811 return m_xActionTbL
->get_item_active(rMesId
);
814 IMPL_LINK( SfxTemplateDialog_Impl
, ToolBoxLSelect
, const OString
&, rEntry
, void)
816 FamilySelect(rEntry
.toUInt32(), m_aStyleList
);
819 IMPL_LINK(SfxTemplateDialog_Impl
, ToolBoxRSelect
, const OString
&, rEntry
, void)
821 if (rEntry
== "newmenu")
822 m_xActionTbR
->set_menu_item_active(rEntry
, !m_xActionTbR
->get_menu_item_active(rEntry
));
824 ActionSelect(rEntry
, m_aStyleList
);
827 void SfxTemplateDialog_Impl::FillToolMenu()
829 //create a popup menu in Writer
830 OUString
sTextDoc("com.sun.star.text.TextDocument");
832 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:StyleNewByExample", sTextDoc
);
833 OUString sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
834 m_xToolMenu
->append("new", sLabel
);
835 aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:StyleUpdateByExample", sTextDoc
);
836 sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
837 m_xToolMenu
->append("update", sLabel
);
838 m_xToolMenu
->append_separator("separator");
840 aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:LoadStyles", sTextDoc
);
841 sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
842 m_xToolMenu
->append("load", sLabel
);
845 IMPL_LINK(SfxTemplateDialog_Impl
, ToolMenuSelectHdl
, const OString
&, rMenuId
, void)
847 if (rMenuId
.isEmpty())
849 ActionSelect(rMenuId
, m_aStyleList
);
852 void SfxCommonTemplateDialog_Impl::SetFamily(SfxStyleFamily
const nFamily
)
854 sal_uInt16
const nId(SfxTemplate::SfxFamilyIdToNId(nFamily
));
855 assert((0 < nId
&& nId
<= MAX_FAMILIES
) || 0xffff == nId
);
856 if ( nId
!= nActFamily
)
858 m_aStyleListSetFamily
.Call(nId
);
863 IMPL_LINK(SfxCommonTemplateDialog_Impl
, UpdateFamily_Hdl
, StyleList
&, rStyleList
, void)
865 bWaterDisabled
= false;
866 bUpdateByExampleDisabled
= false;
868 if (IsCheckedItem("watercan") &&
869 // only if that area is allowed
870 rStyleList
.CurrentFamilyHasState())
872 Execute_Impl(SID_STYLE_APPLY
, rStyleList
.GetSelectedEntry(), OUString(),
873 static_cast<sal_uInt16
>(rStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
877 void SfxCommonTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
882 sal_Int8
SfxTemplateDialog_Impl::AcceptToolbarDrop(const AcceptDropEvent
& rEvt
, const DropTargetHelper
& rHelper
)
884 sal_Int8 nReturn
= DND_ACTION_NONE
;
886 // auto flip to the category under the mouse
887 int nIndex
= m_xActionTbL
->get_drop_index(rEvt
.maPosPixel
);
888 if (nIndex
>= m_nActionTbLVisible
)
889 nIndex
= m_nActionTbLVisible
- 1;
891 OString sIdent
= m_xActionTbL
->get_item_ident(nIndex
);
892 if (!sIdent
.isEmpty() && !m_xActionTbL
->get_item_active(sIdent
))
893 ToolBoxLSelect(sIdent
);
895 // special case: page styles are allowed to create new styles by example
896 // but not allowed to be created by drag and drop
897 if (sIdent
.toUInt32() != SfxTemplate::SfxFamilyIdToNId(SfxStyleFamily::Page
) &&
898 rHelper
.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
899 !bNewByExampleDisabled
)
901 nReturn
= DND_ACTION_COPY
;
906 void SfxCommonTemplateDialog_Impl::EnableEdit(bool b
, StyleList
* rStyleList
)
908 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
909 m_aStyleList
.Enableedit(b
);
911 void SfxCommonTemplateDialog_Impl::EnableDel(bool b
, const StyleList
* rStyleList
)
913 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
914 m_aStyleList
.Enabledel(b
);
916 void SfxCommonTemplateDialog_Impl::EnableNew(bool b
, const StyleList
* rStyleList
)
918 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
919 m_aStyleList
.Enablenew(b
);
921 void SfxCommonTemplateDialog_Impl::EnableHide(bool b
, const StyleList
* rStyleList
)
923 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
924 m_aStyleList
.Enablehide(b
);
926 void SfxCommonTemplateDialog_Impl::EnableShow(bool b
, const StyleList
* rStyleList
)
928 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
929 m_aStyleList
.Enableshow(b
);
931 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */