1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <memory> 21 #include <unordered_map> 22 23 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> 24 #include <com/sun/star/beans/XPropertySet.hpp> 25 #include <com/sun/star/container/XNameAccess.hpp> 26 #include <utility> 27 #include <vcl/commandevent.hxx> 28 #include <vcl/commandinfoprovider.hxx> 29 #include <vcl/event.hxx> 30 #include <vcl/settings.hxx> 31 #include <vcl/svapp.hxx> 32 #include <vcl/weldutils.hxx> 33 #include <vcl/window.hxx> 34 #include <svl/intitem.hxx> 35 #include <svl/style.hxx> 36 #include <comphelper/processfactory.hxx> 37 #include <officecfg/Office/Common.hxx> 38 39 #include <osl/diagnose.h> 40 #include <sfx2/dispatch.hxx> 41 #include <sfx2/bindings.hxx> 42 #include <templdgi.hxx> 43 #include <tplcitem.hxx> 44 #include <sfx2/styfitem.hxx> 45 #include <sfx2/objsh.hxx> 46 #include <sfx2/viewsh.hxx> 47 #include <sfx2/newstyle.hxx> 48 #include <sfx2/tplpitem.hxx> 49 #include <sfx2/sfxresid.hxx> 50 51 #include <sfx2/sfxsids.hrc> 52 #include <sfx2/strings.hrc> 53 #include <sfx2/docfac.hxx> 54 #include <sfx2/module.hxx> 55 #include <helpids.h> 56 #include <sfx2/viewfrm.hxx> 57 58 #include <comphelper/string.hxx> 59 60 #include <sfx2/StyleManager.hxx> 61 #include <sfx2/StylePreviewRenderer.hxx> 62 63 #include <StyleList.hxx> 64 65 using namespace css; 66 using namespace css::beans; 67 using namespace css::frame; 68 using namespace css::uno; 69 70 class TreeViewDropTarget final : public DropTargetHelper 71 { 72 private: 73 StyleList& m_rParent; 74 75 public: 76 TreeViewDropTarget(StyleList& rStyleList, weld::TreeView& rTreeView) 77 : DropTargetHelper(rTreeView.get_drop_target()) 78 , m_rParent(rStyleList) 79 { 80 } 81 82 virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override 83 { 84 return m_rParent.AcceptDrop(rEvt, *this); 85 } 86 87 virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override 88 { 89 return m_rParent.ExecuteDrop(rEvt); 90 } 91 }; 92 93 // Constructor 94 95 StyleList::StyleList(weld::Builder* pBuilder, SfxBindings* pBindings, 96 SfxCommonTemplateDialog_Impl* Parent, weld::Container* pC, 97 OString treeviewname, OString flatviewname) 98 : m_bHierarchical(false) 99 , m_bAllowReParentDrop(false) 100 , m_bNewByExampleDisabled(false) 101 , m_bDontUpdate(false) 102 , m_bTreeDrag(true) 103 , m_bCanEdit(false) 104 , m_bCanHide(true) 105 , m_bCanShow(false) 106 , m_bCanNew(true) 107 , m_bUpdateFamily(false) 108 , m_bCanDel(false) 109 , m_bBindingUpdate(true) 110 , m_pStyleSheetPool(nullptr) 111 , m_nActFilter(0) 112 , m_xFmtLb(pBuilder->weld_tree_view(flatviewname)) 113 , m_xTreeBox(pBuilder->weld_tree_view(treeviewname)) 114 , m_pCurObjShell(nullptr) 115 , m_nActFamily(0xffff) 116 , m_nAppFilter(SfxStyleSearchBits::Auto) 117 , m_pParentDialog(Parent) 118 , m_pBindings(pBindings) 119 , m_Module(nullptr) 120 , m_nModifier(0) 121 , m_pContainer(pC) 122 { 123 m_xFmtLb->set_help_id(HID_TEMPLATE_FMT); 124 } 125 126 // Destructor 127 128 StyleList::~StyleList() {} 129 130 // Called in the destructor of Dialog 131 // Cleans up the StyleList individual components while closing the application 132 IMPL_LINK_NOARG(StyleList, Cleanup, void*, void) 133 { 134 if (m_pStyleSheetPool) 135 EndListening(*m_pStyleSheetPool); 136 m_pStyleSheetPool = nullptr; 137 m_xTreeView1DropTargetHelper.reset(); 138 m_xTreeView2DropTargetHelper.reset(); 139 m_xTreeBox.reset(); 140 m_xFmtLb.reset(); 141 pIdle.reset(); 142 } 143 144 void StyleList::CreateContextMenu() 145 { 146 if (m_bBindingUpdate) 147 { 148 m_pBindings->Invalidate(SID_STYLE_NEW, true); 149 m_pBindings->Update(SID_STYLE_NEW); 150 m_bBindingUpdate = false; 151 } 152 mxMenu.reset(); 153 mxMenuBuilder = Application::CreateBuilder(nullptr, "sfx/ui/stylecontextmenu.ui"); 154 mxMenu = mxMenuBuilder->weld_menu("menu"); 155 mxMenu->set_sensitive("edit", m_bCanEdit); 156 mxMenu->set_sensitive("delete", m_bCanDel); 157 mxMenu->set_sensitive("new", m_bCanNew); 158 mxMenu->set_sensitive("hide", m_bCanHide); 159 mxMenu->set_sensitive("show", m_bCanShow); 160 161 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 162 if (pItem && pItem->GetFamily() == SfxStyleFamily::Table) //tdf#101648, no ui for this yet 163 { 164 mxMenu->set_sensitive("edit", false); 165 mxMenu->set_sensitive("new", false); 166 } 167 if (pItem && pItem->GetFamily() == SfxStyleFamily::Pseudo) 168 { 169 const OUString aTemplName(GetSelectedEntry()); 170 if (aTemplName == "No List") 171 { 172 mxMenu->set_sensitive("edit", false); 173 mxMenu->set_sensitive("new", false); 174 mxMenu->set_sensitive("hide", false); 175 } 176 } 177 } 178 179 IMPL_LINK_NOARG(StyleList, ReadResource, void*, size_t) 180 { 181 // Read global user resource 182 for (auto& i : m_pFamilyState) 183 i.reset(); 184 185 SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); 186 m_pCurObjShell = pViewFrame->GetObjectShell(); 187 m_Module = m_pCurObjShell ? m_pCurObjShell->GetModule() : nullptr; 188 if (m_Module) 189 m_xStyleFamilies = m_Module->CreateStyleFamilies(); 190 if (!m_xStyleFamilies) 191 m_xStyleFamilies.emplace(); 192 193 m_nActFilter = 0xffff; 194 195 if (m_pCurObjShell) 196 { 197 m_nActFilter = static_cast<sal_uInt16>(m_aLoadFactoryStyleFilter.Call(m_pCurObjShell)); 198 if (0xffff == m_nActFilter) 199 { 200 m_nActFilter = m_pCurObjShell->GetAutoStyleFilterIndex(); 201 } 202 } 203 size_t nCount = m_xStyleFamilies->size(); 204 m_pBindings->ENTERREGISTRATIONS(); 205 206 size_t i; 207 for (i = 0; i < nCount; ++i) 208 { 209 sal_uInt16 nSlot = 0; 210 switch (m_xStyleFamilies->at(i).GetFamily()) 211 { 212 case SfxStyleFamily::Char: 213 nSlot = SID_STYLE_FAMILY1; 214 break; 215 case SfxStyleFamily::Para: 216 nSlot = SID_STYLE_FAMILY2; 217 break; 218 case SfxStyleFamily::Frame: 219 nSlot = SID_STYLE_FAMILY3; 220 break; 221 case SfxStyleFamily::Page: 222 nSlot = SID_STYLE_FAMILY4; 223 break; 224 case SfxStyleFamily::Pseudo: 225 nSlot = SID_STYLE_FAMILY5; 226 break; 227 case SfxStyleFamily::Table: 228 nSlot = SID_STYLE_FAMILY6; 229 break; 230 default: 231 OSL_FAIL("unknown StyleFamily"); 232 break; 233 } 234 pBoundItems[i].reset(new SfxTemplateControllerItem(nSlot, *m_pParentDialog, *m_pBindings)); 235 } 236 pBoundItems[i++].reset( 237 new SfxTemplateControllerItem(SID_STYLE_WATERCAN, *m_pParentDialog, *m_pBindings)); 238 pBoundItems[i++].reset( 239 new SfxTemplateControllerItem(SID_STYLE_NEW_BY_EXAMPLE, *m_pParentDialog, *m_pBindings)); 240 pBoundItems[i++].reset( 241 new SfxTemplateControllerItem(SID_STYLE_UPDATE_BY_EXAMPLE, *m_pParentDialog, *m_pBindings)); 242 pBoundItems[i++].reset( 243 new SfxTemplateControllerItem(SID_STYLE_NEW, *m_pParentDialog, *m_pBindings)); 244 pBoundItems[i++].reset( 245 new SfxTemplateControllerItem(SID_STYLE_DRAGHIERARCHIE, *m_pParentDialog, *m_pBindings)); 246 pBoundItems[i++].reset( 247 new SfxTemplateControllerItem(SID_STYLE_EDIT, *m_pParentDialog, *m_pBindings)); 248 pBoundItems[i++].reset( 249 new SfxTemplateControllerItem(SID_STYLE_DELETE, *m_pParentDialog, *m_pBindings)); 250 pBoundItems[i++].reset( 251 new SfxTemplateControllerItem(SID_STYLE_FAMILY, *m_pParentDialog, *m_pBindings)); 252 m_pBindings->LEAVEREGISTRATIONS(); 253 254 for (; i < COUNT_BOUND_FUNC; ++i) 255 pBoundItems[i] = nullptr; 256 257 StartListening(*m_pBindings); 258 259 for (i = SID_STYLE_FAMILY1; i <= SID_STYLE_FAMILY4; i++) 260 m_pBindings->Update(i); 261 262 return nCount; 263 } 264 265 void StyleList::EnableNewByExample(bool newByExampleDisabled) 266 { 267 m_bNewByExampleDisabled = newByExampleDisabled; 268 } 269 270 void StyleList::FilterSelect(sal_uInt16 nActFilter, bool bsetFilter) 271 { 272 m_nActFilter = nActFilter; 273 if (bsetFilter) 274 { 275 SfxObjectShell* const pDocShell = m_aSaveSelection.Call(*this); 276 SfxStyleSheetBasePool* pOldStyleSheetPool = m_pStyleSheetPool; 277 m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr; 278 if (pOldStyleSheetPool != m_pStyleSheetPool) 279 { 280 if (pOldStyleSheetPool) 281 EndListening(*pOldStyleSheetPool); 282 if (m_pStyleSheetPool) 283 StartListening(*m_pStyleSheetPool); 284 } 285 } 286 UpdateStyles(StyleFlags::UpdateFamilyList); 287 } 288 289 IMPL_LINK(StyleList, SetFamily, sal_uInt16, nId, void) 290 { 291 if (m_nActFamily != 0xFFFF) 292 m_pParentDialog->CheckItem(OString::number(m_nActFamily), false); 293 m_nActFamily = nId; 294 if (nId != 0xFFFF) 295 { 296 m_bUpdateFamily = true; 297 } 298 } 299 300 void StyleList::InvalidateBindings() 301 { 302 m_pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, true); 303 m_pBindings->Update(SID_STYLE_NEW_BY_EXAMPLE); 304 m_pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, true); 305 m_pBindings->Update(SID_STYLE_UPDATE_BY_EXAMPLE); 306 m_pBindings->Invalidate(SID_STYLE_WATERCAN, true); 307 m_pBindings->Update(SID_STYLE_WATERCAN); 308 m_pBindings->Invalidate(SID_STYLE_NEW, true); 309 m_pBindings->Update(SID_STYLE_NEW); 310 m_pBindings->Invalidate(SID_STYLE_DRAGHIERARCHIE, true); 311 m_pBindings->Update(SID_STYLE_DRAGHIERARCHIE); 312 } 313 314 void StyleList::Initialize() 315 { 316 m_pBindings->Invalidate(SID_STYLE_FAMILY); 317 m_pBindings->Update(SID_STYLE_FAMILY); 318 319 m_xFmtLb->connect_row_activated(LINK(this, StyleList, TreeListApplyHdl)); 320 m_xFmtLb->connect_mouse_press(LINK(this, StyleList, MousePressHdl)); 321 m_xFmtLb->connect_query_tooltip(LINK(this, StyleList, QueryTooltipHdl)); 322 m_xFmtLb->connect_changed(LINK(this, StyleList, FmtSelectHdl)); 323 m_xFmtLb->connect_popup_menu(LINK(this, StyleList, PopupFlatMenuHdl)); 324 m_xFmtLb->connect_key_press(LINK(this, StyleList, KeyInputHdl)); 325 m_xFmtLb->set_selection_mode(SelectionMode::Multiple); 326 m_xTreeBox->connect_changed(LINK(this, StyleList, FmtSelectHdl)); 327 m_xTreeBox->connect_row_activated(LINK(this, StyleList, TreeListApplyHdl)); 328 m_xTreeBox->connect_mouse_press(LINK(this, StyleList, MousePressHdl)); 329 m_xTreeBox->connect_query_tooltip(LINK(this, StyleList, QueryTooltipHdl)); 330 m_xTreeBox->connect_popup_menu(LINK(this, StyleList, PopupTreeMenuHdl)); 331 m_xTreeBox->connect_key_press(LINK(this, StyleList, KeyInputHdl)); 332 m_xTreeBox->connect_drag_begin(LINK(this, StyleList, DragBeginHdl)); 333 m_xTreeView1DropTargetHelper.reset(new TreeViewDropTarget(*this, *m_xFmtLb)); 334 m_xTreeView2DropTargetHelper.reset(new TreeViewDropTarget(*this, *m_xTreeBox)); 335 336 m_pParentDialog->connect_stylelist_read_resource(LINK(this, StyleList, ReadResource)); 337 m_pParentDialog->connect_stylelist_clear(LINK(this, StyleList, Clear)); 338 m_pParentDialog->connect_stylelist_cleanup(LINK(this, StyleList, Cleanup)); 339 m_pParentDialog->connect_stylelist_execute_drop(LINK(this, StyleList, ExecuteDrop)); 340 m_pParentDialog->connect_stylelist_execute_new_menu( 341 LINK(this, StyleList, NewMenuExecuteAction)); 342 m_pParentDialog->connect_stylelist_for_watercan(LINK(this, StyleList, IsSafeForWaterCan)); 343 m_pParentDialog->connect_stylelist_has_selected_style(LINK(this, StyleList, HasSelectedStyle)); 344 m_pParentDialog->connect_stylelist_update_style_dependents( 345 LINK(this, StyleList, UpdateStyleDependents)); 346 m_pParentDialog->connect_stylelist_enable_tree_drag(LINK(this, StyleList, EnableTreeDrag)); 347 m_pParentDialog->connect_stylelist_enable_delete(LINK(this, StyleList, EnableDelete)); 348 m_pParentDialog->connect_stylelist_set_water_can_state(LINK(this, StyleList, SetWaterCanState)); 349 m_pParentDialog->connect_set_family(LINK(this, StyleList, SetFamily)); 350 351 int nTreeHeight = m_xFmtLb->get_height_rows(8); 352 m_xFmtLb->set_size_request(-1, nTreeHeight); 353 m_xTreeBox->set_size_request(-1, nTreeHeight); 354 355 m_xFmtLb->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl)); 356 m_xFmtLb->connect_custom_render(LINK(this, StyleList, CustomRenderHdl)); 357 m_xTreeBox->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl)); 358 m_xTreeBox->connect_custom_render(LINK(this, StyleList, CustomRenderHdl)); 359 bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get(); 360 m_xFmtLb->set_column_custom_renderer(0, bCustomPreview); 361 m_xTreeBox->set_column_custom_renderer(0, bCustomPreview); 362 363 m_xFmtLb->set_visible(!m_bHierarchical); 364 m_xTreeBox->set_visible(m_bHierarchical); 365 Update(); 366 } 367 368 void StyleList::UpdateFamily() 369 { 370 m_bUpdateFamily = false; 371 372 SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl(); 373 SfxViewFrame* pViewFrame = pDispat->GetFrame(); 374 SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); 375 376 SfxStyleSheetBasePool* pOldStyleSheetPool = m_pStyleSheetPool; 377 m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr; 378 if (pOldStyleSheetPool != m_pStyleSheetPool) 379 { 380 if (pOldStyleSheetPool) 381 EndListening(*pOldStyleSheetPool); 382 if (m_pStyleSheetPool) 383 StartListening(*m_pStyleSheetPool); 384 } 385 386 m_bTreeDrag = true; 387 m_bCanNew = m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1; 388 m_pParentDialog->EnableNew(m_bCanNew, this); 389 m_bTreeDrag = true; 390 if (m_pStyleSheetPool) 391 { 392 if (!m_xTreeBox->get_visible()) 393 UpdateStyles(StyleFlags::UpdateFamily | StyleFlags::UpdateFamilyList); 394 else 395 { 396 UpdateStyles(StyleFlags::UpdateFamily); 397 FillTreeBox(GetActualFamily()); 398 } 399 } 400 401 InvalidateBindings(); 402 } 403 404 bool StyleList::EnableExecute() 405 { 406 return m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1; 407 } 408 409 void StyleList::connect_LoadFactoryStyleFilter(const Link<SfxObjectShell const*, sal_Int32>& rLink) 410 { 411 m_aLoadFactoryStyleFilter = rLink; 412 } 413 414 void StyleList::connect_SaveSelection(const Link<StyleList&, SfxObjectShell*> rLink) 415 { 416 m_aSaveSelection = rLink; 417 } 418 419 /** Drop is enabled as long as it is allowed to create a new style by example, i.e. to 420 create a style out of the current selection. 421 */ 422 sal_Int8 StyleList::AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper) 423 { 424 if (rHelper.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR)) 425 { 426 // special case: page styles are allowed to create new styles by example 427 // but not allowed to be created by drag and drop 428 if (GetActualFamily() == SfxStyleFamily::Page || m_bNewByExampleDisabled) 429 return DND_ACTION_NONE; 430 else 431 return DND_ACTION_COPY; 432 } 433 // to enable the autoscroll when we're close to the edges 434 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 435 pTreeView->get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true); 436 return DND_ACTION_MOVE; 437 } 438 439 // handles drop of content in treeview when creating a new style 440 IMPL_LINK(StyleList, ExecuteDrop, const ExecuteDropEvent&, rEvt, sal_Int8) 441 { 442 SfxObjectShell* pDocShell = m_pCurObjShell; 443 if (pDocShell) 444 { 445 TransferableDataHelper aHelper(rEvt.maDropEvent.Transferable); 446 sal_uInt32 nFormatCount = aHelper.GetFormatCount(); 447 448 sal_Int8 nRet = DND_ACTION_NONE; 449 450 bool bFormatFound = false; 451 452 for (sal_uInt32 i = 0; i < nFormatCount; ++i) 453 { 454 SotClipboardFormatId nId = aHelper.GetFormat(i); 455 TransferableObjectDescriptor aDesc; 456 457 if (aHelper.GetTransferableObjectDescriptor(nId, aDesc)) 458 { 459 if (aDesc.maClassName == pDocShell->GetFactory().GetClassId()) 460 { 461 Application::PostUserEvent( 462 LINK(m_pParentDialog, SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop), 463 this); 464 465 bFormatFound = true; 466 nRet = rEvt.mnAction; 467 break; 468 } 469 } 470 } 471 472 if (bFormatFound) 473 return nRet; 474 } 475 476 if (!m_xTreeBox->get_visible()) 477 return DND_ACTION_NONE; 478 479 if (!m_bAllowReParentDrop) 480 return DND_ACTION_NONE; 481 482 // otherwise if we're dragging with the treeview to set a new parent of the dragged style 483 weld::TreeView* pSource = m_xTreeBox->get_drag_source(); 484 // only dragging within the same widget allowed 485 if (!pSource || pSource != m_xTreeBox.get()) 486 return DND_ACTION_NONE; 487 488 std::unique_ptr<weld::TreeIter> xSource(m_xTreeBox->make_iterator()); 489 if (!m_xTreeBox->get_selected(xSource.get())) 490 return DND_ACTION_NONE; 491 492 std::unique_ptr<weld::TreeIter> xTarget(m_xTreeBox->make_iterator()); 493 if (!m_xTreeBox->get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), true)) 494 { 495 // if nothing under the mouse, use the last row 496 int nChildren = m_xTreeBox->n_children(); 497 if (!nChildren) 498 return DND_ACTION_NONE; 499 if (!m_xTreeBox->get_iter_first(*xTarget) 500 || !m_xTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) 501 return DND_ACTION_NONE; 502 while (m_xTreeBox->get_row_expanded(*xTarget)) 503 { 504 nChildren = m_xTreeBox->iter_n_children(*xTarget); 505 if (!m_xTreeBox->iter_children(*xTarget) 506 || !m_xTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) 507 return DND_ACTION_NONE; 508 } 509 } 510 OUString aTargetStyle = m_xTreeBox->get_text(*xTarget); 511 DropHdl(m_xTreeBox->get_text(*xSource), aTargetStyle); 512 m_xTreeBox->unset_drag_dest_row(); 513 FillTreeBox(GetActualFamily()); 514 m_pParentDialog->SelectStyle(aTargetStyle, false, *this); 515 return DND_ACTION_NONE; 516 } 517 518 IMPL_LINK_NOARG(StyleList, NewMenuExecuteAction, void*, void) 519 { 520 if (!m_pStyleSheetPool || m_nActFamily == 0xffff) 521 return; 522 523 const SfxStyleFamily eFam = GetFamilyItem()->GetFamily(); 524 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 525 SfxStyleSearchBits nFilter(SfxStyleSearchBits::Auto); 526 if (pItem && m_nActFilter != 0xffff) 527 nFilter = pItem->GetFilterList()[m_nActFilter].nFlags; 528 if (nFilter == SfxStyleSearchBits::Auto) // automatic 529 nFilter = m_nAppFilter; 530 531 // why? : FloatingWindow must not be parent of a modal dialog 532 SfxNewStyleDlg aDlg(m_pContainer, *m_pStyleSheetPool, eFam); 533 auto nResult = aDlg.run(); 534 if (nResult == RET_OK) 535 { 536 const OUString aTemplName(aDlg.GetName()); 537 m_pParentDialog->Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE, aTemplName, "", 538 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this, 539 nFilter); 540 UpdateFamily(); 541 m_aUpdateFamily.Call(*this); 542 } 543 } 544 545 void StyleList::DropHdl(const OUString& rStyle, const OUString& rParent) 546 { 547 m_bDontUpdate = true; 548 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 549 const SfxStyleFamily eFam = pItem->GetFamily(); 550 m_pStyleSheetPool->SetParent(eFam, rStyle, rParent); 551 m_bDontUpdate = false; 552 } 553 554 void StyleList::PrepareMenu(const Point& rPos) 555 { 556 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 557 std::unique_ptr<weld::TreeIter> xIter(pTreeView->make_iterator()); 558 if (pTreeView->get_dest_row_at_pos(rPos, xIter.get(), false) && !pTreeView->is_selected(*xIter)) 559 { 560 pTreeView->unselect_all(); 561 pTreeView->set_cursor(*xIter); 562 pTreeView->select(*xIter); 563 } 564 FmtSelectHdl(*pTreeView); 565 } 566 567 /** Internal structure for the establishment of the hierarchical view */ 568 namespace 569 { 570 class StyleTree_Impl; 571 } 572 573 typedef std::vector<std::unique_ptr<StyleTree_Impl>> StyleTreeArr_Impl; 574 575 namespace 576 { 577 class StyleTree_Impl 578 { 579 private: 580 OUString aName; 581 OUString aParent; 582 StyleTreeArr_Impl pChildren; 583 584 public: 585 bool HasParent() const { return !aParent.isEmpty(); } 586 587 StyleTree_Impl(OUString _aName, OUString _aParent) 588 : aName(std::move(_aName)) 589 , aParent(std::move(_aParent)) 590 , pChildren(0) 591 { 592 } 593 594 const OUString& getName() const { return aName; } 595 const OUString& getParent() const { return aParent; } 596 StyleTreeArr_Impl& getChildren() { return pChildren; } 597 }; 598 } 599 600 static void MakeTree_Impl(StyleTreeArr_Impl& rArr, const OUString& aUIName) 601 { 602 const comphelper::string::NaturalStringSorter aSorter( 603 ::comphelper::getProcessComponentContext(), 604 Application::GetSettings().GetLanguageTag().getLocale()); 605 606 std::unordered_map<OUString, StyleTree_Impl*> styleFinder; 607 styleFinder.reserve(rArr.size()); 608 for (const auto& pEntry : rArr) 609 { 610 styleFinder.emplace(pEntry->getName(), pEntry.get()); 611 } 612 613 // Arrange all under their Parents 614 for (auto& pEntry : rArr) 615 { 616 if (!pEntry->HasParent()) 617 continue; 618 auto it = styleFinder.find(pEntry->getParent()); 619 if (it != styleFinder.end()) 620 { 621 StyleTree_Impl* pCmp = it->second; 622 // Insert child entries sorted 623 auto iPos = std::lower_bound( 624 pCmp->getChildren().begin(), pCmp->getChildren().end(), pEntry, 625 [&aSorter](std::unique_ptr<StyleTree_Impl> const& pEntry1, 626 std::unique_ptr<StyleTree_Impl> const& pEntry2) { 627 return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; 628 }); 629 pCmp->getChildren().insert(iPos, std::move(pEntry)); 630 } 631 } 632 633 // Only keep tree roots in rArr, child elements can be accessed through the hierarchy 634 rArr.erase( 635 std::remove_if(rArr.begin(), rArr.end(), 636 [](std::unique_ptr<StyleTree_Impl> const& pEntry) { return !pEntry; }), 637 rArr.end()); 638 639 // tdf#91106 sort top level styles 640 std::sort(rArr.begin(), rArr.end()); 641 std::sort(rArr.begin(), rArr.end(), 642 [&aSorter, &aUIName](std::unique_ptr<StyleTree_Impl> const& pEntry1, 643 std::unique_ptr<StyleTree_Impl> const& pEntry2) { 644 if (pEntry2->getName() == aUIName) 645 return false; 646 if (pEntry1->getName() == aUIName) 647 return true; // default always first 648 return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; 649 }); 650 } 651 652 static bool IsExpanded_Impl(const std::vector<OUString>& rEntries, std::u16string_view rStr) 653 { 654 for (const auto& rEntry : rEntries) 655 { 656 if (rEntry == rStr) 657 return true; 658 } 659 return false; 660 } 661 662 static void FillBox_Impl(weld::TreeView& rBox, StyleTree_Impl* pEntry, 663 const std::vector<OUString>& rEntries, SfxStyleFamily eStyleFamily, 664 const weld::TreeIter* pParent) 665 { 666 std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator(); 667 const OUString& rName = pEntry->getName(); 668 rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get()); 669 670 for (size_t i = 0; i < pEntry->getChildren().size(); ++i) 671 FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get()); 672 } 673 674 namespace SfxTemplate 675 { 676 // converts from SFX_STYLE_FAMILY Ids to 1-6 677 static sal_uInt16 SfxFamilyIdToNId(SfxStyleFamily nFamily) 678 { 679 switch (nFamily) 680 { 681 case SfxStyleFamily::Char: 682 return 1; 683 case SfxStyleFamily::Para: 684 return 2; 685 case SfxStyleFamily::Frame: 686 return 3; 687 case SfxStyleFamily::Page: 688 return 4; 689 case SfxStyleFamily::Pseudo: 690 return 5; 691 case SfxStyleFamily::Table: 692 return 6; 693 default: 694 return 0xffff; 695 } 696 } 697 // converts from 1-6 to SFX_STYLE_FAMILY Ids 698 static SfxStyleFamily NIdToSfxFamilyId(sal_uInt16 nId) 699 { 700 switch (nId) 701 { 702 case 1: 703 return SfxStyleFamily::Char; 704 case 2: 705 return SfxStyleFamily::Para; 706 case 3: 707 return SfxStyleFamily::Frame; 708 case 4: 709 return SfxStyleFamily::Page; 710 case 5: 711 return SfxStyleFamily::Pseudo; 712 case 6: 713 return SfxStyleFamily::Table; 714 default: 715 return SfxStyleFamily::All; 716 } 717 } 718 } 719 720 sal_uInt16 StyleList::StyleNrToInfoOffset(sal_uInt16 nId) 721 { 722 const SfxStyleFamilyItem& rItem = m_xStyleFamilies->at(nId); 723 return SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()) - 1; 724 } 725 726 // Helper function: Access to the current family item 727 const SfxStyleFamilyItem* StyleList::GetFamilyItem() const 728 { 729 const size_t nCount = m_xStyleFamilies->size(); 730 for (size_t i = 0; i < nCount; ++i) 731 { 732 const SfxStyleFamilyItem& rItem = m_xStyleFamilies->at(i); 733 sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()); 734 if (nId == m_nActFamily) 735 return &rItem; 736 } 737 return nullptr; 738 } 739 740 void StyleList::GetSelectedStyle() const 741 { 742 const OUString aTemplName(GetSelectedEntry()); 743 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 744 m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); 745 } 746 747 // Used to get the current selected entry in visible treeview 748 OUString StyleList::GetSelectedEntry() const 749 { 750 OUString aRet; 751 if (m_xTreeBox->get_visible()) 752 aRet = m_xTreeBox->get_selected_text(); 753 else 754 aRet = m_xFmtLb->get_selected_text(); 755 return aRet; 756 } 757 758 /** 759 * Is it safe to show the water-can / fill icon. If we've a 760 * hierarchical widget - we have only single select, otherwise 761 * we need to check if we have a multi-selection. We either have 762 * a m_xTreeBox showing or an m_xFmtLb (which we hide when not shown) 763 */ 764 IMPL_LINK_NOARG(StyleList, IsSafeForWaterCan, void*, bool) 765 { 766 if (m_xTreeBox->get_visible()) 767 return m_xTreeBox->get_selected_index() != -1; 768 else 769 return m_xFmtLb->count_selected_rows() == 1; 770 } 771 772 IMPL_LINK(StyleList, SetWaterCanState, const SfxBoolItem*, pItem, void) 773 { 774 size_t nCount = m_xStyleFamilies->size(); 775 m_pBindings->EnterRegistrations(); 776 for (size_t n = 0; n < nCount; n++) 777 { 778 SfxControllerItem* pCItem = pBoundItems[n].get(); 779 bool bChecked = pItem && pItem->GetValue(); 780 if (pCItem->IsBound() == bChecked) 781 { 782 if (!bChecked) 783 pCItem->ReBind(); 784 else 785 pCItem->UnBind(); 786 } 787 } 788 m_pBindings->LeaveRegistrations(); 789 } 790 791 void StyleList::FamilySelect(sal_uInt16 nEntry) 792 { 793 m_nActFamily = nEntry; 794 SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl(); 795 SfxUInt16Item const aItem(SID_STYLE_FAMILY, 796 static_cast<sal_uInt16>(SfxTemplate::NIdToSfxFamilyId(nEntry))); 797 pDispat->ExecuteList(SID_STYLE_FAMILY, SfxCallMode::SYNCHRON, { &aItem }); 798 m_pBindings->Invalidate(SID_STYLE_FAMILY); 799 m_pBindings->Update(SID_STYLE_FAMILY); 800 UpdateFamily(); 801 m_aUpdateFamily.Call(*this); 802 } 803 804 // It selects the style in treeview 805 // bIsCallBack is true for the selected style. For eg. if "Addressee" is selected in 806 // styles, bIsCallBack will be true for it. 807 void StyleList::SelectStyle(const OUString& rStr, bool bIsCallback) 808 { 809 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 810 if (!pItem) 811 return; 812 const SfxStyleFamily eFam = pItem->GetFamily(); 813 SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(rStr, eFam); 814 if (pStyle) 815 { 816 bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); 817 m_pParentDialog->EnableEdit(bReadWrite, this); 818 m_pParentDialog->EnableHide(bReadWrite && !pStyle->IsHidden() && !pStyle->IsUsed(), this); 819 m_pParentDialog->EnableShow(bReadWrite && pStyle->IsHidden(), this); 820 } 821 else 822 { 823 m_pParentDialog->EnableEdit(false, this); 824 m_pParentDialog->EnableHide(false, this); 825 m_pParentDialog->EnableShow(false, this); 826 } 827 828 if (bIsCallback) 829 return; 830 831 if (m_xTreeBox->get_visible()) 832 { 833 if (!rStr.isEmpty()) 834 { 835 std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator(); 836 bool bEntry = m_xTreeBox->get_iter_first(*xEntry); 837 while (bEntry) 838 { 839 if (m_xTreeBox->get_text(*xEntry) == rStr) 840 { 841 m_xTreeBox->scroll_to_row(*xEntry); 842 m_xTreeBox->select(*xEntry); 843 break; 844 } 845 bEntry = m_xTreeBox->iter_next(*xEntry); 846 } 847 } 848 else if (eFam == SfxStyleFamily::Pseudo) 849 { 850 std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator(); 851 if (m_xTreeBox->get_iter_first(*xEntry)) 852 { 853 m_xTreeBox->scroll_to_row(*xEntry); 854 m_xTreeBox->select(*xEntry); 855 } 856 } 857 else 858 m_xTreeBox->unselect_all(); 859 } 860 else 861 { 862 bool bSelect = !rStr.isEmpty(); 863 if (bSelect) 864 { 865 std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator(); 866 bool bEntry = m_xFmtLb->get_iter_first(*xEntry); 867 while (bEntry && m_xFmtLb->get_text(*xEntry) != rStr) 868 bEntry = m_xFmtLb->iter_next(*xEntry); 869 if (!bEntry) 870 bSelect = false; 871 else 872 { 873 if (!m_xFmtLb->is_selected(*xEntry)) 874 { 875 m_xFmtLb->unselect_all(); 876 m_xFmtLb->scroll_to_row(*xEntry); 877 m_xFmtLb->select(*xEntry); 878 } 879 } 880 } 881 882 if (!bSelect) 883 { 884 m_xFmtLb->unselect_all(); 885 m_pParentDialog->EnableEdit(false, this); 886 m_pParentDialog->EnableHide(false, this); 887 m_pParentDialog->EnableShow(false, this); 888 } 889 } 890 } 891 892 static void MakeExpanded_Impl(const weld::TreeView& rBox, std::vector<OUString>& rEntries) 893 { 894 std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator(); 895 if (rBox.get_iter_first(*xEntry)) 896 { 897 do 898 { 899 if (rBox.get_row_expanded(*xEntry)) 900 rEntries.push_back(rBox.get_text(*xEntry)); 901 } while (rBox.iter_next(*xEntry)); 902 } 903 } 904 905 IMPL_LINK(StyleList, EnableTreeDrag, bool, m_bEnable, void) 906 { 907 if (m_pStyleSheetPool) 908 { 909 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 910 SfxStyleSheetBase* pStyle = pItem ? m_pStyleSheetPool->First(pItem->GetFamily()) : nullptr; 911 m_bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && m_bEnable; 912 } 913 m_bTreeDrag = m_bEnable; 914 } 915 916 // Fill the treeview 917 918 void StyleList::FillTreeBox(SfxStyleFamily eFam) 919 { 920 assert(m_xTreeBox && "FillTreeBox() without treebox"); 921 if (!m_pStyleSheetPool || m_nActFamily == 0xffff) 922 return; 923 924 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 925 if (!pItem) 926 return; 927 928 StyleTreeArr_Impl aArr; 929 SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, SfxStyleSearchBits::AllVisible); 930 931 m_bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && m_bTreeDrag; 932 933 while (pStyle) 934 { 935 StyleTree_Impl* pNew = new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent()); 936 aArr.emplace_back(pNew); 937 pStyle = m_pStyleSheetPool->Next(); 938 } 939 OUString aUIName = getDefaultStyleName(eFam); 940 MakeTree_Impl(aArr, aUIName); 941 std::vector<OUString> aEntries; 942 MakeExpanded_Impl(*m_xTreeBox, aEntries); 943 m_xTreeBox->freeze(); 944 m_xTreeBox->clear(); 945 const sal_uInt16 nCount = aArr.size(); 946 947 for (sal_uInt16 i = 0; i < nCount; ++i) 948 { 949 FillBox_Impl(*m_xTreeBox, aArr[i].get(), aEntries, eFam, nullptr); 950 aArr[i].reset(); 951 } 952 953 m_pParentDialog->EnableItem("watercan", false); 954 955 SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get(); 956 957 m_xTreeBox->thaw(); 958 959 std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator(); 960 bool bEntry = m_xTreeBox->get_iter_first(*xEntry); 961 if (bEntry && nCount) 962 m_xTreeBox->expand_row(*xEntry); 963 964 while (bEntry) 965 { 966 if (IsExpanded_Impl(aEntries, m_xTreeBox->get_text(*xEntry))) 967 m_xTreeBox->expand_row(*xEntry); 968 bEntry = m_xTreeBox->iter_next(*xEntry); 969 } 970 971 OUString aStyle; 972 if (pState) // Select current entry 973 aStyle = pState->GetStyleName(); 974 m_pParentDialog->SelectStyle(aStyle, false, *this); 975 EnableDelete(nullptr); 976 } 977 978 static OUString lcl_GetStyleFamilyName(SfxStyleFamily nFamily) 979 { 980 if (nFamily == SfxStyleFamily::Char) 981 return "CharacterStyles"; 982 if (nFamily == SfxStyleFamily::Para) 983 return "ParagraphStyles"; 984 if (nFamily == SfxStyleFamily::Page) 985 return "PageStyles"; 986 if (nFamily == SfxStyleFamily::Table) 987 return "TableStyles"; 988 if (nFamily == SfxStyleFamily::Pseudo) 989 return "NumberingStyles"; 990 return OUString(); 991 } 992 993 OUString StyleList::getDefaultStyleName(const SfxStyleFamily eFam) 994 { 995 OUString sDefaultStyle; 996 OUString aFamilyName = lcl_GetStyleFamilyName(eFam); 997 if (aFamilyName == "TableStyles") 998 sDefaultStyle = "Default Style"; 999 else if (aFamilyName == "NumberingStyles") 1000 sDefaultStyle = "No List"; 1001 else 1002 sDefaultStyle = "Standard"; 1003 uno::Reference<style::XStyleFamiliesSupplier> xModel(m_pCurObjShell->GetModel(), 1004 uno::UNO_QUERY); 1005 OUString aUIName; 1006 try 1007 { 1008 uno::Reference<container::XNameAccess> xStyles; 1009 uno::Reference<container::XNameAccess> xCont = xModel->getStyleFamilies(); 1010 xCont->getByName(aFamilyName) >>= xStyles; 1011 uno::Reference<beans::XPropertySet> xInfo; 1012 xStyles->getByName(sDefaultStyle) >>= xInfo; 1013 xInfo->getPropertyValue("DisplayName") >>= aUIName; 1014 } 1015 catch (const uno::Exception&) 1016 { 1017 } 1018 return aUIName; 1019 } 1020 1021 SfxStyleFamily StyleList::GetActualFamily() const 1022 { 1023 const SfxStyleFamilyItem* pFamilyItem = GetFamilyItem(); 1024 if (!pFamilyItem || m_nActFamily == 0xffff) 1025 return SfxStyleFamily::Para; 1026 else 1027 return pFamilyItem->GetFamily(); 1028 } 1029 1030 IMPL_LINK_NOARG(StyleList, HasSelectedStyle, void*, bool) 1031 { 1032 return m_xTreeBox->get_visible() ? m_xTreeBox->get_selected_index() != -1 1033 : m_xFmtLb->count_selected_rows() != 0; 1034 } 1035 1036 IMPL_LINK_NOARG(StyleList, UpdateStyleDependents, void*, void) 1037 { 1038 // Trigger Help PI. Only when the watercan is on 1039 if (m_nActFamily != 0xffff && m_pParentDialog->IsCheckedItem("watercan") && 1040 // only if that region is allowed 1041 nullptr != m_pFamilyState[m_nActFamily - 1] && IsSafeForWaterCan(nullptr)) 1042 { 1043 m_pParentDialog->Execute_Impl(SID_STYLE_WATERCAN, "", "", 0, *this); 1044 m_pParentDialog->Execute_Impl(SID_STYLE_WATERCAN, GetSelectedEntry(), "", 1045 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); 1046 } 1047 } 1048 1049 // Comes into action when the current style is changed 1050 void StyleList::UpdateStyles(StyleFlags nFlags) 1051 { 1052 OSL_ENSURE(nFlags != StyleFlags::NONE, "nothing to do"); 1053 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1054 if (!pItem) 1055 { 1056 // Is the case for the template catalog 1057 const size_t nFamilyCount = m_xStyleFamilies->size(); 1058 size_t n; 1059 for (n = 0; n < nFamilyCount; n++) 1060 if (m_pFamilyState[StyleNrToInfoOffset(n)]) 1061 break; 1062 if (n == nFamilyCount) 1063 // It happens sometimes, God knows why 1064 return; 1065 m_nAppFilter = m_pFamilyState[StyleNrToInfoOffset(n)]->GetValue(); 1066 m_pParentDialog->FamilySelect(StyleNrToInfoOffset(n) + 1, *this); 1067 pItem = GetFamilyItem(); 1068 } 1069 1070 const SfxStyleFamily eFam = pItem->GetFamily(); 1071 1072 SfxStyleSearchBits nFilter(m_nActFilter < pItem->GetFilterList().size() 1073 ? pItem->GetFilterList()[m_nActFilter].nFlags 1074 : SfxStyleSearchBits::Auto); 1075 if (nFilter == SfxStyleSearchBits::Auto) // automatic 1076 nFilter = m_nAppFilter; 1077 1078 OSL_ENSURE(m_pStyleSheetPool, "no StyleSheetPool"); 1079 if (!m_pStyleSheetPool) 1080 return; 1081 1082 pItem = GetFamilyItem(); 1083 1084 m_aUpdateStyles.Call(nFlags); 1085 1086 SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, nFilter); 1087 1088 std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator(); 1089 bool bEntry = m_xFmtLb->get_iter_first(*xEntry); 1090 std::vector<OUString> aStrings; 1091 1092 comphelper::string::NaturalStringSorter aSorter( 1093 ::comphelper::getProcessComponentContext(), 1094 Application::GetSettings().GetLanguageTag().getLocale()); 1095 1096 while (pStyle) 1097 { 1098 aStrings.push_back(pStyle->GetName()); 1099 pStyle = m_pStyleSheetPool->Next(); 1100 } 1101 OUString aUIName = getDefaultStyleName(eFam); 1102 1103 // Paradoxically, with a list and non-Latin style names, 1104 // sorting twice is faster than sorting once. 1105 // The first sort has a cheap comparator, and gets the list into mostly-sorted order. 1106 // Then the second sort needs to call its (much more expensive) comparator less often. 1107 std::sort(aStrings.begin(), aStrings.end()); 1108 std::sort(aStrings.begin(), aStrings.end(), 1109 [&aSorter, &aUIName](const OUString& rLHS, const OUString& rRHS) { 1110 if (rRHS == aUIName) 1111 return false; 1112 if (rLHS == aUIName) 1113 return true; // default always first 1114 return aSorter.compare(rLHS, rRHS) < 0; 1115 }); 1116 1117 size_t nCount = aStrings.size(); 1118 size_t nPos = 0; 1119 while (nPos < nCount && bEntry && aStrings[nPos] == m_xFmtLb->get_text(*xEntry)) 1120 { 1121 ++nPos; 1122 bEntry = m_xFmtLb->iter_next(*xEntry); 1123 } 1124 1125 if (nPos < nCount || bEntry) 1126 { 1127 // Fills the display box 1128 m_xFmtLb->freeze(); 1129 m_xFmtLb->clear(); 1130 1131 for (nPos = 0; nPos < nCount; ++nPos) 1132 m_xFmtLb->append(aStrings[nPos], aStrings[nPos]); 1133 1134 m_xFmtLb->thaw(); 1135 } 1136 // Selects the current style if any 1137 SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get(); 1138 OUString aStyle; 1139 if (pState) 1140 aStyle = pState->GetStyleName(); 1141 m_pParentDialog->SelectStyle(aStyle, false, *this); 1142 EnableDelete(nullptr); 1143 } 1144 1145 void StyleList::SetFamilyState(sal_uInt16 nSlotId, const SfxTemplateItem* pItem) 1146 { 1147 sal_uInt16 nIdx = nSlotId - SID_STYLE_FAMILY_START; 1148 m_pFamilyState[nIdx].reset(); 1149 if (pItem) 1150 m_pFamilyState[nIdx].reset(new SfxTemplateItem(*pItem)); 1151 m_bUpdateFamily = true; 1152 } 1153 1154 void StyleList::SetHierarchical() 1155 { 1156 m_bHierarchical = true; 1157 const OUString aSelectEntry(GetSelectedEntry()); 1158 m_xFmtLb->hide(); 1159 FillTreeBox(GetActualFamily()); 1160 m_pParentDialog->SelectStyle(aSelectEntry, false, *this); 1161 m_xTreeBox->show(); 1162 } 1163 1164 void StyleList::SetFilterControlsHandle() 1165 { 1166 m_xTreeBox->hide(); 1167 m_xFmtLb->show(); 1168 m_bHierarchical = false; 1169 } 1170 1171 // Handler for the New-Buttons 1172 void StyleList::NewHdl() 1173 { 1174 if (m_nActFamily == 0xffff 1175 || !(m_xTreeBox->get_visible() || m_xFmtLb->count_selected_rows() <= 1)) 1176 return; 1177 1178 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1179 const SfxStyleFamily eFam = pItem->GetFamily(); 1180 SfxStyleSearchBits nMask(SfxStyleSearchBits::Auto); 1181 if (m_nActFilter != 0xffff) 1182 nMask = pItem->GetFilterList()[m_nActFilter].nFlags; 1183 if (nMask == SfxStyleSearchBits::Auto) // automatic 1184 nMask = m_nAppFilter; 1185 1186 m_pParentDialog->Execute_Impl(SID_STYLE_NEW, "", GetSelectedEntry(), 1187 static_cast<sal_uInt16>(eFam), *this, nMask); 1188 } 1189 1190 // Handler for the edit-Buttons 1191 void StyleList::EditHdl() 1192 { 1193 if (m_nActFamily != 0xffff && HasSelectedStyle(nullptr)) 1194 { 1195 sal_uInt16 nFilter = m_nActFilter; 1196 OUString aTemplName(GetSelectedEntry()); 1197 GetSelectedStyle(); // -Wall required?? 1198 m_pParentDialog->Execute_Impl(SID_STYLE_EDIT, aTemplName, OUString(), 1199 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this, 1200 SfxStyleSearchBits::Auto, &nFilter); 1201 } 1202 } 1203 1204 // Handler for the Delete-Buttons 1205 void StyleList::DeleteHdl() 1206 { 1207 if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr)) 1208 return; 1209 1210 bool bUsedStyle = false; // one of the selected styles are used in the document? 1211 1212 std::vector<std::unique_ptr<weld::TreeIter>> aList; 1213 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 1214 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1215 1216 OUStringBuffer aMsg; 1217 aMsg.append(SfxResId(STR_DELETE_STYLE_USED) + SfxResId(STR_DELETE_STYLE)); 1218 1219 pTreeView->selected_foreach( 1220 [this, pTreeView, pItem, &aList, &bUsedStyle, &aMsg](weld::TreeIter& rEntry) { 1221 aList.emplace_back(pTreeView->make_iterator(&rEntry)); 1222 // check the style is used or not 1223 const OUString aTemplName(pTreeView->get_text(rEntry)); 1224 1225 SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); 1226 1227 if (pStyle->IsUsed()) // pStyle is in use in the document? 1228 { 1229 if (bUsedStyle) // add a separator for the second and later styles 1230 aMsg.append(", "); 1231 aMsg.append(aTemplName); 1232 bUsedStyle = true; 1233 } 1234 1235 return false; 1236 }); 1237 1238 bool aApproved = false; 1239 1240 // we only want to show the dialog once and if we want to delete a style in use (UX-advice) 1241 if (bUsedStyle) 1242 { 1243 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog( 1244 pTreeView, VclMessageType::Question, VclButtonsType::YesNo, aMsg.makeStringAndClear())); 1245 aApproved = xBox->run() == RET_YES; 1246 } 1247 1248 // if there are no used styles selected or the user approved the changes 1249 if (bUsedStyle && !aApproved) 1250 return; 1251 1252 for (auto const& elem : aList) 1253 { 1254 const OUString aTemplName(pTreeView->get_text(*elem)); 1255 m_bDontUpdate = true; // To prevent the Treelistbox to shut down while deleting 1256 m_pParentDialog->Execute_Impl(SID_STYLE_DELETE, aTemplName, OUString(), 1257 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); 1258 1259 if (m_xTreeBox->get_visible()) 1260 { 1261 weld::RemoveParentKeepChildren(*m_xTreeBox, *elem); 1262 m_bDontUpdate = false; 1263 } 1264 } 1265 m_bDontUpdate = false; // if everything is deleted set m_bDontUpdate back to false 1266 UpdateStyles(StyleFlags::UpdateFamilyList); // and force-update the list 1267 } 1268 1269 void StyleList::HideHdl() 1270 { 1271 if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr)) 1272 return; 1273 1274 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 1275 pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry) { 1276 OUString aTemplName = pTreeView->get_text(rEntry); 1277 1278 m_pParentDialog->Execute_Impl(SID_STYLE_HIDE, aTemplName, OUString(), 1279 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); 1280 1281 return false; 1282 }); 1283 } 1284 1285 void StyleList::ShowHdl() 1286 { 1287 if (m_nActFamily == 0xffff || !HasSelectedStyle(nullptr)) 1288 return; 1289 1290 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 1291 pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry) { 1292 OUString aTemplName = pTreeView->get_text(rEntry); 1293 1294 m_pParentDialog->Execute_Impl(SID_STYLE_SHOW, aTemplName, OUString(), 1295 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this); 1296 1297 return false; 1298 }); 1299 } 1300 1301 IMPL_LINK_NOARG(StyleList, EnableDelete, void*, void) 1302 { 1303 bool bEnableDelete(false); 1304 if (m_nActFamily != 0xffff && HasSelectedStyle(nullptr)) 1305 { 1306 OSL_ENSURE(m_pStyleSheetPool, "No StyleSheetPool"); 1307 const OUString aTemplName(GetSelectedEntry()); 1308 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1309 const SfxStyleFamily eFam = pItem->GetFamily(); 1310 SfxStyleSearchBits nFilter = SfxStyleSearchBits::Auto; 1311 if (pItem->GetFilterList().size() > m_nActFilter) 1312 nFilter = pItem->GetFilterList()[m_nActFilter].nFlags; 1313 if (nFilter == SfxStyleSearchBits::Auto) // automatic 1314 nFilter = m_nAppFilter; 1315 const SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find( 1316 aTemplName, eFam, m_xTreeBox->get_visible() ? SfxStyleSearchBits::All : nFilter); 1317 1318 OSL_ENSURE(pStyle, "Style not found"); 1319 if (pStyle && pStyle->IsUserDefined()) 1320 { 1321 if (pStyle->HasClearParentSupport() || !pStyle->IsUsed()) 1322 { 1323 bEnableDelete = true; 1324 } 1325 } 1326 } 1327 m_pParentDialog->EnableDel(bEnableDelete, this); 1328 } 1329 1330 IMPL_LINK_NOARG(StyleList, Clear, void*, void) 1331 { 1332 m_xStyleFamilies.reset(); 1333 for (auto& i : m_pFamilyState) 1334 i.reset(); 1335 m_pCurObjShell = nullptr; 1336 for (auto& i : pBoundItems) 1337 i.reset(); 1338 } 1339 1340 void StyleList::ShowMenu(const CommandEvent& rCEvt) 1341 { 1342 CreateContextMenu(); 1343 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 1344 OString sCommand( 1345 mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))); 1346 MenuSelect(sCommand); 1347 } 1348 1349 void StyleList::MenuSelect(const OString& rIdent) 1350 { 1351 sLastItemIdent = rIdent; 1352 if (sLastItemIdent.isEmpty()) 1353 return; 1354 Application::PostUserEvent(LINK(this, StyleList, MenuSelectAsyncHdl)); /***check this****/ 1355 } 1356 1357 void StyleList::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 1358 { 1359 const SfxHintId nId = rHint.GetId(); 1360 1361 switch (nId) 1362 { 1363 case SfxHintId::UpdateDone: 1364 { 1365 SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); 1366 SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); 1367 if (m_pParentDialog->GetNotifyUpdate() 1368 && (!m_pParentDialog->IsCheckedItem("watercan") 1369 || (pDocShell && pDocShell->GetStyleSheetPool() != m_pStyleSheetPool))) 1370 { 1371 m_pParentDialog->SetNotifyupdate(false); 1372 Update(); 1373 } 1374 else if (m_bUpdateFamily) 1375 { 1376 UpdateFamily(); 1377 m_aUpdateFamily.Call(*this); 1378 } 1379 1380 if (m_pStyleSheetPool) 1381 { 1382 OUString aStr = GetSelectedEntry(); 1383 if (!aStr.isEmpty()) 1384 { 1385 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1386 if (!pItem) 1387 break; 1388 const SfxStyleFamily eFam = pItem->GetFamily(); 1389 SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aStr, eFam); 1390 if (pStyle) 1391 { 1392 bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); 1393 m_pParentDialog->EnableEdit(bReadWrite, this); 1394 m_pParentDialog->EnableHide( 1395 bReadWrite && !pStyle->IsUsed() && !pStyle->IsHidden(), this); 1396 m_pParentDialog->EnableShow(bReadWrite && pStyle->IsHidden(), this); 1397 } 1398 else 1399 { 1400 m_pParentDialog->EnableEdit(false, this); 1401 m_pParentDialog->EnableHide(false, this); 1402 m_pParentDialog->EnableShow(false, this); 1403 } 1404 } 1405 } 1406 break; 1407 } 1408 1409 // Necessary if switching between documents and in both documents 1410 // the same template is used. Do not immediately call Update_Impl, 1411 // for the case that one of the documents is an internal InPlaceObject! 1412 case SfxHintId::DocChanged: 1413 m_pParentDialog->SetNotifyupdate(true); 1414 break; 1415 case SfxHintId::Dying: 1416 { 1417 EndListening(*m_pStyleSheetPool); 1418 m_pStyleSheetPool = nullptr; 1419 break; 1420 } 1421 default: 1422 break; 1423 } 1424 1425 // Do not set timer when the stylesheet pool is in the box, because it is 1426 // possible that a new one is registered after the timer is up - 1427 // works bad in UpdateStyles_Impl ()! 1428 1429 if (!m_bDontUpdate && nId != SfxHintId::Dying 1430 && (dynamic_cast<const SfxStyleSheetPoolHint*>(&rHint) 1431 || dynamic_cast<const SfxStyleSheetHint*>(&rHint) 1432 || dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint) 1433 || nId == SfxHintId::StyleSheetModified)) 1434 { 1435 if (!pIdle) 1436 { 1437 pIdle.reset(new Idle("SfxCommonTemplate")); 1438 pIdle->SetPriority(TaskPriority::LOWEST); 1439 pIdle->SetInvokeHandler(LINK(this, StyleList, TimeOut)); 1440 } 1441 pIdle->Start(); 1442 } 1443 } 1444 1445 IMPL_LINK_NOARG(StyleList, TimeOut, Timer*, void) 1446 { 1447 if (!m_bDontUpdate) 1448 { 1449 m_bDontUpdate = true; 1450 if (!m_xTreeBox->get_visible()) 1451 UpdateStyles(StyleFlags::UpdateFamilyList); 1452 else 1453 { 1454 FillTreeBox(GetActualFamily()); 1455 SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get(); 1456 if (pState) 1457 { 1458 m_pParentDialog->SelectStyle(pState->GetStyleName(), false, *this); 1459 EnableDelete(nullptr); 1460 } 1461 } 1462 m_bDontUpdate = false; 1463 pIdle.reset(); 1464 } 1465 else 1466 pIdle->Start(); 1467 } 1468 1469 IMPL_LINK_NOARG(StyleList, MenuSelectAsyncHdl, void*, void) 1470 { 1471 if (sLastItemIdent == "new") 1472 NewHdl(); 1473 else if (sLastItemIdent == "edit") 1474 EditHdl(); 1475 else if (sLastItemIdent == "delete") 1476 DeleteHdl(); 1477 else if (sLastItemIdent == "hide") 1478 HideHdl(); 1479 else if (sLastItemIdent == "show") 1480 ShowHdl(); 1481 } 1482 1483 // Double-click on a style sheet in the ListBox is applied. 1484 IMPL_LINK(StyleList, DragBeginHdl, bool&, rUnsetDragIcon, bool) 1485 { 1486 rUnsetDragIcon = false; 1487 // Allow normal processing. only if bAllowReParentDrop is true 1488 return !m_bAllowReParentDrop; 1489 } 1490 1491 IMPL_LINK(StyleList, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) 1492 { 1493 bool bRet = false; 1494 const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode(); 1495 if (m_bCanDel && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_DELETE) 1496 { 1497 DeleteHdl(); 1498 bRet = true; 1499 } 1500 return bRet; 1501 } 1502 1503 IMPL_LINK(StyleList, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString) 1504 { 1505 weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); 1506 const OUString aTemplName(pTreeView->get_text(rEntry)); 1507 OUString sQuickHelpText(aTemplName); 1508 1509 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1510 if (!pItem) 1511 return sQuickHelpText; 1512 SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); 1513 1514 if (pStyle && pStyle->IsUsed()) // pStyle is in use in the document? 1515 { 1516 OUString sUsedBy; 1517 if (pStyle->GetFamily() == SfxStyleFamily::Pseudo) 1518 sUsedBy = pStyle->GetUsedBy(); 1519 1520 if (!sUsedBy.isEmpty()) 1521 { 1522 const sal_Int32 nMaxLen = 80; 1523 if (sUsedBy.getLength() > nMaxLen) 1524 { 1525 sUsedBy = OUString::Concat(sUsedBy.subView(0, nMaxLen)) + "..."; 1526 } 1527 1528 OUString aMessage = SfxResId(STR_STYLEUSEDBY); 1529 aMessage = aMessage.replaceFirst("%STYLELIST", sUsedBy); 1530 sQuickHelpText = aTemplName + " " + aMessage; 1531 } 1532 } 1533 1534 return sQuickHelpText; 1535 } 1536 1537 IMPL_LINK(StyleList, CustomRenderHdl, weld::TreeView::render_args, aPayload, void) 1538 { 1539 vcl::RenderContext& rRenderContext = std::get<0>(aPayload); 1540 const ::tools::Rectangle& rRect = std::get<1>(aPayload); 1541 ::tools::Rectangle aRect( 1542 rRect.TopLeft(), 1543 Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), rRect.GetHeight())); 1544 bool bSelected = std::get<2>(aPayload); 1545 const OUString& rId = std::get<3>(aPayload); 1546 1547 rRenderContext.Push(vcl::PushFlags::TEXTCOLOR); 1548 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 1549 if (bSelected) 1550 rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); 1551 else 1552 rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor()); 1553 1554 bool bSuccess = false; 1555 1556 SfxObjectShell* pShell = SfxObjectShell::Current(); 1557 sfx2::StyleManager* pStyleManager = pShell ? pShell->GetStyleManager() : nullptr; 1558 1559 if (pStyleManager) 1560 { 1561 const SfxStyleFamilyItem* pItem = GetFamilyItem(); 1562 SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(rId, pItem->GetFamily()); 1563 1564 if (pStyleSheet) 1565 { 1566 rRenderContext.Push(vcl::PushFlags::ALL); 1567 sal_Int32 nSize = aRect.GetHeight(); 1568 std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer( 1569 pStyleManager->CreateStylePreviewRenderer(rRenderContext, pStyleSheet, nSize)); 1570 bSuccess = pStylePreviewRenderer->recalculate() && pStylePreviewRenderer->render(aRect); 1571 rRenderContext.Pop(); 1572 } 1573 } 1574 1575 if (!bSuccess) 1576 rRenderContext.DrawText(aRect, rId, DrawTextFlags::Left | DrawTextFlags::VCenter); 1577 1578 rRenderContext.Pop(); 1579 } 1580 1581 // Selection of a template during the Watercan-Status 1582 IMPL_LINK(StyleList, FmtSelectHdl, weld::TreeView&, rListBox, void) 1583 { 1584 std::unique_ptr<weld::TreeIter> xHdlEntry = rListBox.make_iterator(); 1585 if (!rListBox.get_cursor(xHdlEntry.get())) 1586 return; 1587 1588 m_pParentDialog->SelectStyle(rListBox.get_text(*xHdlEntry), true, *this); 1589 } 1590 1591 IMPL_LINK_NOARG(StyleList, TreeListApplyHdl, weld::TreeView&, bool) 1592 { 1593 // only if that region is allowed 1594 if (m_nActFamily != 0xffff && nullptr != m_pFamilyState[m_nActFamily - 1] 1595 && !GetSelectedEntry().isEmpty()) 1596 { 1597 m_pParentDialog->Execute_Impl(SID_STYLE_APPLY, GetSelectedEntry(), OUString(), 1598 static_cast<sal_uInt16>(GetFamilyItem()->GetFamily()), *this, 1599 SfxStyleSearchBits::Auto, nullptr, &m_nModifier); 1600 } 1601 // After selecting a focused item if possible again on the app window 1602 if (dynamic_cast<const SfxTemplateDialog_Impl*>(m_pParentDialog) != nullptr) 1603 { 1604 SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); 1605 SfxViewShell* pVu = pViewFrame->GetViewShell(); 1606 vcl::Window* pAppWin = pVu ? pVu->GetWindow() : nullptr; 1607 if (pAppWin) 1608 pAppWin->GrabFocus(); 1609 } 1610 1611 return true; 1612 } 1613 1614 IMPL_LINK(StyleList, MousePressHdl, const MouseEvent&, rMEvt, bool) 1615 { 1616 m_nModifier = rMEvt.GetModifier(); 1617 return false; 1618 } 1619 1620 // Notice from SfxBindings that the update is completed. Pushes out the update 1621 // of the display. 1622 void StyleList::Update() 1623 { 1624 bool bDocChanged = false; 1625 SfxStyleSheetBasePool* pNewPool = nullptr; 1626 SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame(); 1627 SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); 1628 if (pDocShell) 1629 pNewPool = pDocShell->GetStyleSheetPool(); 1630 1631 if (pNewPool != m_pStyleSheetPool && pDocShell) 1632 { 1633 SfxModule* pNewModule = pDocShell->GetModule(); 1634 if (pNewModule && pNewModule != m_Module) 1635 { 1636 m_aClearResource.Call(nullptr); 1637 m_aReadResource.Call(*this); 1638 } 1639 if (m_pStyleSheetPool) 1640 { 1641 EndListening(*m_pStyleSheetPool); 1642 m_pStyleSheetPool = nullptr; 1643 } 1644 1645 if (pNewPool) 1646 { 1647 StartListening(*pNewPool); 1648 m_pStyleSheetPool = pNewPool; 1649 bDocChanged = true; 1650 } 1651 } 1652 1653 if (m_bUpdateFamily) 1654 { 1655 UpdateFamily(); 1656 m_aUpdateFamily.Call(*this); 1657 } 1658 1659 sal_uInt16 i; 1660 for (i = 0; i < MAX_FAMILIES; ++i) 1661 if (m_pFamilyState[i]) 1662 break; 1663 if (i == MAX_FAMILIES || !pNewPool) 1664 // nothing is allowed 1665 return; 1666 1667 SfxTemplateItem* pItem = nullptr; 1668 // current region not within the allowed region or default 1669 if (m_nActFamily == 0xffff || nullptr == (pItem = m_pFamilyState[m_nActFamily - 1].get())) 1670 { 1671 m_pParentDialog->CheckItem(OString::number(m_nActFamily), false); 1672 const size_t nFamilyCount = m_xStyleFamilies->size(); 1673 size_t n; 1674 for (n = 0; n < nFamilyCount; n++) 1675 if (m_pFamilyState[StyleNrToInfoOffset(n)]) 1676 break; 1677 1678 std::unique_ptr<SfxTemplateItem>& pNewItem = m_pFamilyState[StyleNrToInfoOffset(n)]; 1679 m_nAppFilter = pNewItem->GetValue(); 1680 m_pParentDialog->FamilySelect(StyleNrToInfoOffset(n) + 1, *this); 1681 pItem = pNewItem.get(); 1682 } 1683 else if (bDocChanged) 1684 { 1685 // other DocShell -> all new 1686 m_pParentDialog->CheckItem(OString::number(m_nActFamily)); 1687 m_nActFilter = static_cast<sal_uInt16>(m_aLoadFactoryStyleFilter.Call(pDocShell)); 1688 m_pParentDialog->IsUpdate(*this); 1689 if (0xffff == m_nActFilter) 1690 { 1691 m_nActFilter = pDocShell->GetAutoStyleFilterIndex(); 1692 } 1693 1694 m_nAppFilter = pItem->GetValue(); 1695 if (!m_xTreeBox->get_visible()) 1696 { 1697 UpdateStyles(StyleFlags::UpdateFamilyList); 1698 } 1699 else 1700 FillTreeBox(GetActualFamily()); 1701 } 1702 else 1703 { 1704 // other filters for automatic 1705 m_pParentDialog->CheckItem(OString::number(m_nActFamily)); 1706 const SfxStyleFamilyItem* pStyleItem = GetFamilyItem(); 1707 if (pStyleItem 1708 && SfxStyleSearchBits::Auto == pStyleItem->GetFilterList()[m_nActFilter].nFlags 1709 && m_nAppFilter != pItem->GetValue()) 1710 { 1711 m_nAppFilter = pItem->GetValue(); 1712 if (!m_xTreeBox->get_visible()) 1713 UpdateStyles(StyleFlags::UpdateFamilyList); 1714 else 1715 FillTreeBox(GetActualFamily()); 1716 } 1717 else 1718 { 1719 m_nAppFilter = pItem->GetValue(); 1720 } 1721 } 1722 const OUString aStyle(pItem->GetStyleName()); 1723 m_pParentDialog->SelectStyle(aStyle, false, *this); 1724 EnableDelete(nullptr); 1725 m_pParentDialog->EnableNew(m_bCanNew, this); 1726 } 1727 1728 void StyleList::EnablePreview(bool bCustomPreview) 1729 { 1730 m_xFmtLb->clear(); 1731 m_xFmtLb->set_column_custom_renderer(0, bCustomPreview); 1732 m_xTreeBox->clear(); 1733 m_xTreeBox->set_column_custom_renderer(0, bCustomPreview); 1734 } 1735 1736 const SfxStyleFamilyItem& StyleList::GetFamilyItemByIndex(size_t i) const 1737 { 1738 return m_xStyleFamilies->at(i); 1739 } 1740 1741 IMPL_STATIC_LINK(StyleList, CustomGetSizeHdl, weld::TreeView::get_size_args, aPayload, Size) 1742 { 1743 vcl::RenderContext& rRenderContext = aPayload.first; 1744 return Size(42, 32 * rRenderContext.GetDPIScaleFactor()); 1745 } 1746 1747 IMPL_LINK(StyleList, PopupFlatMenuHdl, const CommandEvent&, rCEvt, bool) 1748 { 1749 if (rCEvt.GetCommand() != CommandEventId::ContextMenu) 1750 return false; 1751 1752 PrepareMenu(rCEvt.GetMousePosPixel()); 1753 1754 if (m_xFmtLb->count_selected_rows() <= 0) 1755 { 1756 m_pParentDialog->EnableEdit(false, this); 1757 m_pParentDialog->EnableDel(false, this); 1758 } 1759 1760 ShowMenu(rCEvt); 1761 1762 return true; 1763 } 1764 1765 IMPL_LINK(StyleList, PopupTreeMenuHdl, const CommandEvent&, rCEvt, bool) 1766 { 1767 if (rCEvt.GetCommand() != CommandEventId::ContextMenu) 1768 return false; 1769 1770 PrepareMenu(rCEvt.GetMousePosPixel()); 1771 1772 ShowMenu(rCEvt); 1773 1774 return true; 1775 } 1776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1777
