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("new", 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
, "TemplatePanel", "sfx/ui/templatepanel.ui")
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
, "treeview", "flatview")
244 , mxPreviewCheckbox(pBuilder
->weld_check_button("showpreview"))
245 , mxHighlightCheckbox(pBuilder
->weld_check_button("highlightstyles"))
246 , mxFilterLb(pBuilder
->weld_combo_box("filter"))
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("update", 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();
300 const SfxStyleFamilyItem
&rItem
= rStyleList
.GetFamilyItemByIndex( nCount
);
301 sal_uInt16 nId
= SfxTemplate::SfxFamilyIdToNId( rItem
.GetFamily() );
302 InsertFamilyItem(nId
, rItem
);
306 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, ClearResource_Hdl
, void*, void)
309 m_aStyleListClear
.Call(nullptr);
312 SfxCommonTemplateDialog_Impl::DeletionWatcher
*
313 SfxCommonTemplateDialog_Impl::impl_setDeletionWatcher(
314 DeletionWatcher
*const pNewWatcher
)
316 DeletionWatcher
*const pRet(m_pDeletionWatcher
);
317 m_pDeletionWatcher
= pNewWatcher
;
321 void SfxCommonTemplateDialog_Impl::Initialize()
323 m_aStyleList
.connect_ReadResource(LINK(this, SfxCommonTemplateDialog_Impl
, ReadResource_Hdl
));
324 m_aStyleList
.connect_ClearResource(LINK(this, SfxCommonTemplateDialog_Impl
, ClearResource_Hdl
));
325 m_aStyleList
.connect_LoadFactoryStyleFilter(LINK(this, SfxCommonTemplateDialog_Impl
, LoadFactoryStyleFilter_Hdl
));
326 m_aStyleList
.connect_SaveSelection(LINK(this, SfxCommonTemplateDialog_Impl
, SaveSelection_Hdl
));
327 m_aStyleList
.connect_UpdateFamily(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateFamily_Hdl
));
328 m_aStyleList
.connect_UpdateStyles(LINK(this, SfxCommonTemplateDialog_Impl
, UpdateStyles_Hdl
));
330 mxFilterLb
->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl
, FilterSelectHdl
));
331 mxPreviewCheckbox
->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl
, PreviewHdl
));
332 mxHighlightCheckbox
->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl
, HighlightHdl
));
334 m_aStyleList
.Initialize();
336 SfxStyleFamily eFam
= SfxTemplate::NIdToSfxFamilyId(nActFamily
);
337 mxHighlightCheckbox
->set_visible(m_aStyleList
.HasStylesHighlighterFeature()
338 && (eFam
== SfxStyleFamily::Para
|| eFam
== SfxStyleFamily::Char
));
341 IMPL_LINK(SfxCommonTemplateDialog_Impl
, UpdateStyles_Hdl
, StyleFlags
, nFlags
, void)
343 const SfxStyleFamilyItem
* pItem
= m_aStyleList
.GetFamilyItem();
345 if (nFlags
& StyleFlags::UpdateFamily
) // Update view type list (Hierarchical, All, etc.
347 CheckItem(OUString::number(nActFamily
)); // check Button in Toolbox
349 mxFilterLb
->freeze();
352 //insert hierarchical at the beginning
353 mxFilterLb
->append(OUString::number(static_cast<int>(SfxStyleSearchBits::All
)),
354 SfxResId(STR_STYLE_FILTER_HIERARCHICAL
));
355 const SfxStyleFilter
& rFilter
= pItem
->GetFilterList();
356 for (const SfxFilterTuple
& i
: rFilter
)
357 mxFilterLb
->append(OUString::number(static_cast<int>(i
.nFlags
)), i
.aName
);
360 if (nActFilter
< mxFilterLb
->get_count() - 1)
361 mxFilterLb
->set_active(nActFilter
+ 1);
365 m_aStyleList
.FilterSelect(nActFilter
, false);
366 mxFilterLb
->set_active(1);
369 // if the tree view again, select family hierarchy
370 if (m_aStyleList
.IsTreeView() || m_bWantHierarchical
)
372 mxFilterLb
->set_active_text(SfxResId(STR_STYLE_FILTER_HIERARCHICAL
));
373 EnableHierarchical(true, m_aStyleList
);
378 if (nActFilter
< mxFilterLb
->get_count() - 1)
379 mxFilterLb
->set_active(nActFilter
+ 1);
383 m_aStyleList
.FilterSelect(nActFilter
, false);
384 mxFilterLb
->set_active(1);
388 if (!(nFlags
& StyleFlags::UpdateFamilyList
))
391 EnableItem("watercan", false);
394 SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl()
396 // Set the UNO's in an 'off' state. FN_PARAM_1 is used to prevent the sidebar from trying to
397 // reopen while it is being closed here.
398 if (m_aStyleList
.IsHighlightParaStyles())
400 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
401 SfxFlagItem
aParam(FN_PARAM_1
);
402 rDispatcher
.ExecuteList(SID_SPOTLIGHT_PARASTYLES
, SfxCallMode::SYNCHRON
, { &aParam
});
404 if (m_aStyleList
.IsHighlightCharStyles())
406 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
407 SfxFlagItem
aParam(FN_PARAM_1
);
408 rDispatcher
.ExecuteList(SID_SPOTLIGHT_CHARSTYLES
, SfxCallMode::SYNCHRON
, { &aParam
});
412 Execute_Impl(SID_STYLE_WATERCAN
, "", "", 0, m_aStyleList
);
413 m_aStyleListClear
.Call(nullptr);
414 m_aStyleListCleanup
.Call(nullptr);
415 if ( m_pDeletionWatcher
)
416 m_pDeletionWatcher
->signal();
417 mxPreviewCheckbox
.reset();
422 * Is it safe to show the water-can / fill icon. If we've a
423 * hierarchical widget - we have only single select, otherwise
424 * we need to check if we have a multi-selection. We either have
425 * a mxTreeBox showing or an mxFmtLb (which we hide when not shown)
427 bool SfxCommonTemplateDialog_Impl::IsSafeForWaterCan() const
429 return m_aStyleListWaterCan
.Call(nullptr);
432 void SfxCommonTemplateDialog_Impl::SelectStyle(const OUString
&rStr
, bool bIsCallback
, StyleList
& rStyleList
)
434 rStyleList
.SelectStyle(rStr
, bIsCallback
);
436 bWaterDisabled
= !IsSafeForWaterCan();
438 // tdf#134598 call UpdateStyleDependents to update watercan
439 UpdateStyleDependents_Hdl(nullptr);
442 void SfxCommonTemplateDialog_Impl::EnableTreeDrag(bool bEnable
)
444 m_aStyleListEnableTreeDrag
.Call(bEnable
);
447 // Updated display: Watering the house
448 void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem
*pItem
)
450 bWaterDisabled
= (pItem
== nullptr);
453 //make sure the watercan is only activated when there is (only) one selection
454 bWaterDisabled
= !IsSafeForWaterCan();
456 if(pItem
&& !bWaterDisabled
)
458 CheckItem("watercan", pItem
->GetValue());
459 EnableItem("watercan");
464 EnableItem("watercan");
466 EnableItem("watercan", false);
469 // Ignore while in watercan mode statusupdates
471 m_aStyleListSetWaterCanState
.Call(pItem
);
474 // Item with the status of a Family is copied and noted
475 // (is updated when all states have also been updated.)
476 // See also: <SfxBindings::AddDoneHdl(const Link &)>
477 void SfxCommonTemplateDialog_Impl::SetFamilyState( sal_uInt16 nSlotId
, const SfxTemplateItem
* pItem
)
479 m_aStyleList
.SetFamilyState(nSlotId
, pItem
);
483 // Internal: Perform functions through the Dispatcher
484 bool SfxCommonTemplateDialog_Impl::Execute_Impl(
485 sal_uInt16 nId
, const OUString
&rStr
, const OUString
& rRefStr
, sal_uInt16 nFamily
, StyleList
& rStyleList
,
486 SfxStyleSearchBits nMask
, sal_uInt16
*pIdx
, const sal_uInt16
* pModifier
)
488 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
489 SfxStringItem
aItem(nId
, rStr
);
490 SfxUInt16Item
aFamily(SID_STYLE_FAMILY
, nFamily
);
491 SfxUInt16Item
aMask( SID_STYLE_MASK
, static_cast<sal_uInt16
>(nMask
) );
492 SfxStringItem
aUpdName(SID_STYLE_UPD_BY_EX_NAME
, rStr
);
493 SfxStringItem
aRefName( SID_STYLE_REFERENCE
, rRefStr
);
494 const SfxPoolItem
* pItems
[ 6 ];
495 sal_uInt16 nCount
= 0;
496 if( !rStr
.isEmpty() )
497 pItems
[ nCount
++ ] = &aItem
;
498 pItems
[ nCount
++ ] = &aFamily
;
499 if( nMask
!= SfxStyleSearchBits::Auto
)
500 pItems
[ nCount
++ ] = &aMask
;
501 if(SID_STYLE_UPDATE_BY_EXAMPLE
== nId
)
503 // Special solution for Numbering update in Writer
504 const OUString
aTemplName(rStyleList
.GetSelectedEntry());
505 aUpdName
.SetValue(aTemplName
);
506 pItems
[ nCount
++ ] = &aUpdName
;
509 if ( !rRefStr
.isEmpty() )
510 pItems
[ nCount
++ ] = &aRefName
;
512 pItems
[ nCount
++ ] = nullptr;
514 DeletionWatcher
aDeleted(*this);
515 sal_uInt16 nModi
= pModifier
? *pModifier
: 0;
516 const SfxPoolItemHolder
aResult(rDispatcher
.Execute(
517 nId
, SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
520 // Dialog can be destroyed while in Execute() because started
521 // subdialogs are not modal to it (#i97888#).
522 if ( nullptr == aResult
.getItem() || aDeleted
)
525 if ((nId
== SID_STYLE_NEW
|| SID_STYLE_EDIT
== nId
)
526 && rStyleList
.EnableExecute())
528 const SfxUInt16Item
* pFilterItem(dynamic_cast<const SfxUInt16Item
*>(aResult
.getItem()));
530 SfxStyleSearchBits nFilterFlags
= static_cast<SfxStyleSearchBits
>(pFilterItem
->GetValue()) & ~SfxStyleSearchBits::UserDefined
;
531 if(nFilterFlags
== SfxStyleSearchBits::Auto
) // User Template?
532 nFilterFlags
= static_cast<SfxStyleSearchBits
>(pFilterItem
->GetValue());
533 const SfxStyleFamilyItem
*pFamilyItem
= rStyleList
.GetFamilyItem();
534 const size_t nFilterCount
= pFamilyItem
->GetFilterList().size();
536 for ( size_t i
= 0; i
< nFilterCount
; ++i
)
538 const SfxFilterTuple
&rTupel
= pFamilyItem
->GetFilterList()[ i
];
540 if ( ( rTupel
.nFlags
& nFilterFlags
) == nFilterFlags
&& pIdx
)
548 // Handler Listbox of Filter
549 void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable
, StyleList
& rStyleList
)
551 OUString aSelectedEntry
= rStyleList
.GetSelectedEntry();
554 if (!rStyleList
.IsHierarchical())
557 m_bWantHierarchical
= true;
558 SaveSelection_Hdl(rStyleList
); // fdo#61429 store "hierarchical"
559 m_aStyleList
.SetHierarchical();
564 m_aStyleList
.SetFilterControlsHandle();
565 // If bHierarchical, then the family can have changed
566 // minus one since hierarchical is inserted at the start
567 m_bWantHierarchical
= false; // before FilterSelect
568 FilterSelect(mxFilterLb
->get_active() - 1);
570 SelectStyle(aSelectedEntry
, false, rStyleList
);
573 // Other filters; can be switched by the users or as a result of new or
574 // editing, if the current document has been assigned a different filter.
575 void SfxCommonTemplateDialog_Impl::FilterSelect(
576 sal_uInt16 nEntry
// Idx of the new Filters
580 m_aStyleList
.FilterSelect(nActFilter
, true);
583 void SfxCommonTemplateDialog_Impl::IsUpdate(StyleList
&)
585 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
586 SfxObjectShell
* pDocShell
= pViewFrame
->GetObjectShell();
587 nActFilter
= static_cast<sal_uInt16
>(LoadFactoryStyleFilter_Hdl(pDocShell
));
588 if (0xffff == nActFilter
)
590 nActFilter
= pDocShell
->GetAutoStyleFilterIndex();
594 IMPL_LINK(SfxCommonTemplateDialog_Impl
, FilterSelectHdl
, weld::ComboBox
&, rBox
, void)
596 if (SfxResId(STR_STYLE_FILTER_HIERARCHICAL
) == rBox
.get_active_text())
598 EnableHierarchical(true, m_aStyleList
);
602 EnableHierarchical(false, m_aStyleList
);
606 // Select-Handler for the Toolbox
607 void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry
, StyleList
&, bool bRefresh
)
609 assert((0 < nEntry
&& nEntry
<= MAX_FAMILIES
) || 0xffff == nEntry
);
610 if( nEntry
!= nActFamily
|| bRefresh
)
612 CheckItem(OUString::number(nActFamily
), false);
614 m_aStyleList
.FamilySelect(nEntry
, bRefresh
);
616 SfxStyleFamily eFam
= SfxTemplate::NIdToSfxFamilyId(nActFamily
);
617 mxHighlightCheckbox
->set_visible(m_aStyleList
.HasStylesHighlighterFeature()
618 && (eFam
== SfxStyleFamily::Para
|| eFam
== SfxStyleFamily::Char
));
619 if (mxHighlightCheckbox
->is_visible())
621 bool bActive
= false;
622 if (eFam
== SfxStyleFamily::Para
)
623 bActive
= m_aStyleList
.IsHighlightParaStyles();
624 else if (eFam
== SfxStyleFamily::Char
)
625 bActive
= m_aStyleList
.IsHighlightCharStyles();
626 mxHighlightCheckbox
->set_active(bActive
);
631 void SfxCommonTemplateDialog_Impl::ActionSelect(const OUString
& rEntry
, StyleList
& rStyleList
)
633 if (rEntry
== "watercan")
635 const bool bOldState
= !IsCheckedItem(rEntry
);
638 // when a template is chosen.
639 if (!bOldState
&& m_aStyleListHasSelectedStyle
.Call(nullptr))
641 const OUString
aTemplName(rStyleList
.GetSelectedEntry());
642 Execute_Impl(SID_STYLE_WATERCAN
, aTemplName
, "",
643 static_cast<sal_uInt16
>(m_aStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
648 Execute_Impl(SID_STYLE_WATERCAN
, "", "", 0, rStyleList
);
651 CheckItem(rEntry
, bCheck
);
652 aBool
.SetValue(bCheck
);
653 SetWaterCanState(&aBool
);
655 else if (rEntry
== "new" || rEntry
== "newmenu")
657 m_aStyleListNewMenu
.Call(nullptr);
659 else if (rEntry
== "update")
661 Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE
,
663 static_cast<sal_uInt16
>(m_aStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
665 else if (rEntry
== "load")
666 SfxGetpApp()->GetDispatcher_Impl()->Execute(SID_TEMPLATE_LOAD
);
668 SAL_WARN("sfx", "not implemented: " << rEntry
);
671 static OUString
getModuleIdentifier( const Reference
< XModuleManager2
>& i_xModMgr
, SfxObjectShell
const * i_pObjSh
)
673 OSL_ENSURE( i_xModMgr
.is(), "getModuleIdentifier(): no XModuleManager" );
674 OSL_ENSURE( i_pObjSh
, "getModuleIdentifier(): no ObjectShell" );
676 OUString sIdentifier
;
680 sIdentifier
= i_xModMgr
->identify( i_pObjSh
->GetModel() );
682 catch ( css::frame::UnknownModuleException
& )
684 SAL_WARN("sfx", "getModuleIdentifier(): unknown module" );
688 TOOLS_WARN_EXCEPTION( "sfx", "getModuleIdentifier(): exception of XModuleManager::identify()" );
694 IMPL_LINK(SfxCommonTemplateDialog_Impl
, LoadFactoryStyleFilter_Hdl
, SfxObjectShell
const*, i_pObjSh
, sal_Int32
)
696 OSL_ENSURE( i_pObjSh
, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" );
698 ::comphelper::SequenceAsHashMap
aFactoryProps(
699 xModuleManager
->getByName( getModuleIdentifier( xModuleManager
, i_pObjSh
) ) );
700 sal_Int32 nFilter
= aFactoryProps
.getUnpackedValueOrDefault( "ooSetupFactoryStyleFilter", sal_Int32(-1) );
702 m_bWantHierarchical
= (nFilter
& 0x1000) != 0;
703 nFilter
&= ~0x1000; // clear it
708 void SfxCommonTemplateDialog_Impl::SaveFactoryStyleFilter( SfxObjectShell
const * i_pObjSh
, sal_Int32 i_nFilter
)
710 OSL_ENSURE( i_pObjSh
, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" );
711 Sequence
< PropertyValue
> lProps
{ comphelper::makePropertyValue(
712 "ooSetupFactoryStyleFilter", i_nFilter
| (m_bWantHierarchical
? 0x1000 : 0)) };
713 xModuleManager
->replaceByName( getModuleIdentifier( xModuleManager
, i_pObjSh
), Any( lProps
) );
716 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, SaveSelection_Hdl
, StyleList
&, SfxObjectShell
*)
718 SfxViewFrame
*const pViewFrame(pBindings
->GetDispatcher_Impl()->GetFrame());
719 SfxObjectShell
*const pDocShell(pViewFrame
->GetObjectShell());
722 pDocShell
->SetAutoStyleFilterIndex(nActFilter
);
723 SaveFactoryStyleFilter( pDocShell
, nActFilter
);
728 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, PreviewHdl
, weld::Toggleable
&, void)
730 std::shared_ptr
<comphelper::ConfigurationChanges
> batch( comphelper::ConfigurationChanges::create() );
731 bool bCustomPreview
= mxPreviewCheckbox
->get_active();
732 officecfg::Office::Common::StylesAndFormatting::Preview::set(bCustomPreview
, batch
);
735 FamilySelect(nActFamily
, m_aStyleList
, true);
738 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, HighlightHdl
, weld::Toggleable
&, void)
740 SfxDispatcher
&rDispatcher
= *SfxGetpApp()->GetDispatcher_Impl();
741 SfxStyleFamily eFam
= SfxTemplate::NIdToSfxFamilyId(nActFamily
);
742 if (eFam
== SfxStyleFamily::Para
)
743 rDispatcher
.Execute(SID_SPOTLIGHT_PARASTYLES
, SfxCallMode::SYNCHRON
);
744 else if (eFam
== SfxStyleFamily::Char
)
745 rDispatcher
.Execute(SID_SPOTLIGHT_CHARSTYLES
, SfxCallMode::SYNCHRON
);
748 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl
, UpdateStyleDependents_Hdl
, void*, void)
750 m_aStyleListUpdateStyleDependents
.Call(nullptr);
751 EnableItem("watercan", !bWaterDisabled
);
752 m_aStyleListEnableDelete
.Call(nullptr);
755 void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId
, bool bEnable
)
757 bool bDisable
= !bEnable
|| !IsSafeForWaterCan();
758 if (nId
== SID_STYLE_NEW_BY_EXAMPLE
)
760 bNewByExampleDisabled
= bDisable
;
761 m_aStyleList
.EnableNewByExample(bNewByExampleDisabled
);
762 EnableItem("new", bEnable
);
763 EnableItem("newmenu", bEnable
);
765 else if( nId
== SID_STYLE_UPDATE_BY_EXAMPLE
)
767 bUpdateByExampleDisabled
= bDisable
;
768 EnableItem("update", bEnable
);
772 class ToolbarDropTarget final
: public DropTargetHelper
775 SfxTemplateDialog_Impl
& m_rParent
;
778 ToolbarDropTarget(SfxTemplateDialog_Impl
& rDialog
, weld::Toolbar
& rToolbar
)
779 : DropTargetHelper(rToolbar
.get_drop_target())
784 virtual sal_Int8
AcceptDrop(const AcceptDropEvent
& rEvt
) override
786 return m_rParent
.AcceptToolbarDrop(rEvt
, *this);
789 virtual sal_Int8
ExecuteDrop(const ExecuteDropEvent
& rEvt
) override
791 return m_rParent
.ExecuteDrop(rEvt
);
795 SfxTemplateDialog_Impl::SfxTemplateDialog_Impl(SfxBindings
* pB
, SfxTemplatePanelControl
* pDlgWindow
)
796 : SfxCommonTemplateDialog_Impl(pB
, pDlgWindow
->get_container(), pDlgWindow
->get_builder())
797 , m_xActionTbL(pDlgWindow
->get_builder()->weld_toolbar("left"))
798 , m_xActionTbR(pDlgWindow
->get_builder()->weld_toolbar("right"))
799 , m_xToolMenu(pDlgWindow
->get_builder()->weld_menu("toolmenu"))
800 , m_nActionTbLVisible(0)
802 m_xActionTbR
->set_item_help_id("watercan", HID_TEMPLDLG_WATERCAN
);
803 // shown/hidden in SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
804 m_xActionTbR
->set_item_help_id("new", HID_TEMPLDLG_NEWBYEXAMPLE
);
805 m_xActionTbR
->set_item_help_id("newmenu", HID_TEMPLDLG_NEWBYEXAMPLE
);
806 m_xActionTbR
->set_item_menu("newmenu", m_xToolMenu
.get());
807 m_xToolMenu
->connect_activate(LINK(this, SfxTemplateDialog_Impl
, ToolMenuSelectHdl
));
808 m_xActionTbR
->set_item_help_id("update", HID_TEMPLDLG_UPDATEBYEXAMPLE
);
813 void SfxTemplateDialog_Impl::Initialize()
815 SfxCommonTemplateDialog_Impl::Initialize();
817 m_xActionTbL
->connect_clicked(LINK(this, SfxTemplateDialog_Impl
, ToolBoxLSelect
));
818 m_xActionTbR
->connect_clicked(LINK(this, SfxTemplateDialog_Impl
, ToolBoxRSelect
));
819 m_xActionTbL
->set_help_id(HID_TEMPLDLG_TOOLBOX_LEFT
);
821 m_xToolbarDropTargetHelper
.reset(new ToolbarDropTarget(*this, *m_xActionTbL
));
824 void SfxTemplateDialog_Impl::EnableFamilyItem(sal_uInt16 nId
, bool bEnable
)
826 m_xActionTbL
->set_item_sensitive(OUString::number(nId
), bEnable
);
829 // Insert element into dropdown filter "Frame Styles", "List Styles", etc.
830 void SfxTemplateDialog_Impl::InsertFamilyItem(sal_uInt16 nId
, const SfxStyleFamilyItem
&rItem
)
833 switch( rItem
.GetFamily() )
835 case SfxStyleFamily::Char
: sHelpId
= ".uno:CharStyle"; break;
836 case SfxStyleFamily::Para
: sHelpId
= ".uno:ParaStyle"; break;
837 case SfxStyleFamily::Frame
: sHelpId
= ".uno:FrameStyle"; break;
838 case SfxStyleFamily::Page
: sHelpId
= ".uno:PageStyle"; break;
839 case SfxStyleFamily::Pseudo
: sHelpId
= ".uno:ListStyle"; break;
840 case SfxStyleFamily::Table
: sHelpId
= ".uno:TableStyle"; break;
841 default: OSL_FAIL("unknown StyleFamily"); break;
844 OUString
sId(OUString::number(nId
));
845 m_xActionTbL
->set_item_visible(sId
, true);
846 m_xActionTbL
->set_item_icon_name(sId
, rItem
.GetImage());
847 m_xActionTbL
->set_item_tooltip_text(sId
, rItem
.GetText());
848 m_xActionTbL
->set_item_help_id(sId
, sHelpId
);
849 ++m_nActionTbLVisible
;
852 void SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
854 m_xActionTbR
->set_item_visible("update", false);
855 m_xActionTbR
->set_item_visible("new", false);
856 m_xActionTbR
->set_item_visible("newmenu", true);
860 void SfxTemplateDialog_Impl::ClearFamilyList()
862 for (int i
= 0, nCount
= m_xActionTbL
->get_n_items(); i
< nCount
; ++i
)
863 m_xActionTbL
->set_item_visible(m_xActionTbL
->get_item_ident(i
), false);
867 SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl()
869 m_xToolbarDropTargetHelper
.reset();
870 m_xActionTbL
.reset();
871 m_xActionTbR
.reset();
874 void SfxTemplateDialog_Impl::EnableItem(const OUString
& rMesId
, bool bCheck
)
876 if (rMesId
== "watercan" && !bCheck
&& IsCheckedItem("watercan"))
877 Execute_Impl(SID_STYLE_WATERCAN
, "", "", 0, m_aStyleList
);
878 m_xActionTbR
->set_item_sensitive(rMesId
, bCheck
);
881 void SfxTemplateDialog_Impl::CheckItem(const OUString
&rMesId
, bool bCheck
)
883 if (rMesId
== "watercan")
886 m_xActionTbR
->set_item_active("watercan", bCheck
);
889 m_xActionTbL
->set_item_active(rMesId
, bCheck
);
892 bool SfxTemplateDialog_Impl::IsCheckedItem(const OUString
& rMesId
)
894 if (rMesId
== "watercan")
895 return m_xActionTbR
->get_item_active("watercan");
896 return m_xActionTbL
->get_item_active(rMesId
);
899 IMPL_LINK( SfxTemplateDialog_Impl
, ToolBoxLSelect
, const OUString
&, rEntry
, void)
901 FamilySelect(rEntry
.toUInt32(), m_aStyleList
);
904 IMPL_LINK(SfxTemplateDialog_Impl
, ToolBoxRSelect
, const OUString
&, rEntry
, void)
906 if (rEntry
== "newmenu")
907 m_xActionTbR
->set_menu_item_active(rEntry
, !m_xActionTbR
->get_menu_item_active(rEntry
));
909 ActionSelect(rEntry
, m_aStyleList
);
912 void SfxTemplateDialog_Impl::FillToolMenu()
914 //create a popup menu in Writer
915 OUString
sTextDoc("com.sun.star.text.TextDocument");
917 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:StyleNewByExample", sTextDoc
);
918 OUString sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
919 m_xToolMenu
->append("new", sLabel
);
920 aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:StyleUpdateByExample", sTextDoc
);
921 sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
922 m_xToolMenu
->append("update", sLabel
);
923 m_xToolMenu
->append_separator("separator");
925 aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:LoadStyles", sTextDoc
);
926 sLabel
= vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
);
927 m_xToolMenu
->append("load", sLabel
);
930 IMPL_LINK(SfxTemplateDialog_Impl
, ToolMenuSelectHdl
, const OUString
&, rMenuId
, void)
932 if (rMenuId
.isEmpty())
934 ActionSelect(rMenuId
, m_aStyleList
);
937 void SfxCommonTemplateDialog_Impl::SetFamily(SfxStyleFamily
const nFamily
)
939 sal_uInt16
const nId(SfxTemplate::SfxFamilyIdToNId(nFamily
));
940 assert((0 < nId
&& nId
<= MAX_FAMILIES
) || 0xffff == nId
);
941 if ( nId
!= nActFamily
)
943 m_aStyleListSetFamily
.Call(nId
);
948 IMPL_LINK(SfxCommonTemplateDialog_Impl
, UpdateFamily_Hdl
, StyleList
&, rStyleList
, void)
950 bWaterDisabled
= false;
951 bUpdateByExampleDisabled
= false;
953 if (IsCheckedItem("watercan") &&
954 // only if that area is allowed
955 rStyleList
.CurrentFamilyHasState())
957 Execute_Impl(SID_STYLE_APPLY
, rStyleList
.GetSelectedEntry(), OUString(),
958 static_cast<sal_uInt16
>(rStyleList
.GetFamilyItem()->GetFamily()), rStyleList
);
962 void SfxCommonTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
967 sal_Int8
SfxTemplateDialog_Impl::AcceptToolbarDrop(const AcceptDropEvent
& rEvt
, const DropTargetHelper
& rHelper
)
969 sal_Int8 nReturn
= DND_ACTION_NONE
;
971 // auto flip to the category under the mouse
972 int nIndex
= m_xActionTbL
->get_drop_index(rEvt
.maPosPixel
);
973 if (nIndex
>= m_nActionTbLVisible
)
974 nIndex
= m_nActionTbLVisible
- 1;
976 OUString sIdent
= m_xActionTbL
->get_item_ident(nIndex
);
977 if (!sIdent
.isEmpty() && !m_xActionTbL
->get_item_active(sIdent
))
978 ToolBoxLSelect(sIdent
);
980 // special case: page styles are allowed to create new styles by example
981 // but not allowed to be created by drag and drop
982 if (sIdent
.toUInt32() != SfxTemplate::SfxFamilyIdToNId(SfxStyleFamily::Page
) &&
983 rHelper
.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
984 !bNewByExampleDisabled
)
986 nReturn
= DND_ACTION_COPY
;
991 void SfxCommonTemplateDialog_Impl::EnableEdit(bool b
, StyleList
* rStyleList
)
993 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
994 m_aStyleList
.Enableedit(b
);
996 void SfxCommonTemplateDialog_Impl::EnableDel(bool b
, const StyleList
* rStyleList
)
998 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
999 m_aStyleList
.Enabledel(b
);
1001 void SfxCommonTemplateDialog_Impl::EnableNew(bool b
, const StyleList
* rStyleList
)
1003 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1004 m_aStyleList
.Enablenew(b
);
1006 void SfxCommonTemplateDialog_Impl::EnableHide(bool b
, const StyleList
* rStyleList
)
1008 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1009 m_aStyleList
.Enablehide(b
);
1011 void SfxCommonTemplateDialog_Impl::EnableShow(bool b
, const StyleList
* rStyleList
)
1013 if (rStyleList
== &m_aStyleList
|| rStyleList
== nullptr)
1014 m_aStyleList
.Enableshow(b
);
1016 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */