LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / dialog / templdlg.cxx
blob0cccf5a5d9895c91463b1cc78b969d55ade7dcf7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <memory>
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>
62 #include <helpids.h>
63 #include <sfx2/viewfrm.hxx>
65 #include <comphelper/string.hxx>
67 #include <sfx2/StyleManager.hxx>
68 #include <sfx2/StylePreviewRenderer.hxx>
70 using namespace css;
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)();
79 public:
80 explicit DeletionWatcher(SfxCommonTemplateDialog_Impl& rDialog)
81 : m_pDialog(&rDialog)
82 , m_pPrevious(m_pDialog->impl_setDeletionWatcher(this))
86 ~DeletionWatcher()
88 if (m_pDialog)
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
96 void signal()
98 m_pDialog = nullptr;
99 if (m_pPrevious)
100 m_pPrevious->signal();
103 // Return true if the dialog was deleted
104 operator bool_type() const
106 return m_pDialog ? nullptr : &DeletionWatcher::signal;
109 private:
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)
144 switch ( 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;
189 // Constructor
191 SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl(SfxBindings* pB, weld::Container* pC, weld::Builder* pBuilder)
192 : pBindings(pB)
193 , mpContainer(pC)
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"))
199 , nActFamily(0xffff)
200 , nActFilter(0)
201 , bIsWater(false)
202 , bUpdate(false)
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)
222 nActFilter = 0xffff;
224 SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
225 SfxObjectShell* pCurObjShell = pViewFrame->GetObjectShell();
226 if (pCurObjShell)
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
247 if(nCount > 4)
248 ReplaceUpdateButtonByMenu();
250 for( ; nCount--; )
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)
260 ClearFamilyList();
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;
270 return pRet;
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();
297 mxFilterLb->clear();
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);
305 mxFilterLb->thaw();
307 if (nActFilter < mxFilterLb->get_count() - 1)
308 mxFilterLb->set_active(nActFilter + 1);
309 else
311 nActFilter = 0;
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);
323 else
325 if (nActFilter < mxFilterLb->get_count() - 1)
326 mxFilterLb->set_active(nActFilter + 1);
327 else
329 nActFilter = 0;
330 m_aStyleList.FilterSelect(nActFilter, false);
331 mxFilterLb->set_active(1);
335 if (!(nFlags & StyleFlags::UpdateFamilyList))
336 return;
338 EnableItem("watercan", false);
341 SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl()
343 if ( bIsWater )
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();
350 mxFilterLb.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);
384 if(!bWaterDisabled)
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");
393 else
395 if(!bWaterDisabled)
396 EnableItem("watercan");
397 else
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);
412 bUpdate = true;
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,
450 pItems, nModi );
452 // Dialog can be destroyed while in Execute() because started
453 // subdialogs are not modal to it (#i97888#).
454 if ( !pItem || aDeleted )
455 return false;
457 if ((nId == SID_STYLE_NEW || SID_STYLE_EDIT == nId)
458 && rStyleList.EnableExecute())
460 const SfxUInt16Item *pFilterItem = dynamic_cast< const SfxUInt16Item* >(pItem);
461 assert(pFilterItem);
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 )
473 *pIdx = i;
477 return true;
480 // Handler Listbox of Filter
481 void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable, StyleList& rStyleList)
483 if (bEnable)
485 if (!rStyleList.IsHierarchical())
487 // Turn on treeView
488 m_bWantHierarchical = true;
489 SaveSelection_Hdl(rStyleList); // fdo#61429 store "hierarchical"
490 m_aStyleList.SetHierarchical();
493 else
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)
510 return;
512 nActFilter = nEntry;
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();
520 if (bDoUpdate)
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);
536 else
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);
549 nActFamily = nEntry;
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);
559 bool bCheck;
560 SfxBoolItem aBool;
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);
567 bCheck = true;
569 else
571 Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, rStyleList);
572 bCheck = false;
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,
585 "", "",
586 static_cast<sal_uInt16>(m_aStyleList.GetFamilyItem()->GetFamily()), rStyleList);
588 else if (rEntry == "load")
589 SfxGetpApp()->GetDispatcher_Impl()->Execute(SID_TEMPLATE_LOAD);
590 else
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" );
609 catch ( Exception& )
611 TOOLS_WARN_EXCEPTION( "sfx", "getModuleIdentifier(): exception of XModuleManager::identify()" );
614 return sIdentifier;
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
628 return nFilter;
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());
643 if (pDocShell)
645 pDocShell->SetAutoStyleFilterIndex(nActFilter);
646 SaveFactoryStyleFilter( pDocShell, nActFilter );
648 return pDocShell;
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 );
656 batch->commit();
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);
702 Initialize();
705 class ToolbarDropTarget final : public DropTargetHelper
707 private:
708 SfxTemplateDialog_Impl& m_rParent;
710 public:
711 ToolbarDropTarget(SfxTemplateDialog_Impl& rDialog, weld::Toolbar& rToolbar)
712 : DropTargetHelper(rToolbar.get_drop_target())
713 , m_rParent(rDialog)
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)
747 OString sHelpId;
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);
772 FillToolMenu();
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")
800 bIsWater=bCheck;
801 m_xActionTbR->set_item_active("watercan", bCheck);
803 else
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));
823 else
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())
848 return;
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);
859 nActFamily = 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()
879 //does nothing
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;
903 return nReturn;
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: */