Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/sidebar/MasterPagesSelector.cxx
Line
Count
Source
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 <sal/config.h>
21
22
#include <utility>
23
24
#include "MasterPagesSelector.hxx"
25
26
#include "MasterPageContainer.hxx"
27
#include "DocumentHelper.hxx"
28
#include <pres.hxx>
29
#include <drawdoc.hxx>
30
#include <sdpage.hxx>
31
#include <app.hrc>
32
33
#include <DrawController.hxx>
34
#include <SlideSorterViewShell.hxx>
35
#include <vcl/commandevent.hxx>
36
#include <vcl/vclptr.hxx>
37
#include <ViewShellBase.hxx>
38
#include <o3tl/safeint.hxx>
39
#include <vcl/image.hxx>
40
#include <sfx2/dispatch.hxx>
41
#include <sfx2/viewfrm.hxx>
42
#include <sfx2/sidebar/Theme.hxx>
43
#include <memory>
44
#include <vcl/svapp.hxx>
45
#include <vcl/virdev.hxx>
46
#include <vcl/weld/Builder.hxx>
47
48
#include <com/sun/star/ui/LayoutSize.hpp>
49
50
namespace sd::sidebar {
51
52
    /** menu entry that is executed as default action when the left mouse button is
53
        clicked over a master page.
54
    */
55
constexpr OUStringLiteral gsDefaultClickAction = u"applyselect";
56
57
// Sidebar
58
MasterPagesSelector::MasterPagesSelector(weld::Widget* pParent, SdDrawDocument& rDocument,
59
                                         ViewShellBase& rBase,
60
                                         std::shared_ptr<MasterPageContainer> pContainer,
61
                                         css::uno::Reference<css::ui::XSidebar> xSidebar,
62
                                         const OUString& rUIFileName, const OUString& rIconViewId)
63
0
    : PanelLayout(pParent, u"MasterPagePanel"_ustr, rUIFileName)
64
0
    , mpContainer(std::move(pContainer))
65
0
    , mxPreviewIconView(m_xBuilder->weld_icon_view(rIconViewId))
66
0
    , mrDocument(rDocument)
67
0
    , mrBase(rBase)
68
0
    , mxSidebar(std::move(xSidebar))
69
0
    , maUpdateTask(*this)
70
0
{
71
0
    mxPreviewIconView->connect_item_activated(LINK(this, MasterPagesSelector, MasterPageSelected));
72
0
    mxPreviewIconView->connect_command(LINK(this, MasterPagesSelector, CommandHdl));
73
0
    mxPreviewIconView->connect_query_tooltip(LINK(this, MasterPagesSelector, QueryTooltipHdl));
74
75
0
    Link<MasterPageContainerChangeEvent&,void> aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener));
76
0
    mpContainer->AddChangeListener(aChangeListener);
77
0
    maUpdateTask.Start();
78
0
}
79
80
// Notebookbar
81
MasterPagesSelector::MasterPagesSelector(weld::Widget* pParent, SdDrawDocument& rDocument,
82
                                         ViewShellBase& rBase,
83
                                         std::shared_ptr<MasterPageContainer> pContainer,
84
                                         const OUString& rUIFileName, const OUString& rIconViewId)
85
0
    : PanelLayout(pParent, u"MasterPagePanel"_ustr, rUIFileName)
86
0
    , mpContainer(std::move(pContainer))
87
0
    , mxPreviewIconView(m_xBuilder->weld_icon_view(rIconViewId))
88
0
    , mrDocument(rDocument)
89
0
    , mrBase(rBase)
90
0
    , maUpdateTask(*this)
91
0
{
92
0
    mxPreviewIconView->connect_item_activated(LINK(this, MasterPagesSelector, MasterPageSelected));
93
0
    mxPreviewIconView->connect_command(LINK(this, MasterPagesSelector, CommandHdl));
94
0
    mxPreviewIconView->connect_query_tooltip(LINK(this, MasterPagesSelector, QueryTooltipHdl));
95
96
0
    Link<MasterPageContainerChangeEvent&,void> aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener));
97
0
    mpContainer->AddChangeListener(aChangeListener);
98
0
    maUpdateTask.Start();
99
0
}
100
101
102
MasterPagesSelector::~MasterPagesSelector()
103
0
{
104
0
    Clear();
105
0
    UpdateLocks(ItemList());
106
107
0
    Link<MasterPageContainerChangeEvent&,void> aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener));
108
0
    mpContainer->RemoveChangeListener(aChangeListener);
109
0
    mpContainer.reset();
110
0
    mxPreviewIconView.reset();
111
0
}
112
113
void MasterPagesSelector::LateInit()
114
0
{
115
0
    Fill();
116
0
}
117
118
void MasterPagesSelector::UpdateLocks (const ItemList& rItemList)
119
0
{
120
0
    ItemList aNewLockList;
121
122
    // In here we first lock the master pages in the given list and then
123
    // release the locks acquired in a previous call to this method.  When
124
    // this were done the other way round the lock count of some master
125
    // pages might drop temporarily to 0 and would lead to unnecessary
126
    // deletion and re-creation of MasterPageDescriptor objects.
127
128
    // Lock the master pages in the given list.
129
0
    for (const auto& rItem : rItemList)
130
0
    {
131
0
        mpContainer->AcquireToken(rItem);
132
0
        aNewLockList.push_back(rItem);
133
0
    }
134
135
    // Release the previously locked master pages.
136
0
    for (const auto& rPage : maLockedMasterPages)
137
0
        mpContainer->ReleaseToken(rPage);
138
139
0
    maLockedMasterPages.swap(aNewLockList);
140
0
}
141
142
void MasterPagesSelector::Fill()
143
0
{
144
0
    ::std::unique_ptr<ItemList> pItemList (new ItemList);
145
146
0
    Fill(*pItemList);
147
148
0
    UpdateLocks(*pItemList);
149
0
    UpdateItemList(std::move(pItemList));
150
0
}
151
152
OUString MasterPagesSelector::GetContextMenuUIFile() const
153
0
{
154
0
    return u"modules/simpress/ui/mastermenu.ui"_ustr;
155
0
}
156
157
IMPL_LINK_NOARG(MasterPagesSelector, MasterPageSelected, const weld::TreeIter&, bool)
158
0
{
159
0
    ExecuteCommand(gsDefaultClickAction);
160
0
    return true;
161
0
}
162
163
IMPL_LINK(MasterPagesSelector, CommandHdl, const CommandEvent&, rEvent, bool)
164
0
{
165
0
    if (rEvent.GetCommand() != CommandEventId::ContextMenu)
166
0
        return false;
167
168
0
    Point aPos;
169
0
    if (rEvent.IsMouseEvent())
170
0
    {
171
0
        aPos = rEvent.GetMousePosPixel();
172
0
        std::unique_ptr<weld::TreeIter> pIter = mxPreviewIconView->get_item_at_pos(aPos);
173
0
        if (!pIter)
174
0
            return false;
175
0
        mxPreviewIconView->select(*pIter);
176
0
    }
177
0
    else
178
0
    {
179
0
        std::unique_ptr<weld::TreeIter> pSelected = mxPreviewIconView->get_selected();
180
0
        if (!pSelected)
181
0
            return false;
182
0
        aPos = mxPreviewIconView->get_rect(*pSelected).Center();
183
0
    }
184
185
0
    ShowContextMenu(aPos);
186
0
    return true;
187
0
}
188
189
IMPL_LINK(MasterPagesSelector, QueryTooltipHdl, const weld::TreeIter&, iter, OUString)
190
0
{
191
0
    const OUString sId = mxPreviewIconView->get_id(iter);
192
0
    if (!sId.isEmpty())
193
0
        return mpContainer->GetPageNameForToken(sId.toUInt32());
194
195
0
    return OUString();
196
0
}
197
198
void MasterPagesSelector::ShowContextMenu(const Point& pPos)
199
0
{
200
    // Setup the menu.
201
0
    ::tools::Rectangle aRect(pPos, Size(1, 1));
202
0
    std::unique_ptr<weld::Builder> xBuilder(
203
0
        Application::CreateBuilder(mxPreviewIconView.get(), GetContextMenuUIFile()));
204
0
    std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"menu"_ustr));
205
0
    ProcessPopupMenu(*xMenu);
206
    // Show the menu.
207
0
    ExecuteCommand(xMenu->popup_at_rect(mxPreviewIconView.get(), aRect));
208
0
}
209
210
void MasterPagesSelector::ProcessPopupMenu(weld::Menu& rMenu)
211
0
{
212
    // Disable some entries.
213
0
    if (mpContainer->GetPreviewSize() == MasterPageContainer::SMALL)
214
0
        rMenu.set_sensitive(u"small"_ustr, false);
215
0
    else
216
0
        rMenu.set_sensitive(u"large"_ustr, false);
217
0
}
218
219
void MasterPagesSelector::ExecuteCommand(const OUString &rIdent)
220
0
{
221
0
    if (rIdent == "applyall")
222
0
    {
223
0
        mrBase.SetBusyState (true);
224
0
        AssignMasterPageToAllSlides (GetSelectedMasterPage());
225
0
        mrBase.SetBusyState (false);
226
0
    }
227
0
    else if (rIdent == "applyselect")
228
0
    {
229
0
        mrBase.SetBusyState (true);
230
0
        AssignMasterPageToSelectedSlides (GetSelectedMasterPage());
231
0
        mrBase.SetBusyState (false);
232
0
    }
233
0
    else if (rIdent == "large")
234
0
    {
235
0
        mrBase.SetBusyState (true);
236
0
        mpContainer->SetPreviewSize(MasterPageContainer::LARGE);
237
0
        mrBase.SetBusyState (false);
238
0
        if (mxSidebar.is())
239
0
            mxSidebar->requestLayout();
240
0
    }
241
0
    else if (rIdent == "small")
242
0
    {
243
0
        mrBase.SetBusyState (true);
244
0
        mpContainer->SetPreviewSize(MasterPageContainer::SMALL);
245
0
        mrBase.SetBusyState (false);
246
0
        if (mxSidebar.is())
247
0
            mxSidebar->requestLayout();
248
0
    }
249
0
    else if (rIdent == "edit")
250
0
    {
251
0
        using namespace ::com::sun::star;
252
0
        uno::Reference<drawing::XDrawPage> xSelectedMaster;
253
0
        SdPage* pMasterPage = GetSelectedMasterPage();
254
0
        assert(pMasterPage); //rhbz#902884
255
0
        if (pMasterPage)
256
0
            xSelectedMaster.set(pMasterPage->getUnoPage(), uno::UNO_QUERY);
257
0
        SfxViewFrame& rViewFrame = mrBase.GetViewFrame();
258
0
        if (xSelectedMaster.is())
259
0
        {
260
0
            SfxDispatcher* pDispatcher = rViewFrame.GetDispatcher();
261
0
            if (pDispatcher != nullptr)
262
0
            {
263
0
                pDispatcher->Execute(SID_MASTERPAGE, SfxCallMode::SYNCHRON);
264
0
                mrBase.GetDrawController()->setCurrentPage(xSelectedMaster);
265
0
            }
266
0
        }
267
0
    }
268
0
    mxPreviewIconView->unselect_all();
269
0
}
270
271
IMPL_LINK(MasterPagesSelector, ContainerChangeListener, MasterPageContainerChangeEvent&, rEvent, void)
272
0
{
273
0
    NotifyContainerChangeEvent(rEvent);
274
0
}
275
276
SdPage* MasterPagesSelector::GetSelectedMasterPage()
277
0
{
278
0
    const ::osl::MutexGuard aGuard (maMutex);
279
280
0
    SdPage* pMasterPage = nullptr;
281
0
    OUString sSelectedId = mxPreviewIconView->get_selected_id();
282
283
0
    if (!sSelectedId.isEmpty())
284
0
    {
285
0
        const MasterPageContainer::Token aToken
286
0
            = static_cast<MasterPageContainer::Token>(sSelectedId.toInt32());
287
0
        pMasterPage = mpContainer->GetPageObjectForToken(aToken, true);
288
0
    }
289
0
    return pMasterPage;
290
0
}
291
292
/** Assemble a list of all slides of the document and pass it to
293
    AssignMasterPageToPageList().
294
*/
295
void MasterPagesSelector::AssignMasterPageToAllSlides (SdPage* pMasterPage)
296
0
{
297
0
    if (pMasterPage == nullptr)
298
0
        return;
299
300
0
    sal_uInt16 nPageCount = mrDocument.GetSdPageCount(PageKind::Standard);
301
0
    if (nPageCount == 0)
302
0
        return;
303
304
    // Get a list of all pages.  As a little optimization we only
305
    // include pages that do not already have the given master page
306
    // assigned.
307
0
    OUString sFullLayoutName(pMasterPage->GetLayoutName());
308
0
    ::sd::slidesorter::SharedPageSelection pPageList =
309
0
        std::make_shared<::sd::slidesorter::SlideSorterViewShell::PageSelection>();
310
0
    for (sal_uInt16 nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
311
0
    {
312
0
        SdPage* pPage = mrDocument.GetSdPage (nPageIndex, PageKind::Standard);
313
0
        if (pPage != nullptr && pPage->GetLayoutName() != sFullLayoutName)
314
0
        {
315
0
            pPageList->push_back (pPage);
316
0
        }
317
0
    }
318
319
0
    AssignMasterPageToPageList(pMasterPage, pPageList);
320
0
}
321
322
/** Assemble a list of the currently selected slides (selected in a visible
323
    slide sorter) and pass it to AssignMasterPageToPageList().
324
*/
325
void MasterPagesSelector::AssignMasterPageToSelectedSlides (
326
    SdPage* pMasterPage)
327
0
{
328
0
    using namespace ::sd::slidesorter;
329
0
    using namespace ::sd::slidesorter::controller;
330
331
0
    if (pMasterPage == nullptr)
332
0
        return;
333
334
    // Find a visible slide sorter.
335
0
    SlideSorterViewShell* pSlideSorter = SlideSorterViewShell::GetSlideSorter(mrBase);
336
0
    if (pSlideSorter == nullptr)
337
0
        return;
338
339
    // Get a list of selected pages.
340
0
    SharedPageSelection pPageSelection = pSlideSorter->GetPageSelection();
341
0
    if (pPageSelection->empty())
342
0
        return;
343
344
0
    AssignMasterPageToPageList(pMasterPage, pPageSelection);
345
346
    // Restore the previous selection.
347
0
    pSlideSorter->SetPageSelection(pPageSelection);
348
0
}
349
350
void MasterPagesSelector::AssignMasterPageToPageList (
351
    SdPage* pMasterPage,
352
    const std::shared_ptr<std::vector<SdPage*>>& rPageList)
353
0
{
354
0
    DocumentHelper::AssignMasterPageToPageList(mrDocument, pMasterPage, rPageList);
355
0
}
356
357
void MasterPagesSelector::NotifyContainerChangeEvent (const MasterPageContainerChangeEvent& rEvent)
358
0
{
359
0
    const ::osl::MutexGuard aGuard (maMutex);
360
361
0
    switch (rEvent.meEventType)
362
0
    {
363
0
        case MasterPageContainerChangeEvent::EventType::SIZE_CHANGED:
364
0
            UpdateAllPreviews();
365
0
            break;
366
367
0
        case MasterPageContainerChangeEvent::EventType::PREVIEW_CHANGED:
368
0
        {
369
0
            int nIndex (GetIndexForToken(rEvent.maChildToken));
370
0
            if (nIndex >= 0)
371
0
            {
372
0
                Image aPreview(mpContainer->GetPreviewForToken(rEvent.maChildToken));
373
0
                if (aPreview.GetSizePixel().Width() > 0)
374
0
                {
375
0
                    mxPreviewIconView->set_image(nIndex, *GetVirtualDevice(aPreview));
376
0
                }
377
0
            }
378
0
        }
379
0
        break;
380
381
0
        case MasterPageContainerChangeEvent::EventType::DATA_CHANGED:
382
0
        {
383
0
            InvalidateItem(rEvent.maChildToken);
384
0
            Fill();
385
0
        }
386
0
        break;
387
388
0
        case MasterPageContainerChangeEvent::EventType::CHILD_REMOVED:
389
0
        {
390
0
            int nIndex (GetIndexForToken(rEvent.maChildToken));
391
0
            SetItem(nIndex, MasterPageContainer::NIL_TOKEN);
392
0
            break;
393
0
        }
394
395
0
        default:
396
0
            break;
397
0
   }
398
0
}
399
400
std::unique_ptr<MasterPagesSelector::UserData> MasterPagesSelector::GetUserData(int nIndex) const
401
0
{
402
0
    const ::osl::MutexGuard aGuard(maMutex);
403
404
0
    if (nIndex >= 0 && nIndex < mxPreviewIconView->n_children())
405
0
    {
406
0
        const MasterPageContainer::Token aToken
407
0
            = static_cast<MasterPageContainer::Token>(mxPreviewIconView->get_id(nIndex).toInt32());
408
0
        return std::make_unique<UserData>(std::make_pair(nIndex, aToken));
409
0
    }
410
0
    else
411
0
        return nullptr;
412
0
}
413
414
void MasterPagesSelector::SetItem (
415
    sal_uInt16 nIndex,
416
    MasterPageContainer::Token aToken)
417
0
{
418
0
    const ::osl::MutexGuard aGuard (maMutex);
419
420
0
    RemoveTokenToIndexEntry(nIndex, aToken);
421
422
0
    mxPreviewIconView->freeze();
423
424
0
    if (aToken != MasterPageContainer::NIL_TOKEN)
425
0
    {
426
0
        Image aPreview (mpContainer->GetPreviewForToken(aToken));
427
0
        MasterPageContainer::PreviewState eState (mpContainer->GetPreviewState(aToken));
428
429
0
        if (aPreview.GetSizePixel().Width() > 0)
430
0
        {
431
0
            if (!mxPreviewIconView->get_id(nIndex).isEmpty())
432
0
            {
433
0
                mxPreviewIconView->set_image(nIndex, *GetVirtualDevice(aPreview));
434
0
                mxPreviewIconView->set_id(nIndex, OUString::number(aToken));
435
0
            }
436
0
            else
437
0
            {
438
0
                Bitmap aPreviewBitmap = GetPreviewAsBitmap(aPreview);
439
0
                OUString sId = OUString::number(aToken);
440
0
                mxPreviewIconView->insert(nIndex, nullptr, &sId, &aPreviewBitmap, nullptr);
441
0
                mxPreviewIconView->set_item_accessible_name(
442
0
                    nIndex, mpContainer->GetPageNameForToken(aToken));
443
0
            }
444
445
0
            AddTokenToIndexEntry(nIndex, aToken);
446
0
        }
447
448
0
        if (eState == MasterPageContainer::PS_CREATABLE)
449
0
            mpContainer->RequestPreview(aToken);
450
0
    }
451
0
    else
452
0
    {
453
0
        mxPreviewIconView->remove(nIndex);
454
0
    }
455
0
    mxPreviewIconView->thaw();
456
0
}
457
458
void MasterPagesSelector::AddTokenToIndexEntry (
459
    sal_uInt16 nIndex,
460
    MasterPageContainer::Token aToken)
461
0
{
462
0
    const ::osl::MutexGuard aGuard (maMutex);
463
464
0
    maTokenToValueSetIndex[aToken] = nIndex;
465
0
}
466
467
void MasterPagesSelector::RemoveTokenToIndexEntry (
468
    sal_uInt16 nIndex,
469
    MasterPageContainer::Token aNewToken)
470
0
{
471
0
    const ::osl::MutexGuard aGuard (maMutex);
472
473
0
    std::unique_ptr<UserData> pData = GetUserData(nIndex);
474
0
    if (pData != nullptr)
475
0
    {
476
        // Get the token that the index pointed to previously.
477
0
        MasterPageContainer::Token aOldToken (pData->second);
478
479
0
        if (aNewToken != aOldToken
480
0
            && nIndex == GetIndexForToken(aOldToken))
481
0
        {
482
0
            maTokenToValueSetIndex[aOldToken] = -1;
483
0
        }
484
0
    }
485
0
}
486
487
void MasterPagesSelector::InvalidatePreview (const SdPage* pPage)
488
0
{
489
0
    const ::osl::MutexGuard aGuard (maMutex);
490
491
0
    for (int nIndex = 0; nIndex < mxPreviewIconView->n_children(); nIndex++)
492
0
    {
493
0
        std::unique_ptr<UserData> pData = GetUserData(nIndex);
494
0
        if (pData != nullptr)
495
0
        {
496
0
            MasterPageContainer::Token aToken (pData->second);
497
0
            if (pPage == mpContainer->GetPageObjectForToken(aToken,false))
498
0
            {
499
0
                mpContainer->InvalidatePreview(aToken);
500
0
                mpContainer->RequestPreview(aToken);
501
0
                break;
502
0
            }
503
0
        }
504
0
    }
505
0
}
506
507
ScopedVclPtr<VirtualDevice> MasterPagesSelector::GetVirtualDevice(const Image& rImage)
508
0
{
509
0
    Bitmap aPreviewBitmap = rImage.GetBitmap();
510
0
    VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create();
511
0
    const Point aNull(0, 0);
512
0
    if (pVDev->GetDPIScaleFactor() > 1)
513
0
        aPreviewBitmap.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor());
514
0
    const Size aSize(aPreviewBitmap.GetSizePixel());
515
0
    pVDev->SetOutputSizePixel(aSize);
516
0
    pVDev->DrawBitmap(aNull, aPreviewBitmap);
517
518
0
    return pVDev;
519
0
}
520
521
Bitmap MasterPagesSelector::GetPreviewAsBitmap(const Image& rImage)
522
0
{
523
0
    Bitmap aPreviewBitmap(rImage.GetBitmap());
524
0
    ScopedVclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create();
525
0
    if (pVDev->GetDPIScaleFactor() > 1)
526
0
        aPreviewBitmap.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor());
527
528
0
    return aPreviewBitmap;
529
0
}
530
531
void MasterPagesSelector::UpdateAllPreviews()
532
0
{
533
0
    const ::osl::MutexGuard aGuard (maMutex);
534
535
0
    mxPreviewIconView->freeze();
536
0
    for (int aIndex = 0; aIndex < mxPreviewIconView->n_children(); aIndex++)
537
0
    {
538
0
        const MasterPageContainer::Token aToken
539
0
            = static_cast<MasterPageContainer::Token>(mxPreviewIconView->get_id(aIndex).toInt32());
540
541
0
        Image aPreview(mpContainer->GetPreviewForToken(aToken));
542
0
        if (aPreview.GetSizePixel().Width() > 0)
543
0
        {
544
0
            mxPreviewIconView->set_image(aIndex, *GetVirtualDevice(aPreview));
545
0
        }
546
0
        else if (mpContainer->GetPreviewState(aToken) == MasterPageContainer::PS_CREATABLE)
547
0
        {
548
0
            mpContainer->RequestPreview(aToken);
549
0
        }
550
0
    }
551
0
    mxPreviewIconView->thaw();
552
0
}
553
554
void MasterPagesSelector::ClearPageSet()
555
0
{
556
0
    const ::osl::MutexGuard aGuard (maMutex);
557
0
    mxPreviewIconView->clear();
558
0
}
559
560
void MasterPagesSelector::SetHelpId( const OUString& aId )
561
0
{
562
0
    const ::osl::MutexGuard aGuard (maMutex);
563
0
    mxPreviewIconView->set_help_id(aId);
564
0
}
565
566
sal_Int32 MasterPagesSelector::GetIndexForToken (MasterPageContainer::Token aToken) const
567
0
{
568
0
    const ::osl::MutexGuard aGuard (maMutex);
569
570
0
    TokenToValueSetIndex::const_iterator iIndex (maTokenToValueSetIndex.find(aToken));
571
0
    if (iIndex != maTokenToValueSetIndex.end())
572
0
        return iIndex->second;
573
0
    else
574
0
        return -1;
575
0
}
576
577
void MasterPagesSelector::Clear()
578
0
{
579
0
    const ::osl::MutexGuard aGuard (maMutex);
580
581
0
    ClearPageSet();
582
0
}
583
584
void MasterPagesSelector::InvalidateItem (MasterPageContainer::Token aToken)
585
0
{
586
0
    const ::osl::MutexGuard aGuard (maMutex);
587
588
0
    auto iItem = std::find(maCurrentItemList.begin(), maCurrentItemList.end(), aToken);
589
0
    if (iItem != maCurrentItemList.end())
590
0
        *iItem = MasterPageContainer::NIL_TOKEN;
591
0
}
592
593
void MasterPagesSelector::UpdateItemList (::std::unique_ptr<ItemList> && pNewItemList)
594
0
{
595
0
    const ::osl::MutexGuard aGuard (maMutex);
596
597
0
    ItemList::const_iterator iNewItem (pNewItemList->begin());
598
0
    ItemList::const_iterator iCurrentItem (maCurrentItemList.begin());
599
0
    ItemList::const_iterator iNewEnd (pNewItemList->end());
600
0
    ItemList::const_iterator iCurrentEnd (maCurrentItemList.end());
601
0
    sal_uInt16 nIndex(0);
602
603
    // Update existing items.
604
0
    for ( ; iNewItem!=iNewEnd && iCurrentItem!=iCurrentEnd; ++iNewItem, ++iCurrentItem,++nIndex)
605
0
    {
606
0
        if (*iNewItem != *iCurrentItem)
607
0
        {
608
0
            SetItem(nIndex,*iNewItem);
609
0
        }
610
0
    }
611
612
    // Append new items.
613
0
    for ( ; iNewItem!=iNewEnd; ++iNewItem,++nIndex)
614
0
    {
615
0
        SetItem(nIndex,*iNewItem);
616
0
    }
617
618
    // Remove trailing items.
619
0
    for ( ; iCurrentItem!=iCurrentEnd; ++iCurrentItem,++nIndex)
620
0
    {
621
0
        SetItem(nIndex,MasterPageContainer::NIL_TOKEN);
622
0
    }
623
624
0
    maCurrentItemList.swap(*pNewItemList);
625
626
0
    if (mxSidebar.is())
627
0
        mxSidebar->requestLayout();
628
0
}
629
630
css::ui::LayoutSize MasterPagesSelector::GetHeightForWidth(const sal_Int32 nWidth)
631
0
{
632
    // there is no way to get margin of item programmatically, we use value provided in ui file.
633
0
    const int nMargin = 6;
634
0
    const Size& previewSize = mpContainer->GetPreviewSizePixel();
635
0
    sal_Int32 nColumnCount = nWidth / (previewSize.Width() + (2 * nMargin));
636
0
    if (nColumnCount < 1)
637
0
        nColumnCount = 1;
638
639
0
    sal_Int32 nTotalItems = mxPreviewIconView->n_children();
640
0
    sal_Int32 nRowCount = (nTotalItems + nColumnCount - 1) / nColumnCount;
641
0
    if (nRowCount < 1)
642
0
        nRowCount = 1;
643
644
0
    sal_Int32 nPreferedHeight = nRowCount * (previewSize.getHeight() + (4 * nMargin));
645
0
    return css::ui::LayoutSize(nPreferedHeight, nPreferedHeight, nPreferedHeight);
646
0
}
647
648
} // end of namespace sd::sidebar
649
650
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */