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 <vcl/commandinfoprovider.hxx>
23 #include <svl/intitem.hxx>
24 #include <svl/stritem.hxx>
25 #include <svl/style.hxx>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/propertyvalue.hxx>
28 #include <comphelper/sequenceashashmap.hxx>
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #include <com/sun/star/frame/ModuleManager.hpp>
31 #include <com/sun/star/frame/UnknownModuleException.hpp>
32 #include <officecfg/Office/Common.hxx>
34 #include <sal/log.hxx>
35 #include <osl/diagnose.h>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <sfx2/bindings.hxx>
40 #include <sfx2/templdlg.hxx>
41 #include <templdgi.hxx>
42 #include <sfx2/styfitem.hxx>
43 #include <sfx2/objsh.hxx>
44 #include <sfx2/tplpitem.hxx>
45 #include <sfx2/sfxresid.hxx>
46 #include <svl/itemset.hxx>
48 #include <sfx2/sfxsids.hrc>
49 #include <sfx2/strings.hrc>
51 #include <sfx2/viewfrm.hxx>
54 using namespace css::beans
;
55 using namespace css::frame
;
56 using namespace css::uno
;
58 class SfxCommonTemplateDialog_Impl::DeletionWatcher
60 typedef void (DeletionWatcher::* bool_type
)();
63 explicit DeletionWatcher(SfxCommonTemplateDialog_Impl
& rDialog
)
65 , m_pPrevious(m_pDialog
->impl_setDeletionWatcher(this))
72 m_pDialog
->impl_setDeletionWatcher(m_pPrevious
);
75 DeletionWatcher(const DeletionWatcher
&) = delete;
76 DeletionWatcher
& operator=(const DeletionWatcher
&) = delete;
78 // Signal that the dialog was deleted
83 m_pPrevious
->signal();
86 // Return true if the dialog was deleted
87 operator bool_type() const
89 return m_pDialog
? nullptr : &DeletionWatcher::signal
;
93 SfxCommonTemplateDialog_Impl
* m_pDialog
;
94 DeletionWatcher
*const m_pPrevious
; /// let's add more epicycles!
97 sal_Int8
SfxCommonTemplateDialog_Impl::ExecuteDrop(const ExecuteDropEvent
& rEvt
)
99 // handle drop of content into the treeview to create a new style
100 m_aStyleListExecuteDrop
.Call(rEvt
);
101 return DND_ACTION_NONE
;
104 IMPL_LINK(SfxCommonTemplateDialog_Impl
, OnAsyncExecuteDrop
, void*, pStyleList
, void)
106 StyleList
* pStyle
= static_cast<StyleList
*>(pStyleList
);
107 if (pStyle
== &m_aStyleList
)
108 ActionSelect(u
"new"_ustr
, m_aStyleList
);
111 namespace SfxTemplate
113 // converts from SFX_STYLE_FAMILY Ids to 1-6
114 static sal_uInt16
SfxFamilyIdToNId(SfxStyleFamily nFamily
)
118 case SfxStyleFamily::Char
: return 1;
119 case SfxStyleFamily::Para
: return 2;
120 case SfxStyleFamily::Frame
: return 3;
121 case SfxStyleFamily::Page
: return 4;
122 case SfxStyleFamily::Pseudo
: return 5;
123 case SfxStyleFamily::Table
: return 6;
124 default: return 0xffff;
127 // converts from 1-6 to SFX_STYLE_FAMILY Ids
128 static SfxStyleFamily
NIdToSfxFamilyId(sal_uInt16 nId
)
133 return SfxStyleFamily::Char
;
135 return SfxStyleFamily::Para
;
137 return SfxStyleFamily::Frame
;
139 return SfxStyleFamily::Page
;
141 return SfxStyleFamily::Pseudo
;
143 return SfxStyleFamily::Table
;
145 return SfxStyleFamily::All
;
150 SfxTemplatePanelControl::SfxTemplatePanelControl(SfxBindings
* pBindings
, weld::Widget
* pParent
)
151 : PanelLayout(pParent
, u
"TemplatePanel"_ustr
, u
"sfx/ui/templatepanel.ui"_ustr
)
152 , m_aSpotlightParaStyles(SID_SPOTLIGHT_PARASTYLES
, *pBindings
, *this)
153 , m_aSpotlightCharStyles(SID_SPOTLIGHT_CHARSTYLES
, *pBindings
, *this)
154 , pImpl(new SfxTemplateDialog_Impl(pBindings
, this))
156 OSL_ASSERT(pBindings
!=nullptr);
159 SfxTemplatePanelControl::~SfxTemplatePanelControl()
161 m_aSpotlightParaStyles
.dispose();
162 m_aSpotlightCharStyles
.dispose();
165 void SfxTemplatePanelControl::NotifyItemUpdate(const sal_uInt16 nSId
, const SfxItemState eState
,
166 const SfxPoolItem
* pState
)
170 case SID_SPOTLIGHT_PARASTYLES
:
171 if (eState
>= SfxItemState::DEFAULT
)
173 const SfxBoolItem
* pItem
= dynamic_cast<const SfxBoolItem
*>(pState
);
176 bool bValue
= pItem
->GetValue();
177 if (bValue
|| (!bValue
&& pImpl
->m_aStyleList
.IsHighlightParaStyles()))
179 pImpl
->m_aStyleList
.SetHighlightParaStyles(bValue
);
180 pImpl
->FamilySelect(SfxTemplate::SfxFamilyIdToNId(SfxStyleFamily::Para
),
181 pImpl
->m_aStyleList
, true);
186 case SID_SPOTLIGHT_CHARSTYLES
:
187 if (eState
>= SfxItemState::DEFAULT
)
189 const SfxBoolItem
* pItem
= dynamic_cast<const SfxBoolItem
*>(pState
);
192 bool bValue
= pItem
->GetValue();
193 if (bValue
|| (!bValue
&& pImpl
->m_aStyleList
.IsHighlightCharStyles()))
195 pImpl
->m_aStyleList
.SetHighlightCharStyles(bValue
);
196 pImpl
->FamilySelect(SfxTemplate::SfxFamilyIdToNId(SfxStyleFamily::Char
),
197 pImpl
->m_aStyleList
, true);
205 void SfxCommonTemplateDialog_Impl::connect_stylelist_execute_drop(
206 const Link
<const ExecuteDropEvent
&, sal_Int8
>& rLink
)
208 m_aStyleListExecuteDrop
= rLink
;
211 void SfxCommonTemplateDialog_Impl::connect_stylelist_has_selected_style(const Link
<void*, bool>& rLink
)
213 m_aStyleListHasSelectedStyle
= rLink
;
216 void SfxCommonTemplateDialog_Impl::connect_stylelist_update_style_dependents(const Link
<void*, void>& rLink
)
218 m_aStyleListUpdateStyleDependents
= rLink
;
221 void SfxCommonTemplateDialog_Impl::connect_stylelist_enable_tree_drag(const Link
<bool, void> rLink
)
223 m_aStyleListEnableTreeDrag
= rLink
;
226 void SfxCommonTemplateDialog_Impl::connect_stylelist_enable_delete(const Link
<void*, void> rLink
)
228 m_aStyleListEnableDelete
= rLink
;
231 void SfxCommonTemplateDialog_Impl::connect_stylelist_set_water_can_state(
232 const Link
<const SfxBoolItem
*, void> rLink
)
234 m_aStyleListSetWaterCanState
= rLink
;
239 SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl(SfxBindings
* pB
, weld::Container
* pC
, weld::Builder
* pBuilder
)
241 , xModuleManager(frame::ModuleManager::create(::comphelper::getProcessComponentContext()))
242 , m_pDeletionWatcher(nullptr)
243 , m_aStyleList(pBuilder
, pB
, this, pC
, u
"treeview"_ustr
, u
"flatview"_ustr
)
244 , mxPreviewCheckbox(pBuilder
->weld_check_button(u
"showpreview"_ustr
))
245 , mxHighlightCheckbox(pBuilder
->weld_check_button(u
"highlightstyles"_ustr
))
246 , mxFilterLb(pBuilder
->weld_combo_box(u
"filter"_ustr
))
251 , bWaterDisabled(false)
252 , bNewByExampleDisabled(false)
253 , bUpdateByExampleDisabled(false)
254 , m_bWantHierarchical(false)
256 mxFilterLb
->set_help_id(HID_TEMPLATE_FILTER
);
257 mxPreviewCheckbox
->set_active(officecfg::Office::Common::StylesAndFormatting::Preview::get());
260 void SfxTemplateDialog_Impl::EnableEdit(bool bEnable
, StyleList
* rStyleList
)
262 if(rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
263 SfxCommonTemplateDialog_Impl::EnableEdit( bEnable
, &m_aStyleList
);
264 if( !bEnable
|| !bUpdateByExampleDisabled
)
265 EnableItem(u
"update"_ustr
, bEnable
);
268 IMPL_LINK(SfxCommonTemplateDialog_Impl
, ReadResource_Hdl
, StyleList
&, rStyleList
, void)
272 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
273 SfxObjectShell
* pCurObjShell
= pViewFrame
->GetObjectShell();
276 nActFilter
= static_cast<sal_uInt16
>(LoadFactoryStyleFilter_Hdl(pCurObjShell
));
277 if (0xffff == nActFilter
)
279 nActFilter
= pCurObjShell
->GetAutoStyleFilterIndex();
283 size_t nCount
= m_aStyleListReadResource
.Call(nullptr);
285 // Insert in the reverse order of occurrence in the Style Families. This is for
286 // the toolbar of the designer. The list box of the catalog respects the
287 // correct order by itself.
289 // Sequences: the order of Resource = the order of Toolbar for example list box.
290 // Order of ascending SIDs: Low SIDs are displayed first when templates of
291 // several families are active.
293 // in the Writer the UpdateStyleByExample Toolbox button is removed and
294 // the NewStyle button gets a PopupMenu
296 ReplaceUpdateButtonByMenu();
301 const SfxStyleFamilyItem
&rItem
= rStyleList
.GetFamilyItemByIndex( nCount
);
302 sal_uInt16 nId
= SfxTemplate::SfxFamilyIdToNId( rItem
.GetFamily() );
303 InsertFamilyItem(nId
, rItem
);
307 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, ClearResource_Hdl
, void*, void)
310 m_aStyleListClear
.Call(nullptr);
313 SfxCommonTemplateDialog_Impl::DeletionWatcher
*
314 SfxCommonTemplateDialog_Impl::impl_setDeletionWatcher(
315 DeletionWatcher
*const pNewWatcher
)
317 DeletionWatcher
*const pRet(m_pDeletionWatcher
);
318 m_pDeletionWatcher
= pNewWatcher
;
322 void SfxCommonTemplateDialog_Impl::Initialize()
324 m_aStyleList
.connect_ReadResource(LINK(this, SfxCommonTemplateDialog_Impl
, ReadResource_Hdl
));
325 m_aStyleList
.connect_ClearResource(LINK(this, SfxCommonTemplateDialog_Impl
, ClearResource_Hdl
));
326 m_aStyleList
.connect_LoadFactoryStyleFilter(LINK(this, SfxCommonTemplateDialog_Impl
, LoadFactoryStyleFilter_Hdl
));
327 m_aStyleList
.connect_SaveSelection(LINK(this, SfxCommonTemplateDialog_Impl
, SaveSelection_Hdl
));
328 m_aStyleList
.connect_UpdateFamily(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateFamily_Hdl
));
329 m_aStyleList
.connect_UpdateStyles(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateStyles_Hdl
));
331 mxFilterLb
->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl
, FilterSelectHdl
));
332 mxPreviewCheckbox
->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl
, PreviewHdl
));
333 mxHighlightCheckbox
->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl
, HighlightHdl
));
335 m_aStyleList
.Initialize();
337 SfxStyleFamily eFam
= SfxTemplate::NIdToSfxFamilyId(nActFamily
);
338 mxHighlightCheckbox
->set_visible(m_aStyleList
.HasStylesHighlighterFeature()
339 && (eFam
== SfxStyleFamily::Para
|| eFam
== SfxStyleFamily::Char
));
342 IMPL_LINK(SfxCommonTemplateDialog_Impl
, UpdateStyles_Hdl
, StyleFlags
, nFlags
, void)
344 const SfxStyleFamilyItem
* pItem
= m_aStyleList
.GetFamilyItem();
346 if (nFlags
& StyleFlags::UpdateFamily
) // Update view type list (Hierarchical, All, etc.
348 CheckItem(OUString::number(nActFamily
)); // check Button in Toolbox
350 mxFilterLb
->freeze();
353 //insert hierarchical at the beginning
354 mxFilterLb
->append(OUString::number(static_cast<int>(SfxStyleSearchBits::All
)),
355 SfxResId(STR_STYLE_FILTER_HIERARCHICAL
));
356 const SfxStyleFilter
& rFilter
= pItem
->GetFilterList();
357 for (const SfxFilterTuple
& i
: rFilter
)
358 mxFilterLb
->append(OUString::number(static_cast<int>(i
.nFlags
)), i
.aName
);
361 if (nActFilter
< mxFilterLb
->get_count() - 1)
362 mxFilterLb
->set_active(nActFilter
+ 1);
366 m_aStyleList
.FilterSelect(nActFilter
, false);
367 mxFilterLb
->set_active(1);
370 // if the tree view again, select family hierarchy
371 if (m_aStyleList
.IsTreeView() || m_bWantHierarchical
)
373 mxFilterLb
->set_active_text(SfxResId(STR_STYLE_FILTER_HIERARCHICAL
));
374 EnableHierarchical(true, m_aStyleList
);
379 if (nActFilter
< mxFilterLb
->get_count() - 1)
380 mxFilterLb
->set_active(nActFilter
+ 1);
384 m_aStyleList
.FilterSelect(nActFilter
, false);
385 mxFilterLb
->set_active(1);
389 if (!(nFlags
& StyleFlags::UpdateFamilyList
))
392 EnableItem(u
"watercan"_ustr
, false);
395 SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl()
397 // Set the UNO's in an 'off' state. FN_PARAM_1 is used to prevent the sidebar from trying to
398 // reopen while it is being closed here.
399 if (m_aStyleList
.IsHighlightParaStyles())
401 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
402 SfxFlagItem
aParam(FN_PARAM_1
);
403 rDispatcher
.ExecuteList(SID_SPOTLIGHT_PARASTYLES
, SfxCallMode::SYNCHRON
, { &aParam
});
405 if (m_aStyleList
.IsHighlightCharStyles())
407 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
408 SfxFlagItem
aParam(FN_PARAM_1
);
409 rDispatcher
.ExecuteList(SID_SPOTLIGHT_CHARSTYLES
, SfxCallMode::SYNCHRON
, { &aParam
});
413 Execute_Impl(SID_STYLE_WATERCAN
, u
""_ustr
, u
""_ustr
, 0, m_aStyleList
);
414 m_aStyleListClear
.Call(nullptr);
415 m_aStyleListCleanup
.Call(nullptr);
416 if ( m_pDeletionWatcher
)
417 m_pDeletionWatcher
->signal();
418 mxPreviewCheckbox
.reset();
423 * Is it safe to show the water-can / fill icon. If we've a
424 * hierarchical widget - we have only single select, otherwise
425 * we need to check if we have a multi-selection. We either have
426 * a mxTreeBox showing or an mxFmtLb (which we hide when not shown)
428 bool SfxCommonTemplateDialog_Impl::IsSafeForWaterCan() const
430 return m_aStyleListWaterCan
.Call(nullptr);
433 void SfxCommonTemplateDialog_Impl::SelectStyle(const OUString
&rStr
, bool bIsCallback
, StyleList
& rStyleList
)
435 rStyleList
.SelectStyle(rStr
, bIsCallback
);
437 bWaterDisabled
= !IsSafeForWaterCan();
439 // tdf#134598 call UpdateStyleDependents to update watercan
440 UpdateStyleDependents_Hdl(nullptr);
443 void SfxCommonTemplateDialog_Impl::EnableTreeDrag(bool bEnable
)
445 m_aStyleListEnableTreeDrag
.Call(bEnable
);
448 // Updated display: Watering the house
449 void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem
*pItem
)
451 bWaterDisabled
= (pItem
== nullptr);
454 //make sure the watercan is only activated when there is (only) one selection
455 bWaterDisabled
= !IsSafeForWaterCan();
457 if(pItem
&& !bWaterDisabled
)
459 CheckItem(u
"watercan"_ustr
, pItem
->GetValue());
460 EnableItem(u
"watercan"_ustr
);
465 EnableItem(u
"watercan"_ustr
);
467 EnableItem(u
"watercan"_ustr
, false);
470 // Ignore while in watercan mode statusupdates
472 m_aStyleListSetWaterCanState
.Call(pItem
);
475 // Item with the status of a Family is copied and noted
476 // (is updated when all states have also been updated.)
477 // See also: <SfxBindings::AddDoneHdl(const Link &)>
478 void SfxCommonTemplateDialog_Impl::SetFamilyState( sal_uInt16 nSlotId
, const SfxTemplateItem
* pItem
)
480 m_aStyleList
.SetFamilyState(nSlotId
, pItem
);
484 // Internal: Perform functions through the Dispatcher
485 bool SfxCommonTemplateDialog_Impl::Execute_Impl(
486 sal_uInt16 nId
, const OUString
&rStr
, const OUString
& rRefStr
, sal_uInt16 nFamily
, StyleList
& rStyleList
,
487 SfxStyleSearchBits nMask
, sal_uInt16
*pIdx
, const sal_uInt16
* pModifier
)
489 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
490 SfxStringItem
aItem(nId
, rStr
);
491 SfxUInt16Item
aFamily(SID_STYLE_FAMILY
, nFamily
);
492 SfxUInt16Item
aMask( SID_STYLE_MASK
, static_cast<sal_uInt16
>(nMask
) );
493 SfxStringItem
aUpdName(SID_STYLE_UPD_BY_EX_NAME
, rStr
);
494 SfxStringItem
aRefName( SID_STYLE_REFERENCE
, rRefStr
);
495 const SfxPoolItem
* pItems
[ 6 ];
496 sal_uInt16 nCount
= 0;
497 if( !rStr
.isEmpty() )
498 pItems
[ nCount
++ ] = &aItem
;
499 pItems
[ nCount
++ ] = &aFamily
;
500 if( nMask
!= SfxStyleSearchBits::Auto
)
501 pItems
[ nCount
++ ] = &aMask
;
502 if(SID_STYLE_UPDATE_BY_EXAMPLE
== nId
)
504 // Special solution for Numbering update in Writer
505 const OUString
aTemplName(rStyleList
.GetSelectedEntry());
506 aUpdName
.SetValue(aTemplName
);
507 pItems
[ nCount
++ ] = &aUpdName
;
510 if ( !rRefStr
.isEmpty() )
511 pItems
[ nCount
++ ] = &aRefName
;
513 pItems
[ nCount
++ ] = nullptr;
515 DeletionWatcher
aDeleted(*this);
516 sal_uInt16 nModi
= pModifier
? *pModifier
: 0;
517 const SfxPoolItemHolder
aResult(rDispatcher
.Execute(
518 nId
, SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
521 // Dialog can be destroyed while in Execute() because started
522 // subdialogs are not modal to it (#i97888#).
523 if (!aResult
|| aDeleted
)
526 if ((nId
== SID_STYLE_NEW
|| SID_STYLE_EDIT
== nId
)
527 && rStyleList
.EnableExecute())
529 const SfxUInt16Item
* pFilterItem(dynamic_cast<const SfxUInt16Item
*>(aResult
.getItem()));
531 SfxStyleSearchBits nFilterFlags
= static_cast<SfxStyleSearchBits
>(pFilterItem
->GetValue()) & ~SfxStyleSearchBits::UserDefined
;
532 if(nFilterFlags
== SfxStyleSearchBits::Auto
) // User Template?
533 nFilterFlags
= static_cast<SfxStyleSearchBits
>(pFilterItem
->GetValue());
534 const SfxStyleFamilyItem
*pFamilyItem
= rStyleList
.GetFamilyItem();
535 const size_t nFilterCount
= pFamilyItem
->GetFilterList().size();
537 for ( size_t i
= 0; i
< nFilterCount
; ++i
)
539 const SfxFilterTuple
&rTupel
= pFamilyItem
->GetFilterList()[ i
];
541 if ( ( rTupel
.nFlags
& nFilterFlags
) == nFilterFlags
&& pIdx
)
549 // Handler Listbox of Filter
550 void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable
, StyleList
& rStyleList
)
552 OUString aSelectedEntry
= rStyleList
.GetSelectedEntry();
555 if (!rStyleList
.IsHierarchical())
558 m_bWantHierarchical
= true;
559 SaveSelection_Hdl(rStyleList
); // fdo#61429 store "hierarchical"
560 m_aStyleList
.SetHierarchical();
565 m_aStyleList
.SetFilterControlsHandle();
566 // If bHierarchical, then the family can have changed
567 // minus one since hierarchical is inserted at the start
568 m_bWantHierarchical
= false; // before FilterSelect
569 FilterSelect(mxFilterLb
->get_active() - 1);
571 SelectStyle(aSelectedEntry
, false, rStyleList
);
574 // Other filters; can be switched by the users or as a result of new or
575 // editing, if the current document has been assigned a different filter.
576 void SfxCommonTemplateDialog_Impl::FilterSelect(
577 sal_uInt16 nEntry
// Idx of the new Filters
581 m_aStyleList
.FilterSelect(nActFilter
, true);
584 void SfxCommonTemplateDialog_Impl::IsUpdate(StyleList
&)
586 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
587 SfxObjectShell
* pDocShell
= pViewFrame
->GetObjectShell();
588 nActFilter
= static_cast<sal_uInt16
>(LoadFactoryStyleFilter_Hdl(pDocShell
));
589 if (0xffff == nActFilter
)
591 nActFilter
= pDocShell
->GetAutoStyleFilterIndex();
595 IMPL_LINK(SfxCommonTemplateDialog_Impl
, FilterSelectHdl
, weld::ComboBox
&, rBox
, void)
597 if (SfxResId(STR_STYLE_FILTER_HIERARCHICAL
) == rBox
.get_active_text())
599 EnableHierarchical(true, m_aStyleList
);
603 EnableHierarchical(false, m_aStyleList
);
607 // Select-Handler for the Toolbox
608 void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry
, StyleList
&, bool bRefresh
)
610 assert((0 < nEntry
&& nEntry
<= MAX_FAMILIES
) || 0xffff == nEntry
);
611 if( nEntry
!= nActFamily
|| bRefresh
)
613 CheckItem(OUString::number(nActFamily
), false);
615 m_aStyleList
.FamilySelect(nEntry
, bRefresh
);
617 SfxStyleFamily eFam
= SfxTemplate::NIdToSfxFamilyId(nActFamily
);
618 mxHighlightCheckbox
->set_visible(m_aStyleList
.HasStylesHighlighterFeature()
619 && (eFam
== SfxStyleFamily::Para
|| eFam
== SfxStyleFamily::Char
));
620 if (mxHighlightCheckbox
->is_visible())
622 bool bActive
= false;
623 if (eFam
== SfxStyleFamily::Para
)
624 bActive
= m_aStyleList
.IsHighlightParaStyles();
625 else if (eFam
== SfxStyleFamily::Char
)
626 bActive
= m_aStyleList
.IsHighlightCharStyles();
627 mxHighlightCheckbox
->set_active(bActive
);
632 void SfxCommonTemplateDialog_Impl::ActionSelect(const OUString
& rEntry
, StyleList
& rStyleList
)
634 if (rEntry
== "watercan")
636 const bool bOldState
= !IsCheckedItem(rEntry
);
639 // when a template is chosen.
640 if (!bOldState
&& m_aStyleListHasSelectedStyle
.Call(nullptr))
642 const OUString
aTemplName(rStyleList
.GetSelectedEntry());
643 Execute_Impl(SID_STYLE_WATERCAN
, aTemplName
, u
""_ustr
,
644 static_cast<sal_uInt16
>(m_aStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
649 Execute_Impl(SID_STYLE_WATERCAN
, u
""_ustr
, u
""_ustr
, 0, rStyleList
);
652 CheckItem(rEntry
, bCheck
);
653 aBool
.SetValue(bCheck
);
654 SetWaterCanState(&aBool
);
656 else if (rEntry
== "new" || rEntry
== "newmenu")
658 m_aStyleListNewMenu
.Call(nullptr);
660 else if (rEntry
== "update")
662 Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE
,
664 static_cast<sal_uInt16
>(m_aStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
666 else if (rEntry
== "load")
667 SfxGetpApp()->GetDispatcher_Impl()->Execute(SID_TEMPLATE_LOAD
);
669 SAL_WARN("sfx", "not implemented: " << rEntry
);
672 static OUString
getModuleIdentifier( const Reference
< XModuleManager2
>& i_xModMgr
, SfxObjectShell
const * i_pObjSh
)
674 assert(i_xModMgr
.is() && "getModuleIdentifier(): no XModuleManager");
675 assert(i_pObjSh
&& "getModuleIdentifier(): no ObjectShell");
677 OUString sIdentifier
;
681 sIdentifier
= i_xModMgr
->identify( i_pObjSh
->GetModel() );
683 catch ( css::frame::UnknownModuleException
& )
685 SAL_WARN("sfx", "getModuleIdentifier(): unknown module" );
689 TOOLS_WARN_EXCEPTION( "sfx", "getModuleIdentifier(): exception of XModuleManager::identify()" );
695 IMPL_LINK(SfxCommonTemplateDialog_Impl
, LoadFactoryStyleFilter_Hdl
, SfxObjectShell
const*, i_pObjSh
, sal_Int32
)
697 OSL_ENSURE( i_pObjSh
, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" );
699 ::comphelper::SequenceAsHashMap
aFactoryProps(
700 xModuleManager
->getByName( getModuleIdentifier( xModuleManager
, i_pObjSh
) ) );
701 sal_Int32 nFilter
= aFactoryProps
.getUnpackedValueOrDefault( u
"ooSetupFactoryStyleFilter"_ustr
, sal_Int32(-1) );
703 m_bWantHierarchical
= (nFilter
& 0x1000) != 0;
704 nFilter
&= ~0x1000; // clear it
709 void SfxCommonTemplateDialog_Impl::SaveFactoryStyleFilter( SfxObjectShell
const * i_pObjSh
, sal_Int32 i_nFilter
)
711 OSL_ENSURE( i_pObjSh
, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" );
712 Sequence
< PropertyValue
> lProps
{ comphelper::makePropertyValue(
713 u
"ooSetupFactoryStyleFilter"_ustr
, i_nFilter
| (m_bWantHierarchical
? 0x1000 : 0)) };
714 xModuleManager
->replaceByName( getModuleIdentifier( xModuleManager
, i_pObjSh
), Any( lProps
) );
717 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, SaveSelection_Hdl
, StyleList
&, SfxObjectShell
*)
719 SfxViewFrame
*const pViewFrame(pBindings
->GetDispatcher_Impl()->GetFrame());
720 SfxObjectShell
*const pDocShell(pViewFrame
->GetObjectShell());
723 pDocShell
->SetAutoStyleFilterIndex(nActFilter
);
724 SaveFactoryStyleFilter( pDocShell
, nActFilter
);
729 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, PreviewHdl
, weld::Toggleable
&, void)
731 std::shared_ptr
<comphelper::ConfigurationChanges
> batch( comphelper::ConfigurationChanges::create() );
732 bool bCustomPreview
= mxPreviewCheckbox
->get_active();
733 officecfg::Office::Common::StylesAndFormatting::Preview::set(bCustomPreview
, batch
);
736 FamilySelect(nActFamily
, m_aStyleList
, true);
739 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, HighlightHdl
, weld::Toggleable
&, void)
741 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
742 SfxStyleFamily eFam
= SfxTemplate::NIdToSfxFamilyId(nActFamily
);
743 if (eFam
== SfxStyleFamily::Para
)
744 rDispatcher
.Execute(SID_SPOTLIGHT_PARASTYLES
, SfxCallMode::SYNCHRON
);
745 else if (eFam
== SfxStyleFamily::Char
)
746 rDispatcher
.Execute(SID_SPOTLIGHT_CHARSTYLES
, SfxCallMode::SYNCHRON
);
749 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, UpdateStyleDependents_Hdl
, void*, void)
751 m_aStyleListUpdateStyleDependents
.Call(nullptr);
752 EnableItem(u
"watercan"_ustr
, !bWaterDisabled
);
753 m_aStyleListEnableDelete
.Call(nullptr);
756 void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId
, bool bEnable
)
758 bool bDisable
= !bEnable
|| !IsSafeForWaterCan();
759 if (nId
== SID_STYLE_NEW_BY_EXAMPLE
)
761 bNewByExampleDisabled
= bDisable
;
762 m_aStyleList
.EnableNewByExample(bNewByExampleDisabled
);
763 EnableItem(u
"new"_ustr
, bEnable
);
764 EnableItem(u
"newmenu"_ustr
, bEnable
);
766 else if( nId
== SID_STYLE_UPDATE_BY_EXAMPLE
)
768 bUpdateByExampleDisabled
= bDisable
;
769 EnableItem(u
"update"_ustr
, bEnable
);
773 class ToolbarDropTarget final
: public DropTargetHelper
776 SfxTemplateDialog_Impl
& m_rParent
;
779 ToolbarDropTarget(SfxTemplateDialog_Impl
& rDialog
, weld::Toolbar
& rToolbar
)
780 : DropTargetHelper(rToolbar
.get_drop_target())
785 virtual sal_Int8
AcceptDrop(const AcceptDropEvent
& rEvt
) override
787 return m_rParent
.AcceptToolbarDrop(rEvt
, *this);
790 virtual sal_Int8
ExecuteDrop(const ExecuteDropEvent
& rEvt
) override
792 return m_rParent
.ExecuteDrop(rEvt
);
796 SfxTemplateDialog_Impl::SfxTemplateDialog_Impl(SfxBindings
* pB
, SfxTemplatePanelControl
* pDlgWindow
)
797 : SfxCommonTemplateDialog_Impl(pB
, pDlgWindow
->get_container(), pDlgWindow
->get_builder())
798 , m_xActionTbL(pDlgWindow
->get_builder()->weld_toolbar(u
"left"_ustr
))
799 , m_xActionTbR(pDlgWindow
->get_builder()->weld_toolbar(u
"right"_ustr
))
800 , m_xToolMenu(pDlgWindow
->get_builder()->weld_menu(u
"toolmenu"_ustr
))
801 , m_nActionTbLVisible(0)
803 m_xActionTbR
->set_item_help_id(u
"watercan"_ustr
, HID_TEMPLDLG_WATERCAN
);
804 // shown/hidden in SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
805 m_xActionTbR
->set_item_help_id(u
"new"_ustr
, HID_TEMPLDLG_NEWBYEXAMPLE
);
806 m_xActionTbR
->set_item_help_id(u
"newmenu"_ustr
, HID_TEMPLDLG_NEWBYEXAMPLE
);
807 m_xActionTbR
->set_item_menu(u
"newmenu"_ustr
, m_xToolMenu
.get());
808 m_xToolMenu
->connect_activate(LINK(this, SfxTemplateDialog_Impl
, ToolMenuSelectHdl
));
809 m_xActionTbR
->set_item_help_id(u
"update"_ustr
, HID_TEMPLDLG_UPDATEBYEXAMPLE
);
814 void SfxTemplateDialog_Impl::Initialize()
816 SfxCommonTemplateDialog_Impl::Initialize();
818 m_xActionTbL
->connect_clicked(LINK(this, SfxTemplateDialog_Impl
, ToolBoxLSelect
));
819 m_xActionTbR
->connect_clicked(LINK(this, SfxTemplateDialog_Impl
, ToolBoxRSelect
));
820 m_xActionTbL
->set_help_id(HID_TEMPLDLG_TOOLBOX_LEFT
);
822 m_xToolbarDropTargetHelper
.reset(new ToolbarDropTarget(*this, *m_xActionTbL
));
825 void SfxTemplateDialog_Impl::EnableFamilyItem(sal_uInt16 nId
, bool bEnable
)
827 m_xActionTbL
->set_item_sensitive(OUString::number(nId
), bEnable
);
830 // Insert element into dropdown filter "Frame Styles", "List Styles", etc.
831 void SfxTemplateDialog_Impl::InsertFamilyItem(sal_uInt16 nId
, const SfxStyleFamilyItem
&rItem
)
834 switch( rItem
.GetFamily() )
836 case SfxStyleFamily::Char
: sHelpId
= ".uno:CharStyle"; break;
837 case SfxStyleFamily::Para
: sHelpId
= ".uno:ParaStyle"; break;
838 case SfxStyleFamily::Frame
: sHelpId
= ".uno:FrameStyle"; break;
839 case SfxStyleFamily::Page
: sHelpId
= ".uno:PageStyle"; break;
840 case SfxStyleFamily::Pseudo
: sHelpId
= ".uno:ListStyle"; break;
841 case SfxStyleFamily::Table
: sHelpId
= ".uno:TableStyle"; break;
842 default: OSL_FAIL("unknown StyleFamily"); break;
845 OUString
sId(OUString::number(nId
));
846 m_xActionTbL
->set_item_visible(sId
, true);
847 m_xActionTbL
->set_item_icon_name(sId
, rItem
.GetImage());
848 m_xActionTbL
->set_item_tooltip_text(sId
, rItem
.GetText());
849 m_xActionTbL
->set_item_help_id(sId
, sHelpId
);
850 ++m_nActionTbLVisible
;
853 void SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
855 m_xActionTbR
->set_item_visible(u
"update"_ustr
, false);
856 m_xActionTbR
->set_item_visible(u
"new"_ustr
, false);
857 m_xActionTbR
->set_item_visible(u
"newmenu"_ustr
, true);
861 void SfxTemplateDialog_Impl::ClearFamilyList()
863 for (int i
= 0, nCount
= m_xActionTbL
->get_n_items(); i
< nCount
; ++i
)
864 m_xActionTbL
->set_item_visible(m_xActionTbL
->get_item_ident(i
), false);
868 SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl()
870 m_xToolbarDropTargetHelper
.reset();
871 m_xActionTbL
.reset();
872 m_xActionTbR
.reset();
875 void SfxTemplateDialog_Impl::EnableItem(const OUString
& rMesId
, bool bCheck
)
877 if (rMesId
== "watercan" && !bCheck
&& IsCheckedItem(u
"watercan"_ustr
))
878 Execute_Impl(SID_STYLE_WATERCAN
, u
""_ustr
, u
""_ustr
, 0, m_aStyleList
);
879 m_xActionTbR
->set_item_sensitive(rMesId
, bCheck
);
882 void SfxTemplateDialog_Impl::CheckItem(const OUString
&rMesId
, bool bCheck
)
884 if (rMesId
== "watercan")
887 m_xActionTbR
->set_item_active(u
"watercan"_ustr
, bCheck
);
890 m_xActionTbL
->set_item_active(rMesId
, bCheck
);
893 bool SfxTemplateDialog_Impl::IsCheckedItem(const OUString
& rMesId
)
895 if (rMesId
== "watercan")
896 return m_xActionTbR
->get_item_active(u
"watercan"_ustr
);
897 return m_xActionTbL
->get_item_active(rMesId
);
900 IMPL_LINK( SfxTemplateDialog_Impl
, ToolBoxLSelect
, const OUString
&, rEntry
, void)
902 FamilySelect(rEntry
.toUInt32(), m_aStyleList
);
905 IMPL_LINK(SfxTemplateDialog_Impl
, ToolBoxRSelect
, const OUString
&, rEntry
, void)
907 if (rEntry
== "newmenu")
908 m_xActionTbR
->set_menu_item_active(rEntry
, !m_xActionTbR
->get_menu_item_active(rEntry
));
910 ActionSelect(rEntry
, m_aStyleList
);
913 void SfxTemplateDialog_Impl::FillToolMenu()
915 //create a popup menu in Writer
916 OUString
sTextDoc(u
"com.sun.star.text.TextDocument"_ustr
);
918 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(u
".uno:StyleNewByExample"_ustr
, sTextDoc
);
919 OUString sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
920 m_xToolMenu
->append(u
"new"_ustr
, sLabel
);
921 aProperties
= vcl::CommandInfoProvider::GetCommandProperties(u
".uno:StyleUpdateByExample"_ustr
, sTextDoc
);
922 sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
923 m_xToolMenu
->append(u
"update"_ustr
, sLabel
);
924 m_xToolMenu
->append_separator(u
"separator"_ustr
);
926 aProperties
= vcl::CommandInfoProvider::GetCommandProperties(u
".uno:LoadStyles"_ustr
, sTextDoc
);
927 sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
928 m_xToolMenu
->append(u
"load"_ustr
, sLabel
);
931 IMPL_LINK(SfxTemplateDialog_Impl
, ToolMenuSelectHdl
, const OUString
&, rMenuId
, void)
933 if (rMenuId
.isEmpty())
935 ActionSelect(rMenuId
, m_aStyleList
);
938 void SfxCommonTemplateDialog_Impl::SetFamily(SfxStyleFamily
const nFamily
)
940 sal_uInt16
const nId(SfxTemplate::SfxFamilyIdToNId(nFamily
));
941 assert((0 < nId
&& nId
<= MAX_FAMILIES
) || 0xffff == nId
);
942 if ( nId
!= nActFamily
)
944 m_aStyleListSetFamily
.Call(nId
);
949 IMPL_LINK(SfxCommonTemplateDialog_Impl
, UpdateFamily_Hdl
, StyleList
&, rStyleList
, void)
951 bWaterDisabled
= false;
952 bUpdateByExampleDisabled
= false;
954 if (IsCheckedItem(u
"watercan"_ustr
) &&
955 // only if that area is allowed
956 rStyleList
.CurrentFamilyHasState())
958 Execute_Impl(SID_STYLE_APPLY
, rStyleList
.GetSelectedEntry(), OUString(),
959 static_cast<sal_uInt16
>(rStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
963 void SfxCommonTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
968 sal_Int8
SfxTemplateDialog_Impl::AcceptToolbarDrop(const AcceptDropEvent
& rEvt
, const DropTargetHelper
& rHelper
)
970 sal_Int8 nReturn
= DND_ACTION_NONE
;
972 // auto flip to the category under the mouse
973 int nIndex
= m_xActionTbL
->get_drop_index(rEvt
.maPosPixel
);
974 if (nIndex
>= m_nActionTbLVisible
)
975 nIndex
= m_nActionTbLVisible
- 1;
977 OUString sIdent
= m_xActionTbL
->get_item_ident(nIndex
);
978 if (!sIdent
.isEmpty() && !m_xActionTbL
->get_item_active(sIdent
))
979 ToolBoxLSelect(sIdent
);
981 // special case: page styles are allowed to create new styles by example
982 // but not allowed to be created by drag and drop
983 if (sIdent
.toUInt32() != SfxTemplate::SfxFamilyIdToNId(SfxStyleFamily::Page
) &&
984 rHelper
.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
985 !bNewByExampleDisabled
)
987 nReturn
= DND_ACTION_COPY
;
992 void SfxCommonTemplateDialog_Impl::EnableEdit(bool b
, StyleList
* rStyleList
)
994 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
995 m_aStyleList
.Enableedit(b
);
997 void SfxCommonTemplateDialog_Impl::EnableDel(bool b
, const StyleList
* rStyleList
)
999 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1000 m_aStyleList
.Enabledel(b
);
1002 void SfxCommonTemplateDialog_Impl::EnableNew(bool b
, const StyleList
* rStyleList
)
1004 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1005 m_aStyleList
.Enablenew(b
);
1007 void SfxCommonTemplateDialog_Impl::EnableHide(bool b
, const StyleList
* rStyleList
)
1009 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1010 m_aStyleList
.Enablehide(b
);
1012 void SfxCommonTemplateDialog_Impl::EnableShow(bool b
, const StyleList
* rStyleList
)
1014 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1015 m_aStyleList
.Enableshow(b
);
1017 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */