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 22 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> 23 #include <com/sun/star/beans/XPropertySet.hpp> 24 #include <com/sun/star/container/XNameAccess.hpp> 25 #include <vcl/commandevent.hxx> 26 #include <vcl/commandinfoprovider.hxx> 27 #include <vcl/event.hxx> 28 #include <vcl/settings.hxx> 29 #include <vcl/svapp.hxx> 30 #include <vcl/weldutils.hxx> 31 #include <svl/intitem.hxx> 32 #include <svl/stritem.hxx> 33 #include <svl/style.hxx> 34 #include <comphelper/processfactory.hxx> 35 #include <comphelper/sequenceashashmap.hxx> 36 #include <com/sun/star/beans/PropertyValue.hpp> 37 #include <com/sun/star/frame/ModuleManager.hpp> 38 #include <com/sun/star/frame/UnknownModuleException.hpp> 39 #include <officecfg/Office/Common.hxx> 40 41 #include <sal/log.hxx> 42 #include <osl/diagnose.h> 43 #include <tools/diagnose_ex.h> 44 #include <sfx2/app.hxx> 45 #include <sfx2/dispatch.hxx> 46 #include <sfx2/bindings.hxx> 47 #include <sfx2/templdlg.hxx> 48 #include <templdgi.hxx> 49 #include <tplcitem.hxx> 50 #include <sfx2/styfitem.hxx> 51 #include <sfx2/objsh.hxx> 52 #include <sfx2/viewsh.hxx> 53 #include <sfx2/newstyle.hxx> 54 #include <sfx2/tplpitem.hxx> 55 #include <sfx2/sfxresid.hxx> 56 57 #include <sfx2/sfxsids.hrc> 58 #include <sfx2/strings.hrc> 59 #include <sfx2/docfac.hxx> 60 #include <sfx2/module.hxx> 61 #include <helpids.h> 62 #include <sfx2/viewfrm.hxx> 63 64 #include <comphelper/string.hxx> 65 66 #include <sfx2/StyleManager.hxx> 67 #include <sfx2/StylePreviewRenderer.hxx> 68 69 using namespace css; 70 using namespace css::beans; 71 using namespace css::frame; 72 using namespace css::uno; 73 74 class SfxCommonTemplateDialog_Impl::DeletionWatcher 75 { 76 typedef void (DeletionWatcher::* bool_type)(); 77 78 public: 79 explicit DeletionWatcher(SfxCommonTemplateDialog_Impl& rDialog) 80 : m_pDialog(&rDialog) 81 , m_pPrevious(m_pDialog->impl_setDeletionWatcher(this)) 82 { 83 } 84 85 ~DeletionWatcher() 86 { 87 if (m_pDialog) 88 m_pDialog->impl_setDeletionWatcher(m_pPrevious); 89 } 90 91 DeletionWatcher(const DeletionWatcher&) = delete; 92 DeletionWatcher& operator=(const DeletionWatcher&) = delete; 93 94 // Signal that the dialog was deleted 95 void signal() 96 { 97 m_pDialog = nullptr; 98 if (m_pPrevious) 99 m_pPrevious->signal(); 100 } 101 102 // Return true if the dialog was deleted 103 operator bool_type() const 104 { 105 return m_pDialog ? nullptr : &DeletionWatcher::signal; 106 } 107 108 private: 109 SfxCommonTemplateDialog_Impl* m_pDialog; 110 DeletionWatcher *const m_pPrevious; /// let's add more epicycles! 111 }; 112 113 /** Drop is enabled as long as it is allowed to create a new style by example, i.e. to 114 create a style out of the current selection. 115 */ 116 sal_Int8 SfxCommonTemplateDialog_Impl::AcceptDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper) 117 { 118 if (rHelper.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR)) 119 { 120 // special case: page styles are allowed to create new styles by example 121 // but not allowed to be created by drag and drop 122 if (GetActualFamily() == SfxStyleFamily::Page || bNewByExampleDisabled) 123 return DND_ACTION_NONE; 124 else 125 return DND_ACTION_COPY; 126 } 127 128 // to enable the autoscroll when we're close to the edges 129 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 130 pTreeView->get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true); 131 return DND_ACTION_MOVE; 132 } 133 134 sal_Int8 SfxCommonTemplateDialog_Impl::ExecuteDrop(const ExecuteDropEvent& rEvt) 135 { 136 // handle drop of content into the treeview to create a new style 137 SfxObjectShell* pDocShell = GetObjectShell(); 138 if (pDocShell) 139 { 140 TransferableDataHelper aHelper(rEvt.maDropEvent.Transferable); 141 sal_uInt32 nFormatCount = aHelper.GetFormatCount(); 142 143 sal_Int8 nRet = DND_ACTION_NONE; 144 145 bool bFormatFound = false; 146 147 for ( sal_uInt32 i = 0; i < nFormatCount; ++i ) 148 { 149 SotClipboardFormatId nId = aHelper.GetFormat(i); 150 TransferableObjectDescriptor aDesc; 151 152 if ( aHelper.GetTransferableObjectDescriptor( nId, aDesc ) ) 153 { 154 if ( aDesc.maClassName == pDocShell->GetFactory().GetClassId() ) 155 { 156 Application::PostUserEvent(LINK(this, SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop)); 157 158 bFormatFound = true; 159 nRet = rEvt.mnAction; 160 break; 161 } 162 } 163 } 164 165 if (bFormatFound) 166 return nRet; 167 } 168 169 if (!mxTreeBox->get_visible()) 170 return DND_ACTION_NONE; 171 172 if (!bAllowReParentDrop) 173 return DND_ACTION_NONE; 174 175 // otherwise if we're dragging with the treeview to set a new parent of the dragged style 176 weld::TreeView* pSource = mxTreeBox->get_drag_source(); 177 // only dragging within the same widget allowed 178 if (!pSource || pSource != mxTreeBox.get()) 179 return DND_ACTION_NONE; 180 181 std::unique_ptr<weld::TreeIter> xSource(mxTreeBox->make_iterator()); 182 if (!mxTreeBox->get_selected(xSource.get())) 183 return DND_ACTION_NONE; 184 185 std::unique_ptr<weld::TreeIter> xTarget(mxTreeBox->make_iterator()); 186 if (!mxTreeBox->get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), true)) 187 { 188 // if nothing under the mouse, use the last row 189 int nChildren = mxTreeBox->n_children(); 190 if (!nChildren) 191 return DND_ACTION_NONE; 192 if (!mxTreeBox->get_iter_first(*xTarget) || !mxTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) 193 return DND_ACTION_NONE; 194 while (mxTreeBox->get_row_expanded(*xTarget)) 195 { 196 nChildren = mxTreeBox->iter_n_children(*xTarget); 197 if (!mxTreeBox->iter_children(*xTarget) || !mxTreeBox->iter_nth_sibling(*xTarget, nChildren - 1)) 198 return DND_ACTION_NONE; 199 } 200 } 201 OUString aTargetStyle = mxTreeBox->get_text(*xTarget); 202 DropHdl(mxTreeBox->get_text(*xSource), aTargetStyle); 203 mxTreeBox->unset_drag_dest_row(); 204 FillTreeBox(); 205 SelectStyle(aTargetStyle, false); 206 return DND_ACTION_NONE; 207 } 208 209 IMPL_LINK(SfxCommonTemplateDialog_Impl, DragBeginHdl, bool&, rUnsetDragIcon, bool) 210 { 211 rUnsetDragIcon = false; 212 // Allow normal processing. only if bAllowReParentDrop is true 213 return !bAllowReParentDrop; 214 } 215 216 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, OnAsyncExecuteDrop, void*, void) 217 { 218 ActionSelect("new"); 219 } 220 221 IMPL_LINK(SfxCommonTemplateDialog_Impl, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) 222 { 223 bool bRet = false; 224 const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode(); 225 if (bCanDel && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_DELETE) 226 { 227 DeleteHdl(); 228 bRet = true; 229 } 230 return bRet; 231 } 232 233 IMPL_LINK(SfxCommonTemplateDialog_Impl, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString) 234 { 235 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 236 const OUString aTemplName(pTreeView->get_text(rEntry)); 237 OUString sQuickHelpText(aTemplName); 238 239 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 240 if (!pItem) 241 return sQuickHelpText; 242 SfxStyleSheetBase* pStyle = pStyleSheetPool->Find(aTemplName, pItem->GetFamily()); 243 244 if (pStyle && pStyle->IsUsed()) // pStyle is in use in the document? 245 { 246 OUString sUsedBy; 247 if (pStyle->GetFamily() == SfxStyleFamily::Pseudo) 248 sUsedBy = pStyle->GetUsedBy(); 249 250 if (!sUsedBy.isEmpty()) 251 { 252 const sal_Int32 nMaxLen = 80; 253 if (sUsedBy.getLength() > nMaxLen) 254 { 255 sUsedBy = OUString::Concat(sUsedBy.subView(0, nMaxLen)) + "..."; 256 } 257 258 OUString aMessage = SfxResId(STR_STYLEUSEDBY); 259 aMessage = aMessage.replaceFirst("%STYLELIST", sUsedBy); 260 sQuickHelpText = aTemplName + " " + aMessage; 261 } 262 } 263 264 return sQuickHelpText; 265 } 266 267 IMPL_STATIC_LINK(SfxCommonTemplateDialog_Impl, CustomGetSizeHdl, weld::TreeView::get_size_args, aPayload, Size) 268 { 269 vcl::RenderContext& rRenderContext = aPayload.first; 270 return Size(42, 32 * rRenderContext.GetDPIScaleFactor()); 271 } 272 273 IMPL_LINK(SfxCommonTemplateDialog_Impl, CustomRenderHdl, weld::TreeView::render_args, aPayload, void) 274 { 275 vcl::RenderContext& rRenderContext = std::get<0>(aPayload); 276 const ::tools::Rectangle& rRect = std::get<1>(aPayload); 277 ::tools::Rectangle aRect(rRect.TopLeft(), Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), rRect.GetHeight())); 278 bool bSelected = std::get<2>(aPayload); 279 const OUString& rId = std::get<3>(aPayload); 280 281 rRenderContext.Push(PushFlags::TEXTCOLOR); 282 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 283 if (bSelected) 284 rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); 285 else 286 rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor()); 287 288 bool bSuccess = false; 289 290 SfxObjectShell* pShell = SfxObjectShell::Current(); 291 sfx2::StyleManager* pStyleManager = pShell ? pShell->GetStyleManager(): nullptr; 292 293 if (pStyleManager) 294 { 295 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 296 SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(rId, pItem->GetFamily()); 297 298 if (pStyleSheet) 299 { 300 rRenderContext.Push(PushFlags::ALL); 301 sal_Int32 nSize = aRect.GetHeight(); 302 std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer( 303 pStyleManager->CreateStylePreviewRenderer(rRenderContext, pStyleSheet, nSize)); 304 bSuccess = pStylePreviewRenderer->recalculate() && pStylePreviewRenderer->render(aRect); 305 rRenderContext.Pop(); 306 } 307 } 308 309 if (!bSuccess) 310 rRenderContext.DrawText(aRect, rId, DrawTextFlags::Left | DrawTextFlags::VCenter); 311 312 rRenderContext.Pop(); 313 } 314 315 IMPL_LINK(SfxCommonTemplateDialog_Impl, PopupFlatMenuHdl, const CommandEvent&, rCEvt, bool) 316 { 317 if (rCEvt.GetCommand() != CommandEventId::ContextMenu) 318 return false; 319 320 PrepareMenu(rCEvt.GetMousePosPixel()); 321 322 if (mxFmtLb->count_selected_rows() <= 0) 323 { 324 EnableEdit(false); 325 EnableDel(false); 326 } 327 328 ShowMenu(rCEvt); 329 330 return true; 331 } 332 333 void SfxCommonTemplateDialog_Impl::PrepareMenu(const Point& rPos) 334 { 335 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 336 std::unique_ptr<weld::TreeIter> xIter(pTreeView->make_iterator()); 337 if (pTreeView->get_dest_row_at_pos(rPos, xIter.get(), false) && !pTreeView->is_selected(*xIter)) 338 { 339 pTreeView->unselect_all(); 340 pTreeView->set_cursor(*xIter); 341 pTreeView->select(*xIter); 342 FmtSelectHdl(*pTreeView); 343 } 344 } 345 346 void SfxCommonTemplateDialog_Impl::ShowMenu(const CommandEvent& rCEvt) 347 { 348 CreateContextMenu(); 349 350 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 351 OString sCommand(mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)))); 352 MenuSelect(sCommand); 353 } 354 355 IMPL_LINK(SfxCommonTemplateDialog_Impl, PopupTreeMenuHdl, const CommandEvent&, rCEvt, bool) 356 { 357 if (rCEvt.GetCommand() != CommandEventId::ContextMenu) 358 return false; 359 360 PrepareMenu(rCEvt.GetMousePosPixel()); 361 362 ShowMenu(rCEvt); 363 364 return true; 365 } 366 367 SfxTemplatePanelControl::SfxTemplatePanelControl(SfxBindings* pBindings, vcl::Window* pParentWindow) 368 : PanelLayout(pParentWindow, "TemplatePanel", "sfx/ui/templatepanel.ui", nullptr) 369 , pImpl(new SfxTemplateDialog_Impl(pBindings, this)) 370 { 371 OSL_ASSERT(pBindings!=nullptr); 372 } 373 374 SfxTemplatePanelControl::~SfxTemplatePanelControl() 375 { 376 disposeOnce(); 377 } 378 379 void SfxTemplatePanelControl::dispose() 380 { 381 pImpl.reset(); 382 PanelLayout::dispose(); 383 } 384 385 static void MakeExpanded_Impl(const weld::TreeView& rBox, std::vector<OUString>& rEntries) 386 { 387 std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator(); 388 if (rBox.get_iter_first(*xEntry)) 389 { 390 do 391 { 392 if (rBox.get_row_expanded(*xEntry)) 393 rEntries.push_back(rBox.get_text(*xEntry)); 394 } while (rBox.iter_next(*xEntry)); 395 } 396 } 397 398 /** Internal structure for the establishment of the hierarchical view */ 399 namespace { 400 401 class StyleTree_Impl; 402 403 } 404 405 typedef std::vector<std::unique_ptr<StyleTree_Impl>> StyleTreeArr_Impl; 406 407 namespace { 408 409 class StyleTree_Impl 410 { 411 private: 412 OUString aName; 413 OUString aParent; 414 StyleTreeArr_Impl pChildren; 415 416 public: 417 bool HasParent() const { return !aParent.isEmpty(); } 418 419 StyleTree_Impl(const OUString &rName, const OUString &rParent): 420 aName(rName), aParent(rParent), pChildren(0) {} 421 422 const OUString& getName() const { return aName; } 423 const OUString& getParent() const { return aParent; } 424 StyleTreeArr_Impl& getChildren() { return pChildren; } 425 }; 426 427 } 428 429 static void MakeTree_Impl(StyleTreeArr_Impl& rArr, const OUString& aUIName) 430 { 431 const comphelper::string::NaturalStringSorter aSorter( 432 ::comphelper::getProcessComponentContext(), 433 Application::GetSettings().GetLanguageTag().getLocale()); 434 435 std::unordered_map<OUString, StyleTree_Impl*> styleFinder; 436 styleFinder.reserve(rArr.size()); 437 for (const auto& pEntry : rArr) 438 { 439 styleFinder.emplace(pEntry->getName(), pEntry.get()); 440 } 441 442 // Arrange all under their Parents 443 for (auto& pEntry : rArr) 444 { 445 if (!pEntry->HasParent()) 446 continue; 447 auto it = styleFinder.find(pEntry->getParent()); 448 if (it != styleFinder.end()) 449 { 450 StyleTree_Impl* pCmp = it->second; 451 // Insert child entries sorted 452 auto iPos = std::lower_bound(pCmp->getChildren().begin(), pCmp->getChildren().end(), pEntry, 453 [&aSorter](std::unique_ptr<StyleTree_Impl> const & pEntry1, std::unique_ptr<StyleTree_Impl> const & pEntry2) { return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; }); 454 pCmp->getChildren().insert(iPos, std::move(pEntry)); 455 } 456 } 457 458 // Only keep tree roots in rArr, child elements can be accessed through the hierarchy 459 rArr.erase(std::remove_if(rArr.begin(), rArr.end(), [](std::unique_ptr<StyleTree_Impl> const & pEntry) { return !pEntry; }), rArr.end()); 460 461 // tdf#91106 sort top level styles 462 std::sort(rArr.begin(), rArr.end()); 463 std::sort(rArr.begin(), rArr.end(), 464 [&aSorter, &aUIName](std::unique_ptr<StyleTree_Impl> const & pEntry1, std::unique_ptr<StyleTree_Impl> const & pEntry2) { 465 if (pEntry2->getName() == aUIName) 466 return false; 467 if (pEntry1->getName() == aUIName) 468 return true; // default always first 469 return aSorter.compare(pEntry1->getName(), pEntry2->getName()) < 0; 470 }); 471 } 472 473 static bool IsExpanded_Impl( const std::vector<OUString>& rEntries, 474 std::u16string_view rStr) 475 { 476 for (const auto & rEntry : rEntries) 477 { 478 if (rEntry == rStr) 479 return true; 480 } 481 return false; 482 } 483 484 static void FillBox_Impl(weld::TreeView& rBox, 485 StyleTree_Impl* pEntry, 486 const std::vector<OUString>& rEntries, 487 SfxStyleFamily eStyleFamily, 488 const weld::TreeIter* pParent) 489 { 490 std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator(); 491 const OUString& rName = pEntry->getName(); 492 rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get()); 493 494 for (size_t i = 0; i < pEntry->getChildren().size(); ++i) 495 FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get()); 496 } 497 498 namespace SfxTemplate 499 { 500 // converts from SFX_STYLE_FAMILY Ids to 1-6 501 static sal_uInt16 SfxFamilyIdToNId(SfxStyleFamily nFamily) 502 { 503 switch ( nFamily ) 504 { 505 case SfxStyleFamily::Char: return 1; 506 case SfxStyleFamily::Para: return 2; 507 case SfxStyleFamily::Frame: return 3; 508 case SfxStyleFamily::Page: return 4; 509 case SfxStyleFamily::Pseudo: return 5; 510 case SfxStyleFamily::Table: return 6; 511 default: return 0xffff; 512 } 513 } 514 515 // converts from 1-6 to SFX_STYLE_FAMILY Ids 516 static SfxStyleFamily NIdToSfxFamilyId(sal_uInt16 nId) 517 { 518 switch (nId) 519 { 520 case 1: return SfxStyleFamily::Char; 521 case 2: return SfxStyleFamily::Para; 522 case 3: return SfxStyleFamily::Frame; 523 case 4: return SfxStyleFamily::Page; 524 case 5: return SfxStyleFamily::Pseudo; 525 case 6: return SfxStyleFamily::Table; 526 default: return SfxStyleFamily::All; 527 } 528 } 529 } 530 531 // Constructor 532 533 SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl(SfxBindings* pB, weld::Container* pC, weld::Builder* pBuilder) 534 : pBindings(pB) 535 , mpContainer(pC) 536 , pModule(nullptr) 537 , pStyleSheetPool(nullptr) 538 , pCurObjShell(nullptr) 539 , xModuleManager(frame::ModuleManager::create(::comphelper::getProcessComponentContext())) 540 , m_pDeletionWatcher(nullptr) 541 , mxFmtLb(pBuilder->weld_tree_view("flatview")) 542 , mxTreeBox(pBuilder->weld_tree_view("treeview")) 543 , mxPreviewCheckbox(pBuilder->weld_check_button("showpreview")) 544 , mxFilterLb(pBuilder->weld_combo_box("filter")) 545 546 , nActFamily(0xffff) 547 , nActFilter(0) 548 , nAppFilter(SfxStyleSearchBits::Auto) 549 550 , m_nModifier(0) 551 , bDontUpdate(false) 552 , bIsWater(false) 553 , bUpdate(false) 554 , bUpdateFamily(false) 555 , bCanEdit(false) 556 , bCanDel(false) 557 , bCanNew(true) 558 , bCanHide(true) 559 , bCanShow(false) 560 , bWaterDisabled(false) 561 , bNewByExampleDisabled(false) 562 , bUpdateByExampleDisabled(false) 563 , bTreeDrag(true) 564 , bAllowReParentDrop(false) 565 , bHierarchical(false) 566 , m_bWantHierarchical(false) 567 , bBindingUpdate(true) 568 { 569 mxFmtLb->set_help_id(HID_TEMPLATE_FMT); 570 mxFilterLb->set_help_id(HID_TEMPLATE_FILTER); 571 mxPreviewCheckbox->set_active(officecfg::Office::Common::StylesAndFormatting::Preview::get()); 572 } 573 574 sal_uInt16 SfxCommonTemplateDialog_Impl::StyleNrToInfoOffset(sal_uInt16 nId) 575 { 576 const SfxStyleFamilyItem& rItem = pStyleFamilies->at( nId ); 577 return SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily())-1; 578 } 579 580 void SfxTemplateDialog_Impl::EnableEdit(bool bEnable) 581 { 582 SfxCommonTemplateDialog_Impl::EnableEdit( bEnable ); 583 if( !bEnable || !bUpdateByExampleDisabled ) 584 EnableItem("update", bEnable); 585 } 586 587 void SfxCommonTemplateDialog_Impl::ReadResource() 588 { 589 // Read global user resource 590 for (auto & i : pFamilyState) 591 i.reset(); 592 593 SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); 594 pCurObjShell = pViewFrame->GetObjectShell(); 595 pModule = pCurObjShell ? pCurObjShell->GetModule() : nullptr; 596 if (pModule) 597 pStyleFamilies = pModule->CreateStyleFamilies(); 598 if (!pStyleFamilies) 599 pStyleFamilies.reset(new SfxStyleFamilies); 600 601 nActFilter = 0xffff; 602 if (pCurObjShell) 603 { 604 nActFilter = static_cast< sal_uInt16 >( LoadFactoryStyleFilter( pCurObjShell ) ); 605 if ( 0xffff == nActFilter ) 606 nActFilter = pCurObjShell->GetAutoStyleFilterIndex(); 607 } 608 609 // Paste in the toolbox 610 // reverse order, since always inserted at the head 611 size_t nCount = pStyleFamilies->size(); 612 613 pBindings->ENTERREGISTRATIONS(); 614 615 size_t i; 616 for (i = 0; i < nCount; ++i) 617 { 618 sal_uInt16 nSlot = 0; 619 switch (pStyleFamilies->at(i).GetFamily()) 620 { 621 case SfxStyleFamily::Char: 622 nSlot = SID_STYLE_FAMILY1; break; 623 case SfxStyleFamily::Para: 624 nSlot = SID_STYLE_FAMILY2; break; 625 case SfxStyleFamily::Frame: 626 nSlot = SID_STYLE_FAMILY3; break; 627 case SfxStyleFamily::Page: 628 nSlot = SID_STYLE_FAMILY4; break; 629 case SfxStyleFamily::Pseudo: 630 nSlot = SID_STYLE_FAMILY5; break; 631 case SfxStyleFamily::Table: 632 nSlot = SID_STYLE_FAMILY6; break; 633 default: OSL_FAIL("unknown StyleFamily"); break; 634 } 635 pBoundItems[i].reset( 636 new SfxTemplateControllerItem(nSlot, *this, *pBindings) ); 637 } 638 pBoundItems[i++].reset( new SfxTemplateControllerItem( 639 SID_STYLE_WATERCAN, *this, *pBindings) ); 640 pBoundItems[i++].reset( new SfxTemplateControllerItem( 641 SID_STYLE_NEW_BY_EXAMPLE, *this, *pBindings) ); 642 pBoundItems[i++].reset( new SfxTemplateControllerItem( 643 SID_STYLE_UPDATE_BY_EXAMPLE, *this, *pBindings) ); 644 pBoundItems[i++].reset( new SfxTemplateControllerItem( 645 SID_STYLE_NEW, *this, *pBindings) ); 646 pBoundItems[i++].reset( new SfxTemplateControllerItem( 647 SID_STYLE_DRAGHIERARCHIE, *this, *pBindings) ); 648 pBoundItems[i++].reset( new SfxTemplateControllerItem( 649 SID_STYLE_EDIT, *this, *pBindings) ); 650 pBoundItems[i++].reset( new SfxTemplateControllerItem( 651 SID_STYLE_DELETE, *this, *pBindings) ); 652 pBoundItems[i++].reset( new SfxTemplateControllerItem( 653 SID_STYLE_FAMILY, *this, *pBindings) ); 654 pBindings->LEAVEREGISTRATIONS(); 655 656 for(; i < COUNT_BOUND_FUNC; ++i) 657 pBoundItems[i] = nullptr; 658 659 StartListening(*pBindings); 660 661 // Insert in the reverse order of occurrence in the Style Families. This is for 662 // the toolbar of the designer. The list box of the catalog respects the 663 // correct order by itself. 664 665 // Sequences: the order of Resource = the order of Toolbar for example list box. 666 // Order of ascending SIDs: Low SIDs are displayed first when templates of 667 // several families are active. 668 669 // in the Writer the UpdateStyleByExample Toolbox button is removed and 670 // the NewStyle button gets a PopupMenu 671 if(nCount > 4) 672 ReplaceUpdateButtonByMenu(); 673 674 for( ; nCount--; ) 675 { 676 const SfxStyleFamilyItem &rItem = pStyleFamilies->at( nCount ); 677 sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId( rItem.GetFamily() ); 678 InsertFamilyItem(nId, rItem); 679 } 680 681 for ( i = SID_STYLE_FAMILY1; i <= SID_STYLE_FAMILY4; i++ ) 682 pBindings->Update(i); 683 } 684 685 void SfxCommonTemplateDialog_Impl::ClearResource() 686 { 687 ClearFamilyList(); 688 impl_clear(); 689 } 690 691 void SfxCommonTemplateDialog_Impl::impl_clear() 692 { 693 pStyleFamilies.reset(); 694 for (auto & i : pFamilyState) 695 i.reset(); 696 for (auto & i : pBoundItems) 697 i.reset(); 698 pCurObjShell = nullptr; 699 } 700 701 SfxCommonTemplateDialog_Impl::DeletionWatcher * 702 SfxCommonTemplateDialog_Impl::impl_setDeletionWatcher( 703 DeletionWatcher *const pNewWatcher) 704 { 705 DeletionWatcher *const pRet(m_pDeletionWatcher); 706 m_pDeletionWatcher = pNewWatcher; 707 return pRet; 708 } 709 710 class TreeViewDropTarget final : public DropTargetHelper 711 { 712 private: 713 SfxCommonTemplateDialog_Impl& m_rParent; 714 715 public: 716 TreeViewDropTarget(SfxCommonTemplateDialog_Impl& rDialog, weld::TreeView& rTreeView) 717 : DropTargetHelper(rTreeView.get_drop_target()) 718 , m_rParent(rDialog) 719 { 720 } 721 722 virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override 723 { 724 return m_rParent.AcceptDrop(rEvt, *this); 725 } 726 727 virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override 728 { 729 return m_rParent.ExecuteDrop(rEvt); 730 } 731 }; 732 733 void SfxCommonTemplateDialog_Impl::Initialize() 734 { 735 // Read global user resource 736 ReadResource(); 737 pBindings->Invalidate( SID_STYLE_FAMILY ); 738 pBindings->Update( SID_STYLE_FAMILY ); 739 740 mxFilterLb->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FilterSelectHdl)); 741 mxFmtLb->connect_row_activated(LINK( this, SfxCommonTemplateDialog_Impl, TreeListApplyHdl)); 742 mxFmtLb->connect_mouse_press(LINK(this, SfxCommonTemplateDialog_Impl, MousePressHdl)); 743 mxFmtLb->connect_query_tooltip(LINK(this, SfxCommonTemplateDialog_Impl, QueryTooltipHdl)); 744 mxFmtLb->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FmtSelectHdl)); 745 mxFmtLb->connect_popup_menu(LINK(this, SfxCommonTemplateDialog_Impl, PopupFlatMenuHdl)); 746 mxFmtLb->connect_key_press(LINK(this, SfxCommonTemplateDialog_Impl, KeyInputHdl)); 747 mxFmtLb->set_selection_mode(SelectionMode::Multiple); 748 mxTreeBox->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FmtSelectHdl)); 749 mxTreeBox->connect_row_activated(LINK( this, SfxCommonTemplateDialog_Impl, TreeListApplyHdl)); 750 mxTreeBox->connect_mouse_press(LINK(this, SfxCommonTemplateDialog_Impl, MousePressHdl)); 751 mxTreeBox->connect_query_tooltip(LINK(this, SfxCommonTemplateDialog_Impl, QueryTooltipHdl)); 752 mxTreeBox->connect_popup_menu(LINK(this, SfxCommonTemplateDialog_Impl, PopupTreeMenuHdl)); 753 mxTreeBox->connect_key_press(LINK(this, SfxCommonTemplateDialog_Impl, KeyInputHdl)); 754 mxTreeBox->connect_drag_begin(LINK(this, SfxCommonTemplateDialog_Impl, DragBeginHdl)); 755 mxPreviewCheckbox->connect_clicked(LINK(this, SfxCommonTemplateDialog_Impl, PreviewHdl)); 756 m_xTreeView1DropTargetHelper.reset(new TreeViewDropTarget(*this, *mxFmtLb)); 757 m_xTreeView2DropTargetHelper.reset(new TreeViewDropTarget(*this, *mxTreeBox)); 758 759 int nTreeHeight = mxFmtLb->get_height_rows(8); 760 mxFmtLb->set_size_request(-1, nTreeHeight); 761 mxTreeBox->set_size_request(-1, nTreeHeight); 762 763 mxFmtLb->connect_custom_get_size(LINK(this, SfxCommonTemplateDialog_Impl, CustomGetSizeHdl)); 764 mxFmtLb->connect_custom_render(LINK(this, SfxCommonTemplateDialog_Impl, CustomRenderHdl)); 765 mxTreeBox->connect_custom_get_size(LINK(this, SfxCommonTemplateDialog_Impl, CustomGetSizeHdl)); 766 mxTreeBox->connect_custom_render(LINK(this, SfxCommonTemplateDialog_Impl, CustomRenderHdl)); 767 bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get(); 768 mxFmtLb->set_column_custom_renderer(0, bCustomPreview); 769 mxTreeBox->set_column_custom_renderer(0, bCustomPreview); 770 771 mxFmtLb->set_visible(!bHierarchical); 772 mxTreeBox->set_visible(bHierarchical); 773 774 Update_Impl(); 775 } 776 777 SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl() 778 { 779 if ( bIsWater ) 780 Execute_Impl(SID_STYLE_WATERCAN, "", "", 0); 781 impl_clear(); 782 if ( pStyleSheetPool ) 783 EndListening(*pStyleSheetPool); 784 pStyleSheetPool = nullptr; 785 m_xTreeView1DropTargetHelper.reset(); 786 m_xTreeView2DropTargetHelper.reset(); 787 mxTreeBox.reset(); 788 pIdle.reset(); 789 if ( m_pDeletionWatcher ) 790 m_pDeletionWatcher->signal(); 791 mxFmtLb.reset(); 792 mxPreviewCheckbox.reset(); 793 mxFilterLb.reset(); 794 } 795 796 // Helper function: Access to the current family item 797 const SfxStyleFamilyItem *SfxCommonTemplateDialog_Impl::GetFamilyItem_Impl() const 798 { 799 const size_t nCount = pStyleFamilies->size(); 800 for(size_t i = 0; i < nCount; ++i) 801 { 802 const SfxStyleFamilyItem &rItem = pStyleFamilies->at( i ); 803 sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId(rItem.GetFamily()); 804 if(nId == nActFamily) 805 return &rItem; 806 } 807 return nullptr; 808 } 809 810 void SfxCommonTemplateDialog_Impl::GetSelectedStyle() const 811 { 812 if (!IsInitialized() || !pStyleSheetPool || !HasSelectedStyle()) 813 return; 814 const OUString aTemplName( GetSelectedEntry() ); 815 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 816 pStyleSheetPool->Find( aTemplName, pItem->GetFamily() ); 817 } 818 819 /** 820 * Is it safe to show the water-can / fill icon. If we've a 821 * hierarchical widget - we have only single select, otherwise 822 * we need to check if we have a multi-selection. We either have 823 * a mxTreeBox showing or an mxFmtLb (which we hide when not shown) 824 */ 825 bool SfxCommonTemplateDialog_Impl::IsSafeForWaterCan() const 826 { 827 if (mxTreeBox->get_visible()) 828 return mxTreeBox->get_selected_index() != -1; 829 else 830 return mxFmtLb->count_selected_rows() == 1; 831 } 832 833 void SfxCommonTemplateDialog_Impl::SelectStyle(const OUString &rStr, bool bIsCallback) 834 { 835 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 836 if ( !pItem ) 837 return; 838 const SfxStyleFamily eFam = pItem->GetFamily(); 839 SfxStyleSheetBase* pStyle = pStyleSheetPool->Find( rStr, eFam ); 840 if( pStyle ) 841 { 842 bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); 843 EnableEdit( bReadWrite ); 844 EnableHide( bReadWrite && !pStyle->IsHidden( ) && !pStyle->IsUsed( ) ); 845 EnableShow( bReadWrite && pStyle->IsHidden( ) ); 846 } 847 else 848 { 849 EnableEdit(false); 850 EnableHide(false); 851 EnableShow(false); 852 } 853 854 if (!bIsCallback) 855 { 856 if (mxTreeBox->get_visible()) 857 { 858 if (!rStr.isEmpty()) 859 { 860 std::unique_ptr<weld::TreeIter> xEntry = mxTreeBox->make_iterator(); 861 bool bEntry = mxTreeBox->get_iter_first(*xEntry); 862 while (bEntry) 863 { 864 if (mxTreeBox->get_text(*xEntry) == rStr) 865 { 866 mxTreeBox->scroll_to_row(*xEntry); 867 mxTreeBox->select(*xEntry); 868 break; 869 } 870 bEntry = mxTreeBox->iter_next(*xEntry); 871 } 872 } 873 else 874 mxTreeBox->unselect_all(); 875 } 876 else 877 { 878 bool bSelect = !rStr.isEmpty(); 879 if (bSelect) 880 { 881 std::unique_ptr<weld::TreeIter> xEntry = mxFmtLb->make_iterator(); 882 bool bEntry = mxFmtLb->get_iter_first(*xEntry); 883 while (bEntry && mxFmtLb->get_text(*xEntry) != rStr) 884 bEntry = mxFmtLb->iter_next(*xEntry); 885 if (!bEntry) 886 bSelect = false; 887 else 888 { 889 if (!mxFmtLb->is_selected(*xEntry)) 890 { 891 mxFmtLb->unselect_all(); 892 mxFmtLb->scroll_to_row(*xEntry); 893 mxFmtLb->select(*xEntry); 894 } 895 } 896 } 897 898 if (!bSelect) 899 { 900 mxFmtLb->unselect_all(); 901 EnableEdit(false); 902 EnableHide(false); 903 EnableShow(false); 904 } 905 } 906 } 907 908 bWaterDisabled = !IsSafeForWaterCan(); 909 910 if (!bIsCallback) 911 { 912 // tdf#134598 call UpdateStyleDependents to update watercan 913 UpdateStyleDependents(); 914 } 915 } 916 917 OUString SfxCommonTemplateDialog_Impl::GetSelectedEntry() const 918 { 919 OUString aRet; 920 if (mxTreeBox->get_visible()) 921 aRet = mxTreeBox->get_selected_text(); 922 else 923 aRet = mxFmtLb->get_selected_text(); 924 return aRet; 925 } 926 927 void SfxCommonTemplateDialog_Impl::EnableTreeDrag(bool bEnable) 928 { 929 if (pStyleSheetPool) 930 { 931 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 932 SfxStyleSheetBase* pStyle = pItem ? pStyleSheetPool->First(pItem->GetFamily()) : nullptr; 933 bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && bEnable; 934 } 935 bTreeDrag = bEnable; 936 } 937 938 static OUString lcl_GetStyleFamilyName( SfxStyleFamily nFamily ) 939 { 940 if(nFamily == SfxStyleFamily::Char) 941 return "CharacterStyles" ; 942 if(nFamily == SfxStyleFamily::Para) 943 return "ParagraphStyles"; 944 if(nFamily == SfxStyleFamily::Page) 945 return "PageStyles"; 946 if(nFamily == SfxStyleFamily::Table) 947 return "TableStyles"; 948 return OUString(); 949 } 950 951 OUString SfxCommonTemplateDialog_Impl::getDefaultStyleName( const SfxStyleFamily eFam ) 952 { 953 OUString sDefaultStyle; 954 OUString aFamilyName = lcl_GetStyleFamilyName(eFam); 955 if( aFamilyName == "TableStyles" ) 956 sDefaultStyle = "Default Style"; 957 else 958 sDefaultStyle = "Standard"; 959 uno::Reference< style::XStyleFamiliesSupplier > xModel(GetObjectShell()->GetModel(), uno::UNO_QUERY); 960 OUString aUIName; 961 try 962 { 963 uno::Reference< container::XNameAccess > xStyles; 964 uno::Reference< container::XNameAccess > xCont = xModel->getStyleFamilies(); 965 xCont->getByName( aFamilyName ) >>= xStyles; 966 uno::Reference< beans::XPropertySet > xInfo; 967 xStyles->getByName( sDefaultStyle ) >>= xInfo; 968 xInfo->getPropertyValue("DisplayName") >>= aUIName; 969 } 970 catch (const uno::Exception&) 971 { 972 } 973 return aUIName; 974 } 975 976 void SfxCommonTemplateDialog_Impl::FillTreeBox() 977 { 978 assert(mxTreeBox && "FillTreeBox() without treebox"); 979 if (!pStyleSheetPool || nActFamily == 0xffff) 980 return; 981 982 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 983 if (!pItem) 984 return; 985 const SfxStyleFamily eFam = pItem->GetFamily(); 986 StyleTreeArr_Impl aArr; 987 SfxStyleSheetBase* pStyle = pStyleSheetPool->First(eFam, SfxStyleSearchBits::AllVisible); 988 989 bAllowReParentDrop = pStyle && pStyle->HasParentSupport() && bTreeDrag; 990 991 while (pStyle) 992 { 993 StyleTree_Impl* pNew = new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent()); 994 aArr.emplace_back(pNew); 995 pStyle = pStyleSheetPool->Next(); 996 } 997 OUString aUIName = getDefaultStyleName(eFam); 998 MakeTree_Impl(aArr, aUIName); 999 std::vector<OUString> aEntries; 1000 MakeExpanded_Impl(*mxTreeBox, aEntries); 1001 mxTreeBox->freeze(); 1002 mxTreeBox->clear(); 1003 const sal_uInt16 nCount = aArr.size(); 1004 1005 for (sal_uInt16 i = 0; i < nCount; ++i) 1006 { 1007 FillBox_Impl(*mxTreeBox, aArr[i].get(), aEntries, eFam, nullptr); 1008 aArr[i].reset(); 1009 } 1010 1011 EnableItem("watercan", false); 1012 1013 SfxTemplateItem* pState = pFamilyState[nActFamily - 1].get(); 1014 1015 mxTreeBox->thaw(); 1016 1017 std::unique_ptr<weld::TreeIter> xEntry = mxTreeBox->make_iterator(); 1018 bool bEntry = mxTreeBox->get_iter_first(*xEntry); 1019 if (bEntry && nCount) 1020 mxTreeBox->expand_row(*xEntry); 1021 1022 while (bEntry) 1023 { 1024 if (IsExpanded_Impl(aEntries, mxTreeBox->get_text(*xEntry))) 1025 mxTreeBox->expand_row(*xEntry); 1026 bEntry = mxTreeBox->iter_next(*xEntry); 1027 } 1028 1029 OUString aStyle; 1030 if(pState) // Select current entry 1031 aStyle = pState->GetStyleName(); 1032 SelectStyle(aStyle, false); 1033 EnableDelete(); 1034 } 1035 1036 bool SfxCommonTemplateDialog_Impl::HasSelectedStyle() const 1037 { 1038 return mxTreeBox->get_visible() ? mxTreeBox->get_selected_index() != -1 1039 : mxFmtLb->count_selected_rows() != 0; 1040 } 1041 1042 // internal: Refresh the display 1043 // nFlags: what we should update. 1044 void SfxCommonTemplateDialog_Impl::UpdateStyles_Impl(StyleFlags nFlags) 1045 { 1046 OSL_ENSURE(nFlags != StyleFlags::NONE, "nothing to do"); 1047 const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); 1048 if (!pItem) 1049 { 1050 // Is the case for the template catalog 1051 const size_t nFamilyCount = pStyleFamilies->size(); 1052 size_t n; 1053 for( n = 0; n < nFamilyCount; n++ ) 1054 if( pFamilyState[ StyleNrToInfoOffset(n) ] ) break; 1055 if ( n == nFamilyCount ) 1056 // It happens sometimes, God knows why 1057 return; 1058 nAppFilter = pFamilyState[StyleNrToInfoOffset(n)]->GetValue(); 1059 FamilySelect( StyleNrToInfoOffset(n)+1 ); 1060 pItem = GetFamilyItem_Impl(); 1061 } 1062 1063 const SfxStyleFamily eFam = pItem->GetFamily(); 1064 1065 SfxStyleSearchBits nFilter (nActFilter < pItem->GetFilterList().size() ? pItem->GetFilterList()[nActFilter].nFlags : SfxStyleSearchBits::Auto); 1066 if (nFilter == SfxStyleSearchBits::Auto) // automatic 1067 nFilter = nAppFilter; 1068 1069 OSL_ENSURE(pStyleSheetPool, "no StyleSheetPool"); 1070 if(!pStyleSheetPool) 1071 return; 1072 1073 pItem = GetFamilyItem_Impl(); 1074 if(nFlags & StyleFlags::UpdateFamily) // Update view type list (Hierarchical, All, etc. 1075 { 1076 CheckItem(OString::number(nActFamily)); // check Button in Toolbox 1077 1078 mxFilterLb->freeze(); 1079 mxFilterLb->clear(); 1080 1081 //insert hierarchical at the beginning 1082 mxFilterLb->append(OUString::number(static_cast<int>(SfxStyleSearchBits::All)), SfxResId(STR_STYLE_FILTER_HIERARCHICAL)); 1083 const SfxStyleFilter& rFilter = pItem->GetFilterList(); 1084 for (const SfxFilterTuple& i : rFilter) 1085 mxFilterLb->append(OUString::number(static_cast<int>(i.nFlags)), i.aName); 1086 mxFilterLb->thaw(); 1087 1088 if (nActFilter < mxFilterLb->get_count() - 1) 1089 mxFilterLb->set_active(nActFilter + 1); 1090 else 1091 { 1092 nActFilter = 0; 1093 mxFilterLb->set_active(1); 1094 nFilter = (nActFilter < rFilter.size()) ? rFilter[nActFilter].nFlags : SfxStyleSearchBits::Auto; 1095 } 1096 1097 // if the tree view again, select family hierarchy 1098 if (mxTreeBox->get_visible() || m_bWantHierarchical) 1099 { 1100 mxFilterLb->set_active_text(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)); 1101 EnableHierarchical(true); 1102 } 1103 } 1104 else 1105 { 1106 if (nActFilter < mxFilterLb->get_count() - 1) 1107 mxFilterLb->set_active(nActFilter + 1); 1108 else 1109 { 1110 nActFilter = 0; 1111 mxFilterLb->set_active(1); 1112 } 1113 } 1114 1115 if(!(nFlags & StyleFlags::UpdateFamilyList)) 1116 return; 1117 1118 EnableItem("watercan", false); 1119 1120 SfxStyleSheetBase *pStyle = pStyleSheetPool->First(eFam, nFilter); 1121 1122 std::unique_ptr<weld::TreeIter> xEntry = mxFmtLb->make_iterator(); 1123 bool bEntry = mxFmtLb->get_iter_first(*xEntry); 1124 std::vector<OUString> aStrings; 1125 1126 comphelper::string::NaturalStringSorter aSorter( 1127 ::comphelper::getProcessComponentContext(), 1128 Application::GetSettings().GetLanguageTag().getLocale()); 1129 1130 while( pStyle ) 1131 { 1132 aStrings.push_back(pStyle->GetName()); 1133 pStyle = pStyleSheetPool->Next(); 1134 } 1135 OUString aUIName = getDefaultStyleName(eFam); 1136 1137 // Paradoxically, with a list and non-Latin style names, 1138 // sorting twice is faster than sorting once. 1139 // The first sort has a cheap comparator, and gets the list into mostly-sorted order. 1140 // Then the second sort needs to call its (much more expensive) comparator less often. 1141 std::sort(aStrings.begin(), aStrings.end()); 1142 std::sort(aStrings.begin(), aStrings.end(), 1143 [&aSorter, &aUIName](const OUString& rLHS, const OUString& rRHS) { 1144 if(rRHS == aUIName) 1145 return false; 1146 if(rLHS == aUIName) 1147 return true; // default always first 1148 return aSorter.compare(rLHS, rRHS) < 0; 1149 }); 1150 1151 size_t nCount = aStrings.size(); 1152 size_t nPos = 0; 1153 while (nPos < nCount && bEntry && 1154 aStrings[nPos] == mxFmtLb->get_text(*xEntry)) 1155 { 1156 ++nPos; 1157 bEntry = mxFmtLb->iter_next(*xEntry); 1158 } 1159 1160 if (nPos < nCount || bEntry) 1161 { 1162 // Fills the display box 1163 mxFmtLb->freeze(); 1164 mxFmtLb->clear(); 1165 1166 for (nPos = 0; nPos < nCount; ++nPos) 1167 mxFmtLb->append(aStrings[nPos], aStrings[nPos]); 1168 1169 mxFmtLb->thaw(); 1170 } 1171 // Selects the current style if any 1172 SfxTemplateItem *pState = pFamilyState[nActFamily-1].get(); 1173 OUString aStyle; 1174 if(pState) 1175 aStyle = pState->GetStyleName(); 1176 SelectStyle(aStyle, false); 1177 EnableDelete(); 1178 } 1179 1180 // Updated display: Watering the house 1181 void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem *pItem) 1182 { 1183 bWaterDisabled = (pItem == nullptr); 1184 1185 if(!bWaterDisabled) 1186 //make sure the watercan is only activated when there is (only) one selection 1187 bWaterDisabled = !IsSafeForWaterCan(); 1188 1189 if(pItem && !bWaterDisabled) 1190 { 1191 CheckItem("watercan", pItem->GetValue()); 1192 EnableItem("watercan"); 1193 } 1194 else 1195 { 1196 if(!bWaterDisabled) 1197 EnableItem("watercan"); 1198 else 1199 EnableItem("watercan", false); 1200 } 1201 1202 // Ignore while in watercan mode statusupdates 1203 1204 size_t nCount = pStyleFamilies->size(); 1205 pBindings->EnterRegistrations(); 1206 for(size_t n = 0; n < nCount; n++) 1207 { 1208 SfxControllerItem *pCItem=pBoundItems[n].get(); 1209 bool bChecked = pItem && pItem->GetValue(); 1210 if( pCItem->IsBound() == bChecked ) 1211 { 1212 if( !bChecked ) 1213 pCItem->ReBind(); 1214 else 1215 pCItem->UnBind(); 1216 } 1217 } 1218 pBindings->LeaveRegistrations(); 1219 } 1220 1221 // Item with the status of a Family is copied and noted 1222 // (is updated when all states have also been updated.) 1223 // See also: <SfxBindings::AddDoneHdl(const Link &)> 1224 void SfxCommonTemplateDialog_Impl::SetFamilyState( sal_uInt16 nSlotId, const SfxTemplateItem* pItem ) 1225 { 1226 sal_uInt16 nIdx = nSlotId - SID_STYLE_FAMILY_START; 1227 pFamilyState[nIdx].reset(); 1228 if ( pItem ) 1229 pFamilyState[nIdx].reset( new SfxTemplateItem(*pItem) ); 1230 bUpdate = true; 1231 1232 // If used templates (how the hell you find this out??) 1233 bUpdateFamily = true; 1234 } 1235 1236 // Notice from SfxBindings that the update is completed. Pushes out the update 1237 // of the display. 1238 void SfxCommonTemplateDialog_Impl::Update_Impl() 1239 { 1240 bool bDocChanged=false; 1241 SfxStyleSheetBasePool* pNewPool = nullptr; 1242 SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); 1243 SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); 1244 if( pDocShell ) 1245 pNewPool = pDocShell->GetStyleSheetPool(); 1246 1247 if ( pNewPool != pStyleSheetPool && pDocShell ) 1248 { 1249 SfxModule* pNewModule = pDocShell->GetModule(); 1250 if( pNewModule && pNewModule != pModule ) 1251 { 1252 ClearResource(); 1253 ReadResource(); 1254 } 1255 if ( pStyleSheetPool ) 1256 { 1257 EndListening(*pStyleSheetPool); 1258 pStyleSheetPool = nullptr; 1259 } 1260 1261 if ( pNewPool ) 1262 { 1263 StartListening(*pNewPool); 1264 pStyleSheetPool = pNewPool; 1265 bDocChanged=true; 1266 } 1267 } 1268 1269 if (bUpdateFamily) 1270 UpdateFamily_Impl(); 1271 1272 sal_uInt16 i; 1273 for(i = 0; i < MAX_FAMILIES; ++i) 1274 if(pFamilyState[i]) 1275 break; 1276 if(i == MAX_FAMILIES || !pNewPool) 1277 // nothing is allowed 1278 return; 1279 1280 SfxTemplateItem *pItem = nullptr; 1281 // current region not within the allowed region or default 1282 if(nActFamily == 0xffff || nullptr == (pItem = pFamilyState[nActFamily-1].get() ) ) 1283 { 1284 CheckItem(OString::number(nActFamily), false); 1285 const size_t nFamilyCount = pStyleFamilies->size(); 1286 size_t n; 1287 for( n = 0; n < nFamilyCount; n++ ) 1288 if( pFamilyState[ StyleNrToInfoOffset(n) ] ) break; 1289 1290 std::unique_ptr<SfxTemplateItem> & pNewItem = pFamilyState[StyleNrToInfoOffset(n)]; 1291 nAppFilter = pNewItem->GetValue(); 1292 FamilySelect( StyleNrToInfoOffset(n) + 1 ); 1293 pItem = pNewItem.get(); 1294 } 1295 else if( bDocChanged ) 1296 { 1297 // other DocShell -> all new 1298 CheckItem(OString::number(nActFamily)); 1299 nActFilter = static_cast< sal_uInt16 >( LoadFactoryStyleFilter( pDocShell ) ); 1300 if ( 0xffff == nActFilter ) 1301 nActFilter = pDocShell->GetAutoStyleFilterIndex(); 1302 1303 nAppFilter = pItem->GetValue(); 1304 if (!mxTreeBox->get_visible()) 1305 { 1306 UpdateStyles_Impl(StyleFlags::UpdateFamilyList); 1307 } 1308 else 1309 FillTreeBox(); 1310 } 1311 else 1312 { 1313 // other filters for automatic 1314 CheckItem(OString::number(nActFamily)); 1315 const SfxStyleFamilyItem *pStyleItem = GetFamilyItem_Impl(); 1316 if ( pStyleItem && SfxStyleSearchBits::Auto == pStyleItem->GetFilterList()[nActFilter].nFlags 1317 && nAppFilter != pItem->GetValue()) 1318 { 1319 nAppFilter = pItem->GetValue(); 1320 if (!mxTreeBox->get_visible()) 1321 UpdateStyles_Impl(StyleFlags::UpdateFamilyList); 1322 else 1323 FillTreeBox(); 1324 } 1325 else 1326 nAppFilter = pItem->GetValue(); 1327 } 1328 const OUString aStyle(pItem->GetStyleName()); 1329 SelectStyle(aStyle, false); 1330 EnableDelete(); 1331 EnableNew( bCanNew ); 1332 } 1333 1334 IMPL_LINK_NOARG( SfxCommonTemplateDialog_Impl, TimeOut, Timer *, void ) 1335 { 1336 if(!bDontUpdate) 1337 { 1338 bDontUpdate=true; 1339 if (!mxTreeBox->get_visible()) 1340 UpdateStyles_Impl(StyleFlags::UpdateFamilyList); 1341 else 1342 { 1343 FillTreeBox(); 1344 SfxTemplateItem *pState = pFamilyState[nActFamily-1].get(); 1345 if(pState) 1346 { 1347 SelectStyle(pState->GetStyleName(), false); 1348 EnableDelete(); 1349 } 1350 } 1351 bDontUpdate=false; 1352 pIdle.reset(); 1353 } 1354 else 1355 pIdle->Start(); 1356 } 1357 1358 void SfxCommonTemplateDialog_Impl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 1359 { 1360 const SfxHintId nId = rHint.GetId(); 1361 1362 // tap update 1363 switch(nId) 1364 { 1365 case SfxHintId::UpdateDone: 1366 { 1367 SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); 1368 SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); 1369 if ( 1370 bUpdate && 1371 ( 1372 !IsCheckedItem("watercan") || 1373 (pDocShell && pDocShell->GetStyleSheetPool() != pStyleSheetPool) 1374 ) 1375 ) 1376 { 1377 bUpdate = false; 1378 Update_Impl(); 1379 } 1380 else if ( bUpdateFamily ) 1381 { 1382 UpdateFamily_Impl(); 1383 } 1384 1385 if( pStyleSheetPool ) 1386 { 1387 OUString aStr = GetSelectedEntry(); 1388 if (!aStr.isEmpty()) 1389 { 1390 const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); 1391 if( !pItem ) break; 1392 const SfxStyleFamily eFam = pItem->GetFamily(); 1393 SfxStyleSheetBase *pStyle = pStyleSheetPool->Find( aStr, eFam ); 1394 if( pStyle ) 1395 { 1396 bool bReadWrite = !(pStyle->GetMask() & SfxStyleSearchBits::ReadOnly); 1397 EnableEdit( bReadWrite ); 1398 EnableHide( bReadWrite && !pStyle->IsUsed( ) && !pStyle->IsHidden( ) ); 1399 EnableShow( bReadWrite && pStyle->IsHidden( ) ); 1400 } 1401 else 1402 { 1403 EnableEdit(false); 1404 EnableHide(false); 1405 EnableShow(false); 1406 } 1407 } 1408 } 1409 break; 1410 } 1411 1412 // Necessary if switching between documents and in both documents 1413 // the same template is used. Do not immediately call Update_Impl, 1414 // for the case that one of the documents is an internal InPlaceObject! 1415 case SfxHintId::DocChanged: 1416 bUpdate = true; 1417 break; 1418 case SfxHintId::Dying: 1419 { 1420 EndListening(*pStyleSheetPool); 1421 pStyleSheetPool=nullptr; 1422 break; 1423 } 1424 default: break; 1425 } 1426 1427 // Do not set timer when the stylesheet pool is in the box, because it is 1428 // possible that a new one is registered after the timer is up - 1429 // works bad in UpdateStyles_Impl ()! 1430 1431 if(!bDontUpdate && nId != SfxHintId::Dying && 1432 (dynamic_cast<const SfxStyleSheetPoolHint*>(&rHint) || 1433 dynamic_cast<const SfxStyleSheetHint*>(&rHint) || 1434 dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint) || 1435 nId == SfxHintId::StyleSheetModified)) 1436 { 1437 if(!pIdle) 1438 { 1439 pIdle.reset(new Idle("SfxCommonTemplate")); 1440 pIdle->SetPriority(TaskPriority::LOWEST); 1441 pIdle->SetInvokeHandler(LINK(this,SfxCommonTemplateDialog_Impl,TimeOut)); 1442 } 1443 pIdle->Start(); 1444 1445 } 1446 } 1447 1448 // Other filters; can be switched by the users or as a result of new or 1449 // editing, if the current document has been assigned a different filter. 1450 void SfxCommonTemplateDialog_Impl::FilterSelect( 1451 sal_uInt16 nEntry, // Idx of the new Filters 1452 bool bForce ) // Force update, even if the new filter is 1453 // equal to the current 1454 { 1455 if( nEntry == nActFilter && !bForce ) 1456 return; 1457 1458 nActFilter = nEntry; 1459 SfxObjectShell *const pDocShell = SaveSelection(); 1460 SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool; 1461 pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): nullptr; 1462 if ( pOldStyleSheetPool != pStyleSheetPool ) 1463 { 1464 if ( pOldStyleSheetPool ) 1465 EndListening(*pOldStyleSheetPool); 1466 if ( pStyleSheetPool ) 1467 StartListening(*pStyleSheetPool); 1468 } 1469 1470 UpdateStyles_Impl(StyleFlags::UpdateFamilyList); 1471 } 1472 1473 // Internal: Perform functions through the Dispatcher 1474 bool SfxCommonTemplateDialog_Impl::Execute_Impl( 1475 sal_uInt16 nId, const OUString &rStr, const OUString& rRefStr, sal_uInt16 nFamily, 1476 SfxStyleSearchBits nMask, sal_uInt16 *pIdx, const sal_uInt16* pModifier) 1477 { 1478 SfxDispatcher &rDispatcher = *SfxGetpApp()->GetDispatcher_Impl(); 1479 SfxStringItem aItem(nId, rStr); 1480 SfxUInt16Item aFamily(SID_STYLE_FAMILY, nFamily); 1481 SfxUInt16Item aMask( SID_STYLE_MASK, static_cast<sal_uInt16>(nMask) ); 1482 SfxStringItem aUpdName(SID_STYLE_UPD_BY_EX_NAME, rStr); 1483 SfxStringItem aRefName( SID_STYLE_REFERENCE, rRefStr ); 1484 const SfxPoolItem* pItems[ 6 ]; 1485 sal_uInt16 nCount = 0; 1486 if( !rStr.isEmpty() ) 1487 pItems[ nCount++ ] = &aItem; 1488 pItems[ nCount++ ] = &aFamily; 1489 if( nMask != SfxStyleSearchBits::Auto ) 1490 pItems[ nCount++ ] = &aMask; 1491 if(SID_STYLE_UPDATE_BY_EXAMPLE == nId) 1492 { 1493 // Special solution for Numbering update in Writer 1494 const OUString aTemplName(GetSelectedEntry()); 1495 aUpdName.SetValue(aTemplName); 1496 pItems[ nCount++ ] = &aUpdName; 1497 } 1498 1499 if ( !rRefStr.isEmpty() ) 1500 pItems[ nCount++ ] = &aRefName; 1501 1502 pItems[ nCount++ ] = nullptr; 1503 1504 DeletionWatcher aDeleted(*this); 1505 sal_uInt16 nModi = pModifier ? *pModifier : 0; 1506 const SfxPoolItem* pItem = rDispatcher.Execute( 1507 nId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, 1508 pItems, nModi ); 1509 1510 // Dialog can be destroyed while in Execute() because started 1511 // subdialogs are not modal to it (#i97888#). 1512 if ( !pItem || aDeleted ) 1513 return false; 1514 1515 if ( (nId == SID_STYLE_NEW || SID_STYLE_EDIT == nId) && (mxTreeBox->get_visible() || mxFmtLb->count_selected_rows() <= 1) ) 1516 { 1517 const SfxUInt16Item *pFilterItem = dynamic_cast< const SfxUInt16Item* >(pItem); 1518 assert(pFilterItem); 1519 SfxStyleSearchBits nFilterFlags = static_cast<SfxStyleSearchBits>(pFilterItem->GetValue()) & ~SfxStyleSearchBits::UserDefined; 1520 if(nFilterFlags == SfxStyleSearchBits::Auto) // User Template? 1521 nFilterFlags = static_cast<SfxStyleSearchBits>(pFilterItem->GetValue()); 1522 const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl(); 1523 const size_t nFilterCount = pFamilyItem->GetFilterList().size(); 1524 1525 for ( size_t i = 0; i < nFilterCount; ++i ) 1526 { 1527 const SfxFilterTuple &rTupel = pFamilyItem->GetFilterList()[ i ]; 1528 1529 if ( ( rTupel.nFlags & nFilterFlags ) == nFilterFlags && pIdx ) 1530 *pIdx = i; 1531 } 1532 } 1533 1534 return true; 1535 } 1536 1537 // Handler Listbox of Filter 1538 void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable) 1539 { 1540 if (bEnable) 1541 { 1542 if (!bHierarchical) 1543 { 1544 // Turn on treeView 1545 bHierarchical=true; 1546 m_bWantHierarchical = true; 1547 SaveSelection(); // fdo#61429 store "hierarchical" 1548 const OUString aSelectEntry( GetSelectedEntry()); 1549 mxFmtLb->hide(); 1550 FillTreeBox(); 1551 SelectStyle(aSelectEntry, false); 1552 mxTreeBox->show(); 1553 } 1554 } 1555 else 1556 { 1557 mxTreeBox->hide(); 1558 mxFmtLb->show(); 1559 // If bHierarchical, then the family can have changed 1560 // minus one since hierarchical is inserted at the start 1561 m_bWantHierarchical = false; // before FilterSelect 1562 FilterSelect(mxFilterLb->get_active() - 1, bHierarchical ); 1563 bHierarchical=false; 1564 } 1565 } 1566 1567 IMPL_LINK(SfxCommonTemplateDialog_Impl, FilterSelectHdl, weld::ComboBox&, rBox, void) 1568 { 1569 if (SfxResId(STR_STYLE_FILTER_HIERARCHICAL) == rBox.get_active_text()) 1570 { 1571 EnableHierarchical(true); 1572 } 1573 else 1574 { 1575 EnableHierarchical(false); 1576 } 1577 } 1578 1579 // Select-Handler for the Toolbox 1580 void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry, bool bPreviewRefresh) 1581 { 1582 assert((0 < nEntry && nEntry <= MAX_FAMILIES) || 0xffff == nEntry); 1583 if( nEntry != nActFamily || bPreviewRefresh ) 1584 { 1585 CheckItem(OString::number(nActFamily), false); 1586 nActFamily = nEntry; 1587 SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl(); 1588 SfxUInt16Item const aItem(SID_STYLE_FAMILY, 1589 static_cast<sal_uInt16>(SfxTemplate::NIdToSfxFamilyId(nEntry))); 1590 pDispat->ExecuteList(SID_STYLE_FAMILY, SfxCallMode::SYNCHRON, { &aItem }); 1591 pBindings->Invalidate( SID_STYLE_FAMILY ); 1592 pBindings->Update( SID_STYLE_FAMILY ); 1593 UpdateFamily_Impl(); 1594 } 1595 } 1596 1597 void SfxCommonTemplateDialog_Impl::ActionSelect(const OString& rEntry) 1598 { 1599 if (rEntry == "watercan") 1600 { 1601 const bool bOldState = !IsCheckedItem(rEntry); 1602 bool bCheck; 1603 SfxBoolItem aBool; 1604 // when a template is chosen. 1605 if (!bOldState && HasSelectedStyle()) 1606 { 1607 const OUString aTemplName( 1608 GetSelectedEntry()); 1609 Execute_Impl( 1610 SID_STYLE_WATERCAN, aTemplName, "", 1611 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); 1612 bCheck = true; 1613 } 1614 else 1615 { 1616 Execute_Impl(SID_STYLE_WATERCAN, "", "", 0); 1617 bCheck = false; 1618 } 1619 CheckItem(rEntry, bCheck); 1620 aBool.SetValue(bCheck); 1621 SetWaterCanState(&aBool); 1622 } 1623 else if (rEntry == "new" || rEntry == "newmenu") 1624 { 1625 if(pStyleSheetPool && nActFamily != 0xffff) 1626 { 1627 const SfxStyleFamily eFam=GetFamilyItem_Impl()->GetFamily(); 1628 const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); 1629 SfxStyleSearchBits nFilter(SfxStyleSearchBits::Auto); 1630 if (pItem && nActFilter != 0xffff) 1631 nFilter = pItem->GetFilterList()[nActFilter].nFlags; 1632 if (nFilter == SfxStyleSearchBits::Auto) // automatic 1633 nFilter = nAppFilter; 1634 1635 // why? : FloatingWindow must not be parent of a modal dialog 1636 SfxNewStyleDlg aDlg(mpContainer, *pStyleSheetPool, eFam); 1637 auto nResult = aDlg.run(); 1638 if (nResult == RET_OK) 1639 { 1640 const OUString aTemplName(aDlg.GetName()); 1641 Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE, 1642 aTemplName, "", 1643 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()), 1644 nFilter); 1645 UpdateFamily_Impl(); 1646 } 1647 } 1648 } 1649 else if (rEntry == "update") 1650 { 1651 Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE, 1652 "", "", 1653 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily())); 1654 } 1655 else if (rEntry == "load") 1656 SfxGetpApp()->GetDispatcher_Impl()->Execute(SID_TEMPLATE_LOAD); 1657 else 1658 SAL_WARN("sfx", "not implemented: " << rEntry); 1659 } 1660 1661 static OUString getModuleIdentifier( const Reference< XModuleManager2 >& i_xModMgr, SfxObjectShell const * i_pObjSh ) 1662 { 1663 OSL_ENSURE( i_xModMgr.is(), "getModuleIdentifier(): no XModuleManager" ); 1664 OSL_ENSURE( i_pObjSh, "getModuleIdentifier(): no ObjectShell" ); 1665 1666 OUString sIdentifier; 1667 1668 try 1669 { 1670 sIdentifier = i_xModMgr->identify( i_pObjSh->GetModel() ); 1671 } 1672 catch ( css::frame::UnknownModuleException& ) 1673 { 1674 SAL_WARN("sfx", "getModuleIdentifier(): unknown module" ); 1675 } 1676 catch ( Exception& ) 1677 { 1678 TOOLS_WARN_EXCEPTION( "sfx", "getModuleIdentifier(): exception of XModuleManager::identify()" ); 1679 } 1680 1681 return sIdentifier; 1682 } 1683 1684 sal_Int32 SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter( SfxObjectShell const * i_pObjSh ) 1685 { 1686 OSL_ENSURE( i_pObjSh, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" ); 1687 1688 ::comphelper::SequenceAsHashMap aFactoryProps( 1689 xModuleManager->getByName( getModuleIdentifier( xModuleManager, i_pObjSh ) ) ); 1690 sal_Int32 nFilter = aFactoryProps.getUnpackedValueOrDefault( "ooSetupFactoryStyleFilter", sal_Int32(-1) ); 1691 1692 m_bWantHierarchical = (nFilter & 0x1000) != 0; 1693 nFilter &= ~0x1000; // clear it 1694 1695 return nFilter; 1696 } 1697 1698 void SfxCommonTemplateDialog_Impl::SaveFactoryStyleFilter( SfxObjectShell const * i_pObjSh, sal_Int32 i_nFilter ) 1699 { 1700 OSL_ENSURE( i_pObjSh, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" ); 1701 Sequence< PropertyValue > lProps(1); 1702 lProps[0].Name = "ooSetupFactoryStyleFilter"; 1703 lProps[0].Value <<= i_nFilter | (m_bWantHierarchical ? 0x1000 : 0); 1704 xModuleManager->replaceByName( getModuleIdentifier( xModuleManager, i_pObjSh ), makeAny( lProps ) ); 1705 } 1706 1707 SfxObjectShell* SfxCommonTemplateDialog_Impl::SaveSelection() 1708 { 1709 SfxViewFrame *const pViewFrame(pBindings->GetDispatcher_Impl()->GetFrame()); 1710 SfxObjectShell *const pDocShell(pViewFrame->GetObjectShell()); 1711 if (pDocShell) 1712 { 1713 pDocShell->SetAutoStyleFilterIndex(nActFilter); 1714 SaveFactoryStyleFilter( pDocShell, nActFilter ); 1715 } 1716 return pDocShell; 1717 } 1718 1719 void SfxCommonTemplateDialog_Impl::DropHdl(const OUString& rStyle, const OUString& rParent) 1720 { 1721 bDontUpdate = true; 1722 const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); 1723 const SfxStyleFamily eFam = pItem->GetFamily(); 1724 pStyleSheetPool->SetParent(eFam, rStyle, rParent); 1725 bDontUpdate = false; 1726 } 1727 1728 // Handler for the New-Buttons 1729 void SfxCommonTemplateDialog_Impl::NewHdl() 1730 { 1731 if ( nActFamily == 0xffff || !(mxTreeBox->get_visible() || mxFmtLb->count_selected_rows() <= 1)) 1732 return; 1733 1734 const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); 1735 const SfxStyleFamily eFam = pItem->GetFamily(); 1736 SfxStyleSearchBits nMask(SfxStyleSearchBits::Auto); 1737 if (nActFilter != 0xffff) 1738 nMask = pItem->GetFilterList()[nActFilter].nFlags; 1739 if (nMask == SfxStyleSearchBits::Auto) // automatic 1740 nMask = nAppFilter; 1741 1742 Execute_Impl(SID_STYLE_NEW, 1743 "", GetSelectedEntry(), 1744 static_cast<sal_uInt16>(eFam), 1745 nMask); 1746 } 1747 1748 // Handler for the edit-Buttons 1749 void SfxCommonTemplateDialog_Impl::EditHdl() 1750 { 1751 if(IsInitialized() && HasSelectedStyle()) 1752 { 1753 sal_uInt16 nFilter = nActFilter; 1754 OUString aTemplName(GetSelectedEntry()); 1755 GetSelectedStyle(); // -Wall required?? 1756 Execute_Impl( SID_STYLE_EDIT, aTemplName, OUString(), 1757 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()), SfxStyleSearchBits::Auto, &nFilter ); 1758 } 1759 } 1760 1761 // Handler for the Delete-Buttons 1762 void SfxCommonTemplateDialog_Impl::DeleteHdl() 1763 { 1764 if ( !IsInitialized() || !HasSelectedStyle() ) 1765 return; 1766 1767 bool bUsedStyle = false; // one of the selected styles are used in the document? 1768 1769 std::vector<std::unique_ptr<weld::TreeIter>> aList; 1770 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 1771 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 1772 1773 OUStringBuffer aMsg; 1774 aMsg.append(SfxResId(STR_DELETE_STYLE_USED)).append(SfxResId(STR_DELETE_STYLE)); 1775 1776 pTreeView->selected_foreach([this, pTreeView, pItem, &aList, &bUsedStyle, &aMsg](weld::TreeIter& rEntry){ 1777 aList.emplace_back(pTreeView->make_iterator(&rEntry)); 1778 // check the style is used or not 1779 const OUString aTemplName(pTreeView->get_text(rEntry)); 1780 1781 SfxStyleSheetBase* pStyle = pStyleSheetPool->Find( aTemplName, pItem->GetFamily() ); 1782 1783 if ( pStyle->IsUsed() ) // pStyle is in use in the document? 1784 { 1785 if (bUsedStyle) // add a separator for the second and later styles 1786 aMsg.append(", "); 1787 aMsg.append(aTemplName); 1788 bUsedStyle = true; 1789 } 1790 1791 return false; 1792 }); 1793 1794 bool aApproved = false; 1795 1796 // we only want to show the dialog once and if we want to delete a style in use (UX-advice) 1797 if (bUsedStyle) 1798 { 1799 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pTreeView, 1800 VclMessageType::Question, VclButtonsType::YesNo, 1801 aMsg.makeStringAndClear())); 1802 aApproved = xBox->run() == RET_YES; 1803 } 1804 1805 // if there are no used styles selected or the user approved the changes 1806 if ( bUsedStyle && !aApproved ) 1807 return; 1808 1809 for (auto const& elem : aList) 1810 { 1811 const OUString aTemplName(pTreeView->get_text(*elem)); 1812 bDontUpdate = true; // To prevent the Treelistbox to shut down while deleting 1813 Execute_Impl( SID_STYLE_DELETE, aTemplName, 1814 OUString(), static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); 1815 1816 if (mxTreeBox->get_visible()) 1817 { 1818 weld::RemoveParentKeepChildren(*mxTreeBox, *elem); 1819 bDontUpdate = false; 1820 } 1821 } 1822 bDontUpdate = false; //if everything is deleted set bDontUpdate back to false 1823 UpdateStyles_Impl(StyleFlags::UpdateFamilyList); //and force-update the list 1824 } 1825 1826 void SfxCommonTemplateDialog_Impl::HideHdl() 1827 { 1828 if ( !IsInitialized() || !HasSelectedStyle() ) 1829 return; 1830 1831 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 1832 pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry){ 1833 OUString aTemplName = pTreeView->get_text(rEntry); 1834 1835 Execute_Impl( SID_STYLE_HIDE, aTemplName, 1836 OUString(), static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); 1837 1838 return false; 1839 }); 1840 } 1841 1842 void SfxCommonTemplateDialog_Impl::ShowHdl() 1843 { 1844 if ( !IsInitialized() || !HasSelectedStyle() ) 1845 return; 1846 1847 weld::TreeView* pTreeView = mxTreeBox->get_visible() ? mxTreeBox.get() : mxFmtLb.get(); 1848 pTreeView->selected_foreach([this, pTreeView](weld::TreeIter& rEntry){ 1849 OUString aTemplName = pTreeView->get_text(rEntry); 1850 1851 Execute_Impl( SID_STYLE_SHOW, aTemplName, 1852 OUString(), static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()) ); 1853 1854 return false; 1855 }); 1856 } 1857 1858 void SfxCommonTemplateDialog_Impl::EnableDelete() 1859 { 1860 bool bEnableDelete(false); 1861 if(IsInitialized() && HasSelectedStyle()) 1862 { 1863 OSL_ENSURE(pStyleSheetPool, "No StyleSheetPool"); 1864 const OUString aTemplName(GetSelectedEntry()); 1865 const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); 1866 const SfxStyleFamily eFam = pItem->GetFamily(); 1867 SfxStyleSearchBits nFilter = SfxStyleSearchBits::Auto; 1868 if (pItem->GetFilterList().size() > nActFilter) 1869 nFilter = pItem->GetFilterList()[nActFilter].nFlags; 1870 if(nFilter == SfxStyleSearchBits::Auto) // automatic 1871 nFilter = nAppFilter; 1872 const SfxStyleSheetBase *pStyle = 1873 pStyleSheetPool->Find(aTemplName,eFam, mxTreeBox->get_visible() ? SfxStyleSearchBits::All : nFilter); 1874 1875 OSL_ENSURE(pStyle, "Style not found"); 1876 if (pStyle && pStyle->IsUserDefined()) 1877 { 1878 if (pStyle->HasClearParentSupport() || !pStyle->IsUsed()) 1879 { 1880 bEnableDelete = true; 1881 } 1882 else if (pStyle->GetFamily() == SfxStyleFamily::Page) 1883 { 1884 // Hack to allow Calc page styles to be deleted, 1885 // remove when IsUsed is fixed for Calc page styles. 1886 SfxViewFrame* pFrame = GetObjectShell()->GetFrame(); 1887 if (pFrame) 1888 { 1889 uno::Reference<frame::XFrame > xFrame = pFrame->GetFrame().GetFrameInterface(); 1890 if (vcl::CommandInfoProvider::GetModuleIdentifier(xFrame) == "com.sun.star.sheet.SpreadsheetDocument") 1891 { 1892 bEnableDelete = true; 1893 } 1894 } 1895 } 1896 } 1897 } 1898 EnableDel(bEnableDelete); 1899 } 1900 1901 IMPL_LINK(SfxCommonTemplateDialog_Impl, MousePressHdl, const MouseEvent&, rMEvt, bool) 1902 { 1903 m_nModifier = rMEvt.GetModifier(); 1904 return false; 1905 } 1906 1907 // Double-click on a style sheet in the ListBox is applied. 1908 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, TreeListApplyHdl, weld::TreeView&, bool) 1909 { 1910 // only if that region is allowed 1911 if ( IsInitialized() && nullptr != pFamilyState[nActFamily-1] && 1912 !GetSelectedEntry().isEmpty() ) 1913 { 1914 Execute_Impl(SID_STYLE_APPLY, 1915 GetSelectedEntry(), OUString(), 1916 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily()), 1917 SfxStyleSearchBits::Auto, nullptr, &m_nModifier); 1918 } 1919 // After selecting a focused item if possible again on the app window 1920 if ( dynamic_cast< const SfxTemplateDialog_Impl* >(this) != nullptr ) 1921 { 1922 SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); 1923 SfxViewShell *pVu = pViewFrame->GetViewShell(); 1924 vcl::Window *pAppWin = pVu ? pVu->GetWindow(): nullptr; 1925 if(pAppWin) 1926 pAppWin->GrabFocus(); 1927 } 1928 1929 return true; 1930 } 1931 1932 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, PreviewHdl, weld::Button&, void) 1933 { 1934 std::shared_ptr<comphelper::ConfigurationChanges> batch( comphelper::ConfigurationChanges::create() ); 1935 bool bCustomPreview = mxPreviewCheckbox->get_active(); 1936 officecfg::Office::Common::StylesAndFormatting::Preview::set(bCustomPreview, batch ); 1937 batch->commit(); 1938 1939 mxFmtLb->clear(); 1940 mxFmtLb->set_column_custom_renderer(0, bCustomPreview); 1941 mxTreeBox->clear(); 1942 mxTreeBox->set_column_custom_renderer(0, bCustomPreview); 1943 1944 FamilySelect(nActFamily, true); 1945 } 1946 1947 // Selection of a template during the Watercan-Status 1948 IMPL_LINK(SfxCommonTemplateDialog_Impl, FmtSelectHdl, weld::TreeView&, rListBox, void) 1949 { 1950 std::unique_ptr<weld::TreeIter> xHdlEntry = rListBox.make_iterator(); 1951 if (!rListBox.get_cursor(xHdlEntry.get())) 1952 return; 1953 1954 if (rListBox.is_selected(*xHdlEntry)) 1955 UpdateStyleDependents(); 1956 1957 SelectStyle(rListBox.get_text(*xHdlEntry), true); 1958 } 1959 1960 void SfxCommonTemplateDialog_Impl::UpdateStyleDependents() 1961 { 1962 // Trigger Help PI. Only when the watercan is on 1963 if ( IsInitialized() && 1964 IsCheckedItem("watercan") && 1965 // only if that region is allowed 1966 nullptr != pFamilyState[nActFamily-1] && (mxTreeBox || mxFmtLb->count_selected_rows() <= 1) ) 1967 { 1968 Execute_Impl(SID_STYLE_WATERCAN, 1969 "", "", 0); 1970 Execute_Impl(SID_STYLE_WATERCAN, 1971 GetSelectedEntry(), "", 1972 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily())); 1973 } 1974 EnableItem("watercan", !bWaterDisabled); 1975 EnableDelete(); 1976 } 1977 1978 void SfxCommonTemplateDialog_Impl::MenuSelect(const OString& rIdent) 1979 { 1980 sLastItemIdent = rIdent; 1981 if (sLastItemIdent.isEmpty()) 1982 return; 1983 Application::PostUserEvent( 1984 LINK(this, SfxCommonTemplateDialog_Impl, MenuSelectAsyncHdl)); 1985 } 1986 1987 IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, MenuSelectAsyncHdl, void*, void) 1988 { 1989 if (sLastItemIdent == "new") 1990 NewHdl(); 1991 else if (sLastItemIdent == "edit") 1992 EditHdl(); 1993 else if (sLastItemIdent == "delete") 1994 DeleteHdl(); 1995 else if (sLastItemIdent == "hide") 1996 HideHdl(); 1997 else if (sLastItemIdent == "show") 1998 ShowHdl(); 1999 } 2000 2001 SfxStyleFamily SfxCommonTemplateDialog_Impl::GetActualFamily() const 2002 { 2003 const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl(); 2004 if( !pFamilyItem || nActFamily == 0xffff ) 2005 return SfxStyleFamily::Para; 2006 else 2007 return pFamilyItem->GetFamily(); 2008 } 2009 2010 void SfxCommonTemplateDialog_Impl::EnableExample_Impl(sal_uInt16 nId, bool bEnable) 2011 { 2012 bool bDisable = !bEnable || !IsSafeForWaterCan(); 2013 if (nId == SID_STYLE_NEW_BY_EXAMPLE) 2014 { 2015 bNewByExampleDisabled = bDisable; 2016 EnableItem("new", bEnable); 2017 EnableItem("newmenu", bEnable); 2018 } 2019 else if( nId == SID_STYLE_UPDATE_BY_EXAMPLE ) 2020 { 2021 bUpdateByExampleDisabled = bDisable; 2022 EnableItem("update", bEnable); 2023 } 2024 } 2025 2026 void SfxCommonTemplateDialog_Impl::CreateContextMenu() 2027 { 2028 if ( bBindingUpdate ) 2029 { 2030 pBindings->Invalidate( SID_STYLE_NEW, true ); 2031 pBindings->Update( SID_STYLE_NEW ); 2032 bBindingUpdate = false; 2033 } 2034 mxMenu.reset(); 2035 mxMenuBuilder.reset(Application::CreateBuilder(nullptr, "sfx/ui/stylecontextmenu.ui")); 2036 mxMenu = mxMenuBuilder->weld_menu("menu"); 2037 mxMenu->set_sensitive("edit", bCanEdit); 2038 mxMenu->set_sensitive("delete", bCanDel); 2039 mxMenu->set_sensitive("new", bCanNew); 2040 mxMenu->set_sensitive("hide", bCanHide); 2041 mxMenu->set_sensitive("show", bCanShow); 2042 2043 const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); 2044 if (pItem && pItem->GetFamily() == SfxStyleFamily::Table) //tdf#101648, no ui for this yet 2045 { 2046 mxMenu->set_sensitive("edit", false); 2047 mxMenu->set_sensitive("new", false); 2048 } 2049 } 2050 2051 SfxTemplateDialog_Impl::SfxTemplateDialog_Impl(SfxBindings* pB, SfxTemplatePanelControl* pDlgWindow) 2052 : SfxCommonTemplateDialog_Impl(pB, pDlgWindow->get_container(), pDlgWindow->get_builder()) 2053 , m_xActionTbL(pDlgWindow->get_builder()->weld_toolbar("left")) 2054 , m_xActionTbR(pDlgWindow->get_builder()->weld_toolbar("right")) 2055 , m_xToolMenu(pDlgWindow->get_builder()->weld_menu("toolmenu")) 2056 , m_nActionTbLVisible(0) 2057 { 2058 m_xActionTbR->set_item_help_id("watercan", HID_TEMPLDLG_WATERCAN); 2059 // shown/hidden in SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu() 2060 m_xActionTbR->set_item_help_id("new", HID_TEMPLDLG_NEWBYEXAMPLE); 2061 m_xActionTbR->set_item_help_id("newmenu", HID_TEMPLDLG_NEWBYEXAMPLE); 2062 m_xActionTbR->set_item_menu("newmenu", m_xToolMenu.get()); 2063 m_xToolMenu->connect_activate(LINK(this, SfxTemplateDialog_Impl, ToolMenuSelectHdl)); 2064 m_xActionTbR->set_item_help_id("update", HID_TEMPLDLG_UPDATEBYEXAMPLE); 2065 2066 Initialize(); 2067 } 2068 2069 class ToolbarDropTarget final : public DropTargetHelper 2070 { 2071 private: 2072 SfxTemplateDialog_Impl& m_rParent; 2073 2074 public: 2075 ToolbarDropTarget(SfxTemplateDialog_Impl& rDialog, weld::Toolbar& rToolbar) 2076 : DropTargetHelper(rToolbar.get_drop_target()) 2077 , m_rParent(rDialog) 2078 { 2079 } 2080 2081 virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override 2082 { 2083 return m_rParent.AcceptToolbarDrop(rEvt, *this); 2084 } 2085 2086 virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override 2087 { 2088 return m_rParent.ExecuteDrop(rEvt); 2089 } 2090 }; 2091 2092 void SfxTemplateDialog_Impl::Initialize() 2093 { 2094 SfxCommonTemplateDialog_Impl::Initialize(); 2095 2096 m_xActionTbL->connect_clicked(LINK(this, SfxTemplateDialog_Impl, ToolBoxLSelect)); 2097 m_xActionTbR->connect_clicked(LINK(this, SfxTemplateDialog_Impl, ToolBoxRSelect)); 2098 m_xActionTbL->set_help_id(HID_TEMPLDLG_TOOLBOX_LEFT); 2099 2100 m_xToolbarDropTargetHelper.reset(new ToolbarDropTarget(*this, *m_xActionTbL)); 2101 } 2102 2103 void SfxTemplateDialog_Impl::EnableFamilyItem(sal_uInt16 nId, bool bEnable) 2104 { 2105 m_xActionTbL->set_item_sensitive(OString::number(nId), bEnable); 2106 } 2107 2108 // Insert element into dropdown filter "Frame Styles", "List Styles", etc. 2109 void SfxTemplateDialog_Impl::InsertFamilyItem(sal_uInt16 nId, const SfxStyleFamilyItem &rItem) 2110 { 2111 OString sHelpId; 2112 switch( rItem.GetFamily() ) 2113 { 2114 case SfxStyleFamily::Char: sHelpId = ".uno:CharStyle"; break; 2115 case SfxStyleFamily::Para: sHelpId = ".uno:ParaStyle"; break; 2116 case SfxStyleFamily::Frame: sHelpId = ".uno:FrameStyle"; break; 2117 case SfxStyleFamily::Page: sHelpId = ".uno:PageStyle"; break; 2118 case SfxStyleFamily::Pseudo: sHelpId = ".uno:ListStyle"; break; 2119 case SfxStyleFamily::Table: sHelpId = ".uno:TableStyle"; break; 2120 default: OSL_FAIL("unknown StyleFamily"); break; 2121 } 2122 2123 OString sId(OString::number(nId)); 2124 m_xActionTbL->set_item_visible(sId, true); 2125 m_xActionTbL->set_item_icon_name(sId, rItem.GetImage()); 2126 m_xActionTbL->set_item_tooltip_text(sId, rItem.GetText()); 2127 m_xActionTbL->set_item_help_id(sId, sHelpId); 2128 ++m_nActionTbLVisible; 2129 } 2130 2131 void SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu() 2132 { 2133 m_xActionTbR->set_item_visible("update", false); 2134 m_xActionTbR->set_item_visible("new", false); 2135 m_xActionTbR->set_item_visible("newmenu", true); 2136 FillToolMenu(); 2137 } 2138 2139 void SfxTemplateDialog_Impl::ClearFamilyList() 2140 { 2141 for (int i = 0, nCount = m_xActionTbL->get_n_items(); i < nCount; ++i) 2142 m_xActionTbL->set_item_visible(m_xActionTbL->get_item_ident(i), false); 2143 2144 } 2145 2146 void SfxCommonTemplateDialog_Impl::InvalidateBindings() 2147 { 2148 pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, true); 2149 pBindings->Update( SID_STYLE_NEW_BY_EXAMPLE ); 2150 pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, true); 2151 pBindings->Update( SID_STYLE_UPDATE_BY_EXAMPLE ); 2152 pBindings->Invalidate( SID_STYLE_WATERCAN, true); 2153 pBindings->Update( SID_STYLE_WATERCAN ); 2154 pBindings->Invalidate( SID_STYLE_NEW, true); 2155 pBindings->Update( SID_STYLE_NEW ); 2156 pBindings->Invalidate( SID_STYLE_DRAGHIERARCHIE, true); 2157 pBindings->Update( SID_STYLE_DRAGHIERARCHIE ); 2158 } 2159 2160 SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl() 2161 { 2162 m_xToolbarDropTargetHelper.reset(); 2163 m_xActionTbL.reset(); 2164 m_xActionTbR.reset(); 2165 } 2166 2167 void SfxTemplateDialog_Impl::EnableItem(const OString& rMesId, bool bCheck) 2168 { 2169 if (rMesId == "watercan" && !bCheck && IsCheckedItem("watercan")) 2170 Execute_Impl(SID_STYLE_WATERCAN, "", "", 0); 2171 m_xActionTbR->set_item_sensitive(rMesId, bCheck); 2172 } 2173 2174 void SfxTemplateDialog_Impl::CheckItem(const OString &rMesId, bool bCheck) 2175 { 2176 if (rMesId == "watercan") 2177 { 2178 bIsWater=bCheck; 2179 m_xActionTbR->set_item_active("watercan", bCheck); 2180 } 2181 else 2182 m_xActionTbL->set_item_active(rMesId, bCheck); 2183 } 2184 2185 bool SfxTemplateDialog_Impl::IsCheckedItem(const OString& rMesId) 2186 { 2187 if (rMesId == "watercan") 2188 return m_xActionTbR->get_item_active("watercan"); 2189 return m_xActionTbL->get_item_active(rMesId); 2190 } 2191 2192 IMPL_LINK( SfxTemplateDialog_Impl, ToolBoxLSelect, const OString&, rEntry, void) 2193 { 2194 FamilySelect(rEntry.toUInt32()); 2195 } 2196 2197 IMPL_LINK(SfxTemplateDialog_Impl, ToolBoxRSelect, const OString&, rEntry, void) 2198 { 2199 if (rEntry == "newmenu") 2200 m_xActionTbR->set_menu_item_active(rEntry, !m_xActionTbR->get_menu_item_active(rEntry)); 2201 else 2202 ActionSelect(rEntry); 2203 } 2204 2205 void SfxTemplateDialog_Impl::FillToolMenu() 2206 { 2207 //create a popup menu in Writer 2208 OUString sTextDoc("com.sun.star.text.TextDocument"); 2209 2210 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:StyleNewByExample", sTextDoc); 2211 OUString sLabel = vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties); 2212 m_xToolMenu->append("new", sLabel); 2213 aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:StyleUpdateByExample", sTextDoc); 2214 sLabel = vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties); 2215 m_xToolMenu->append("update", sLabel); 2216 m_xToolMenu->append_separator("separator"); 2217 2218 aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:LoadStyles", sTextDoc); 2219 sLabel = vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties); 2220 m_xToolMenu->append("load", sLabel); 2221 } 2222 2223 IMPL_LINK(SfxTemplateDialog_Impl, ToolMenuSelectHdl, const OString&, rMenuId, void) 2224 { 2225 if (rMenuId.isEmpty()) 2226 return; 2227 ActionSelect(rMenuId); 2228 } 2229 2230 void SfxCommonTemplateDialog_Impl::SetFamily(SfxStyleFamily const nFamily) 2231 { 2232 sal_uInt16 const nId(SfxTemplate::SfxFamilyIdToNId(nFamily)); 2233 assert((0 < nId && nId <= MAX_FAMILIES) || 0xffff == nId); 2234 if ( nId != nActFamily ) 2235 { 2236 if ( nActFamily != 0xFFFF ) 2237 CheckItem(OString::number(nActFamily), false); 2238 nActFamily = nId; 2239 if ( nId != 0xFFFF ) 2240 bUpdateFamily = true; 2241 } 2242 } 2243 2244 void SfxCommonTemplateDialog_Impl::UpdateFamily_Impl() 2245 { 2246 bUpdateFamily = false; 2247 2248 SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl(); 2249 SfxViewFrame *pViewFrame = pDispat->GetFrame(); 2250 SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); 2251 2252 SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool; 2253 pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): nullptr; 2254 if ( pOldStyleSheetPool != pStyleSheetPool ) 2255 { 2256 if ( pOldStyleSheetPool ) 2257 EndListening(*pOldStyleSheetPool); 2258 if ( pStyleSheetPool ) 2259 StartListening(*pStyleSheetPool); 2260 } 2261 2262 bWaterDisabled = false; 2263 bCanNew = mxTreeBox->get_visible() || mxFmtLb->count_selected_rows() <= 1; 2264 bTreeDrag = true; 2265 bUpdateByExampleDisabled = false; 2266 2267 if (pStyleSheetPool) 2268 { 2269 if (!mxTreeBox->get_visible()) 2270 UpdateStyles_Impl(StyleFlags::UpdateFamily | StyleFlags::UpdateFamilyList); 2271 else 2272 { 2273 UpdateStyles_Impl(StyleFlags::UpdateFamily); 2274 FillTreeBox(); 2275 } 2276 } 2277 2278 InvalidateBindings(); 2279 2280 if (IsCheckedItem("watercan") && 2281 // only if that area is allowed 2282 nullptr != pFamilyState[nActFamily - 1]) 2283 { 2284 Execute_Impl(SID_STYLE_APPLY, 2285 GetSelectedEntry(), 2286 OUString(), 2287 static_cast<sal_uInt16>(GetFamilyItem_Impl()->GetFamily())); 2288 } 2289 } 2290 2291 void SfxCommonTemplateDialog_Impl::ReplaceUpdateButtonByMenu() 2292 { 2293 //does nothing 2294 } 2295 2296 sal_Int8 SfxTemplateDialog_Impl::AcceptToolbarDrop(const AcceptDropEvent& rEvt, const DropTargetHelper& rHelper) 2297 { 2298 sal_Int8 nReturn = DND_ACTION_NONE; 2299 2300 // auto flip to the category under the mouse 2301 int nIndex = m_xActionTbL->get_drop_index(rEvt.maPosPixel); 2302 if (nIndex >= m_nActionTbLVisible) 2303 nIndex = m_nActionTbLVisible - 1; 2304 2305 OString sIdent = m_xActionTbL->get_item_ident(nIndex); 2306 if (!sIdent.isEmpty() && !m_xActionTbL->get_item_active(sIdent)) 2307 ToolBoxLSelect(sIdent); 2308 2309 // special case: page styles are allowed to create new styles by example 2310 // but not allowed to be created by drag and drop 2311 if (sIdent.toUInt32() != SfxTemplate::SfxFamilyIdToNId(SfxStyleFamily::Page) && 2312 rHelper.IsDropFormatSupported(SotClipboardFormatId::OBJECTDESCRIPTOR) && 2313 !bNewByExampleDisabled) 2314 { 2315 nReturn = DND_ACTION_COPY; 2316 } 2317 return nReturn; 2318 } 2319 2320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 2321
