diff options
author | Anshu <anshukhare50@gmail.com> | 2021-06-26 08:34:06 +0530 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-07-30 12:14:24 +0200 |
commit | 172f589471edcac9a4974132a3145b721942879a (patch) | |
tree | e0ff8483c2303812c8c146069e1289add28adf3c | |
parent | 5c9001acf25bf1795f683fc1a43dc6ec0ba6ced9 (diff) |
tdf#38194 related: introduce StylesList control
Change-Id: I31202c213e034ab96f28e16d1f6a59b52f47507d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117918
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r-- | sfx2/Library_sfx.mk | 1 | ||||
-rw-r--r-- | sfx2/source/dialog/StyleList.cxx | 1814 | ||||
-rw-r--r-- | sfx2/source/dialog/templdlg.cxx | 1722 | ||||
-rw-r--r-- | sfx2/source/inc/StyleList.hxx | 235 | ||||
-rw-r--r-- | sfx2/source/inc/templdgi.hxx | 243 |
5 files changed, 2327 insertions, 1688 deletions
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk index fff97d011a02..39b5438c65a2 100644 --- a/sfx2/Library_sfx.mk +++ b/sfx2/Library_sfx.mk @@ -203,6 +203,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\ sfx2/source/dialog/styledlg \ sfx2/source/dialog/tabdlg \ sfx2/source/dialog/templdlg \ + sfx2/source/dialog/StyleList \ sfx2/source/dialog/titledockwin \ sfx2/source/dialog/tplcitem \ sfx2/source/dialog/tplpitem \ diff --git a/sfx2/source/dialog/StyleList.cxx b/sfx2/source/dialog/StyleList.cxx new file mode 100644 index 000000000000..8525c620b2dd --- /dev/null +++ b/sfx2/source/dialog/StyleList.cxx @@ -0,0 +1,1814 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> + +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <vcl/commandevent.hxx> +#include <vcl/commandinfoprovider.hxx> +#include <vcl/event.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weldutils.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/style.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/UnknownModuleException.hpp> +#include <officecfg/Office/Common.hxx> + +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <tools/diagnose_ex.h> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/templdlg.hxx> +#include <templdgi.hxx> +#include <tplcitem.hxx> +#include <sfx2/styfitem.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/newstyle.hxx> +#include <sfx2/tplpitem.hxx> +#include <sfx2/sfxresid.hxx> + +#include <sfx2/sfxsids.hrc> +#include <sfx2/strings.hrc> +#include <sfx2/docfac.hxx> +#include <sfx2/module.hxx> +#include <helpids.h> +#include <sfx2/viewfrm.hxx> + +#include <comphelper/string.hxx> + +#include <sfx2/StyleManager.hxx> +#include <sfx2/StylePreviewRenderer.hxx> + +#include <StyleList.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/menu.hxx> + +using namespace css; +using namespace css::beans; +using namespace css::frame; +using namespace css::uno; + +// Constructor + +StyleList::StyleList(weld::Builder* pBuilder, std::optional<SfxStyleFamilies> xFamilies, + SfxBindings* pBindings, SfxCommonTemplateDialog_Impl* Parent, + SfxModule* Module, weld::Container* pC, OString treeviewname, + OString flatviewname) + : m_bHierarchical(false) + , m_bAllowReParentDrop(false) + , m_bNewByExampleDisabled(false) + , m_bDontUpdate(false) + , m_bTreeDrag(true) + , m_bCanEdit(false) + , m_bCanHide(true) + , m_bCanShow(false) + , m_bCanNew(true) + , m_bUpdateFamily(false) + , m_bCanDel(false) + , m_bBindingUpdate(true) + , m_pStyleSheetPool(nullptr) + , m_nActFilter(0) + , m_xFmtLb(pBuilder->weld_tree_view(flatviewname)) + , m_xTreeBox(pBuilder->weld_tree_view(treeviewname)) + , m_xStyleFamilies(xFamilies) + , m_nActFamily(0xffff) + , m_nAppFilter(SfxStyleSearchBits::Auto) + , m_pParentDialog(Parent) + , m_pBindings(pBindings) + , m_Module(Module) + , m_nModifier(0) + , m_pContainer(pC) +{ + m_xFmtLb->set_help_id(HID_TEMPLATE_FMT); +} + +// Destructor + +StyleList::~StyleList() {} + +// Called in the destructor of Dialog +// Cleans up the StyleList individual components while closing the application +IMPL_LINK_NOARG(StyleList, Cleanup, void*, void) +{ + if (m_pStyleSheetPool) + EndListening(*m_pStyleSheetPool); + m_pStyleSheetPool = nullptr; + m_xTreeView1DropTargetHelper.reset(); + m_xTreeView2DropTargetHelper.reset(); + m_xTreeBox.reset(); + m_xFmtLb.reset(); + pIdle.reset(); +} + +void StyleList::CreateContextMenu() +{ + if (m_bBindingUpdate) + { + m_pBindings->Invalidate(SID_STYLE_NEW, true); + m_pBindings->Update(SID_STYLE_NEW); + m_bBindingUpdate = false; + } + mxMenu.reset(); + mxMenuBuilder.reset(Application::CreateBuilder(nullptr, "sfx/ui/stylecontextmenu.ui")); + mxMenu = mxMenuBuilder->weld_menu("menu"); + mxMenu->set_sensitive("edit", m_bCanEdit); + mxMenu->set_sensitive("delete", m_bCanDel); + mxMenu->set_sensitive("new", m_bCanNew); + mxMenu->set_sensitive("hide", m_bCanHide); + mxMenu->set_sensitive("show", m_bCanShow); + + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + if (pItem && pItem->GetFamily() == SfxStyleFamily::Table) //tdf#101648, no ui for this yet + { + mxMenu->set_sensitive("edit", false); + mxMenu->set_sensitive("new", false); + } + if (pItem && pItem->GetFamily() == SfxStyleFamily::Pseudo) + { + const OUString aTemplName(GetSelectedEntry()); + if (aTemplName == "No List") + { + mxMenu->set_sensitive("edit", false); + mxMenu->set_sensitive("new", false); + mxMenu->set_sensitive("hide", false); + } + } +} + +IMPL_LINK_NOARG(StyleList, ReadResource, void*, size_t) +{ + // Read global user resource + for (auto& i : m_pFamilyState) + i.reset(); + + SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); + m_pCurObjShell = pViewFrame->GetObjectShell(); + m_Module = m_pCurObjShell ? m_pCurObjShell->GetModule() : nullptr; + if (m_Module) + m_xStyleFamilies = m_Module->CreateStyleFamilies(); + if (!m_xStyleFamilies) + m_xStyleFamilies.emplace(); + + m_nActFilter = 0xffff; + // Assigning value to Dialog's nActFilter so that both nActFilters are in sync + m_pParentDialog->SetFilterByIndex(m_nActFilter); + if (m_pCurObjShell) + { + m_nActFilter = static_cast<sal_uInt16>(m_aLoadFactoryStyleFilter.Call(m_pCurObjShell)); + // Assigning value to Dialog's nActFilter so that both nActFilters are in sync + m_pParentDialog->SetFilterByIndex(m_nActFilter); + if (0xffff == m_nActFilter) + { + m_nActFilter = m_pCurObjShell->GetAutoStyleFilterIndex(); + m_pParentDialog->SetFilterByIndex(m_nActFilter); + } + } + size_t nCount = m_xStyleFamilies->size(); + m_pBindings->ENTERREGISTRATIONS(); + + size_t i; + for (i = 0; i < nCount; ++i) + { + sal_uInt16 nSlot = 0; + switch (m_xStyleFamilies->at(i).GetFamily()) + { + case SfxStyleFamily::Char: + nSlot = SID_STYLE_FAMILY1; + break; + case SfxStyleFamily::Para: + nSlot = SID_STYLE_FAMILY2; + break; + case SfxStyleFamily::Frame: + nSlot = SID_STYLE_FAMILY3; + break; + case SfxStyleFamily::Page: + nSlot = SID_STYLE_FAMILY4; + break; + case SfxStyleFamily::Pseudo: + nSlot = SID_STYLE_FAMILY5; + break; + case SfxStyleFamily::Table: + nSlot = SID_STYLE_FAMILY6; + break; + default: + OSL_FAIL("unknown StyleFamily"); + break; + } + pBoundItems[i].reset(new SfxTemplateControllerItem(nSlot, *m_pParentDialog, *m_pBindings)); + } + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_WATERCAN, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_NEW_BY_EXAMPLE, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_UPDATE_BY_EXAMPLE, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_NEW, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_DRAGHIERARCHIE, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_EDIT, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_DELETE, *m_pParentDialog, *m_pBindings)); + pBoundItems[i++].reset( + new SfxTemplateControllerItem(SID_STYLE_FAMILY, *m_pParentDialog, *m_pBindings)); + m_pBindings->LEAVEREGISTRATIONS(); + + for (; i < COUNT_BOUND_FUNC; ++i) + pBoundItems[i] = nullptr; + + StartListening(*m_pBindings); + + for (i = SID_STYLE_FAMILY1; i <= SID_STYLE_FAMILY4; i++) + m_pBindings->Update(i); + + return nCount; +} + +void StyleList::EnableNewByExample(bool newByExampleDisabled) +{ + m_bNewByExampleDisabled = newByExampleDisabled; +} + +class TreeViewDropTarget final : public DropTargetHelper +{ +private: + StyleList& m_rParent; + +public: + TreeViewDropTarget(StyleList& rStyleList, weld::TreeView& rTreeView) + : DropTargetHelper(rTreeView.get_drop_target()) + , m_rParent(rStyleList) + { + } + + virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override + { + return m_rParent.AcceptDrop(rEvt, *this); + } + + virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override + { + return m_rParent.ExecuteDrop(rEvt); + } +}; + +IMPL_LINK(StyleList, FilterSelect, sal_uInt16, mActFilter, void) +{ + m_nActFilter = mActFilter; + SfxObjectShell* const pDocShell = m_aSaveSelection.Call(nullptr); + SfxStyleSheetBasePool* pOldStyleSheetPool = m_pStyleSheetPool; + m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr; + if (pOldStyleSheetPool != m_pStyleSheetPool) + { + if (pOldStyleSheetPool) + EndListening(*pOldStyleSheetPool); + if (m_pStyleSheetPool) + StartListening(*m_pStyleSheetPool); + } +} + +IMPL_LINK(StyleList, SetFamily, sal_uInt16, nId, void) +{ + if (m_nActFamily != 0xFFFF) + m_pParentDialog->CheckItem(OString::number(m_nActFamily), false); + m_nActFamily = nId; + if (nId != 0xFFFF) + { + m_bUpdateFamily = true; + } +} + +void StyleList::InvalidateBindings() +{ + m_pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, true); + m_pBindings->Update(SID_STYLE_NEW_BY_EXAMPLE); + m_pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, true); + m_pBindings->Update(SID_STYLE_UPDATE_BY_EXAMPLE); + m_pBindings->Invalidate(SID_STYLE_WATERCAN, true); + m_pBindings->Update(SID_STYLE_WATERCAN); + m_pBindings->Invalidate(SID_STYLE_NEW, true); + m_pBindings->Update(SID_STYLE_NEW); + m_pBindings->Invalidate(SID_STYLE_DRAGHIERARCHIE, true); + m_pBindings->Update(SID_STYLE_DRAGHIERARCHIE); +} + +void StyleList::Initialize() +{ + m_pBindings->Invalidate(SID_STYLE_FAMILY); + m_pBindings->Update(SID_STYLE_FAMILY); + + m_xFmtLb->connect_row_activated(LINK(this, StyleList, TreeListApplyHdl)); + m_xFmtLb->connect_mouse_press(LINK(this, StyleList, MousePressHdl)); + m_xFmtLb->connect_query_tooltip(LINK(this, StyleList, QueryTooltipHdl)); + m_xFmtLb->connect_changed(LINK(this, StyleList, FmtSelectHdl)); + m_xFmtLb->connect_popup_menu(LINK(this, StyleList, PopupFlatMenuHdl)); + m_xFmtLb->connect_key_press(LINK(this, StyleList, KeyInputHdl)); + m_xFmtLb->set_selection_mode(SelectionMode::Multiple); + m_xTreeBox->connect_changed(LINK(this, StyleList, FmtSelectHdl)); + m_xTreeBox->connect_row_activated(LINK(this, StyleList, TreeListApplyHdl)); + m_xTreeBox->connect_mouse_press(LINK(this, StyleList, MousePressHdl)); + m_xTreeBox->connect_query_tooltip(LINK(this, StyleList, QueryTooltipHdl)); + m_xTreeBox->connect_popup_menu(LINK(this, StyleList, PopupTreeMenuHdl)); + m_xTreeBox->connect_key_press(LINK(this, StyleList, KeyInputHdl)); + m_xTreeBox->connect_drag_begin(LINK(this, StyleList, DragBeginHdl)); + m_xTreeView1DropTargetHelper.reset(new TreeViewDropTarget(*this, *m_xFmtLb)); + m_xTreeView2DropTargetHelper.reset(new TreeViewDropTarget(*this, *m_xTreeBox)); + + m_pParentDialog->connect_stylelist_read_resource(LINK(this, StyleList, ReadResource)); + m_pParentDialog->connect_stylelist_clear(LINK(this, StyleList, Clear)); + m_pParentDialog->connect_stylelist_cleanup(LINK(this, StyleList, Cleanup)); + m_pParentDialog->connect_stylelist_execute_drop(LINK(this, StyleList, ExecuteDrop)); + m_pParentDialog->connect_stylelist_execute_new_menu( + LINK(this, StyleList, NewMenuExecuteAction)); + m_pParentDialog->connect_stylelist_for_watercan(LINK(this, StyleList, IsSafeForWaterCan)); + m_pParentDialog->connect_stylelist_has_selected_style(LINK(this, StyleList, HasSelectedStyle)); + m_pParentDialog->connect_stylelist_update_styles(LINK(this, StyleList, UpdateStyles)); + m_pParentDialog->connect_stylelist_update_family(LINK(this, StyleList, UpdateFamily)); + m_pParentDialog->connect_stylelist_update_style_dependents( + LINK(this, StyleList, UpdateStyleDependents)); + m_pParentDialog->connect_stylelist_enable_tree_drag(LINK(this, StyleList, EnableTreeDrag)); + m_pParentDialog->connect_stylelist_filter_select(LINK(this, StyleList, FilterSelect)); + m_pParentDialog->connect_stylelist_enable_delete(LINK(this, StyleList, EnableDelete)); + m_pParentDialog->connect_stylelist_set_water_can_state(LINK(this, StyleList, SetWaterCanState)); + m_pParentDialog->connect_family_select(LINK(this, StyleList, FamilySelect)); + m_pParentDialog->connect_set_family(LINK(this, StyleList, SetFamily)); + + int nTreeHeight = m_xFmtLb->get_height_rows(8); + m_xFmtLb->set_size_request(-1, nTreeHeight); + m_xTreeBox->set_size_request(-1, nTreeHeight); + + m_xFmtLb->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl)); + m_xFmtLb->connect_custom_render(LINK(this, StyleList, CustomRenderHdl)); + m_xTreeBox->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl)); + m_xTreeBox->connect_custom_render(LINK(this, StyleList, CustomRenderHdl)); + bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get(); + m_xFmtLb->set_column_custom_renderer(0, bCustomPreview); + m_xTreeBox->set_column_custom_renderer(0, bCustomPreview); + + m_xFmtLb->set_visible(!m_bHierarchical); + m_xTreeBox->set_visible(m_bHierarchical); + Update(); +} + +IMPL_LINK_NOARG(StyleList, UpdateFamily, void*, void) +{ + m_bUpdateFamily = false; + + SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl(); + SfxViewFrame* pViewFrame = pDispat->GetFrame(); + SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); + + SfxStyleSheetBasePool* pOldStyleSheetPool = m_pStyleSheetPool; + m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr; + if (pOldStyleSheetPool != m_pStyleSheetPool) + { + if (pOldStyleSheetPool) + EndListening(*pOldStyleSheetPool); + if (m_pStyleSheetPool) + StartListening(*m_pStyleSheetPool); + } + + m_bTreeDrag = true; + m_bCanNew = m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1; + m_pParentDialog->EnableNew(m_bCanNew); + m_bTreeDrag = true; + if (m_pStyleSheetPool) + { + if (!m_xTreeBox->get_visible()) + UpdateStyles(StyleFlags::UpdateFamily | StyleFlags::UpdateFamilyList); + else + { + UpdateStyles(StyleFlags::UpdateFamily); + FillTreeBox(GetActualFamily()); + } + } + + InvalidateBindings(); +} + +bool StyleList::EnableExecute() +{ + return m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1; +} + +void StyleList::connect_LoadFactoryStyleFilter(const Link<SfxObjectShell const*, sal_Int32>& rLink) +{ + m_aLoadFactoryStyleFilter = rLink; +} + +void StyleList::connect_SaveSelection(const Link<void*, SfxObjectShell*> rLink) +{ + m_aSaveSelection = rLink; +} + +void StyleList::connect_UpdateStyleDependents(const Link<void*, void> rLink) +{ + m_aUpdateStyleDependents = rLink; +} + +/** Drop is enabled as long as it is allowed to create a new style by example, i.e. to + create a style out of the current selection. +*/ +sal_Int8 StyleList::AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper) +{ + if (rHelper.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR)) + { + // special case: page styles are allowed to create new styles by example + // but not allowed to be created by drag and drop + if (GetActualFamily() == SfxStyleFamily::Page || m_bNewByExampleDisabled) + return DND_ACTION_NONE; + else + return DND_ACTION_COPY; + } + // to enable the autoscroll when we're close to the edges + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + pTreeView->get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true); + return DND_ACTION_MOVE; +} + +// handles drop of content in treeview when creating a new style +IMPL_LINK(StyleList, ExecuteDrop, const ExecuteDropEvent&, rEvt, sal_Int8) +{ + SfxObjectShell* pDocShell = m_pCurObjShell; + if (pDocShell) + { + TransferableDataHelper aHelper(rEvt.maDropEvent.Transferable); + sal_uInt32 nFormatCount = aHelper.GetFormatCount(); + + sal_Int8 nRet = DND_ACTION_NONE; + + bool bFormatFound = false; + + for (sal_uInt32 i = 0; i < nFormatCount; ++i) + { + SotClipboardFormatId nId = aHelper.GetFormat(i); + TransferableObjectDescriptor aDesc; + + if (aHelper.GetTransferableObjectDescriptor(nId, aDesc)) + { + if (aDesc.maClassName == pDocShell->GetFactory().GetClassId()) + { + Application::PostUserEvent( + LINK(m_pParentDialog, SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop)); + + bFormatFound = true; + nRet = rEvt.mnAction; + break; + } + } + } + + if (bFormatFound) + return nRet; + } + + if (!m_xTreeBox->get_visible()) + return DND_ACTION_NONE; + + if (!m_bAllowReParentDrop) + return DND_ACTION_NONE; + + // otherwise if we're dragging with the treeview to set a new parent of the dragged style + weld::TreeView* pSource = m_xTreeBox->get_drag_source(); + // only dragging within the same widget allowed + if (!pSource || pSource != m_xTreeBox.get()) + return DND_ACTION_NONE; + + std::unique_ptr<weld::TreeIter> xSource(m_xTreeBox->make_iterator()); + if (!m_xTreeBox->get_selected(xSource.get())) + return DND_ACTION_NONE; + + std::unique_ptr<weld::TreeIter> xTarget(m_xTreeBox->make_iterator()); + if (!m_xTreeBox->get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), true)) + { + // if nothing under the mouse, use the last row + int nChildren = m_xTreeBox->n_children(); + if (!nChildren) + return DND_ACTION_NONE; + if (!m_xTreeBox->get_iter_first(*xTarget) + || !m_xTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) + return DND_ACTION_NONE; + while (m_xTreeBox->get_row_expanded(*xTarget)) + { + nChildren = m_xTreeBox->iter_n_children(*xTarget); + if (!m_xTreeBox->iter_children(*xTarget) + || !m_xTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) + return DND_ACTION_NONE; + } + } + OUString aTargetStyle = m_xTreeBox->get_text(*xTarget); + DropHdl(m_xTreeBox->get_text(*xSource), aTargetStyle); + m_xTreeBox->unset_drag_dest_row(); + FillTreeBox(GetActualFamily()); + m_pParentDialog->SelectStyle(aTargetStyle, false, *this); + return DND_ACTION_NONE; +} + +IMPL_LINK_NOARG(StyleList, NewMenuExecuteAction, void*, void) +{ + if (m_pStyleSheetPool && m_nActFamily != 0xffff) + { + const SfxStyleFamily eFam = GetFamilyItem()->GetFamily(); + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + SfxStyleSearchBits nFilter(SfxStyleSearchBits::Auto); + if (pItem && m_nActFilter != 0xffff) + nFilter = pItem->GetFilterList()[m_nActFilter].nFlags; + if (nFilter == SfxStyleSearchBits::Auto) // automatic + nFilter = m_nAppFilter; + + // why? : FloatingWindow must not be parent of a modal dialog + SfxNewStyleDlg aDlg(m_pContainer, *m_pStyleSheetPool, eFam); + auto nResult = aDlg.run(); + if (nResult == RET_OK) + { + const OUString aTemplName(aDlg.GetName()); + m_pParentDialog->Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE, aTemplName, "", + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), + *this, nFilter); + m_aUpdateFamily.Call(*this); + } + } +} + +void StyleList::DropHdl(const OUString& rStyle, const OUString& rParent) +{ + m_bDontUpdate = true; + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + const SfxStyleFamily eFam = pItem->GetFamily(); + m_pStyleSheetPool->SetParent(eFam, rStyle, rParent); + m_bDontUpdate = false; +} + +void StyleList::PrepareMenu(const Point& rPos) +{ + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + std::unique_ptr<weld::TreeIter> xIter(pTreeView->make_iterator()); + if (pTreeView->get_dest_row_at_pos(rPos, xIter.get(), false) && !pTreeView->is_selected(*xIter)) + { + pTreeView->unselect_all(); + pTreeView->set_cursor(*xIter); + pTreeView->select(*xIter); + } + FmtSelectHdl(*pTreeView); +} + +/** Internal structure for the establishment of the hierarchical view */ +namespace +{ +class StyleTree_Impl; +} + +typedef std::vector<std::unique_ptr<StyleTree_Impl>> StyleTreeArr_Impl; + +namespace +{ +class StyleTree_Impl +{ +private: + OUString aName; + OUString aParent; + StyleTreeArr_Impl pChildren; + +public: + bool HasParent() const { return !aParent.isEmpty(); } + + StyleTree_Impl(const OUString& rName, const OUString& rParent) + : aName(rName) + , aParent(rParent) + , pChildren(0) + { + } + + const OUString& getName() const { return aName; } + const OUString& getParent() const { return aParent; } + StyleTreeArr_Impl& getChildren() { return pChildren; } +}; +} + +static void MakeTree_Impl(StyleTreeArr_Impl& rArr, const OUString& aUIName) +{ + const comphelper::string::NaturalStringSorter aSorter( + ::comphelper::getProcessComponentContext(), + Application::GetSettings().GetLanguageTag().getLocale()); + + std::unordered_map<OUString, StyleTree_Impl*> styleFinder; + styleFinder.reserve(rArr.size()); + for (const auto& pEntry : rArr) + { + styleFinder.emplace(pEntry->getName(), pEntry.get()); + } + + // Arrange all under their Parents + for (auto& pEntry : rArr) + { + if (!pEntry->HasParent()) + continue; + auto it = styleFinder.find(pEntry->getParent()); + if (it != styleFinder.end()) + { + StyleTree_Impl* pCmp = it->second; + // Insert child entries sorted + auto iPos = std::lower_bound( + pCmp->getChildren().begin(), pCmp->getChildren().end(), pEntry, + [&aSorter](std::unique_ptr<StyleTree_Impl> const& pEntry1, + std::unique_ptr<StyleTree_Impl> const& pEntry2) { + return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; + }); + pCmp->getChildren().insert(iPos, std::move(pEntry)); + } + } + + // Only keep tree roots in rArr, child elements can be accessed through the hierarchy + rArr.erase( + std::remove_if(rArr.begin(), rArr.end(), + [](std::unique_ptr<StyleTree_Impl> const& pEntry) { return !pEntry; }), + rArr.end()); + + // tdf#91106 sort top level styles + std::sort(rArr.begin(), rArr.end()); + std::sort(rArr.begin(), rArr.end(), + [&aSorter, &aUIName](std::unique_ptr<StyleTree_Impl> const& pEntry1, + std::unique_ptr<StyleTree_Impl> const& pEntry2) { + if (pEntry2->getName() == aUIName) + return false; + if (pEntry1->getName() == aUIName) + return true; // default always first + return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; + }); +} + +static bool IsExpanded_Impl(const std::vector<OUString>& rEntries, std::u16string_view rStr) +{ + for (const auto& rEntry : rEntries) + { + if (rEntry == rStr) + return true; + } + return false; +} + +static void FillBox_Impl(weld::TreeView& rBox, StyleTree_Impl* pEntry, + const std::vector<OUString>& rEntries, SfxStyleFamily eStyleFamily, + const weld::TreeIter* pParent) +{ + std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator(); + const OUString& rName = pEntry->getName(); + rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get()); + + for (size_t i = 0; i < pEntry->getChildren().size(); ++i) + FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get()); +} + +namespace SfxTemplate +{ +// converts from SFX_STYLE_FAMILY Ids to 1-6 +static sal_uInt16 SfxFamilyIdToNId(SfxStyleFamily nFamily) +{ + switch (nFamily) + { + case SfxStyleFamily::Char: + return 1; + case SfxStyleFamily::Para: + return 2; + case SfxStyleFamily::Frame: + return 3; + case SfxStyleFamily::Page: + return 4; + case SfxStyleFamily::Pseudo: + return 5; + case SfxStyleFamily::Table: + return 6; + default: + return 0xffff; + } +} +// converts from 1-6 to SFX_STYLE_FAMILY Ids +static SfxStyleFamily NIdToSfxFamilyId(sal_uInt16 nId) +{ + switch (nId) + { + case 1: + return SfxStyleFamily::Char; + case 2: + return SfxStyleFamily::Para; + case 3: + return SfxStyleFamily::Frame; + case 4: + return SfxStyleFamily::Page; + case 5: + return SfxStyleFamily::Pseudo; + case 6: + return SfxStyleFamily::Table; + default: + return SfxStyleFamily::All; + } +} +} + +sal_uInt16 StyleList::StyleNrToInfoOffset(sal_uInt16 nId) +{ + const SfxStyleFamilyItem& rItem = m_xStyleFamilies->at(nId); + return SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()) - 1; +} + +// Helper function: Access to the current family item +const SfxStyleFamilyItem* StyleList::GetFamilyItem() const +{ + const size_t nCount = m_xStyleFamilies->size(); + for (size_t i = 0; i < nCount; ++i) + { + const SfxStyleFamilyItem& rItem = m_xStyleFamilies->at(i); + sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()); + if (nId == m_nActFamily) + return &rItem; + } + return nullptr; +} + +void StyleList::GetSelectedStyle() const +{ + const OUString aTemplName(GetSelectedEntry()); + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); +} + +// Used to get the current selected entry in visible treeview +OUString StyleList::GetSelectedEntry() const +{ + OUString aRet; + if (m_xTreeBox->get_visible()) + aRet = m_xTreeBox->get_selected_text(); + else + aRet = m_xFmtLb->get_selected_text(); + return aRet; +} + +/** + * Is it safe to show the water-can / fill icon. If we've a + * hierarchical widget - we have only single select, otherwise + * we need to check if we have a multi-selection. We either have + * a m_xTreeBox showing or an m_xFmtLb (which we hide when not shown) + */ +IMPL_LINK_NOARG(StyleList, IsSafeForWaterCan, void*, bool) +{ + if (m_xTreeBox->get_visible()) + return m_xTreeBox->get_selected_index() != -1; + else + return m_xFmtLb->count_selected_rows() == 1; +} + +IMPL_LINK(StyleList, SetWaterCanState, const SfxBoolItem*, pItem, void) +{ + size_t nCount = m_xStyleFamilies->size(); + m_pBindings->EnterRegistrations(); + for (size_t n = 0; n < nCount; n++) + { + SfxControllerItem* pCItem = pBoundItems[n].get(); + bool bChecked = pItem && pItem->GetValue(); + if (pCItem->IsBound() == bChecked) + { + if (!bChecked) + pCItem->ReBind(); + else + pCItem->UnBind(); + } + } + m_pBindings->LeaveRegistrations(); +} + +IMPL_LINK(StyleList, FamilySelect, sal_uInt16, nEntry, void) +{ + m_nActFamily = nEntry; + SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl(); + SfxUInt16Item const aItem(SID_STYLE_FAMILY, + static_cast<sal_uInt16>(SfxTemplate::NIdToSfxFamilyId(nEntry))); + pDispat->ExecuteList(SID_STYLE_FAMILY, SfxCallMode::SYNCHRON, { &aItem }); + m_pBindings->Invalidate(SID_STYLE_FAMILY); + m_pBindings->Update(SID_STYLE_FAMILY); + m_aUpdateFamily.Call(*this); +} + +// It selects the style in treeview +// bIsCallBack is true for the selected style. For eg. if "Addressee" is selected in +// styles, bIsCallBack will be true for it. +void StyleList::SelectStyle(const OUString& rStr, bool bIsCallback) +{ + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + if (!pItem) + return; + const SfxStyleFamily eFam = pItem->GetFamily(); + SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(rStr, eFam); + if (pStyle) + { + bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); + m_pParentDialog->EnableEdit(bReadWrite); + m_pParentDialog->EnableHide(bReadWrite && !pStyle->IsHidden() && !pStyle->IsUsed()); + m_pParentDialog->EnableShow(bReadWrite && pStyle->IsHidden()); + } + else + { + m_pParentDialog->EnableEdit(false); + m_pParentDialog->EnableHide(false); + m_pParentDialog->EnableShow(false); + } + + if (!bIsCallback) + { + if (m_xTreeBox->get_visible()) + { + if (!rStr.isEmpty()) + { + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator(); + bool bEntry = m_xTreeBox->get_iter_first(*xEntry); + while (bEntry) + { + if (m_xTreeBox->get_text(*xEntry) == rStr) + { + m_xTreeBox->scroll_to_row(*xEntry); + m_xTreeBox->select(*xEntry); + break; + } + bEntry = m_xTreeBox->iter_next(*xEntry); + } + } + else if (eFam == SfxStyleFamily::Pseudo) + { + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator(); + if (m_xTreeBox->get_iter_first(*xEntry)) + { + m_xTreeBox->scroll_to_row(*xEntry); + m_xTreeBox->select(*xEntry); + } + } + else + m_xTreeBox->unselect_all(); + } + else + { + bool bSelect = !rStr.isEmpty(); + if (bSelect) + { + std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator(); + bool bEntry = m_xFmtLb->get_iter_first(*xEntry); + while (bEntry && m_xFmtLb->get_text(*xEntry) != rStr) + bEntry = m_xFmtLb->iter_next(*xEntry); + if (!bEntry) + bSelect = false; + else + { + if (!m_xFmtLb->is_selected(*xEntry)) + { + m_xFmtLb->unselect_all(); + m_xFmtLb->scroll_to_row(*xEntry); + m_xFmtLb->select(*xEntry); + } + } + } + + if (!bSelect) + { + m_xFmtLb->unselect_all(); + m_pParentDialog->EnableEdit(false); + m_pParentDialog->EnableHide(false); + m_pParentDialog->EnableShow(false); + } + } + } +} + +static void MakeExpanded_Impl(const weld::TreeView& rBox, std::vector<OUString>& rEntries) +{ + std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator(); + if (rBox.get_iter_first(*xEntry)) + { + do + { + if (rBox.get_row_expanded(*xEntry)) + rEntries.push_back(rBox.get_text(*xEntry)); + } while (rBox.iter_next(*xEntry)); + } +} + +IMPL_LINK(StyleList, EnableTreeDrag, bool, m_bEnable, void) +{ + if (m_pStyleSheetPool) + { + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + SfxStyleSheetBase* pStyle = pItem ? m_pStyleSheetPool->First(pItem->GetFamily()) : nullptr; + m_bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && m_bEnable; + } + m_bTreeDrag = m_bEnable; + m_pParentDialog->SetEnableDrag(m_bTreeDrag); +} + +// Fill the treeview + +void StyleList::FillTreeBox(SfxStyleFamily eFam) +{ + assert(m_xTreeBox && "FillTreeBox() without treebox"); + if (!m_pStyleSheetPool || m_nActFamily == 0xffff) + return; + + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + if (!pItem) + return; + + StyleTreeArr_Impl aArr; + SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, SfxStyleSearchBits::AllVisible); + + m_bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && m_bTreeDrag; + + while (pStyle) + { + StyleTree_Impl* pNew = new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent()); + aArr.emplace_back(pNew); + pStyle = m_pStyleSheetPool->Next(); + } + OUString aUIName = getDefaultStyleName(eFam); + MakeTree_Impl(aArr, aUIName); + std::vector<OUString> aEntries; + MakeExpanded_Impl(*m_xTreeBox, aEntries); + m_xTreeBox->freeze(); + m_xTreeBox->clear(); + const sal_uInt16 nCount = aArr.size(); + + for (sal_uInt16 i = 0; i < nCount; ++i) + { + FillBox_Impl(*m_xTreeBox, aArr[i].get(), aEntries, eFam, nullptr); + aArr[i].reset(); + } + + m_pParentDialog->EnableItem("watercan", false); + + SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get(); + + m_xTreeBox->thaw(); + + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator(); + bool bEntry = m_xTreeBox->get_iter_first(*xEntry); + if (bEntry && nCount) + m_xTreeBox->expand_row(*xEntry); + + while (bEntry) + { + if (IsExpanded_Impl(aEntries, m_xTreeBox->get_text(*xEntry))) + m_xTreeBox->expand_row(*xEntry); + bEntry = m_xTreeBox->iter_next(*xEntry); + } + + OUString aStyle; + if (pState) // Select current entry + aStyle = pState->GetStyleName(); + m_pParentDialog->SelectStyle(aStyle, false, *this); + EnableDelete(nullptr); +} + +static OUString lcl_GetStyleFamilyName(SfxStyleFamily nFamily) +{ + if (nFamily == SfxStyleFamily::Char) + return "CharacterStyles"; + if (nFamily == SfxStyleFamily::Para) + return "ParagraphStyles"; + if (nFamily == SfxStyleFamily::Page) + return "PageStyles"; + if (nFamily == SfxStyleFamily::Table) + return "TableStyles"; + if (nFamily == SfxStyleFamily::Pseudo) + return "NumberingStyles"; + return OUString(); +} + +OUString StyleList::getDefaultStyleName(const SfxStyleFamily eFam) +{ + OUString sDefaultStyle; + OUString aFamilyName = lcl_GetStyleFamilyName(eFam); + if (aFamilyName == "TableStyles") + sDefaultStyle = "Default Style"; + else if (aFamilyName == "NumberingStyles") + sDefaultStyle = "No List"; + else + sDefaultStyle = "Standard"; + uno::Reference<style::XStyleFamiliesSupplier> xModel(m_pCurObjShell->GetModel(), + uno::UNO_QUERY); + OUString aUIName; + try + { + uno::Reference<container::XNameAccess> xStyles; + uno::Reference<container::XNameAccess> xCont = xModel->getStyleFamilies(); + xCont->getByName(aFamilyName) >>= xStyles; + uno::Reference<beans::XPropertySet> xInfo; + xStyles->getByName(sDefaultStyle) >>= xInfo; + xInfo->getPropertyValue("DisplayName") >>= aUIName; + } + catch (const uno::Exception&) + { + } + return aUIName; +} + +SfxStyleFamily StyleList::GetActualFamily() const +{ + const SfxStyleFamilyItem* pFamilyItem = GetFamilyItem(); + if (!pFamilyItem || m_nActFamily == 0xffff) + return SfxStyleFamily::Para; + else + return pFamilyItem->GetFamily(); +} + +IMPL_LINK_NOARG(StyleList, HasSelectedStyle, void*, bool) +{ + return m_xTreeBox->get_visible() ? m_xTreeBox->get_selected_index() != -1 + : m_xFmtLb->count_selected_rows() != 0; +} + +IMPL_LINK_NOARG(StyleList, UpdateStyleDependents, void*, void) +{ + // Trigger Help PI. Only when the watercan is on + if (m_nActFamily != 0xffff && m_pParentDialog->IsCheckedItem("watercan") && + // only if that region is allowed + nullptr != m_pFamilyState[m_nActFamily - 1] + && (m_xTreeBox || m_xFmtLb->count_selected_rows() <= 1)) + { + m_pParentDialog->Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, *this); + m_pParentDialog->Execute_Impl(SID_STYLE_WATERCAN, GetSelectedEntry(), "", + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); + } +} + +// Comes into action when the current style is changed +IMPL_LINK(StyleList, UpdateStyles, StyleFlags, nFlags, void) +{ + OSL_ENSURE(nFlags != StyleFlags::NONE, "nothing to do"); + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + if (!pItem) + { + // Is the case for the template catalog + const size_t nFamilyCount = m_xStyleFamilies->size(); + size_t n; + for (n = 0; n < nFamilyCount; n++) + if (m_pFamilyState[StyleNrToInfoOffset(n)]) + break; + if (n == nFamilyCount) + // It happens sometimes, God knows why + return; + m_nAppFilter = m_pFamilyState[StyleNrToInfoOffset(n)]->GetValue(); + m_pParentDialog->SetApplicationFilter(m_nAppFilter); + m_pParentDialog->FamilySelect(StyleNrToInfoOffset(n) + 1); + pItem = GetFamilyItem(); + } + + const SfxStyleFamily eFam = pItem->GetFamily(); + + SfxStyleSearchBits nFilter(m_nActFilter < pItem->GetFilterList().size() + ? pItem->GetFilterList()[m_nActFilter].nFlags + : SfxStyleSearchBits::Auto); + if (nFilter == SfxStyleSearchBits::Auto) // automatic + nFilter = m_nAppFilter; + + OSL_ENSURE(m_pStyleSheetPool, "no StyleSheetPool"); + if (!m_pStyleSheetPool) + return; + + pItem = GetFamilyItem(); + + m_aUpdateStyles.Call(nFlags); + + SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, nFilter); + + std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator(); + bool bEntry = m_xFmtLb->get_iter_first(*xEntry); + std::vector<OUString> aStrings; + + comphelper::string::NaturalStringSorter aSorter( + ::comphelper::getProcessComponentContext(), + Application::GetSettings().GetLanguageTag().getLocale()); + + while (pStyle) + { + aStrings.push_back(pStyle->GetName()); + pStyle = m_pStyleSheetPool->Next(); + } + OUString aUIName = getDefaultStyleName(eFam); + + // Paradoxically, with a list and non-Latin style names, + // sorting twice is faster than sorting once. + // The first sort has a cheap comparator, and gets the list into mostly-sorted order. + // Then the second sort needs to call its (much more expensive) comparator less often. + std::sort(aStrings.begin(), aStrings.end()); + std::sort(aStrings.begin(), aStrings.end(), + [&aSorter, &aUIName](const OUString& rLHS, const OUString& rRHS) { + if (rRHS == aUIName) + return false; + if (rLHS == aUIName) + return true; // default always first + return aSorter.compare(rLHS, rRHS) < 0; + }); + + size_t nCount = aStrings.size(); + size_t nPos = 0; + while (nPos < nCount && bEntry && aStrings[nPos] == m_xFmtLb->get_text(*xEntry)) + { + ++nPos; + bEntry = m_xFmtLb->iter_next(*xEntry); + } + + if (nPos < nCount || bEntry) + { + // Fills the display box + m_xFmtLb->freeze(); + m_xFmtLb->clear(); + + for (nPos = 0; nPos < nCount; ++nPos) + m_xFmtLb->append(aStrings[nPos], aStrings[nPos]); + + m_xFmtLb->thaw(); + } + // Selects the current style if any + SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get(); + OUString aStyle; + if (pState) + aStyle = pState->GetStyleName(); + m_pParentDialog->SelectStyle(aStyle, false, *this); + EnableDelete(nullptr); +} + +void StyleList::SetFamilyState(sal_uInt16 nSlotId, const SfxTemplateItem* pItem) +{ + sal_uInt16 nIdx = nSlotId - SID_STYLE_FAMILY_START; + m_pFamilyState[nIdx].reset(); + if (pItem) + m_pFamilyState[nIdx].reset(new SfxTemplateItem(*pItem)); + m_bUpdateFamily = true; +} + +void StyleList::SetHierarchical() +{ + m_bHierarchical = true; + const OUString aSelectEntry(GetSelectedEntry()); + m_xFmtLb->hide(); + FillTreeBox(GetActualFamily()); + m_pParentDialog->SelectStyle(aSelectEntry, false, *this); + m_xTreeBox->show(); +} + +void StyleList::SetFilterControlsHandle() +{ + m_xTreeBox->hide(); + m_xFmtLb->show(); + m_bHierarchical = false; +} + +// Handler for the New-Buttons +void StyleList::NewHdl() +{ + if (m_nActFamily == 0xffff + || !(m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1)) + return; + + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + const SfxStyleFamily eFam = pItem->GetFamily(); + SfxStyleSearchBits nMask(SfxStyleSearchBits::Auto); + if (m_nActFilter != 0xffff) + nMask = pItem->GetFilterList()[m_nActFilter].nFlags; + if (nMask == SfxStyleSearchBits::Auto) // automatic + nMask = m_nAppFilter; + + m_pParentDialog->Execute_Impl(SID_STYLE_NEW, "", GetSelectedEntry(), + static_cast<sal_uInt16>(eFam), *this, nMask); +} + +// Handler for the edit-Buttons +void StyleList::EditHdl() +{ + if (m_nActFamily != 0xffff && HasSelectedStyle(nullptr)) + { + sal_uInt16 nFilter = m_nActFilter; + OUString aTemplName(GetSelectedEntry()); + GetSelectedStyle(); // -Wall required?? + m_pParentDialog->Execute_Impl(SID_STYLE_EDIT, aTemplName, OUString(), + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this, + SfxStyleSearchBits::Auto, &nFilter); + } +} + +// Handler for the Delete-Buttons +void StyleList::DeleteHdl() +{ + if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr)) + return; + + bool bUsedStyle = false; // one of the selected styles are used in the document? + + std::vector<std::unique_ptr<weld::TreeIter>> aList; + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + + OUStringBuffer aMsg; + aMsg.append(SfxResId(STR_DELETE_STYLE_USED) + SfxResId(STR_DELETE_STYLE)); + + pTreeView->selected_foreach( + [this, pTreeView, pItem, &aList, &bUsedStyle, &aMsg](weld::TreeIter& rEntry) { + aList.emplace_back(pTreeView->make_iterator(&rEntry)); + // check the style is used or not + const OUString aTemplName(pTreeView->get_text(rEntry)); + + SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); + + if (pStyle->IsUsed()) // pStyle is in use in the document? + { + if (bUsedStyle) // add a separator for the second and later styles + aMsg.append(", "); + aMsg.append(aTemplName); + bUsedStyle = true; + } + + return false; + }); + + bool aApproved = false; + + // we only want to show the dialog once and if we want to delete a style in use (UX-advice) + if (bUsedStyle) + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog( + pTreeView, VclMessageType::Question, VclButtonsType::YesNo, aMsg.makeStringAndClear())); + aApproved = xBox->run() == RET_YES; + } + + // if there are no used styles selected or the user approved the changes + if (bUsedStyle && !aApproved) + return; + + for (auto const& elem : aList) + { + const OUString aTemplName(pTreeView->get_text(*elem)); + m_bDontUpdate = true; // To prevent the Treelistbox to shut down while deleting + m_pParentDialog->Execute_Impl(SID_STYLE_DELETE, aTemplName, OUString(), + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); + + if (m_xTreeBox->get_visible()) + { + weld::RemoveParentKeepChildren(*m_xTreeBox, *elem); + m_bDontUpdate = false; + } + } + m_bDontUpdate = false; // if everything is deleted set m_bDontUpdate back to false + UpdateStyles(StyleFlags::UpdateFamilyList); // and force-update the list +} + +void StyleList::HideHdl() +{ + if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr)) + return; + + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry) { + OUString aTemplName = pTreeView->get_text(rEntry); + + m_pParentDialog->Execute_Impl(SID_STYLE_HIDE, aTemplName, OUString(), + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); + + return false; + }); +} + +void StyleList::ShowHdl() +{ + if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr)) + return; + + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry) { + OUString aTemplName = pTreeView->get_text(rEntry); + + m_pParentDialog->Execute_Impl(SID_STYLE_SHOW, aTemplName, OUString(), + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); + + return false; + }); +} + +IMPL_LINK_NOARG(StyleList, EnableDelete, void*, void) +{ + bool bEnableDelete(false); + if (m_nActFamily != 0xffff && HasSelectedStyle(nullptr)) + { + OSL_ENSURE(m_pStyleSheetPool, "No StyleSheetPool"); + const OUString aTemplName(GetSelectedEntry()); + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + const SfxStyleFamily eFam = pItem->GetFamily(); + SfxStyleSearchBits nFilter = SfxStyleSearchBits::Auto; + if (pItem->GetFilterList().size() > m_nActFilter) + nFilter = pItem->GetFilterList()[m_nActFilter].nFlags; + if (nFilter == SfxStyleSearchBits::Auto) // automatic + nFilter = m_nAppFilter; + const SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find( + aTemplName, eFam, m_xTreeBox->get_visible() ? SfxStyleSearchBits::All : nFilter); + + OSL_ENSURE(pStyle, "Style not found"); + if (pStyle && pStyle->IsUserDefined()) + { + if (pStyle->HasClearParentSupport() || !pStyle->IsUsed()) + { + bEnableDelete = true; + } + else if (pStyle->GetFamily() == SfxStyleFamily::Page) + { + // Hack to allow Calc page styles to be deleted, + // remove when IsUsed is fixed for Calc page styles. + SfxViewFrame* pFrame = m_pCurObjShell->GetFrame(); + if (pFrame) + { + uno::Reference<frame::XFrame> xFrame = pFrame->GetFrame().GetFrameInterface(); + if (vcl::CommandInfoProvider::GetModuleIdentifier(xFrame) + == "com.sun.star.sheet.SpreadsheetDocument") + { + bEnableDelete = true; + } + } + } + } + } + m_pParentDialog->EnableDel(bEnableDelete); +} + +IMPL_LINK_NOARG(StyleList, Clear, void*, void) +{ + m_xStyleFamilies.reset(); + for (auto& i : m_pFamilyState) + i.reset(); + m_pCurObjShell = nullptr; + for (auto& i : pBoundItems) + i.reset(); +} + +void StyleList::ShowMenu(const CommandEvent& rCEvt) +{ + CreateContextMenu(); + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + OString sCommand( + mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))); + MenuSelect(sCommand); +} + +void StyleList::MenuSelect(const OString& rIdent) +{ + sLastItemIdent = rIdent; + if (sLastItemIdent.isEmpty()) + return; + Application::PostUserEvent(LINK(this, StyleList, MenuSelectAsyncHdl)); /***check this****/ +} + +void StyleList::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + const SfxHintId nId = rHint.GetId(); + + switch (nId) + { + case SfxHintId::UpdateDone: + { + SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); + SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); + if (m_pParentDialog->GetNotifyUpdate() + && (!m_pParentDialog->IsCheckedItem("watercan") + || (pDocShell && pDocShell->GetStyleSheetPool() != m_pStyleSheetPool))) + { + m_pParentDialog->SetNotifyupdate(false); + Update(); + } + else if (m_bUpdateFamily) + { + m_aUpdateFamily.Call(*this); + } + + if (m_pStyleSheetPool) + { + OUString aStr = GetSelectedEntry(); + if (!aStr.isEmpty()) + { + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + if (!pItem) + break; + const SfxStyleFamily eFam = pItem->GetFamily(); + SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aStr, eFam); + if (pStyle) + { + bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); + m_pParentDialog->EnableEdit(bReadWrite); + m_pParentDialog->EnableHide(bReadWrite && !pStyle->IsUsed() + && !pStyle->IsHidden()); + m_pParentDialog->EnableShow(bReadWrite && pStyle->IsHidden()); + } + else + { + m_pParentDialog->EnableEdit(false); + m_pParentDialog->EnableHide(false); + m_pParentDialog->EnableShow(false); + } + } + } + break; + } + + // Necessary if switching between documents and in both documents + // the same template is used. Do not immediately call Update_Impl, + // for the case that one of the documents is an internal InPlaceObject! + case SfxHintId::DocChanged: + m_pParentDialog->SetNotifyupdate(true); + break; + case SfxHintId::Dying: + { + EndListening(*m_pStyleSheetPool); + m_pStyleSheetPool = nullptr; + break; + } + default: + break; + } + + // Do not set timer when the stylesheet pool is in the box, because it is + // possible that a new one is registered after the timer is up - + // works bad in UpdateStyles_Impl ()! + + if (!m_bDontUpdate && nId != SfxHintId::Dying + && (dynamic_cast<const SfxStyleSheetPoolHint*>(&rHint) + || dynamic_cast<const SfxStyleSheetHint*>(&rHint) + || dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint) + || nId == SfxHintId::StyleSheetModified)) + { + if (!pIdle) + { + pIdle.reset(new Idle("SfxCommonTemplate")); + pIdle->SetPriority(TaskPriority::LOWEST); + pIdle->SetInvokeHandler(LINK(this, StyleList, TimeOut)); + } + pIdle->Start(); + } +} + +IMPL_LINK_NOARG(StyleList, TimeOut, Timer*, void) +{ + if (!m_bDontUpdate) + { + m_bDontUpdate = true; + if (!m_xTreeBox->get_visible()) + UpdateStyles(StyleFlags::UpdateFamilyList); + else + { + FillTreeBox(GetActualFamily()); + SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get(); + if (pState) + { + m_pParentDialog->SelectStyle(pState->GetStyleName(), false, *this); + EnableDelete(nullptr); + } + } + m_bDontUpdate = false; + pIdle.reset(); + } + else + pIdle->Start(); +} + +IMPL_LINK_NOARG(StyleList, MenuSelectAsyncHdl, void*, void) +{ + if (sLastItemIdent == "new") + NewHdl(); + else if (sLastItemIdent == "edit") + EditHdl(); + else if (sLastItemIdent == "delete") + DeleteHdl(); + else if (sLastItemIdent == "hide") + HideHdl(); + else if (sLastItemIdent == "show") + ShowHdl(); +} + +// Double-click on a style sheet in the ListBox is applied. +IMPL_LINK(StyleList, DragBeginHdl, bool&, rUnsetDragIcon, bool) +{ + rUnsetDragIcon = false; + // Allow normal processing. only if bAllowReParentDrop is true + return !m_bAllowReParentDrop; +} + +IMPL_LINK(StyleList, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + bool bRet = false; + const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode(); + if (m_bCanDel && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_DELETE) + { + DeleteHdl(); + bRet = true; + } + return bRet; +} + +IMPL_LINK(StyleList, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString) +{ + weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); + const OUString aTemplName(pTreeView->get_text(rEntry)); + OUString sQuickHelpText(aTemplName); + + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + if (!pItem) + return sQuickHelpText; + SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); + + if (pStyle && pStyle->IsUsed()) // pStyle is in use in the document? + { + OUString sUsedBy; + if (pStyle->GetFamily() == SfxStyleFamily::Pseudo) + sUsedBy = pStyle->GetUsedBy(); + + if (!sUsedBy.isEmpty()) + { + const sal_Int32 nMaxLen = 80; + if (sUsedBy.getLength() > nMaxLen) + { + sUsedBy = OUString::Concat(sUsedBy.subView(0, nMaxLen)) + "..."; + } + + OUString aMessage = SfxResId(STR_STYLEUSEDBY); + aMessage = aMessage.replaceFirst("%STYLELIST", sUsedBy); + sQuickHelpText = aTemplName + " " + aMessage; + } + } + + return sQuickHelpText; +} + +IMPL_LINK(StyleList, CustomRenderHdl, weld::TreeView::render_args, aPayload, void) +{ + vcl::RenderContext& rRenderContext = std::get<0>(aPayload); + const ::tools::Rectangle& rRect = std::get<1>(aPayload); + ::tools::Rectangle aRect( + rRect.TopLeft(), + Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), rRect.GetHeight())); + bool bSelected = std::get<2>(aPayload); + const OUString& rId = std::get<3>(aPayload); + + rRenderContext.Push(PushFlags::TEXTCOLOR); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + if (bSelected) + rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); + else + rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor()); + + bool bSuccess = false; + + SfxObjectShell* pShell = SfxObjectShell::Current(); + sfx2::StyleManager* pStyleManager = pShell ? pShell->GetStyleManager() : nullptr; + + if (pStyleManager) + { + const SfxStyleFamilyItem* pItem = GetFamilyItem(); + SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(rId, pItem->GetFamily()); + + if (pStyleSheet) + { + rRenderContext.Push(PushFlags::ALL); + sal_Int32 nSize = aRect.GetHeight(); + std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer( + pStyleManager->CreateStylePreviewRenderer(rRenderContext, pStyleSheet, nSize)); + bSuccess = pStylePreviewRenderer->recalculate() && pStylePreviewRenderer->render(aRect); + rRenderContext.Pop(); + } + } + + if (!bSuccess) + rRenderContext.DrawText(aRect, rId, DrawTextFlags::Left | DrawTextFlags::VCenter); + + rRenderContext.Pop(); +} + +// Selection of a template during the Watercan-Status +IMPL_LINK(StyleList, FmtSelectHdl, weld::TreeView&, rListBox, void) +{ + std::unique_ptr<weld::TreeIter> xHdlEntry = rListBox.make_iterator(); + if (!rListBox.get_cursor(xHdlEntry.get())) + return; + + if (rListBox.is_selected(*xHdlEntry)) + m_aUpdateStyleDependents.Call(nullptr); + + m_pParentDialog->SelectStyle(rListBox.get_text(*xHdlEntry), true, *this); +} + +IMPL_LINK_NOARG(StyleList, TreeListApplyHdl, weld::TreeView&, bool) +{ + // only if that region is allowed + if (m_nActFamily != 0xffff && nullptr != m_pFamilyState[m_nActFamily - 1] + && !GetSelectedEntry().isEmpty()) + { + m_pParentDialog->Execute_Impl(SID_STYLE_APPLY, GetSelectedEntry(), OUString(), + static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this, + SfxStyleSearchBits::Auto, nullptr, &m_nModifier); + } + // After selecting a focused item if possible again on the app window + if (dynamic_cast<const SfxTemplateDialog_Impl*>(m_pParentDialog) != nullptr) + { + SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); + SfxViewShell* pVu = pViewFrame->GetViewShell(); + vcl::Window* pAppWin = pVu ? pVu->GetWindow() : nullptr; + if (pAppWin) + pAppWin->GrabFocus(); + } + + return true; +} + +IMPL_LINK(StyleList, MousePressHdl, const MouseEvent&, rMEvt, bool) +{ + m_nModifier = rMEvt.GetModifier(); + return false; +} + +// Notice from SfxBindings that the update is completed. Pushes out the update +// of the display. +void StyleList::Update() +{ + bool bDocChanged = false; + SfxStyleSheetBasePool* pNewPool = nullptr; + SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); + SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); + if (pDocShell) + pNewPool = pDocShell->GetStyleSheetPool(); + + if (pNewPool != m_pStyleSheetPool && pDocShell) + { + SfxModule* pNewModule = pDocShell->GetModule(); + if (pNewModule && pNewModule != m_Module) + { + m_aClearResource.Call(nullptr); + m_aReadResource.Call(*this); + } + if (m_pStyleSheetPool) + { + EndListening(*m_pStyleSheetPool); + m_pStyleSheetPool = nullptr; + } + + if (pNewPool) + { + StartListening(*pNewPool); + m_pStyleSheetPool = pNewPool; + bDocChanged = true; + } + } + + if (m_bUpdateFamily) + m_aUpdateFamily.Call(*this); + + sal_uInt16 i; + for (i = 0; i < MAX_FAMILIES; ++i) + if (m_pFamilyState[i]) + break; + if (i == MAX_FAMILIES || !pNewPool) + // nothing is allowed + return; + + SfxTemplateItem* pItem = nullptr; + // current region not within the allowed region or default + if (m_nActFamily == 0xffff || nullptr == (pItem = m_pFamilyState[m_nActFamily - 1].get())) + { + m_pParentDialog->CheckItem(OString::number(m_nActFamily), false); + const size_t nFamilyCount = m_xStyleFamilies->size(); + size_t n; + for (n = 0; n < nFamilyCount; n++) + if (m_pFamilyState[StyleNrToInfoOffset(n)]) + break; + + std::unique_ptr<SfxTemplateItem>& pNewItem = m_pFamilyState[StyleNrToInfoOffset(n)]; + m_nAppFilter = pNewItem->GetValue(); + m_pParentDialog->SetApplicationFilter(m_nAppFilter); + m_pParentDialog->FamilySelect(StyleNrToInfoOffset(n) + 1); + pItem = pNewItem.get(); + } + else if (bDocChanged) + { + // other DocShell -> all new + m_pParentDialog->CheckItem(OString::number(m_nActFamily)); + m_nActFilter = static_cast<sal_uInt16>(m_aLoadFactoryStyleFilter.Call(pDocShell)); + m_pParentDialog->SetFilterByIndex(m_nActFilter); + if (0xffff == m_nActFilter) + { + m_nActFilter = pDocShell->GetAutoStyleFilterIndex(); + m_pParentDialog->SetFilterByIndex(m_nActFilter); + } + + m_nAppFilter = pItem->GetValue(); + m_pParentDialog->SetApplicationFilter(m_nAppFilter); + if (!m_xTreeBox->get_visible()) + { + UpdateStyles(StyleFlags::UpdateFamilyList); + } + else + FillTreeBox(GetActualFamily()); + } + else + { + // other filters for automatic + m_pParentDialog->CheckItem(OString::number(m_nActFamily)); + const SfxStyleFamilyItem* pStyleItem = GetFamilyItem(); + if (pStyleItem + && SfxStyleSearchBits::Auto == pStyleItem->GetFilterList()[m_nActFilter].nFlags + && m_nAppFilter != pItem->GetValue()) + { + m_nAppFilter = pItem->GetValue(); + m_pParentDialog->SetApplicationFilter(m_nAppFilter); + if (!m_xTreeBox->get_visible()) + UpdateStyles(StyleFlags::UpdateFamilyList); + else + FillTreeBox(GetActualFamily()); + } + else + { + m_nAppFilter = pItem->GetValue(); + m_pParentDialog->SetApplicationFilter(m_nAppFilter); + } + } + const OUString aStyle(pItem->GetStyleName()); + m_pParentDialog->SelectStyle(aStyle, false, *this); + EnableDelete(nullptr); + m_pParentDialog->EnableNew(m_bCanNew); +} + +void StyleList::EnablePreview(bool bCustomPreview) +{ + m_xFmtLb->clear(); + m_xFmtLb->set_column_custom_renderer(0, bCustomPreview); + m_xTreeBox->clear(); + m_xTreeBox->set_column_custom_renderer(0, bCustomPreview); +} + +const SfxStyleFamilyItem& StyleList::GetFamilyItemByIndex(size_t i) const +{ + return m_xStyleFamilies->at(i); +} + +IMPL_STATIC_LINK(StyleList, CustomGetSizeHdl, weld::TreeView::get_size_args, aPayload, Size) +{ + vcl::RenderContext& rRenderContext = aPayload.first; + return Size(42, 32 * rRenderContext.GetDPIScaleFactor()); +} + +IMPL_LINK(StyleList, PopupFlatMenuHdl, const CommandEvent&, rCEvt, bool) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + PrepareMenu(rCEvt.GetMousePosPixel()); + + if (m_xFmtLb->count_selected_rows() <= 0) + { + m_pParentDialog->EnableEdit(false); + m_pParentDialog->EnableDel(false); + } + + ShowMenu(rCEvt); + + return true; +} + +IMPL_LINK(StyleList, PopupTreeMenuHdl, const CommandEvent&, rCEvt, bool) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + PrepareMenu(rCEvt.GetMousePosPixel()); + + ShowMenu(rCEvt); + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/dialog/templdlg.cxx b/sfx2/source/dialog/templdlg.cxx index 8951cfb71cbf..ae0d646abc75 100644 --- a/sfx2/source/dialog/templdlg.cxx +++ b/sfx2/source/dialog/templdlg.cxx @@ -110,415 +110,87 @@ private: DeletionWatcher *const m_pPrevious; /// let's add more epicycles! }; -/** Drop is enabled as long as it is allowed to create a new style by example, i.e. to - create a style out of the current selection. -*/ -sal_Int8 SfxCommonTemplateDialog_Impl::AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper) -{ - if (rHelper.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR)) - { - // special case: page styles are allowed to create new styles by example - // but not allowed to be created by drag and drop - if (GetActualFamily() == SfxStyleFamily::Page || bNewByExampleDisabled) - return DND_ACTION_NONE; - else - return DND_ACTION_COPY; - } - - // to enable the autoscroll when we're close to the edges - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - pTreeView->get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true); - return DND_ACTION_MOVE; -} - sal_Int8 SfxCommonTemplateDialog_Impl::ExecuteDrop(const ExecuteDropEvent& rEvt) { // handle drop of content into the treeview to create a new style - SfxObjectShell* pDocShell = GetObjectShell(); - if (pDocShell) - { - TransferableDataHelper aHelper(rEvt.maDropEvent.Transferable); - sal_uInt32 nFormatCount = aHelper.GetFormatCount(); - - sal_Int8 nRet = DND_ACTION_NONE; - - bool bFormatFound = false; - - for ( sal_uInt32 i = 0; i < nFormatCount; ++i ) - { - SotClipboardFormatId nId = aHelper.GetFormat(i); - TransferableObjectDescriptor aDesc; - - if ( aHelper.GetTransferableObjectDescriptor( nId, aDesc ) ) - { - if ( aDesc.maClassName == pDocShell->GetFactory().GetClassId() ) - { - Application::PostUserEvent(LINK(this, SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop)); - - bFormatFound = true; - nRet = rEvt.mnAction; - break; - } - } - } - - if (bFormatFound) - return nRet; - } - - if (!mxTreeBox->get_visible()) - return DND_ACTION_NONE; - - if (!bAllowReParentDrop) - return DND_ACTION_NONE; - - // otherwise if we're dragging with the treeview to set a new parent of the dragged style - weld::TreeView* pSource = mxTreeBox->get_drag_source(); - // only dragging within the same widget allowed - if (!pSource || pSource != mxTreeBox.get()) - return DND_ACTION_NONE; - - std::unique_ptr<weld::TreeIter> xSource(mxTreeBox->make_iterator()); - if (!mxTreeBox->get_selected(xSource.get())) - return DND_ACTION_NONE; - - std::unique_ptr<weld::TreeIter> xTarget(mxTreeBox->make_iterator()); - if (!mxTreeBox->get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), true)) - { - // if nothing under the mouse, use the last row - int nChildren = mxTreeBox->n_children(); - if (!nChildren) - return DND_ACTION_NONE; - if (!mxTreeBox->get_iter_first(*xTarget) || !mxTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) - return DND_ACTION_NONE; - while (mxTreeBox->get_row_expanded(*xTarget)) - { - nChildren = mxTreeBox->iter_n_children(*xTarget); - if (!mxTreeBox->iter_children(*xTarget) || !mxTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) - return DND_ACTION_NONE; - } - } - OUString aTargetStyle = mxTreeBox->get_text(*xTarget); - DropHdl(mxTreeBox->get_text(*xSource), aTargetStyle); - mxTreeBox->unset_drag_dest_row(); - FillTreeBox(); - SelectStyle(aTargetStyle, false); + m_aStyleListExecuteDrop.Call(rEvt); return DND_ACTION_NONE; } -IMPL_LINK(SfxCommonTemplateDialog_Impl, DragBeginHdl, bool&, rUnsetDragIcon, bool) -{ - rUnsetDragIcon = false; - // Allow normal processing. only if bAllowReParentDrop is true - return !bAllowReParentDrop; -} - IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop, void*, void) { - ActionSelect("new"); -} - -IMPL_LINK(SfxCommonTemplateDialog_Impl, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) -{ - bool bRet = false; - const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode(); - if (bCanDel && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_DELETE) - { - DeleteHdl(); - bRet = true; - } - return bRet; + ActionSelect("new", m_aStyleList); } -IMPL_LINK(SfxCommonTemplateDialog_Impl, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString) +SfxTemplatePanelControl::SfxTemplatePanelControl(SfxBindings* pBindings, weld::Widget* pParent) + : PanelLayout(pParent, "TemplatePanel", "sfx/ui/templatepanel.ui") + , pImpl(new SfxTemplateDialog_Impl(pBindings, this)) { - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - const OUString aTemplName(pTreeView->get_text(rEntry)); - OUString sQuickHelpText(aTemplName); - - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - if (!pItem) - return sQuickHelpText; - SfxStyleSheetBase* pStyle = pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); - - if (pStyle && pStyle->IsUsed()) // pStyle is in use in the document? - { - OUString sUsedBy; - if (pStyle->GetFamily() == SfxStyleFamily::Pseudo) - sUsedBy = pStyle->GetUsedBy(); - - if (!sUsedBy.isEmpty()) - { - const sal_Int32 nMaxLen = 80; - if (sUsedBy.getLength() > nMaxLen) - { - sUsedBy = OUString::Concat(sUsedBy.subView(0, nMaxLen)) + "..."; - } - - OUString aMessage = SfxResId(STR_STYLEUSEDBY); - aMessage = aMessage.replaceFirst("%STYLELIST", sUsedBy); - sQuickHelpText = aTemplName + " " + aMessage; - } - } - - return sQuickHelpText; + OSL_ASSERT(pBindings!=nullptr); } -IMPL_STATIC_LINK(SfxCommonTemplateDialog_Impl, CustomGetSizeHdl, weld::TreeView::get_size_args, aPayload, Size) +SfxTemplatePanelControl::~SfxTemplatePanelControl() { - vcl::RenderContext& rRenderContext = aPayload.first; - return Size(42, 32 * rRenderContext.GetDPIScaleFactor()); } -IMPL_LINK(SfxCommonTemplateDialog_Impl, CustomRenderHdl, weld::TreeView::render_args, aPayload, void) +namespace SfxTemplate { - vcl::RenderContext& rRenderContext = std::get<0>(aPayload); - const ::tools::Rectangle& rRect = std::get<1>(aPayload); - ::tools::Rectangle aRect(rRect.TopLeft(), Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), rRect.GetHeight())); - bool bSelected = std::get<2>(aPayload); - const OUString& rId = std::get<3>(aPayload); - - rRenderContext.Push(PushFlags::TEXTCOLOR); - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); - if (bSelected) - rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); - else - rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor()); - - bool bSuccess = false; - - SfxObjectShell* pShell = SfxObjectShell::Current(); - sfx2::StyleManager* pStyleManager = pShell ? pShell->GetStyleManager(): nullptr; - - if (pStyleManager) + // converts from SFX_STYLE_FAMILY Ids to 1-6 + static sal_uInt16 SfxFamilyIdToNId(SfxStyleFamily nFamily) { - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(rId, pItem->GetFamily()); - - if (pStyleSheet) + switch ( nFamily ) { - rRenderContext.Push(PushFlags::ALL); - sal_Int32 nSize = aRect.GetHeight(); - std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer( - pStyleManager->CreateStylePreviewRenderer(rRenderContext, pStyleSheet, nSize)); - bSuccess = pStylePreviewRenderer->recalculate() && pStylePreviewRenderer->render(aRect); - rRenderContext.Pop(); + case SfxStyleFamily::Char: return 1; + case SfxStyleFamily::Para: return 2; + case SfxStyleFamily::Frame: return 3; + case SfxStyleFamily::Page: return 4; + case SfxStyleFamily::Pseudo: return 5; + case SfxStyleFamily::Table: return 6; + default: return 0xffff; } } - - if (!bSuccess) - rRenderContext.DrawText(aRect, rId, DrawTextFlags::Left | DrawTextFlags::VCenter); - - rRenderContext.Pop(); } -IMPL_LINK(SfxCommonTemplateDialog_Impl, PopupFlatMenuHdl, const CommandEvent&, rCEvt, bool) +void SfxCommonTemplateDialog_Impl::connect_stylelist_execute_drop( + const Link<const ExecuteDropEvent&, sal_Int8>& rLink) { - if (rCEvt.GetCommand() != CommandEventId::ContextMenu) - return false; - - PrepareMenu(rCEvt.GetMousePosPixel()); - - if (mxFmtLb->count_selected_rows() <= 0) - { - EnableEdit(false); - EnableDel(false); - } - - ShowMenu(rCEvt); - - return true; + m_aStyleListExecuteDrop = rLink; } -void SfxCommonTemplateDialog_Impl::PrepareMenu(const Point& rPos) +void SfxCommonTemplateDialog_Impl::connect_stylelist_has_selected_style(const Link<void*, bool>& rLink) { - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - std::unique_ptr<weld::TreeIter> xIter(pTreeView->make_iterator()); - if (pTreeView->get_dest_row_at_pos(rPos, xIter.get(), false) && !pTreeView->is_selected(*xIter)) - { - pTreeView->unselect_all(); - pTreeView->set_cursor(*xIter); - pTreeView->select(*xIter); - FmtSelectHdl(*pTreeView); - } + m_aStyleListHasSelectedStyle = rLink; } -void SfxCommonTemplateDialog_Impl::ShowMenu(const CommandEvent& rCEvt) +void SfxCommonTemplateDialog_Impl::connect_stylelist_update_style_dependents(const Link<void*, void>& rLink) { - CreateContextMenu(); - - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - OString sCommand(mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)))); - MenuSelect(sCommand); + m_aStyleListUpdateStyleDependents = rLink; } -IMPL_LINK(SfxCommonTemplateDialog_Impl, PopupTreeMenuHdl, const CommandEvent&, rCEvt, bool) +void SfxCommonTemplateDialog_Impl::connect_stylelist_enable_tree_drag(const Link<bool, void> rLink) { - if (rCEvt.GetCommand() != CommandEventId::ContextMenu) - return false; - - PrepareMenu(rCEvt.GetMousePosPixel()); - - ShowMenu(rCEvt); - - return true; + m_aStyleListEnableTreeDrag = rLink; } -SfxTemplatePanelControl::SfxTemplatePanelControl(SfxBindings* pBindings, weld::Widget* pParent) - : PanelLayout(pParent, "TemplatePanel", "sfx/ui/templatepanel.ui") - , pImpl(new SfxTemplateDialog_Impl(pBindings, this)) +void SfxCommonTemplateDialog_Impl::connect_stylelist_filter_select(Link<sal_uInt16, void> rLink) { - OSL_ASSERT(pBindings!=nullptr); + m_aStyleListFilterSelect = rLink; } -SfxTemplatePanelControl::~SfxTemplatePanelControl() +void SfxCommonTemplateDialog_Impl::connect_stylelist_enable_delete(const Link<void*, void> rLink) { + m_aStyleListEnableDelete = rLink; } -static void MakeExpanded_Impl(const weld::TreeView& rBox, std::vector<OUString>& rEntries) +void SfxCommonTemplateDialog_Impl::connect_stylelist_set_water_can_state( + const Link<const SfxBoolItem*, void> rLink) { - std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator(); - if (rBox.get_iter_first(*xEntry)) - { - do - { - if (rBox.get_row_expanded(*xEntry)) - rEntries.push_back(rBox.get_text(*xEntry)); - } while (rBox.iter_next(*xEntry)); - } -} - -/** Internal structure for the establishment of the hierarchical view */ -namespace { - -class StyleTree_Impl; - + m_aStyleListSetWaterCanState = rLink; } -typedef std::vector<std::unique_ptr<StyleTree_Impl>> StyleTreeArr_Impl; - -namespace { - -class StyleTree_Impl +void SfxCommonTemplateDialog_Impl::connect_family_select(const Link<sal_uInt16, void> rLink) { -private: - OUString aName; - OUString aParent; - StyleTreeArr_Impl pChildren; - -public: - bool HasParent() const { return !aParent.isEmpty(); } - - StyleTree_Impl(const OUString &rName, const OUString &rParent): - aName(rName), aParent(rParent), pChildren(0) {} - - const OUString& getName() const { return aName; } - const OUString& getParent() const { return aParent; } - StyleTreeArr_Impl& getChildren() { return pChildren; } -}; - -} - -static void MakeTree_Impl(StyleTreeArr_Impl& rArr, const OUString& aUIName) -{ - const comphelper::string::NaturalStringSorter aSorter( - ::comphelper::getProcessComponentContext(), - Application::GetSettings().GetLanguageTag().getLocale()); - - std::unordered_map<OUString, StyleTree_Impl*> styleFinder; - styleFinder.reserve(rArr.size()); - for (const auto& pEntry : rArr) - { - styleFinder.emplace(pEntry->getName(), pEntry.get()); - } - - // Arrange all under their Parents - for (auto& pEntry : rArr) - { - if (!pEntry->HasParent()) - continue; - auto it = styleFinder.find(pEntry->getParent()); - if (it != styleFinder.end()) - { - StyleTree_Impl* pCmp = it->second; - // Insert child entries sorted - auto iPos = std::lower_bound(pCmp->getChildren().begin(), pCmp->getChildren().end(), pEntry, - [&aSorter](std::unique_ptr<StyleTree_Impl> const & pEntry1, std::unique_ptr<StyleTree_Impl> const & pEntry2) { return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; }); - pCmp->getChildren().insert(iPos, std::move(pEntry)); - } - } - - // Only keep tree roots in rArr, child elements can be accessed through the hierarchy - rArr.erase(std::remove_if(rArr.begin(), rArr.end(), [](std::unique_ptr<StyleTree_Impl> const & pEntry) { return !pEntry; }), rArr.end()); - - // tdf#91106 sort top level styles - std::sort(rArr.begin(), rArr.end()); - std::sort(rArr.begin(), rArr.end(), - [&aSorter, &aUIName](std::unique_ptr<StyleTree_Impl> const & pEntry1, std::unique_ptr<StyleTree_Impl> const & pEntry2) { - if (pEntry2->getName() == aUIName) - return false; - if (pEntry1->getName() == aUIName) - return true; // default always first - return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; - }); -} - -static bool IsExpanded_Impl( const std::vector<OUString>& rEntries, - std::u16string_view rStr) -{ - for (const auto & rEntry : rEntries) - { - if (rEntry == rStr) - return true; - } - return false; -} - -static void FillBox_Impl(weld::TreeView& rBox, - StyleTree_Impl* pEntry, - const std::vector<OUString>& rEntries, - SfxStyleFamily eStyleFamily, - const weld::TreeIter* pParent) -{ - std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator(); - const OUString& rName = pEntry->getName(); - rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get()); - - for (size_t i = 0; i < pEntry->getChildren().size(); ++i) - FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get()); -} - -namespace SfxTemplate -{ - // converts from SFX_STYLE_FAMILY Ids to 1-6 - static sal_uInt16 SfxFamilyIdToNId(SfxStyleFamily nFamily) - { - switch ( nFamily ) - { - case SfxStyleFamily::Char: return 1; - case SfxStyleFamily::Para: return 2; - case SfxStyleFamily::Frame: return 3; - case SfxStyleFamily::Page: return 4; - case SfxStyleFamily::Pseudo: return 5; - case SfxStyleFamily::Table: return 6; - default: return 0xffff; - } - } - - // converts from 1-6 to SFX_STYLE_FAMILY Ids - static SfxStyleFamily NIdToSfxFamilyId(sal_uInt16 nId) - { - switch (nId) - { - case 1: return SfxStyleFamily::Char; - case 2: return SfxStyleFamily::Para; - case 3: return SfxStyleFamily::Frame; - case 4: return SfxStyleFamily::Page; - case 5: return SfxStyleFamily::Pseudo; - case 6: return SfxStyleFamily::Table; - default: return SfxStyleFamily::All; - } - } + m_aStyleListFamilySelect = rLink; } // Constructor @@ -527,49 +199,27 @@ SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl(SfxBindings* pB, weld : pBindings(pB) , mpContainer(pC) , pModule(nullptr) - , pStyleSheetPool(nullptr) - , pCurObjShell(nullptr) , xModuleManager(frame::ModuleManager::create(::comphelper::getProcessComponentContext())) , m_pDeletionWatcher(nullptr) - , mxFmtLb(pBuilder->weld_tree_view("flatview")) - , mxTreeBox(pBuilder->weld_tree_view("treeview")) + , m_aStyleList(pBuilder, mxStyleFamilies, pB, this, pModule, pC, "treeview", "flatview") , mxPreviewCheckbox(pBuilder->weld_check_button("showpreview")) , mxFilterLb(pBuilder->weld_combo_box("filter")) - , nActFamily(0xffff) , nActFilter(0) , nAppFilter(SfxStyleSearchBits::Auto) - - , m_nModifier(0) - , bDontUpdate(false) , bIsWater(false) , bUpdate(false) , bUpdateFamily(false) - , bCanEdit(false) - , bCanDel(false) - , bCanNew(true) - , bCanHide(true) - , bCanShow(false) , bWaterDisabled(false) , bNewByExampleDisabled(false) , bUpdateByExampleDisabled(false) , bTreeDrag(true) - , bAllowReParentDrop(false) - , bHierarchical(false) , m_bWantHierarchical(false) - , bBindingUpdate(true) { - mxFmtLb->set_help_id(HID_TEMPLATE_FMT); mxFilterLb->set_help_id(HID_TEMPLATE_FILTER); mxPreviewCheckbox->set_active(officecfg::Office::Common::StylesAndFormatting::Preview::get()); } -sal_uInt16 SfxCommonTemplateDialog_Impl::StyleNrToInfoOffset(sal_uInt16 nId) -{ - const SfxStyleFamilyItem& rItem = mxStyleFamilies->at( nId ); - return SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily())-1; -} - void SfxTemplateDialog_Impl::EnableEdit(bool bEnable) { SfxCommonTemplateDialog_Impl::EnableEdit( bEnable ); @@ -577,79 +227,10 @@ void SfxTemplateDialog_Impl::EnableEdit(bool bEnable) EnableItem("update", bEnable); } -void SfxCommonTemplateDialog_Impl::ReadResource() +IMPL_LINK(SfxCommonTemplateDialog_Impl, ReadResource_Hdl, StyleList&, rStyleList, void) { - // Read global user resource - for (auto & i : pFamilyState) - i.reset(); - - SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); - pCurObjShell = pViewFrame->GetObjectShell(); - pModule = pCurObjShell ? pCurObjShell->GetModule() : nullptr; - if (pModule) - mxStyleFamilies = pModule->CreateStyleFamilies(); - if (!mxStyleFamilies) - mxStyleFamilies.emplace(); - - nActFilter = 0xffff; - if (pCurObjShell) - { - nActFilter = static_cast< sal_uInt16 >( LoadFactoryStyleFilter( pCurObjShell ) ); - if ( 0xffff == nActFilter ) - nActFilter = pCurObjShell->GetAutoStyleFilterIndex(); - } - // Paste in the toolbox - // reverse order, since always inserted at the head - size_t nCount = mxStyleFamilies->size(); - - pBindings->ENTERREGISTRATIONS(); - - size_t i; - for (i = 0; i < nCount; ++i) - { - sal_uInt16 nSlot = 0; - switch (mxStyleFamilies->at(i).GetFamily()) - { - case SfxStyleFamily::Char: - nSlot = SID_STYLE_FAMILY1; break; - case SfxStyleFamily::Para: - nSlot = SID_STYLE_FAMILY2; break; - case SfxStyleFamily::Frame: - nSlot = SID_STYLE_FAMILY3; break; - case SfxStyleFamily::Page: - nSlot = SID_STYLE_FAMILY4; break; - case SfxStyleFamily::Pseudo: - nSlot = SID_STYLE_FAMILY5; break; - case SfxStyleFamily::Table: - nSlot = SID_STYLE_FAMILY6; break; - default: OSL_FAIL("unknown StyleFamily"); break; - } - pBoundItems[i].reset( - new SfxTemplateControllerItem(nSlot, *this, *pBindings) ); - } - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_WATERCAN, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_NEW_BY_EXAMPLE, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_UPDATE_BY_EXAMPLE, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_NEW, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_DRAGHIERARCHIE, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_EDIT, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_DELETE, *this, *pBindings) ); - pBoundItems[i++].reset( new SfxTemplateControllerItem( - SID_STYLE_FAMILY, *this, *pBindings) ); - pBindings->LEAVEREGISTRATIONS(); - - for(; i < COUNT_BOUND_FUNC; ++i) - pBoundItems[i] = nullptr; - - StartListening(*pBindings); + size_t nCount = m_aStyleListReadResource.Call(nullptr); // Insert in the reverse order of occurrence in the Style Families. This is for // the toolbar of the designer. The list box of the catalog respects the @@ -666,29 +247,16 @@ void SfxCommonTemplateDialog_Impl::ReadResource() for( ; nCount--; ) { - const SfxStyleFamilyItem &rItem = mxStyleFamilies->at( nCount ); + const SfxStyleFamilyItem &rItem = rStyleList.GetFamilyItemByIndex( nCount ); sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId( rItem.GetFamily() ); InsertFamilyItem(nId, rItem); } - - for ( i = SID_STYLE_FAMILY1; i <= SID_STYLE_FAMILY4; i++ ) - pBindings->Update(i); } -void SfxCommonTemplateDialog_Impl::ClearResource() +IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, ClearResource_Hdl, void*, void) { ClearFamilyList(); - impl_clear(); -} - -void SfxCommonTemplateDialog_Impl::impl_clear() -{ - mxStyleFamilies.reset(); - for (auto & i : pFamilyState) - i.reset(); - for (auto & i : pBoundItems) - i.reset(); - pCurObjShell = nullptr; + m_aStyleListClear.Call(nullptr); } SfxCommonTemplateDialog_Impl::DeletionWatcher * @@ -700,115 +268,93 @@ SfxCommonTemplateDialog_Impl::impl_setDeletionWatcher( return pRet; } -class TreeViewDropTarget final : public DropTargetHelper +void SfxCommonTemplateDialog_Impl::Initialize() { -private: - SfxCommonTemplateDialog_Impl& m_rParent; + m_aStyleList.connect_ReadResource(LINK(this, SfxCommonTemplateDialog_Impl, ReadResource_Hdl)); + m_aStyleList.connect_ClearResource(LINK(this, SfxCommonTemplateDialog_Impl, ClearResource_Hdl)); + m_aStyleList.connect_LoadFactoryStyleFilter(LINK(this, SfxCommonTemplateDialog_Impl, LoadFactoryStyleFilter_Hdl)); + m_aStyleList.connect_SaveSelection(LINK(this, SfxCommonTemplateDialog_Impl, SaveSelection_Hdl)); + m_aStyleList.connect_UpdateStyleDependents(LINK(this, SfxCommonTemplateDialog_Impl, UpdateStyleDependents_Hdl)); + m_aStyleList.connect_UpdateFamily(LINK(this, SfxCommonTemplateDialog_Impl, UpdateFamily_Hdl)); + m_aStyleList.connect_UpdateStyles(LINK(this, SfxCommonTemplateDialog_Impl, UpdateStyles_Hdl)); -public: - TreeViewDropTarget(SfxCommonTemplateDialog_Impl& rDialog, weld::TreeView& rTreeView) - : DropTargetHelper(rTreeView.get_drop_target()) - , m_rParent(rDialog) - { - } + mxFilterLb->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FilterSelectHdl)); + mxPreviewCheckbox->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl, PreviewHdl)); + m_aStyleList.Initialize(); +} - virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override - { - return m_rParent.AcceptDrop(rEvt, *this); - } +IMPL_LINK(SfxCommonTemplateDialog_Impl, UpdateStyles_Hdl, StyleFlags, nFlags, void) +{ + const SfxStyleFamilyItem* pItem = m_aStyleList.GetFamilyItem(); + SfxStyleSearchBits nFilter(nActFilter < pItem->GetFilterList().size() + ? pItem->GetFilterList()[nActFilter].nFlags + : SfxStyleSearchBits::Auto); + if (nFilter == SfxStyleSearchBits::Auto) // automatic + nFilter = nAppFilter; - virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override + if (nFlags & StyleFlags::UpdateFamily) // Update view type list (Hierarchical, All, etc. { - return m_rParent.ExecuteDrop(rEvt); - } -}; + CheckItem(OString::number(nActFamily)); // check Button in Toolbox -void SfxCommonTemplateDialog_Impl::Initialize() -{ - // Read global user resource - ReadResource(); - pBindings->Invalidate( SID_STYLE_FAMILY ); - pBindings->Update( SID_STYLE_FAMILY ); + mxFilterLb->freeze(); + mxFilterLb->clear(); - mxFilterLb->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FilterSelectHdl)); - mxFmtLb->connect_row_activated(LINK( this, SfxCommonTemplateDialog_Impl, TreeListApplyHdl)); - mxFmtLb->connect_mouse_press(LINK(this, SfxCommonTemplateDialog_Impl, MousePressHdl)); - mxFmtLb->connect_query_tooltip(LINK(this, SfxCommonTemplateDialog_Impl, QueryTooltipHdl)); - mxFmtLb->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FmtSelectHdl)); - mxFmtLb->connect_popup_menu(LINK(this, SfxCommonTemplateDialog_Impl, PopupFlatMenuHdl)); - mxFmtLb->connect_key_press(LINK(this, SfxCommonTemplateDialog_Impl, KeyInputHdl)); - mxFmtLb->set_selection_mode(SelectionMode::Multiple); - mxTreeBox->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FmtSelectHdl)); - mxTreeBox->connect_row_activated(LINK( this, SfxCommonTemplateDialog_Impl, TreeListApplyHdl)); - mxTreeBox->connect_mouse_press(LINK(this, SfxCommonTemplateDialog_Impl, MousePressHdl)); - mxTreeBox->connect_query_tooltip(LINK(this, SfxCommonTemplateDialog_Impl, QueryTooltipHdl)); - mxTreeBox->connect_popup_menu(LINK(this, SfxCommonTemplateDialog_Impl, PopupTreeMenuHdl)); - mxTreeBox->connect_key_press(LINK(this, SfxCommonTemplateDialog_Impl, KeyInputHdl)); - mxTreeBox->connect_drag_begin(LINK(this, SfxCommonTemplateDialog_Impl, DragBeginHdl)); - mxPreviewCheckbox->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl, PreviewHdl)); - m_xTreeView1DropTargetHelper.reset(new TreeViewDropTarget(*this, *mxFmtLb)); - m_xTreeView2DropTargetHelper.reset(new TreeViewDropTarget(*this, *mxTreeBox)); + //insert hierarchical at the beginning + mxFilterLb->append(OUString::number(static_cast<int>(SfxStyleSearchBits::All)), + SfxResId(STR_STYLE_FILTER_HIERARCHICAL)); + const SfxStyleFilter& rFilter = pItem->GetFilterList(); + for (const SfxFilterTuple& i : rFilter) + mxFilterLb->append(OUString::number(static_cast<int>(i.nFlags)), i.aName); + mxFilterLb->thaw(); - int nTreeHeight = mxFmtLb->get_height_rows(8); - mxFmtLb->set_size_request(-1, nTreeHeight); - mxTreeBox->set_size_request(-1, nTreeHeight); + if (nActFilter < mxFilterLb->get_count() - 1) + mxFilterLb->set_active(nActFilter + 1); + else + { + nActFilter = 0; + m_aStyleList.SetFilterIdx(nActFilter); + mxFilterLb->set_active(1); + nFilter = (nActFilter < rFilter.size()) ? rFilter[nActFilter].nFlags + : SfxStyleSearchBits::Auto; + } - mxFmtLb->connect_custom_get_size(LINK(this, SfxCommonTemplateDialog_Impl, CustomGetSizeHdl)); - mxFmtLb->connect_custom_render(LINK(this, SfxCommonTemplateDialog_Impl, CustomRenderHdl)); - mxTreeBox->connect_custom_get_size(LINK(this, SfxCommonTemplateDialog_Impl, CustomGetSizeHdl)); - mxTreeBox->connect_custom_render(LINK(this, SfxCommonTemplateDialog_Impl, CustomRenderHdl)); - bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get(); - mxFmtLb->set_column_custom_renderer(0, bCustomPreview); - mxTreeBox->set_column_custom_renderer(0, bCustomPreview); + // if the tree view again, select family hierarchy + if (m_aStyleList.IsTreeView() || m_bWantHierarchical) + { + mxFilterLb->set_active_text(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)); + EnableHierarchical(true, m_aStyleList); + } + } + else + { + if (nActFilter < mxFilterLb->get_count() - 1) + mxFilterLb->set_active(nActFilter + 1); + else + { + nActFilter = 0; + m_aStyleList.SetFilterIdx(nActFilter); + mxFilterLb->set_active(1); + } + } - mxFmtLb->set_visible(!bHierarchical); - mxTreeBox->set_visible(bHierarchical); + if (!(nFlags & StyleFlags::UpdateFamilyList)) + return; - Update_Impl(); + EnableItem("watercan", false); } SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl() { if ( bIsWater ) - Execute_Impl(SID_STYLE_WATERCAN, "", "", 0); - impl_clear(); - if ( pStyleSheetPool ) - EndListening(*pStyleSheetPool); - pStyleSheetPool = nullptr; - m_xTreeView1DropTargetHelper.reset(); - m_xTreeView2DropTargetHelper.reset(); - mxTreeBox.reset(); - pIdle.reset(); + Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, m_aStyleList); + m_aStyleListClear.Call(nullptr); + m_aStyleListCleanup.Call(nullptr); if ( m_pDeletionWatcher ) m_pDeletionWatcher->signal(); - mxFmtLb.reset(); mxPreviewCheckbox.reset(); mxFilterLb.reset(); } -// Helper function: Access to the current family item -const SfxStyleFamilyItem *SfxCommonTemplateDialog_Impl::GetFamilyItem_Impl() const -{ - const size_t nCount = mxStyleFamilies->size(); - for(size_t i = 0; i < nCount; ++i) - { - const SfxStyleFamilyItem &rItem = mxStyleFamilies->at( i ); - sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()); - if(nId == nActFamily) - return &rItem; - } - return nullptr; -} - -void SfxCommonTemplateDialog_Impl::GetSelectedStyle() const -{ - if (!IsInitialized() || !pStyleSheetPool || !HasSelectedStyle()) - return; - const OUString aTemplName( GetSelectedEntry() ); - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - pStyleSheetPool->Find( aTemplName, pItem->GetFamily() ); -} - /** * Is it safe to show the water-can / fill icon. If we've a * hierarchical widget - we have only single select, otherwise @@ -817,124 +363,25 @@ void SfxCommonTemplateDialog_Impl::GetSelectedStyle() const */ bool SfxCommonTemplateDialog_Impl::IsSafeForWaterCan() const { - if (mxTreeBox->get_visible()) - return mxTreeBox->get_selected_index() != -1; - else - return mxFmtLb->count_selected_rows() == 1; + return m_aStyleListWaterCan.Call(nullptr); } -void SfxCommonTemplateDialog_Impl::SelectStyle(const OUString &rStr, bool bIsCallback) +void SfxCommonTemplateDialog_Impl::SelectStyle(const OUString &rStr, bool bIsCallback, StyleList& rStyleList) { - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - if ( !pItem ) - return; - const SfxStyleFamily eFam = pItem->GetFamily(); - SfxStyleSheetBase* pStyle = pStyleSheetPool->Find( rStr, eFam ); - if( pStyle ) - { - bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); - EnableEdit( bReadWrite ); - EnableHide( bReadWrite && !pStyle->IsHidden( ) && !pStyle->IsUsed( ) ); - EnableShow( bReadWrite && pStyle->IsHidden( ) ); - } - else - { - EnableEdit(false); - EnableHide(false); - EnableShow(false); - } - - if (!bIsCallback) - { - if (mxTreeBox->get_visible()) - { - if (!rStr.isEmpty()) - { - std::unique_ptr<weld::TreeIter> xEntry = mxTreeBox->make_iterator(); - bool bEntry = mxTreeBox->get_iter_first(*xEntry); - while (bEntry) - { - if (mxTreeBox->get_text(*xEntry) == rStr) - { - mxTreeBox->scroll_to_row(*xEntry); - mxTreeBox->select(*xEntry); - break; - } - bEntry = mxTreeBox->iter_next(*xEntry); - } - } - else if (eFam == SfxStyleFamily::Pseudo) - { - std::unique_ptr<weld::TreeIter> xEntry = mxTreeBox->make_iterator(); - if (mxTreeBox->get_iter_first(*xEntry)) - { - mxTreeBox->scroll_to_row(*xEntry); - mxTreeBox->select(*xEntry); - } - } - else - mxTreeBox->unselect_all(); - } - else - { - bool bSelect = !rStr.isEmpty(); - if (bSelect) - { - std::unique_ptr<weld::TreeIter> xEntry = mxFmtLb->make_iterator(); - bool bEntry = mxFmtLb->get_iter_first(*xEntry); - while (bEntry && mxFmtLb->get_text(*xEntry) != rStr) - bEntry = mxFmtLb->iter_next(*xEntry); - if (!bEntry) - bSelect = false; - else - { - if (!mxFmtLb->is_selected(*xEntry)) - { - mxFmtLb->unselect_all(); - mxFmtLb->scroll_to_row(*xEntry); - mxFmtLb->select(*xEntry); - } - } - } - - if (!bSelect) - { - mxFmtLb->unselect_all(); - EnableEdit(false); - EnableHide(false); - EnableShow(false); - } - } - } + rStyleList.SelectStyle(rStr, bIsCallback); bWaterDisabled = !IsSafeForWaterCan(); if (!bIsCallback) { // tdf#134598 call UpdateStyleDependents to update watercan - UpdateStyleDependents(); + UpdateStyleDependents_Hdl(nullptr); } } -OUString SfxCommonTemplateDialog_Impl::GetSelectedEntry() const -{ - OUString aRet; - if (mxTreeBox->get_visible()) - aRet = mxTreeBox->get_selected_text(); - else - aRet = mxFmtLb->get_selected_text(); - return aRet; -} - void SfxCommonTemplateDialog_Impl::EnableTreeDrag(bool bEnable) { - if (pStyleSheetPool) - { - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - SfxStyleSheetBase* pStyle = pItem ? pStyleSheetPool->First(pItem->GetFamily()) : nullptr; - bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && bEnable; - } - bTreeDrag = bEnable; + m_aStyleListEnableTreeDrag.Call(bEnable); } static OUString lcl_GetStyleFamilyName( SfxStyleFamily nFamily ) @@ -952,7 +399,7 @@ static OUString lcl_GetStyleFamilyName( SfxStyleFamily nFamily ) return OUString(); } -OUString SfxCommonTemplateDialog_Impl::getDefaultStyleName( const SfxStyleFamily eFam ) +OUString SfxCommonTemplateDialog_Impl::getDefaultStyleName( const SfxStyleFamily eFam, StyleList& rStyleList ) { OUString sDefaultStyle; OUString aFamilyName = lcl_GetStyleFamilyName(eFam); @@ -962,7 +409,7 @@ OUString SfxCommonTemplateDialog_Impl::getDefaultStyleName( const SfxStyleFamily sDefaultStyle = "No List"; else sDefaultStyle = "Standard"; - uno::Reference< style::XStyleFamiliesSupplier > xModel(GetObjectShell()->GetModel(), uno::UNO_QUERY); + uno::Reference<style::XStyleFamiliesSupplier> xModel(rStyleList.GetObjectShell()->GetModel(), uno::UNO_QUERY); OUString aUIName; try { @@ -979,210 +426,6 @@ OUString SfxCommonTemplateDialog_Impl::getDefaultStyleName( const SfxStyleFamily return aUIName; } -void SfxCommonTemplateDialog_Impl::FillTreeBox() -{ - assert(mxTreeBox && "FillTreeBox() without treebox"); - if (!pStyleSheetPool || nActFamily == 0xffff) - return; - - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - if (!pItem) - return; - const SfxStyleFamily eFam = pItem->GetFamily(); - StyleTreeArr_Impl aArr; - SfxStyleSheetBase* pStyle = pStyleSheetPool->First(eFam, SfxStyleSearchBits::AllVisible); - - bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && bTreeDrag; - - while (pStyle) - { - StyleTree_Impl* pNew = new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent()); - aArr.emplace_back(pNew); - pStyle = pStyleSheetPool->Next(); - } - OUString aUIName = getDefaultStyleName(eFam); - MakeTree_Impl(aArr, aUIName); - std::vector<OUString> aEntries; - MakeExpanded_Impl(*mxTreeBox, aEntries); - mxTreeBox->freeze(); - mxTreeBox->clear(); - const sal_uInt16 nCount = aArr.size(); - - for (sal_uInt16 i = 0; i < nCount; ++i) - { - FillBox_Impl(*mxTreeBox, aArr[i].get(), aEntries, eFam, nullptr); - aArr[i].reset(); - } - - EnableItem("watercan", false); - - SfxTemplateItem* pState = pFamilyState[nActFamily - 1].get(); - - mxTreeBox->thaw(); - - std::unique_ptr<weld::TreeIter> xEntry = mxTreeBox->make_iterator(); - bool bEntry = mxTreeBox->get_iter_first(*xEntry); - if (bEntry && nCount) - mxTreeBox->expand_row(*xEntry); - - while (bEntry) - { - if (IsExpanded_Impl(aEntries, mxTreeBox->get_text(*xEntry))) - mxTreeBox->expand_row(*xEntry); - bEntry = mxTreeBox->iter_next(*xEntry); - } - - OUString aStyle; - if(pState) // Select current entry - aStyle = pState->GetStyleName(); - SelectStyle(aStyle, false); - EnableDelete(); -} - -bool SfxCommonTemplateDialog_Impl::HasSelectedStyle() const -{ - return mxTreeBox->get_visible() ? mxTreeBox->get_selected_index() != -1 - : mxFmtLb->count_selected_rows() != 0; -} - -// internal: Refresh the display -// nFlags: what we should update. -void SfxCommonTemplateDialog_Impl::UpdateStyles_Impl(StyleFlags nFlags) -{ - OSL_ENSURE(nFlags != StyleFlags::NONE, "nothing to do"); - const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); - if (!pItem) - { - // Is the case for the template catalog - const size_t nFamilyCount = mxStyleFamilies->size(); - size_t n; - for( n = 0; n < nFamilyCount; n++ ) - if( pFamilyState[ StyleNrToInfoOffset(n) ] ) break; - if ( n == nFamilyCount ) - // It happens sometimes, God knows why - return; - nAppFilter = pFamilyState[StyleNrToInfoOffset(n)]->GetValue(); - FamilySelect( StyleNrToInfoOffset(n)+1 ); - pItem = GetFamilyItem_Impl(); - } - - const SfxStyleFamily eFam = pItem->GetFamily(); - - SfxStyleSearchBits nFilter (nActFilter < pItem->GetFilterList().size() ? pItem->GetFilterList()[nActFilter].nFlags : SfxStyleSearchBits::Auto); - if (nFilter == SfxStyleSearchBits::Auto) // automatic - nFilter = nAppFilter; - - OSL_ENSURE(pStyleSheetPool, "no StyleSheetPool"); - if(!pStyleSheetPool) - return; - - pItem = GetFamilyItem_Impl(); - if(nFlags & StyleFlags::UpdateFamily) // Update view type list (Hierarchical, All, etc. - { - CheckItem(OString::number(nActFamily)); // check Button in Toolbox - - mxFilterLb->freeze(); - mxFilterLb->clear(); - - //insert hierarchical at the beginning - mxFilterLb->append(OUString::number(static_cast<int>(SfxStyleSearchBits::All)), SfxResId(STR_STYLE_FILTER_HIERARCHICAL)); - const SfxStyleFilter& rFilter = pItem->GetFilterList(); - for (const SfxFilterTuple& i : rFilter) - mxFilterLb->append(OUString::number(static_cast<int>(i.nFlags)), i.aName); - mxFilterLb->thaw(); - - if (nActFilter < mxFilterLb->get_count() - 1) - mxFilterLb->set_active(nActFilter + 1); - else - { - nActFilter = 0; - mxFilterLb->set_active(1); - nFilter = (nActFilter < rFilter.size()) ? rFilter[nActFilter].nFlags : SfxStyleSearchBits::Auto; - } - - // if the tree view again, select family hierarchy - if (mxTreeBox->get_visible() || m_bWantHierarchical) - { - mxFilterLb->set_active_text(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)); - EnableHierarchical(true); - } - } - else - { - if (nActFilter < mxFilterLb->get_count() - 1) - mxFilterLb->set_active(nActFilter + 1); - else - { - nActFilter = 0; - mxFilterLb->set_active(1); - } - } - - if(!(nFlags & StyleFlags::UpdateFamilyList)) - return; - - EnableItem("watercan", false); - - SfxStyleSheetBase *pStyle = pStyleSheetPool->First(eFam, nFilter); - - std::unique_ptr<weld::TreeIter> xEntry = mxFmtLb->make_iterator(); - bool bEntry = mxFmtLb->get_iter_first(*xEntry); - std::vector<OUString> aStrings; - - comphelper::string::NaturalStringSorter aSorter( - ::comphelper::getProcessComponentContext(), - Application::GetSettings().GetLanguageTag().getLocale()); - - while( pStyle ) - { - aStrings.push_back(pStyle->GetName()); - pStyle = pStyleSheetPool->Next(); - } - OUString aUIName = getDefaultStyleName(eFam); - - // Paradoxically, with a list and non-Latin style names, - // sorting twice is faster than sorting once. - // The first sort has a cheap comparator, and gets the list into mostly-sorted order. - // Then the second sort needs to call its (much more expensive) comparator less often. - std::sort(aStrings.begin(), aStrings.end()); - std::sort(aStrings.begin(), aStrings.end(), - [&aSorter, &aUIName](const OUString& rLHS, const OUString& rRHS) { - if(rRHS == aUIName) - return false; - if(rLHS == aUIName) - return true; // default always first - return aSorter.compare(rLHS, rRHS) < 0; - }); - - size_t nCount = aStrings.size(); - size_t nPos = 0; - while (nPos < nCount && bEntry && - aStrings[nPos] == mxFmtLb->get_text(*xEntry)) - { - ++nPos; - bEntry = mxFmtLb->iter_next(*xEntry); - } - - if (nPos < nCount || bEntry) - { - // Fills the display box - mxFmtLb->freeze(); - mxFmtLb->clear(); - - for (nPos = 0; nPos < nCount; ++nPos) - mxFmtLb->append(aStrings[nPos], aStrings[nPos]); - - mxFmtLb->thaw(); - } - // Selects the current style if any - SfxTemplateItem *pState = pFamilyState[nActFamily-1].get(); - OUString aStyle; - if(pState) - aStyle = pState->GetStyleName(); - SelectStyle(aStyle, false); - EnableDelete(); -} - // Updated display: Watering the house void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem *pItem) { @@ -1207,21 +450,7 @@ void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem *pItem) // Ignore while in watercan mode statusupdates - size_t nCount = mxStyleFamilies->size(); - pBindings->EnterRegistrations(); - for(size_t n = 0; n < nCount; n++) - { - SfxControllerItem *pCItem=pBoundItems[n].get(); - bool bChecked = pItem && pItem->GetValue(); - if( pCItem->IsBound() == bChecked ) - { - if( !bChecked ) - pCItem->ReBind(); - else - pCItem->UnBind(); - } - } - pBindings->LeaveRegistrations(); + m_aStyleListSetWaterCanState.Call(pItem); } // Item with the status of a Family is copied and noted @@ -1229,256 +458,16 @@ void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem *pItem) // See also: <SfxBindings::AddDoneHdl(const Link &)> void SfxCommonTemplateDialog_Impl::SetFamilyState( sal_uInt16 nSlotId, const SfxTemplateItem* pItem ) { - sal_uInt16 nIdx = nSlotId - SID_STYLE_FAMILY_START; - pFamilyState[nIdx].reset(); - if ( pItem ) - pFamilyState[nIdx].reset( new SfxTemplateItem(*pItem) ); + m_aStyleList.SetFamilyState(nSlotId, pItem); bUpdate = true; // If used templates (how the hell you find this out??) bUpdateFamily = true; } -// Notice from SfxBindings that the update is completed. Pushes out the update -// of the display. -void SfxCommonTemplateDialog_Impl::Update_Impl() -{ - bool bDocChanged=false; - SfxStyleSheetBasePool* pNewPool = nullptr; - SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); - SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); - if( pDocShell ) - pNewPool = pDocShell->GetStyleSheetPool(); - - if ( pNewPool != pStyleSheetPool && pDocShell ) - { - SfxModule* pNewModule = pDocShell->GetModule(); - if( pNewModule && pNewModule != pModule ) - { - ClearResource(); - ReadResource(); - } - if ( pStyleSheetPool ) - { - EndListening(*pStyleSheetPool); - pStyleSheetPool = nullptr; - } - - if ( pNewPool ) - { - StartListening(*pNewPool); - pStyleSheetPool = pNewPool; - bDocChanged=true; - } - } - - if (bUpdateFamily) - UpdateFamily_Impl(); - - sal_uInt16 i; - for(i = 0; i < MAX_FAMILIES; ++i) - if(pFamilyState[i]) - break; - if(i == MAX_FAMILIES || !pNewPool) - // nothing is allowed - return; - - SfxTemplateItem *pItem = nullptr; - // current region not within the allowed region or default - if(nActFamily == 0xffff || nullptr == (pItem = pFamilyState[nActFamily-1].get() ) ) - { - CheckItem(OString::number(nActFamily), false); - const size_t nFamilyCount = mxStyleFamilies->size(); - size_t n; - for( n = 0; n < nFamilyCount; n++ ) - if( pFamilyState[ StyleNrToInfoOffset(n) ] ) break; - - std::unique_ptr<SfxTemplateItem> & pNewItem = pFamilyState[StyleNrToInfoOffset(n)]; - nAppFilter = pNewItem->GetValue(); - FamilySelect( StyleNrToInfoOffset(n) + 1 ); - pItem = pNewItem.get(); - } - else if( bDocChanged ) - { - // other DocShell -> all new - CheckItem(OString::number(nActFamily)); - nActFilter = static_cast< sal_uInt16 >( LoadFactoryStyleFilter( pDocShell ) ); - if ( 0xffff == nActFilter ) - nActFilter = pDocShell->GetAutoStyleFilterIndex(); - - nAppFilter = pItem->GetValue(); - if (!mxTreeBox->get_visible()) - { - UpdateStyles_Impl(StyleFlags::UpdateFamilyList); - } - else - FillTreeBox(); - } - else - { - // other filters for automatic - CheckItem(OString::number(nActFamily)); - const SfxStyleFamilyItem *pStyleItem = GetFamilyItem_Impl(); - if ( pStyleItem && SfxStyleSearchBits::Auto == pStyleItem->GetFilterList()[nActFilter].nFlags - && nAppFilter != pItem->GetValue()) - { - nAppFilter = pItem->GetValue(); - if (!mxTreeBox->get_visible()) - UpdateStyles_Impl(StyleFlags::UpdateFamilyList); - else - FillTreeBox(); - } - else - nAppFilter = pItem->GetValue(); - } - const OUString aStyle(pItem->GetStyleName()); - SelectStyle(aStyle, false); - EnableDelete(); - EnableNew( bCanNew ); -} - -IMPL_LINK_NOARG( SfxCommonTemplateDialog_Impl, TimeOut, Timer *, void ) -{ - if(!bDontUpdate) - { - bDontUpdate=true; - if (!mxTreeBox->get_visible()) - UpdateStyles_Impl(StyleFlags::UpdateFamilyList); - else - { - FillTreeBox(); - SfxTemplateItem *pState = pFamilyState[nActFamily-1].get(); - if(pState) - { - SelectStyle(pState->GetStyleName(), false); - EnableDelete(); - } - } - bDontUpdate=false; - pIdle.reset(); - } - else - pIdle->Start(); -} - -void SfxCommonTemplateDialog_Impl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) -{ - const SfxHintId nId = rHint.GetId(); - - // tap update - switch(nId) - { - case SfxHintId::UpdateDone: - { - SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); - SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); - if ( - bUpdate && - ( - !IsCheckedItem("watercan") || - (pDocShell && pDocShell->GetStyleSheetPool() != pStyleSheetPool) - ) - ) - { - bUpdate = false; - Update_Impl(); - } - else if ( bUpdateFamily ) - { - UpdateFamily_Impl(); - } - - if( pStyleSheetPool ) - { - OUString aStr = GetSelectedEntry(); - if (!aStr.isEmpty()) - { - const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); - if( !pItem ) break; - const SfxStyleFamily eFam = pItem->GetFamily(); - SfxStyleSheetBase *pStyle = pStyleSheetPool->Find( aStr, eFam ); - if( pStyle ) - { - bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); - EnableEdit( bReadWrite ); - EnableHide( bReadWrite && !pStyle->IsUsed( ) && !pStyle->IsHidden( ) ); - EnableShow( bReadWrite && pStyle->IsHidden( ) ); - } - else - { - EnableEdit(false); - EnableHide(false); - EnableShow(false); - } - } - } - break; - } - - // Necessary if switching between documents and in both documents - // the same template is used. Do not immediately call Update_Impl, - // for the case that one of the documents is an internal InPlaceObject! - case SfxHintId::DocChanged: - bUpdate = true; - break; - case SfxHintId::Dying: - { - EndListening(*pStyleSheetPool); - pStyleSheetPool=nullptr; - break; - } - default: break; - } - - // Do not set timer when the stylesheet pool is in the box, because it is - // possible that a new one is registered after the timer is up - - // works bad in UpdateStyles_Impl ()! - - if(!bDontUpdate && nId != SfxHintId::Dying && - (dynamic_cast<const SfxStyleSheetPoolHint*>(&rHint) || - dynamic_cast<const SfxStyleSheetHint*>(&rHint) || - dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint) || - nId == SfxHintId::StyleSheetModified)) - { - if(!pIdle) - { - pIdle.reset(new Idle("SfxCommonTemplate")); - pIdle->SetPriority(TaskPriority::LOWEST); - pIdle->SetInvokeHandler(LINK(this,SfxCommonTemplateDialog_Impl,TimeOut)); - } - pIdle->Start(); - - } -} - -// Other filters; can be switched by the users or as a result of new or -// editing, if the current document has been assigned a different filter. -void SfxCommonTemplateDialog_Impl::FilterSelect( - sal_uInt16 nEntry, // Idx of the new Filters - bool bForce ) // Force update, even if the new filter is - // equal to the current -{ - if( nEntry == nActFilter && !bForce ) - return; - - nActFilter = nEntry; - SfxObjectShell *const pDocShell = SaveSelection(); - SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool; - pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): nullptr; - if ( pOldStyleSheetPool != pStyleSheetPool ) - { - if ( pOldStyleSheetPool ) - EndListening(*pOldStyleSheetPool); - if ( pStyleSheetPool ) - StartListening(*pStyleSheetPool); - } - - UpdateStyles_Impl(StyleFlags::UpdateFamilyList); -} - // Internal: Perform functions through the Dispatcher bool SfxCommonTemplateDialog_Impl::Execute_Impl( - sal_uInt16 nId, const OUString &rStr, const OUString& rRefStr, sal_uInt16 nFamily, + sal_uInt16 nId, const OUString &rStr, const OUString& rRefStr, sal_uInt16 nFamily, StyleList& rStyleList, SfxStyleSearchBits nMask, sal_uInt16 *pIdx, const sal_uInt16* pModifier) { SfxDispatcher &rDispatcher = *SfxGetpApp()->GetDispatcher_Impl(); @@ -1497,7 +486,7 @@ bool SfxCommonTemplateDialog_Impl::Execute_Impl( if(SID_STYLE_UPDATE_BY_EXAMPLE == nId) { // Special solution for Numbering update in Writer - const OUString aTemplName(GetSelectedEntry()); + const OUString aTemplName(rStyleList.GetSelectedEntry()); aUpdName.SetValue(aTemplName); pItems[ nCount++ ] = &aUpdName; } @@ -1518,14 +507,15 @@ bool SfxCommonTemplateDialog_Impl::Execute_Impl( if ( !pItem || aDeleted ) return false; - if ( (nId == SID_STYLE_NEW || SID_STYLE_EDIT == nId) && (mxTreeBox->get_visible() || mxFmtLb->count_selected_rows() <= 1) ) + if ((nId == SID_STYLE_NEW || SID_STYLE_EDIT == nId) + && rStyleList.EnableExecute()) { const SfxUInt16Item *pFilterItem = dynamic_cast< const SfxUInt16Item* >(pItem); assert(pFilterItem); SfxStyleSearchBits nFilterFlags = static_cast<SfxStyleSearchBits>(pFilterItem->GetValue()) & ~SfxStyleSearchBits::UserDefined; if(nFilterFlags == SfxStyleSearchBits::Auto) // User Template? nFilterFlags = static_cast<SfxStyleSearchBits>(pFilterItem->GetValue()); - const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl(); + const SfxStyleFamilyItem *pFamilyItem = rStyleList.GetFamilyItem(); const size_t nFilterCount = pFamilyItem->GetFilterList().size(); for ( size_t i = 0; i < nFilterCount; ++i ) @@ -1541,44 +531,52 @@ bool SfxCommonTemplateDialog_Impl::Execute_Impl( } // Handler Listbox of Filter -void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable) +void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable, StyleList& rStyleList) { if (bEnable) { - if (!bHierarchical) + if (!rStyleList.IsHierarchical()) { // Turn on treeView - bHierarchical=true; m_bWantHierarchical = true; - SaveSelection(); // fdo#61429 store "hierarchical" - const OUString aSelectEntry( GetSelectedEntry()); - mxFmtLb->hide(); - FillTreeBox(); - SelectStyle(aSelectEntry, false); - mxTreeBox->show(); + SaveSelection_Hdl(nullptr); // fdo#61429 store "hierarchical" + m_aStyleList.SetHierarchical(); } } else { - mxTreeBox->hide(); - mxFmtLb->show(); + m_aStyleList.SetFilterControlsHandle(); // If bHierarchical, then the family can have changed // minus one since hierarchical is inserted at the start m_bWantHierarchical = false; // before FilterSelect - FilterSelect(mxFilterLb->get_active() - 1, bHierarchical ); - bHierarchical=false; + FilterSelect(mxFilterLb->get_active() - 1, rStyleList.IsHierarchical() ); } } +// Other filters; can be switched by the users or as a result of new or +// editing, if the current document has been assigned a different filter. +void SfxCommonTemplateDialog_Impl::FilterSelect( + sal_uInt16 nEntry, // Idx of the new Filters + bool bForce) // Force update, even if the new filter is equal to the current +{ + if (nEntry == nActFilter && !bForce) + return; + + nActFilter = nEntry; + m_aStyleListFilterSelect.Call(nActFilter); + + m_aStyleListUpdateStyles.Call(StyleFlags::UpdateFamilyList); +} + IMPL_LINK(SfxCommonTemplateDialog_Impl, FilterSelectHdl, weld::ComboBox&, rBox, void) { if (SfxResId(STR_STYLE_FILTER_HIERARCHICAL) == rBox.get_active_text()) { - EnableHierarchical(true); + EnableHierarchical(true, m_aStyleList); } else { - EnableHierarchical(false); + EnableHierarchical(false, m_aStyleList); } } @@ -1590,17 +588,11 @@ void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry, bool bPreview { CheckItem(OString::number(nActFamily), false); nActFamily = nEntry; - SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl(); - SfxUInt16Item const aItem(SID_STYLE_FAMILY, - static_cast<sal_uInt16>(SfxTemplate::NIdToSfxFamilyId(nEntry))); - pDispat->ExecuteList(SID_STYLE_FAMILY, SfxCallMode::SYNCHRON, { &aItem }); - pBindings->Invalidate( SID_STYLE_FAMILY ); - pBindings->Update( SID_STYLE_FAMILY ); - UpdateFamily_Impl(); + m_aStyleListFamilySelect.Call(nEntry); } } -void SfxCommonTemplateDialog_Impl::ActionSelect(const OString& rEntry) +void SfxCommonTemplateDialog_Impl::ActionSelect(const OString& rEntry, StyleList& rStyleList) { if (rEntry == "watercan") { @@ -1608,18 +600,16 @@ void SfxCommonTemplateDialog_Impl::ActionSelect(const OString& rEntry) bool bCheck; SfxBoolItem aBool; // when a template is chosen. - if (!bOldState && HasSelectedStyle()) + if (!bOldState && m_aStyleListHasSelectedStyle.Call(nullptr)) { - const OUString aTemplName( - GetSelectedEntry()); - Execute_Impl( - SID_STYLE_WATERCAN, aTemplName, "", - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); + const OUString aTemplName(rStyleList.GetSelectedEntry()); + Execute_Impl(SID_STYLE_WATERCAN, aTemplName, "", + static_cast<sal_uInt16>(m_aStyleList.GetFamilyItem()->GetFamily()), rStyleList); bCheck = true; } else { - Execute_Impl(SID_STYLE_WATERCAN, "", "", 0); + Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, rStyleList); bCheck = false; } CheckItem(rEntry, bCheck); @@ -1628,35 +618,13 @@ void SfxCommonTemplateDialog_Impl::ActionSelect(const OString& rEntry) } else if (rEntry == "new" || rEntry == "newmenu") { - if(pStyleSheetPool && nActFamily != 0xffff) - { - const SfxStyleFamily eFam=GetFamilyItem_Impl()->GetFamily(); - const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); - SfxStyleSearchBits nFilter(SfxStyleSearchBits::Auto); - if (pItem && nActFilter != 0xffff) - nFilter = pItem->GetFilterList()[nActFilter].nFlags; - if (nFilter == SfxStyleSearchBits::Auto) // automatic - nFilter = nAppFilter; - - // why? : FloatingWindow must not be parent of a modal dialog - SfxNewStyleDlg aDlg(mpContainer, *pStyleSheetPool, eFam); - auto nResult = aDlg.run(); - if (nResult == RET_OK) - { - const OUString aTemplName(aDlg.GetName()); - Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE, - aTemplName, "", - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()), - nFilter); - UpdateFamily_Impl(); - } - } + m_aStyleListNewMenu.Call(nullptr); } else if (rEntry == "update") { Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE, "", "", - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily())); + static_cast<sal_uInt16>(m_aStyleList.GetFamilyItem()->GetFamily()), rStyleList); } else if (rEntry == "load") SfxGetpApp()->GetDispatcher_Impl()->Execute(SID_TEMPLATE_LOAD); @@ -1687,7 +655,7 @@ static OUString getModuleIdentifier( const Reference< XModuleManager2 >& i_xModM return sIdentifier; } -sal_Int32 SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter( SfxObjectShell const * i_pObjSh ) +IMPL_LINK(SfxCommonTemplateDialog_Impl, LoadFactoryStyleFilter_Hdl, SfxObjectShell const*, i_pObjSh, sal_Int32) { OSL_ENSURE( i_pObjSh, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" ); @@ -1710,7 +678,7 @@ void SfxCommonTemplateDialog_Impl::SaveFactoryStyleFilter( SfxObjectShell const xModuleManager->replaceByName( getModuleIdentifier( xModuleManager, i_pObjSh ), makeAny( lProps ) ); } -SfxObjectShell* SfxCommonTemplateDialog_Impl::SaveSelection() +IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, SaveSelection_Hdl, void*, SfxObjectShell*) { SfxViewFrame *const pViewFrame(pBindings->GetDispatcher_Impl()->GetFrame()); SfxObjectShell *const pDocShell(pViewFrame->GetObjectShell()); @@ -1722,219 +690,6 @@ SfxObjectShell* SfxCommonTemplateDialog_Impl::SaveSelection() return pDocShell; } -void SfxCommonTemplateDialog_Impl::DropHdl(const OUString& rStyle, const OUString& rParent) -{ - bDontUpdate = true; - const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); - const SfxStyleFamily eFam = pItem->GetFamily(); - pStyleSheetPool->SetParent(eFam, rStyle, rParent); - bDontUpdate = false; -} - -// Handler for the New-Buttons -void SfxCommonTemplateDialog_Impl::NewHdl() -{ - if ( nActFamily == 0xffff || !(mxTreeBox->get_visible() || mxFmtLb->count_selected_rows() <= 1)) - return; - - const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); - const SfxStyleFamily eFam = pItem->GetFamily(); - SfxStyleSearchBits nMask(SfxStyleSearchBits::Auto); - if (nActFilter != 0xffff) - nMask = pItem->GetFilterList()[nActFilter].nFlags; - if (nMask == SfxStyleSearchBits::Auto) // automatic - nMask = nAppFilter; - - Execute_Impl(SID_STYLE_NEW, - "", GetSelectedEntry(), - static_cast<sal_uInt16>(eFam), - nMask); -} - -// Handler for the edit-Buttons -void SfxCommonTemplateDialog_Impl::EditHdl() -{ - if(IsInitialized() && HasSelectedStyle()) - { - sal_uInt16 nFilter = nActFilter; - OUString aTemplName(GetSelectedEntry()); - GetSelectedStyle(); // -Wall required?? - Execute_Impl( SID_STYLE_EDIT, aTemplName, OUString(), - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()), SfxStyleSearchBits::Auto, &nFilter ); - } -} - -// Handler for the Delete-Buttons -void SfxCommonTemplateDialog_Impl::DeleteHdl() -{ - if ( !IsInitialized() || !HasSelectedStyle() ) - return; - - bool bUsedStyle = false; // one of the selected styles are used in the document? - - std::vector<std::unique_ptr<weld::TreeIter>> aList; - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - - OUStringBuffer aMsg; - aMsg.append(SfxResId(STR_DELETE_STYLE_USED) + SfxResId(STR_DELETE_STYLE)); - - pTreeView->selected_foreach([this, pTreeView, pItem, &aList, &bUsedStyle, &aMsg](weld::TreeIter& rEntry){ - aList.emplace_back(pTreeView->make_iterator(&rEntry)); - // check the style is used or not - const OUString aTemplName(pTreeView->get_text(rEntry)); - - SfxStyleSheetBase* pStyle = pStyleSheetPool->Find( aTemplName, pItem->GetFamily() ); - - if ( pStyle->IsUsed() ) // pStyle is in use in the document? - { - if (bUsedStyle) // add a separator for the second and later styles - aMsg.append(", "); - aMsg.append(aTemplName); - bUsedStyle = true; - } - - return false; - }); - - bool aApproved = false; - - // we only want to show the dialog once and if we want to delete a style in use (UX-advice) - if (bUsedStyle) - { - std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pTreeView, - VclMessageType::Question, VclButtonsType::YesNo, - aMsg.makeStringAndClear())); - aApproved = xBox->run() == RET_YES; - } - - // if there are no used styles selected or the user approved the changes - if ( bUsedStyle && !aApproved ) - return; - - for (auto const& elem : aList) - { - const OUString aTemplName(pTreeView->get_text(*elem)); - bDontUpdate = true; // To prevent the Treelistbox to shut down while deleting - Execute_Impl( SID_STYLE_DELETE, aTemplName, - OUString(), static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); - - if (mxTreeBox->get_visible()) - { - weld::RemoveParentKeepChildren(*mxTreeBox, *elem); - bDontUpdate = false; - } - } - bDontUpdate = false; //if everything is deleted set bDontUpdate back to false - UpdateStyles_Impl(StyleFlags::UpdateFamilyList); //and force-update the list -} - -void SfxCommonTemplateDialog_Impl::HideHdl() -{ - if ( !IsInitialized() || !HasSelectedStyle() ) - return; - - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry){ - OUString aTemplName = pTreeView->get_text(rEntry); - - Execute_Impl( SID_STYLE_HIDE, aTemplName, - OUString(), static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); - - return false; - }); -} - -void SfxCommonTemplateDialog_Impl::ShowHdl() -{ - if ( !IsInitialized() || !HasSelectedStyle() ) - return; - - weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); - pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry){ - OUString aTemplName = pTreeView->get_text(rEntry); - - Execute_Impl( SID_STYLE_SHOW, aTemplName, - OUString(), static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); - - return false; - }); -} - -void SfxCommonTemplateDialog_Impl::EnableDelete() -{ - bool bEnableDelete(false); - if(IsInitialized() && HasSelectedStyle()) - { - OSL_ENSURE(pStyleSheetPool, "No StyleSheetPool"); - const OUString aTemplName(GetSelectedEntry()); - const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); - const SfxStyleFamily eFam = pItem->GetFamily(); - SfxStyleSearchBits nFilter = SfxStyleSearchBits::Auto; - if (pItem->GetFilterList().size() > nActFilter) - nFilter = pItem->GetFilterList()[nActFilter].nFlags; - if(nFilter == SfxStyleSearchBits::Auto) // automatic - nFilter = nAppFilter; - const SfxStyleSheetBase *pStyle = - pStyleSheetPool->Find(aTemplName,eFam, mxTreeBox->get_visible() ? SfxStyleSearchBits::All : nFilter); - - OSL_ENSURE(pStyle, "Style not found"); - if (pStyle && pStyle->IsUserDefined()) - { - if (pStyle->HasClearParentSupport() || !pStyle->IsUsed()) - { - bEnableDelete = true; - } - else if (pStyle->GetFamily() == SfxStyleFamily::Page) - { - // Hack to allow Calc page styles to be deleted, - // remove when IsUsed is fixed for Calc page styles. - SfxViewFrame* pFrame = GetObjectShell()->GetFrame(); - if (pFrame) - { - uno::Reference<frame::XFrame > xFrame = pFrame->GetFrame().GetFrameInterface(); - if (vcl::CommandInfoProvider::GetModuleIdentifier(xFrame) == "com.sun.star.sheet.SpreadsheetDocument") - { - bEnableDelete = true; - } - } - } - } - } - EnableDel(bEnableDelete); -} - -IMPL_LINK(SfxCommonTemplateDialog_Impl, MousePressHdl, const MouseEvent&, rMEvt, bool) -{ - m_nModifier = rMEvt.GetModifier(); - return false; -} - -// Double-click on a style sheet in the ListBox is applied. -IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, TreeListApplyHdl, weld::TreeView&, bool) -{ - // only if that region is allowed - if ( IsInitialized() && nullptr != pFamilyState[nActFamily-1] && - !GetSelectedEntry().isEmpty() ) - { - Execute_Impl(SID_STYLE_APPLY, - GetSelectedEntry(), OUString(), - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()), - SfxStyleSearchBits::Auto, nullptr, &m_nModifier); - } - // After selecting a focused item if possible again on the app window - if ( dynamic_cast< const SfxTemplateDialog_Impl* >(this) != nullptr ) - { - SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); - SfxViewShell *pVu = pViewFrame->GetViewShell(); - vcl::Window *pAppWin = pVu ? pVu->GetWindow(): nullptr; - if(pAppWin) - pAppWin->GrabFocus(); - } - - return true; -} - IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, PreviewHdl, weld::Toggleable&, void) { std::shared_ptr<comphelper::ConfigurationChanges> batch( comphelper::ConfigurationChanges::create() ); @@ -1942,75 +697,16 @@ IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, PreviewHdl, weld::Toggleable&, voi officecfg::Office::Common::StylesAndFormatting::Preview::set(bCustomPreview, batch ); batch->commit(); - mxFmtLb->clear(); - mxFmtLb->set_column_custom_renderer(0, bCustomPreview); - mxTreeBox->clear(); - mxTreeBox->set_column_custom_renderer(0, bCustomPreview); + m_aStyleList.EnablePreview(bCustomPreview); FamilySelect(nActFamily, true); } -// Selection of a template during the Watercan-Status -IMPL_LINK(SfxCommonTemplateDialog_Impl, FmtSelectHdl, weld::TreeView&, rListBox, void) -{ - std::unique_ptr<weld::TreeIter> xHdlEntry = rListBox.make_iterator(); - if (!rListBox.get_cursor(xHdlEntry.get())) - return; - - if (rListBox.is_selected(*xHdlEntry)) - UpdateStyleDependents(); - - SelectStyle(rListBox.get_text(*xHdlEntry), true); -} - -void SfxCommonTemplateDialog_Impl::UpdateStyleDependents() +IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, UpdateStyleDependents_Hdl, void*, void) { - // Trigger Help PI. Only when the watercan is on - if ( IsInitialized() && - IsCheckedItem("watercan") && - // only if that region is allowed - nullptr != pFamilyState[nActFamily-1] && (mxTreeBox || mxFmtLb->count_selected_rows() <= 1) ) - { - Execute_Impl(SID_STYLE_WATERCAN, - "", "", 0); - Execute_Impl(SID_STYLE_WATERCAN, - GetSelectedEntry(), "", - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily())); - } + m_aStyleListUpdateStyleDependents.Call(nullptr); EnableItem("watercan", !bWaterDisabled); - EnableDelete(); -} - -void SfxCommonTemplateDialog_Impl::MenuSelect(const OString& rIdent) -{ - sLastItemIdent = rIdent; - if (sLastItemIdent.isEmpty()) - return; - Application::PostUserEvent( - LINK(this, SfxCommonTemplateDialog_Impl, MenuSelectAsyncHdl)); -} - -IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, MenuSelectAsyncHdl, void*, void) -{ - if (sLastItemIdent == "new") - NewHdl(); - else if (sLastItemIdent == "edit") - EditHdl(); - else if (sLastItemIdent == "delete") - DeleteHdl(); - else if (sLastItemIdent == "hide") - HideHdl(); - else if (sLastItemIdent == "show") - ShowHdl(); -} - -SfxStyleFamily SfxCommonTemplateDialog_Impl::GetActualFamily() const -{ - const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl(); - if( !pFamilyItem || nActFamily == 0xffff ) - return SfxStyleFamily::Para; - else - return pFamilyItem->GetFamily(); + m_aStyleListEnableDelete.Call(nullptr); } void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId, bool bEnable) @@ -2019,6 +715,7 @@ void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId, bool bEnab if (nId == SID_STYLE_NEW_BY_EXAMPLE) { bNewByExampleDisabled = bDisable; + m_aStyleList.EnableNewByExample(bNewByExampleDisabled); EnableItem("new", bEnable); EnableItem("newmenu", bEnable); } @@ -2029,41 +726,6 @@ void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId, bool bEnab } } -void SfxCommonTemplateDialog_Impl::CreateContextMenu() -{ - if ( bBindingUpdate ) - { - pBindings->Invalidate( SID_STYLE_NEW, true ); - pBindings->Update( SID_STYLE_NEW ); - bBindingUpdate = false; - } - mxMenu.reset(); - mxMenuBuilder.reset(Application::CreateBuilder(nullptr, "sfx/ui/stylecontextmenu.ui")); - mxMenu = mxMenuBuilder->weld_menu("menu"); - mxMenu->set_sensitive("edit", bCanEdit); - mxMenu->set_sensitive("delete", bCanDel); - mxMenu->set_sensitive("new", bCanNew); - mxMenu->set_sensitive("hide", bCanHide); - mxMenu->set_sensitive("show", bCanShow); - - const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); - if (pItem && pItem->GetFamily() == SfxStyleFamily::Table) //tdf#101648, no ui for this yet - { - mxMenu->set_sensitive("edit", false); - mxMenu->set_sensitive("new", false); - } - if (pItem && pItem->GetFamily() == SfxStyleFamily::Pseudo) - { - const OUString aTemplName(GetSelectedEntry()); - if (aTemplName == "No List") - { - mxMenu->set_sensitive("edit", false); - mxMenu->set_sensitive("new", false); - mxMenu->set_sensitive("hide", false); - } - } -} - SfxTemplateDialog_Impl::SfxTemplateDialog_Impl(SfxBindings* pB, SfxTemplatePanelControl* pDlgWindow) : SfxCommonTemplateDialog_Impl(pB, pDlgWindow->get_container(), pDlgWindow->get_builder()) , m_xActionTbL(pDlgWindow->get_builder()->weld_toolbar("left")) @@ -2159,20 +821,6 @@ void SfxTemplateDialog_Impl::ClearFamilyList() } -void SfxCommonTemplateDialog_Impl::InvalidateBindings() -{ - pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, true); - pBindings->Update( SID_STYLE_NEW_BY_EXAMPLE ); - pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, true); - pBindings->Update( SID_STYLE_UPDATE_BY_EXAMPLE ); - pBindings->Invalidate( SID_STYLE_WATERCAN, true); - pBindings->Update( SID_STYLE_WATERCAN ); - pBindings->Invalidate( SID_STYLE_NEW, true); - pBindings->Update( SID_STYLE_NEW ); - pBindings->Invalidate( SID_STYLE_DRAGHIERARCHIE, true); - pBindings->Update( SID_STYLE_DRAGHIERARCHIE ); -} - SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl() { m_xToolbarDropTargetHelper.reset(); @@ -2183,7 +831,7 @@ SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl() void SfxTemplateDialog_Impl::EnableItem(const OString& rMesId, bool bCheck) { if (rMesId == "watercan" && !bCheck && IsCheckedItem("watercan")) - Execute_Impl(SID_STYLE_WATERCAN, "", "", 0); + Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, m_aStyleList); m_xActionTbR->set_item_sensitive(rMesId, bCheck); } @@ -2215,7 +863,7 @@ IMPL_LINK(SfxTemplateDialog_Impl, ToolBoxRSelect, const OString&, rEntry, void) if (rEntry == "newmenu") m_xActionTbR->set_menu_item_active(rEntry, !m_xActionTbR->get_menu_item_active(rEntry)); else - ActionSelect(rEntry); + ActionSelect(rEntry, m_aStyleList); } void SfxTemplateDialog_Impl::FillToolMenu() @@ -2240,7 +888,7 @@ IMPL_LINK(SfxTemplateDialog_Impl, ToolMenuSelectHdl, const OString&, rMenuId, vo { if (rMenuId.isEmpty()) return; - ActionSelect(rMenuId); + ActionSelect(rMenuId, m_aStyleList); } void SfxCommonTemplateDialog_Impl::SetFamily(SfxStyleFamily const nFamily) @@ -2249,58 +897,28 @@ void SfxCommonTemplateDialog_Impl::SetFamily(SfxStyleFamily const nFamily) assert((0 < nId && nId <= MAX_FAMILIES) || 0xffff == nId); if ( nId != nActFamily ) { - if ( nActFamily != 0xFFFF ) - CheckItem(OString::number(nActFamily), false); + m_aStyleListSetFamily.Call(nId); nActFamily = nId; if ( nId != 0xFFFF ) bUpdateFamily = true; } } -void SfxCommonTemplateDialog_Impl::UpdateFamily_Impl() +IMPL_LINK(SfxCommonTemplateDialog_Impl, UpdateFamily_Hdl, StyleList&, rStyleList, void) { bUpdateFamily = false; - - SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl(); - SfxViewFrame *pViewFrame = pDispat->GetFrame(); - SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); - - SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool; - pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): nullptr; - if ( pOldStyleSheetPool != pStyleSheetPool ) - { - if ( pOldStyleSheetPool ) - EndListening(*pOldStyleSheetPool); - if ( pStyleSheetPool ) - StartListening(*pStyleSheetPool); - } - bWaterDisabled = false; - bCanNew = mxTreeBox->get_visible() || mxFmtLb->count_selected_rows() <= 1; bTreeDrag = true; bUpdateByExampleDisabled = false; - if (pStyleSheetPool) - { - if (!mxTreeBox->get_visible()) - UpdateStyles_Impl(StyleFlags::UpdateFamily | StyleFlags::UpdateFamilyList); - else - { - UpdateStyles_Impl(StyleFlags::UpdateFamily); - FillTreeBox(); - } - } - - InvalidateBindings(); + m_aStyleListUpdateFamily.Call(nullptr); if (IsCheckedItem("watercan") && - // only if that area is allowed - nullptr != pFamilyState[nActFamily - 1]) + // only if that area is allowed + rStyleList.CurrentFamilyHasState()) { - Execute_Impl(SID_STYLE_APPLY, - GetSelectedEntry(), - OUString(), - static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily())); + Execute_Impl(SID_STYLE_APPLY, rStyleList.GetSelectedEntry(), OUString(), + static_cast<sal_uInt16>(rStyleList.GetFamilyItem()->GetFamily()), rStyleList); } } diff --git a/sfx2/source/inc/StyleList.hxx b/sfx2/source/inc/StyleList.hxx new file mode 100644 index 000000000000..65bb21cf9e82 --- /dev/null +++ b/sfx2/source/inc/StyleList.hxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +class SfxObjectShell; +class SfxStyleFamilyItem; +class SfxTemplateItem; +class SfxCommonTemplateDialog_Impl; + +enum class StyleFlags +{ + NONE = 0, + UpdateFamilyList = 1, + UpdateFamily = 2 +}; + +namespace o3tl +{ +template <> struct typed_flags<StyleFlags> : is_typed_flags<StyleFlags, 3> +{ +}; +} + +class TreeViewDropTarget; + +constexpr int MAX_FAMILIES = 6; +constexpr int COUNT_BOUND_FUNC = 14; + +class StyleList : public SfxListener +{ + friend class TreeViewDropTarget; + friend class SfxTemplateControllerItem; + +public: + // Constructor + StyleList(weld::Builder* pBuilder, std::optional<SfxStyleFamilies> xFamilies, + SfxBindings* pBindings, SfxCommonTemplateDialog_Impl* Parent, SfxModule* Module, + weld::Container* pC, OString treeviewname, OString flatviewname); + + // Destructor + ~StyleList(); + + // This function connects m_xTreeBox, m_xFmtLb and m_pParentDialog with certain LINKs + void Initialize(); + + // It selects the style in treeview + // bIsCallBack is true for the selected style. For eg. if "Addressee" is selected in + // styles, bIsCallBack will be true for it. + void SelectStyle(const OUString& rStr, bool bIsCallback); + // Checks whether a family has a saved state + bool CurrentFamilyHasState() { return nullptr != m_pFamilyState[m_nActFamily - 1]; } + + // This function is a subpart of Dialog's SetFamilyState + // When a new style is selected for use, it resets it. + void SetFamilyState(sal_uInt16 nSlotId, const SfxTemplateItem* pItem); + + // It is used in Dialog's EnableExample_Impl + // When the value of m_bNewbyExampleDisabled is updated there + // while creating a new style by example, + // the corresponding value gets updated here too. + void EnableNewByExample(bool newByExampleDisabled); + + // This function is used to set a hierarchical view. + void SetHierarchical(); + // This function handles the controls while setting a filter except heirarchical + void SetFilterControlsHandle(); + // Return whether treeview is visible + // It is used in StyleList's UpdateStyles_Hdl + // It is used to defaultly set the heirarchical view + bool IsTreeView() { return m_xTreeBox->get_visible(); } + + // Dialog and StyleList have their own copies of m_nActFilter + // When this value gets updated in Dialog's UpdateStyles_Hdl while setting a filter, + // the corresponding value gets updated here too. + void SetFilterIdx(sal_uInt16 filter) { m_nActFilter = filter; } + + // Helper function: Access to the current family item + // Used in Dialog's updateStyleHandler, Execute_Impl etc... + const SfxStyleFamilyItem* GetFamilyItem() const; + // Used to get the current selected entry in treeview + // Used in Dialog's Execute_Impl, Action_Select etc... + OUString GetSelectedEntry() const; + // Returns the Family Item at ith index + // Used in Dialog's ReadResource_Hdl + const SfxStyleFamilyItem& GetFamilyItemByIndex(size_t i) const; + const SfxObjectShell* GetObjectShell() const { return m_pCurObjShell; } + bool IsHierarchical() const { return m_bHierarchical; } + + void Enabledel(bool candel) { m_bCanDel = candel; } + void Enablehide(bool canhide) { m_bCanHide = canhide; } + void Enableshow(bool canshow) { m_bCanShow = canshow; } + void Enablenew(bool cannew) { m_bCanNew = cannew; } + void Enableedit(bool canedit) { m_bCanEdit = canedit; } + // Handles the enabling/Disabling of Preview + void EnablePreview(bool bCustomPreview); + // Used in Dialog's Execute_Impl + // It is a necessary condition to execute a style + bool EnableExecute(); + + void connect_UpdateStyles(const Link<StyleFlags, void>& rLink) { m_aUpdateStyles = rLink; } + void connect_ReadResource(const Link<StyleList&, void>& rLink) { m_aReadResource = rLink; } + void connect_ClearResource(const Link<void*, void>& rLink) { m_aClearResource = rLink; } + void connect_LoadFactoryStyleFilter(const Link<SfxObjectShell const*, sal_Int32>& rLink); + void connect_SaveSelection(const Link<void*, SfxObjectShell*> rLink); + void connect_UpdateStyleDependents(const Link<void*, void> rLink); + void connect_UpdateFamily(const Link<StyleList&, void> rLink) { m_aUpdateFamily = rLink; } + +private: + void FillTreeBox(SfxStyleFamily eFam); + + OUString getDefaultStyleName(const SfxStyleFamily eFam); + SfxStyleFamily GetActualFamily() const; + void GetSelectedStyle() const; + + sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper); + void DropHdl(const OUString& rStyle, const OUString& rParent); + + void MenuSelect(const OString& rIdent); + void PrepareMenu(const Point& rPos); + void ShowMenu(const CommandEvent& rCEvt); + void CreateContextMenu(); + + void Notify(SfxBroadcaster& rBC, const SfxHint& rHint); + + // In which FamilyState do I have to look, in order to get the + // information of the ith Family in the pStyleFamilies. + sal_uInt16 StyleNrToInfoOffset(sal_uInt16 i); + + DECL_LINK(ReadResource, void*, size_t); + DECL_LINK(Clear, void*, void); + DECL_LINK(Cleanup, void*, void); + DECL_LINK(ExecuteDrop, const ExecuteDropEvent&, sal_Int8); + DECL_LINK(NewMenuExecuteAction, void*, void); + DECL_LINK(IsSafeForWaterCan, void*, bool); + DECL_LINK(HasSelectedStyle, void*, bool); + DECL_LINK(UpdateFamily, void*, void); + DECL_LINK(UpdateStyles, StyleFlags, void); + DECL_LINK(UpdateStyleDependents, void*, void); + DECL_LINK(TimeOut, Timer*, void); + DECL_LINK(EnableTreeDrag, bool, void); + DECL_LINK(EnableDelete, void*, void); + DECL_LINK(FilterSelect, sal_uInt16, void); + DECL_LINK(SetWaterCanState, const SfxBoolItem*, void); + DECL_LINK(SetFamily, sal_uInt16, void); + DECL_LINK(FamilySelect, sal_uInt16, void); + + void InvalidateBindings(); + + void Update(); + Link<StyleFlags, void> m_aUpdateStyles; + Link<StyleList&, void> m_aReadResource; + Link<void*, void> m_aClearResource; + Link<SfxObjectShell const*, sal_Int32> m_aLoadFactoryStyleFilter; + Link<void*, SfxObjectShell*> m_aSaveSelection; + Link<void*, void> m_aUpdateStyleDependents; + Link<StyleList&, void> m_aUpdateFamily; + + void NewHdl(); + void EditHdl(); + void DeleteHdl(); + void HideHdl(); + void ShowHdl(); + + DECL_LINK(DragBeginHdl, bool&, bool); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString); + DECL_LINK(CustomRenderHdl, weld::TreeView::render_args, void); + DECL_LINK(FmtSelectHdl, weld::TreeView&, void); + DECL_LINK(TreeListApplyHdl, weld::TreeView&, bool); + DECL_LINK(MousePressHdl, const MouseEvent&, bool); + DECL_STATIC_LINK(StyleList, CustomGetSizeHdl, weld::TreeView::get_size_args, Size); + DECL_LINK(PopupFlatMenuHdl, const CommandEvent&, bool); + DECL_LINK(PopupTreeMenuHdl, const CommandEvent&, bool); + DECL_LINK(MenuSelectAsyncHdl, void*, void); + + bool m_bHierarchical : 1; + + bool m_bAllowReParentDrop : 1; + bool m_bNewByExampleDisabled : 1; + bool m_bDontUpdate : 1; + bool m_bTreeDrag : 1; + bool m_bCanEdit : 1; + bool m_bCanHide : 1; + bool m_bCanShow : 1; + bool m_bCanNew : 1; + bool m_bUpdateFamily : 1; + bool m_bCanDel : 1; + bool m_bBindingUpdate : 1; + SfxStyleSheetBasePool* m_pStyleSheetPool; + sal_uInt16 m_nActFilter; + std::unique_ptr<weld::TreeView> m_xFmtLb; + std::unique_ptr<weld::TreeView> m_xTreeBox; + + std::unique_ptr<weld::Builder> mxMenuBuilder; + std::unique_ptr<weld::Menu> mxMenu; + + std::optional<SfxStyleFamilies> m_xStyleFamilies; + std::array<std::unique_ptr<SfxTemplateItem>, MAX_FAMILIES> m_pFamilyState; + SfxObjectShell* m_pCurObjShell; + sal_uInt16 m_nActFamily; + SfxStyleSearchBits m_nAppFilter; + + std::unique_ptr<TreeViewDropTarget> m_xTreeView1DropTargetHelper; + std::unique_ptr<TreeViewDropTarget> m_xTreeView2DropTargetHelper; + + SfxCommonTemplateDialog_Impl* m_pParentDialog; + SfxBindings* m_pBindings; + std::array<std::unique_ptr<SfxTemplateControllerItem>, COUNT_BOUND_FUNC> pBoundItems; + + std::unique_ptr<Idle> pIdle; + + OString sLastItemIdent; + SfxModule* m_Module; + sal_uInt16 m_nModifier; + weld::Container* m_pContainer; +}; diff --git a/sfx2/source/inc/templdgi.hxx b/sfx2/source/inc/templdgi.hxx index 61d6de8001cb..daedd86de98c 100644 --- a/sfx2/source/inc/templdgi.hxx +++ b/sfx2/source/inc/templdgi.hxx @@ -41,6 +41,8 @@ class SfxTemplateControllerItem; #include <vcl/idle.hxx> +#include "StyleList.hxx" + class SfxStyleFamilyItem; class SfxTemplateItem; class SfxBindings; @@ -54,26 +56,14 @@ namespace com::sun::star::frame { class XModuleManager2; } -enum class StyleFlags { - NONE=0, UpdateFamilyList=1, UpdateFamily=2 -}; -namespace o3tl { - template<> struct typed_flags<StyleFlags> : is_typed_flags<StyleFlags, 3> {}; -} - -class TreeViewDropTarget; - -class SfxCommonTemplateDialog_Impl : public SfxListener +class SfxCommonTemplateDialog_Impl { private: class DeletionWatcher; friend class DeletionWatcher; - void ReadResource(); - void ClearResource(); - void impl_clear(); DeletionWatcher* impl_setDeletionWatcher(DeletionWatcher* pNewWatcher); - OUString getDefaultStyleName( const SfxStyleFamily eFam ); + static OUString getDefaultStyleName( const SfxStyleFamily eFam, StyleList& rStyleList ); protected: #define MAX_FAMILIES 6 @@ -82,177 +72,158 @@ protected: friend class SfxTemplateControllerItem; SfxBindings* pBindings; - std::array<std::unique_ptr<SfxTemplateControllerItem>, COUNT_BOUND_FUNC> pBoundItems; weld::Container* mpContainer; - std::unique_ptr<weld::Builder> mxMenuBuilder; - std::unique_ptr<weld::Menu> mxMenu; - OString sLastItemIdent; SfxModule* pModule; - std::unique_ptr<Idle> pIdle; std::optional<SfxStyleFamilies> mxStyleFamilies; - std::array<std::unique_ptr<SfxTemplateItem>, MAX_FAMILIES> pFamilyState; - SfxStyleSheetBasePool* pStyleSheetPool; - SfxObjectShell* pCurObjShell; css::uno::Reference<css::frame::XModuleManager2> xModuleManager; DeletionWatcher* m_pDeletionWatcher; - std::unique_ptr<weld::TreeView> mxFmtLb; - std::unique_ptr<weld::TreeView> mxTreeBox; + StyleList m_aStyleList; std::unique_ptr<weld::CheckButton> mxPreviewCheckbox; std::unique_ptr<weld::ComboBox> mxFilterLb; - std::unique_ptr<TreeViewDropTarget> m_xTreeView1DropTargetHelper; - std::unique_ptr<TreeViewDropTarget> m_xTreeView2DropTargetHelper; sal_uInt16 nActFamily; // Id in the ToolBox = Position - 1 sal_uInt16 nActFilter; // FilterIdx SfxStyleSearchBits nAppFilter; // Filter, which has set the application (for automatic) - sal_uInt16 m_nModifier; - bool bDontUpdate :1; bool bIsWater :1; bool bUpdate :1; bool bUpdateFamily :1; - bool bCanEdit :1; - bool bCanDel :1; - bool bCanNew :1; - bool bCanHide :1; - bool bCanShow :1; bool bWaterDisabled :1; bool bNewByExampleDisabled :1; bool bUpdateByExampleDisabled :1; bool bTreeDrag :1; - bool bAllowReParentDrop:1; - bool bHierarchical :1; bool m_bWantHierarchical :1; - bool bBindingUpdate :1; + + Link<void*, size_t> m_aStyleListReadResource; + Link<void*, void> m_aStyleListClear; + Link<void*, void> m_aStyleListCleanup; + Link<const ExecuteDropEvent&, sal_Int8> m_aStyleListExecuteDrop; + Link<void*, void> m_aStyleListNewMenu; + Link<void*, bool> m_aStyleListWaterCan; + Link<void*, bool> m_aStyleListHasSelectedStyle; + Link<StyleFlags, void> m_aStyleListUpdateStyles; + Link<void*, void> m_aStyleListUpdateFamily; + Link<SfxHintId, void> m_aStyleListNotify; + Link<void*, void> m_aStyleListUpdateStyleDependents; + Link<bool, void> m_aStyleListEnableTreeDrag; + Link<sal_uInt16, void> m_aStyleListFilterSelect; + Link<void*, void> m_aStyleListEnableDelete; + Link<const SfxBoolItem*, void> m_aStyleListSetWaterCanState; + Link<sal_uInt16, void> m_aStyleListFamilySelect; + Link<sal_uInt16, void> m_aStyleListSetFamily; DECL_LINK(FilterSelectHdl, weld::ComboBox&, void ); - DECL_LINK(FmtSelectHdl, weld::TreeView&, void); - DECL_LINK(TreeListApplyHdl, weld::TreeView&, bool); - DECL_LINK(MousePressHdl, const MouseEvent&, bool); - DECL_LINK(TimeOut, Timer*, void ); DECL_LINK(PreviewHdl, weld::Toggleable&, void); - DECL_LINK(PopupFlatMenuHdl, const CommandEvent&, bool); - DECL_LINK(PopupTreeMenuHdl, const CommandEvent&, bool); - DECL_LINK(KeyInputHdl, const KeyEvent&, bool); - DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString); - DECL_LINK(OnAsyncExecuteDrop, void *, void); - DECL_LINK(DragBeginHdl, bool&, bool); - DECL_LINK(CustomRenderHdl, weld::TreeView::render_args, void); - DECL_STATIC_LINK(SfxCommonTemplateDialog_Impl, CustomGetSizeHdl, weld::TreeView::get_size_args, Size); - - void DropHdl(const OUString& rStyle, const OUString& rParent); - - virtual void EnableItem(const OString& /*rMesId*/, bool /*bCheck*/ = true) - {} - virtual void CheckItem(const OString& /*rMesId*/, bool /*bCheck*/ = true) - {} - virtual bool IsCheckedItem(const OString& /*rMesId*/ ) - { - return true; - } - - void InvalidateBindings(); + virtual void InsertFamilyItem(sal_uInt16 nId, const SfxStyleFamilyItem& rItem) = 0; virtual void EnableFamilyItem(sal_uInt16 nId, bool bEnabled) = 0; virtual void ClearFamilyList() = 0; virtual void ReplaceUpdateButtonByMenu(); - void NewHdl(); - void EditHdl(); - void DeleteHdl(); - void HideHdl(); - void ShowHdl(); - - bool Execute_Impl(sal_uInt16 nId, const OUString& rStr, const OUString& rRefStr, - sal_uInt16 nFamily, SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto, - sal_uInt16* pIdx = nullptr, const sal_uInt16* pModifier = nullptr ); - - void UpdateStyles_Impl(StyleFlags nFlags); - const SfxStyleFamilyItem* GetFamilyItem_Impl() const; - bool IsInitialized() const - { - return nActFamily != 0xffff; - } - void EnableDelete(); void Initialize(); - void EnableHierarchical(bool); + void EnableHierarchical(bool, StyleList& rStyleList); void FilterSelect( sal_uInt16 nFilterIdx, bool bForce ); void SetFamilyState( sal_uInt16 nSlotId, const SfxTemplateItem* ); void SetWaterCanState( const SfxBoolItem* pItem ); bool IsSafeForWaterCan() const; - void SelectStyle(const OUString& rStyle, bool bIsCallback); - void UpdateStyleDependents(); - bool HasSelectedStyle() const; - void GetSelectedStyle() const; - void FillTreeBox(); - void Update_Impl(); - void UpdateFamily_Impl(); - - // In which FamilyState do I have to look, in order to get the - // information of the ith Family in the pStyleFamilies. - sal_uInt16 StyleNrToInfoOffset( sal_uInt16 i ); - - void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; - - void FamilySelect( sal_uInt16 nId, bool bPreviewRefresh = false ); void SetFamily(SfxStyleFamily nFamily); - void ActionSelect(const OString& rId); + void ActionSelect(const OString& rId, StyleList& rStyleList); - sal_Int32 LoadFactoryStyleFilter( SfxObjectShell const * i_pObjSh ); - void SaveFactoryStyleFilter( SfxObjectShell const * i_pObjSh, sal_Int32 i_nFilter ); - SfxObjectShell* SaveSelection(); + void SaveFactoryStyleFilter(SfxObjectShell const* i_pObjSh, sal_Int32 i_nFilter); - void PrepareMenu(const Point& rPos); - void ShowMenu(const CommandEvent& rCEvt); + DECL_LINK(ReadResource_Hdl, StyleList&, void); + DECL_LINK(ClearResource_Hdl, void*, void); + DECL_LINK(SaveSelection_Hdl, void*, SfxObjectShell*); + DECL_LINK(LoadFactoryStyleFilter_Hdl, SfxObjectShell const*, sal_Int32); + DECL_LINK(UpdateStyles_Hdl, StyleFlags, void); + DECL_LINK(UpdateFamily_Hdl, StyleList&, void); + DECL_LINK(UpdateStyleDependents_Hdl, void*, void); public: + // Used in StyleList::NewMenuExecuteAction, StyleList::UpdateStyleDependents, StyleList::NewHdl, EditHdl... + // It comes into action whenever an existing style is selected for use, or a new style is created etc.. + bool Execute_Impl(sal_uInt16 nId, const OUString& rStr, const OUString& rRefStr, + sal_uInt16 nFamily, StyleList& rStyleList, SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto, + sal_uInt16* pIdx = nullptr, const sal_uInt16* pModifier = nullptr); + + // This function handles drop of content into the treeview to create a new style + sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt); + // This function is used when a newstyle is created + DECL_LINK(OnAsyncExecuteDrop, void*, void); + + // Used in StyleList::UpdateStyles, StyleList::Update + // Whenever a new family(Eg. Character, List etc.) is selected it comes into action + void FamilySelect(sal_uInt16 nId, bool bPreviewRefresh = false); + // Constructor SfxCommonTemplateDialog_Impl(SfxBindings* pB, weld::Container*, weld::Builder* pBuilder); - virtual ~SfxCommonTemplateDialog_Impl() override; - - void MenuSelect(const OString& rIdent); - DECL_LINK( MenuSelectAsyncHdl, void*, void ); - - virtual void EnableEdit( bool b ) - { - bCanEdit = b; - } - void EnableDel( bool b ) - { - bCanDel = b; - } - void EnableNew( bool b ) - { - bCanNew = b; - } - void EnableHide( bool b ) - { - bCanHide = b; - } - void EnableShow( bool b ) - { - bCanShow = b; - } - void EnableTreeDrag(bool b); - void EnableExample_Impl(sal_uInt16 nId, bool bEnable); - SfxStyleFamily GetActualFamily() const; - OUString GetSelectedEntry() const; + // Destructor + virtual ~SfxCommonTemplateDialog_Impl(); - SfxObjectShell* GetObjectShell() const - { - return pCurObjShell; - } + // Used in StyleList::SelectStyle, StyleList::Notify, IMPL_LINK(PopupFlatMenuHdl) + // These functions are used when a style is edited, deleted, created etc.. + virtual void EnableEdit(bool b) { m_aStyleList.Enableedit(b); } + void EnableDel(bool b) { m_aStyleList.Enabledel(b); } + void EnableNew(bool b) { m_aStyleList.Enablenew(b); } + void EnableHide(bool b) { m_aStyleList.Enablehide(b); } + void EnableShow(bool b) { m_aStyleList.Enableshow(b); } - sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper); - sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt); + // Used in TreeDrag + void EnableTreeDrag(bool b); + // Dialog and StyleList have their own copies of variable bTreeDrag. + // When TreeDrag is enabled in StyleList, the value of m_bTreeDrag is updated in StyleList + // This function updates the value of bTreeDrag here too. + void SetEnableDrag(bool treedrag) { bTreeDrag = treedrag; } + // It comes into action when a style is created or updated or newmenu is created + void EnableExample_Impl(sal_uInt16 nId, bool bEnable); - void CreateContextMenu(); + // This comes into action when a family is selected or a style is applied for use + virtual void CheckItem(const OString& /*rMesId*/, bool /*bCheck*/ = true) {} + // This is used for watercan or when newmenu or watercan is enabled or updated + virtual void EnableItem(const OString& /*rMesId*/, bool /*bCheck*/ = true) {} + // This is used for watercan + virtual bool IsCheckedItem(const OString& /*rMesId*/) { return true; } + + // This is used when a style is selected + void SelectStyle(const OUString& rStyle, bool bIsCallback, StyleList& rStyleList); + + // Dialog and StyleList have their own copies of variable nAppFilter. + // When a filter is applied, it comes into action and updates the value of nAppFilter + void SetApplicationFilter(SfxStyleSearchBits filter) { nAppFilter = filter; } + // Dialog and StyleList have their own copies of variable nActFilter. + // When a filter is applied, it comes into action and updates the value of nActFilter + void SetFilterByIndex(sal_uInt16 filter) { nActFilter = filter; } + + // This function return the value of bUpdate in Stylelist + // This value is used in StyleList's Notify + bool GetNotifyUpdate() { return bUpdate; } + // This function sets the value of bUpdate in Dialog + // This function is used in StyleList's Notify to update the value of bUpdate when required + void SetNotifyupdate(bool b) { bUpdate = b; } + + void connect_stylelist_read_resource(const Link<void*, size_t>& rLink) { m_aStyleListReadResource = rLink; } + void connect_stylelist_clear(const Link<void*, void>& rLink) { m_aStyleListClear = rLink; } + void connect_stylelist_cleanup(const Link<void*, void>& rLink) { m_aStyleListCleanup = rLink; } + void connect_stylelist_execute_drop(const Link<const ExecuteDropEvent&, sal_Int8>& rLink); + void connect_stylelist_execute_new_menu(const Link<void*, void>& rLink) { m_aStyleListNewMenu = rLink; } + void connect_stylelist_for_watercan(const Link<void*, bool>& rLink) { m_aStyleListWaterCan = rLink; } + void connect_stylelist_has_selected_style(const Link<void*, bool>& rLink); + void connect_stylelist_update_styles(const Link<StyleFlags, void> rLink) { m_aStyleListUpdateStyles = rLink; } + void connect_stylelist_update_family(const Link<void*, void> rLink) { m_aStyleListUpdateFamily = rLink; } + void connect_stylelist_update_style_dependents(const Link<void*, void>& rLink); + void connect_stylelist_enable_tree_drag(const Link<bool, void> rLink); + void connect_stylelist_notify(const Link<SfxHintId, void> rLink) { m_aStyleListNotify = rLink; } + void connect_stylelist_filter_select(Link<sal_uInt16, void> rLink); + void connect_stylelist_enable_delete(const Link<void*, void> rLink); + void connect_stylelist_set_water_can_state(const Link<const SfxBoolItem*, void> rLink); + void connect_family_select(const Link<sal_uInt16, void> rLink); + void connect_set_family(const Link<sal_uInt16, void> rLink) { m_aStyleListSetFamily = rLink; } }; class ToolbarDropTarget; |