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 "PreviewValueSet.hxx"
36 #include <ViewShellBase.hxx>
37 #include <vcl/commandevent.hxx>
38 #include <vcl/image.hxx>
39 #include <vcl/floatwin.hxx>
40 #include <sfx2/dispatch.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/sidebar/Theme.hxx>
43 #include <memory>
44 
45 using namespace ::com::sun::star::text;
46 
47 namespace sd { namespace sidebar {
48 
49     /** menu entry that is executed as default action when the left mouse button is
50         clicked over a master page.
51     */
52 static const char gsDefaultClickAction[] = "applyselect";
53 
MasterPagesSelector(vcl::Window * pParent,SdDrawDocument & rDocument,ViewShellBase & rBase,const std::shared_ptr<MasterPageContainer> & rpContainer,const css::uno::Reference<css::ui::XSidebar> & rxSidebar)54 MasterPagesSelector::MasterPagesSelector (
55     vcl::Window* pParent,
56     SdDrawDocument& rDocument,
57     ViewShellBase& rBase,
58     const std::shared_ptr<MasterPageContainer>& rpContainer,
59     const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
60     : PreviewValueSet(pParent),
61       maMutex(),
62       mpContainer(rpContainer),
63       mrDocument(rDocument),
64       mrBase(rBase),
65       maCurrentItemList(),
66       maTokenToValueSetIndex(),
67       maLockedMasterPages(),
68       mxSidebar(rxSidebar)
69 {
70     PreviewValueSet::SetSelectHdl (
71         LINK(this, MasterPagesSelector, ClickHandler));
72     PreviewValueSet::SetRightMouseClickHandler (
73         LINK(this, MasterPagesSelector, RightClickHandler));
74     PreviewValueSet::SetStyle(PreviewValueSet::GetStyle() | WB_NO_DIRECTSELECT);
75 
76     if ( GetDPIScaleFactor() > 1 )
77         mpContainer->SetPreviewSize(MasterPageContainer::LARGE);
78 
79     PreviewValueSet::SetPreviewSize(mpContainer->GetPreviewSizePixel());
80     PreviewValueSet::Show();
81 
82     SetBackground(sfx2::sidebar::Theme::GetWallpaper(sfx2::sidebar::Theme::Paint_PanelBackground));
83     SetColor(sfx2::sidebar::Theme::GetColor(sfx2::sidebar::Theme::Paint_PanelBackground));
84 
85     Link<MasterPageContainerChangeEvent&,void> aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener));
86     mpContainer->AddChangeListener(aChangeListener);
87 }
88 
~MasterPagesSelector()89 MasterPagesSelector::~MasterPagesSelector()
90 {
91     disposeOnce();
92 }
93 
dispose()94 void MasterPagesSelector::dispose()
95 {
96     Clear();
97     UpdateLocks(ItemList());
98 
99     Link<MasterPageContainerChangeEvent&,void> aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener));
100     mpContainer->RemoveChangeListener(aChangeListener);
101     mpContainer.reset();
102     PreviewValueSet::dispose();
103 }
104 
LateInit()105 void MasterPagesSelector::LateInit()
106 {
107 }
108 
GetPreferredHeight(sal_Int32 nWidth)109 sal_Int32 MasterPagesSelector::GetPreferredHeight (sal_Int32 nWidth)
110 {
111     const ::osl::MutexGuard aGuard (maMutex);
112 
113     return PreviewValueSet::GetPreferredHeight (nWidth);
114 }
115 
UpdateLocks(const ItemList & rItemList)116 void MasterPagesSelector::UpdateLocks (const ItemList& rItemList)
117 {
118     ItemList aNewLockList;
119 
120     // In here we first lock the master pages in the given list and then
121     // release the locks acquired in a previous call to this method.  When
122     // this were done the other way round the lock count of some master
123     // pages might drop temporarily to 0 and would lead to unnecessary
124     // deletion and re-creation of MasterPageDescriptor objects.
125 
126     // Lock the master pages in the given list.
127     for (const auto& rItem : rItemList)
128     {
129         mpContainer->AcquireToken(rItem);
130         aNewLockList.push_back(rItem);
131     }
132 
133     // Release the previously locked master pages.
134     for (const auto& rPage : maLockedMasterPages)
135         mpContainer->ReleaseToken(rPage);
136 
137     maLockedMasterPages.swap(aNewLockList);
138 }
139 
Fill()140 void MasterPagesSelector::Fill()
141 {
142     ::std::unique_ptr<ItemList> pItemList (new ItemList);
143 
144     Fill(*pItemList);
145 
146     UpdateLocks(*pItemList);
147     UpdateItemList(std::move(pItemList));
148 }
149 
GetContextMenuUIFile() const150 OUString MasterPagesSelector::GetContextMenuUIFile() const
151 {
152     return "modules/simpress/ui/mastermenu.ui";
153 }
154 
IMPL_LINK_NOARG(MasterPagesSelector,ClickHandler,ValueSet *,void)155 IMPL_LINK_NOARG(MasterPagesSelector, ClickHandler, ValueSet*, void)
156 {
157     // We use the framework to assign the clicked-on master page because we
158     // so use the same mechanism as the context menu does (where we do not
159     // have the option to call the assignment method directly.)
160     ExecuteCommand(gsDefaultClickAction);
161 }
162 
IMPL_LINK(MasterPagesSelector,RightClickHandler,const MouseEvent &,rEvent,void)163 IMPL_LINK(MasterPagesSelector, RightClickHandler, const MouseEvent&, rEvent, void)
164 {
165     // Here we only prepare the display of the context menu: the item under
166     // the mouse is selected.  The actual display of the context menu is
167     // done in ContextMenuCallback which is called indirectly through
168     // PreviewValueSet::Command().
169     PreviewValueSet::GrabFocus ();
170     PreviewValueSet::ReleaseMouse();
171     SfxViewFrame* pViewFrame = mrBase.GetViewFrame();
172     if (pViewFrame != nullptr)
173     {
174         SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
175         if (pDispatcher != nullptr)
176         {
177             sal_uInt16 nIndex = PreviewValueSet::GetItemId (rEvent.GetPosPixel());
178             if (nIndex > 0)
179                 PreviewValueSet::SelectItem (nIndex);
180         }
181     }
182 }
183 
Command(const CommandEvent & rEvent)184 void MasterPagesSelector::Command (const CommandEvent& rEvent)
185 {
186     switch (rEvent.GetCommand())
187     {
188         case CommandEventId::ContextMenu:
189         {
190             // Use the currently selected item and show the popup menu in its
191             // center.
192             const sal_uInt16 nIndex = PreviewValueSet::GetSelectedItemId();
193             if (nIndex > 0)
194             {
195                 // The position of the upper left corner of the context menu is
196                 // taken either from the mouse position (when the command was sent
197                 // as reaction to a right click) or in the center of the selected
198                 // item (when the command was sent as reaction to Shift+F10.)
199                 Point aPosition (rEvent.GetMousePosPixel());
200                 if ( ! rEvent.IsMouseEvent())
201                 {
202                     ::tools::Rectangle aBBox (PreviewValueSet::GetItemRect(nIndex));
203                     aPosition = aBBox.Center();
204                 }
205 
206                 // Setup the menu.
207                 VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), GetContextMenuUIFile(), "");
208                 VclPtr<PopupMenu> pMenu(aBuilder.get_menu("menu"));
209                 FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow());
210                 if (pMenuWindow != nullptr)
211                     pMenuWindow->SetPopupModeFlags(
212                         pMenuWindow->GetPopupModeFlags() | FloatWinPopupFlags::NoMouseUpClose);
213                 pMenu->SetSelectHdl(LINK(this, MasterPagesSelector, OnMenuItemSelected));
214 
215                 ProcessPopupMenu(*pMenu);
216 
217                 // Show the menu.
218                 pMenu->Execute(this, ::tools::Rectangle(aPosition,Size(1,1)), PopupMenuFlags::ExecuteDown);
219             }
220         }
221         break;
222         default: break;
223     }
224 }
225 
ProcessPopupMenu(Menu & rMenu)226 void MasterPagesSelector::ProcessPopupMenu (Menu& rMenu)
227 {
228     // Disable some entries.
229     if (mpContainer->GetPreviewSize() == MasterPageContainer::SMALL)
230         rMenu.EnableItem(rMenu.GetItemId("small"), false);
231     else
232         rMenu.EnableItem(rMenu.GetItemId("large"), false);
233 }
234 
IMPL_LINK(MasterPagesSelector,OnMenuItemSelected,Menu *,pMenu,bool)235 IMPL_LINK(MasterPagesSelector, OnMenuItemSelected, Menu*, pMenu, bool)
236 {
237     if (pMenu == nullptr)
238     {
239         OSL_ENSURE(pMenu!=nullptr, "MasterPagesSelector::OnMenuItemSelected: illegal menu!");
240         return false;
241     }
242 
243     pMenu->Deactivate();
244     ExecuteCommand(pMenu->GetCurItemIdent());
245     return false;
246 }
247 
ExecuteCommand(const OString & rIdent)248 void MasterPagesSelector::ExecuteCommand(const OString &rIdent)
249 {
250     if (rIdent == "applyall")
251     {
252         mrBase.SetBusyState (true);
253         AssignMasterPageToAllSlides (GetSelectedMasterPage());
254         mrBase.SetBusyState (false);
255     }
256     else if (rIdent == "applyselect")
257     {
258         mrBase.SetBusyState (true);
259         AssignMasterPageToSelectedSlides (GetSelectedMasterPage());
260         mrBase.SetBusyState (false);
261     }
262     else if (rIdent == "large")
263     {
264         mrBase.SetBusyState (true);
265         mpContainer->SetPreviewSize(MasterPageContainer::LARGE);
266         mrBase.SetBusyState (false);
267         if (mxSidebar.is())
268             mxSidebar->requestLayout();
269     }
270     else if (rIdent == "small")
271     {
272         mrBase.SetBusyState (true);
273         mpContainer->SetPreviewSize(MasterPageContainer::SMALL);
274         mrBase.SetBusyState (false);
275         if (mxSidebar.is())
276             mxSidebar->requestLayout();
277     }
278     else if (rIdent == "edit")
279     {
280         using namespace ::com::sun::star;
281         uno::Reference<drawing::XDrawPage> xSelectedMaster;
282         SdPage* pMasterPage = GetSelectedMasterPage();
283         assert(pMasterPage); //rhbz#902884
284         if (pMasterPage)
285             xSelectedMaster.set(pMasterPage->getUnoPage(), uno::UNO_QUERY);
286         SfxViewFrame* pViewFrame = mrBase.GetViewFrame();
287         if (pViewFrame != nullptr && xSelectedMaster.is())
288         {
289             SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
290             if (pDispatcher != nullptr)
291             {
292                 sal_uInt16 nIndex = PreviewValueSet::GetSelectedItemId();
293                 pDispatcher->Execute(SID_MASTERPAGE, SfxCallMode::SYNCHRON);
294                 PreviewValueSet::SelectItem (nIndex);
295                 mrBase.GetDrawController().setCurrentPage(xSelectedMaster);
296             }
297         }
298     }
299 }
300 
IMPL_LINK(MasterPagesSelector,ContainerChangeListener,MasterPageContainerChangeEvent &,rEvent,void)301 IMPL_LINK(MasterPagesSelector, ContainerChangeListener, MasterPageContainerChangeEvent&, rEvent, void)
302 {
303     NotifyContainerChangeEvent(rEvent);
304 }
305 
GetSelectedMasterPage()306 SdPage* MasterPagesSelector::GetSelectedMasterPage()
307 {
308     const ::osl::MutexGuard aGuard (maMutex);
309 
310     SdPage* pMasterPage = nullptr;
311     sal_uInt16 nIndex = PreviewValueSet::GetSelectedItemId();
312     UserData* pData = GetUserData(nIndex);
313     if (pData != nullptr)
314     {
315         pMasterPage = mpContainer->GetPageObjectForToken(pData->second, true);
316     }
317     return pMasterPage;
318 }
319 
320 /** Assemble a list of all slides of the document and pass it to
321     AssignMasterPageToPageList().
322 */
AssignMasterPageToAllSlides(SdPage * pMasterPage)323 void MasterPagesSelector::AssignMasterPageToAllSlides (SdPage* pMasterPage)
324 {
325     if (pMasterPage == nullptr)
326         return;
327 
328     sal_uInt16 nPageCount = mrDocument.GetSdPageCount(PageKind::Standard);
329     if (nPageCount == 0)
330         return;
331 
332     // Get a list of all pages.  As a little optimization we only
333     // include pages that do not already have the given master page
334     // assigned.
335     OUString sFullLayoutName(pMasterPage->GetLayoutName());
336     ::sd::slidesorter::SharedPageSelection pPageList (
337         new ::sd::slidesorter::SlideSorterViewShell::PageSelection);
338     for (sal_uInt16 nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
339     {
340         SdPage* pPage = mrDocument.GetSdPage (nPageIndex, PageKind::Standard);
341         if (pPage != nullptr && pPage->GetLayoutName() != sFullLayoutName)
342         {
343             pPageList->push_back (pPage);
344         }
345     }
346 
347     AssignMasterPageToPageList(pMasterPage, pPageList);
348 }
349 
350 /** Assemble a list of the currently selected slides (selected in a visible
351     slide sorter) and pass it to AssignMasterPageToPageList().
352 */
AssignMasterPageToSelectedSlides(SdPage * pMasterPage)353 void MasterPagesSelector::AssignMasterPageToSelectedSlides (
354     SdPage* pMasterPage)
355 {
356     using namespace ::sd::slidesorter;
357     using namespace ::sd::slidesorter::controller;
358 
359     if (pMasterPage == nullptr)
360         return;
361 
362     // Find a visible slide sorter.
363     SlideSorterViewShell* pSlideSorter = SlideSorterViewShell::GetSlideSorter(mrBase);
364     if (pSlideSorter == nullptr)
365         return;
366 
367     // Get a list of selected pages.
368     SharedPageSelection pPageSelection = pSlideSorter->GetPageSelection();
369     if (pPageSelection->empty())
370         return;
371 
372     AssignMasterPageToPageList(pMasterPage, pPageSelection);
373 
374     // Restore the previous selection.
375     pSlideSorter->SetPageSelection(pPageSelection);
376 }
377 
AssignMasterPageToPageList(SdPage * pMasterPage,const std::shared_ptr<std::vector<SdPage * >> & rPageList)378 void MasterPagesSelector::AssignMasterPageToPageList (
379     SdPage* pMasterPage,
380     const std::shared_ptr<std::vector<SdPage*>>& rPageList)
381 {
382     DocumentHelper::AssignMasterPageToPageList(mrDocument, pMasterPage, rPageList);
383 }
384 
NotifyContainerChangeEvent(const MasterPageContainerChangeEvent & rEvent)385 void MasterPagesSelector::NotifyContainerChangeEvent (const MasterPageContainerChangeEvent& rEvent)
386 {
387     const ::osl::MutexGuard aGuard (maMutex);
388 
389     switch (rEvent.meEventType)
390     {
391         case MasterPageContainerChangeEvent::EventType::SIZE_CHANGED:
392             PreviewValueSet::SetPreviewSize(mpContainer->GetPreviewSizePixel());
393             UpdateAllPreviews();
394             break;
395 
396         case MasterPageContainerChangeEvent::EventType::PREVIEW_CHANGED:
397         {
398             int nIndex (GetIndexForToken(rEvent.maChildToken));
399             if (nIndex >= 0)
400             {
401                 PreviewValueSet::SetItemImage (
402                     static_cast<sal_uInt16>(nIndex),
403                     mpContainer->GetPreviewForToken(rEvent.maChildToken));
404                 PreviewValueSet::Invalidate(PreviewValueSet::GetItemRect(static_cast<sal_uInt16>(nIndex)));
405             }
406         }
407         break;
408 
409         case MasterPageContainerChangeEvent::EventType::DATA_CHANGED:
410         {
411             InvalidateItem(rEvent.maChildToken);
412             Fill();
413         }
414         break;
415 
416         case MasterPageContainerChangeEvent::EventType::CHILD_REMOVED:
417         {
418             int nIndex (GetIndexForToken(rEvent.maChildToken));
419             SetItem(nIndex, MasterPageContainer::NIL_TOKEN);
420             break;
421         }
422 
423         default:
424             break;
425    }
426 }
427 
GetUserData(int nIndex) const428 MasterPagesSelector::UserData* MasterPagesSelector::GetUserData (int nIndex) const
429 {
430     const ::osl::MutexGuard aGuard (maMutex);
431 
432     if (nIndex>0 && static_cast<unsigned int>(nIndex)<=PreviewValueSet::GetItemCount())
433         return static_cast<UserData*>(PreviewValueSet::GetItemData(static_cast<sal_uInt16>(nIndex)));
434     else
435         return nullptr;
436 }
437 
SetUserData(int nIndex,std::unique_ptr<UserData> pData)438 void MasterPagesSelector::SetUserData (int nIndex, std::unique_ptr<UserData> pData)
439 {
440     const ::osl::MutexGuard aGuard (maMutex);
441 
442     delete GetUserData(nIndex);
443     PreviewValueSet::SetItemData(static_cast<sal_uInt16>(nIndex), pData.release());
444 }
445 
SetItem(sal_uInt16 nIndex,MasterPageContainer::Token aToken)446 void MasterPagesSelector::SetItem (
447     sal_uInt16 nIndex,
448     MasterPageContainer::Token aToken)
449 {
450     const ::osl::MutexGuard aGuard (maMutex);
451 
452     RemoveTokenToIndexEntry(nIndex,aToken);
453 
454     if (nIndex <= 0)
455         return;
456 
457     if (aToken != MasterPageContainer::NIL_TOKEN)
458     {
459         Image aPreview (mpContainer->GetPreviewForToken(aToken));
460         MasterPageContainer::PreviewState eState (mpContainer->GetPreviewState(aToken));
461 
462         if (aPreview.GetSizePixel().Width()>0)
463         {
464             if (PreviewValueSet::GetItemPos(nIndex) != VALUESET_ITEM_NOTFOUND)
465             {
466                 PreviewValueSet::SetItemImage(nIndex,aPreview);
467                 PreviewValueSet::SetItemText(nIndex, mpContainer->GetPageNameForToken(aToken));
468             }
469             else
470             {
471                 PreviewValueSet::InsertItem (
472                     nIndex,
473                     aPreview,
474                     mpContainer->GetPageNameForToken(aToken),
475                     nIndex);
476             }
477             SetUserData(nIndex, std::make_unique<UserData>(nIndex,aToken));
478 
479             AddTokenToIndexEntry(nIndex,aToken);
480         }
481 
482         if (eState == MasterPageContainer::PS_CREATABLE)
483             mpContainer->RequestPreview(aToken);
484     }
485     else
486     {
487         PreviewValueSet::RemoveItem(nIndex);
488     }
489 
490 }
491 
AddTokenToIndexEntry(sal_uInt16 nIndex,MasterPageContainer::Token aToken)492 void MasterPagesSelector::AddTokenToIndexEntry (
493     sal_uInt16 nIndex,
494     MasterPageContainer::Token aToken)
495 {
496     const ::osl::MutexGuard aGuard (maMutex);
497 
498     maTokenToValueSetIndex[aToken] = nIndex;
499 }
500 
RemoveTokenToIndexEntry(sal_uInt16 nIndex,MasterPageContainer::Token aNewToken)501 void MasterPagesSelector::RemoveTokenToIndexEntry (
502     sal_uInt16 nIndex,
503     MasterPageContainer::Token aNewToken)
504 {
505     const ::osl::MutexGuard aGuard (maMutex);
506 
507     UserData* pData = GetUserData(nIndex);
508     if (pData != nullptr)
509     {
510         // Get the token that the index pointed to previously.
511         MasterPageContainer::Token aOldToken (pData->second);
512 
513         if (aNewToken != aOldToken
514             && nIndex == GetIndexForToken(aOldToken))
515         {
516             maTokenToValueSetIndex[aOldToken] = 0;
517         }
518     }
519 }
520 
InvalidatePreview(const SdPage * pPage)521 void MasterPagesSelector::InvalidatePreview (const SdPage* pPage)
522 {
523     const ::osl::MutexGuard aGuard (maMutex);
524 
525     for (size_t nIndex=1; nIndex<=PreviewValueSet::GetItemCount(); nIndex++)
526     {
527         UserData* pData = GetUserData(nIndex);
528         if (pData != nullptr)
529         {
530             MasterPageContainer::Token aToken (pData->second);
531             if (pPage == mpContainer->GetPageObjectForToken(aToken,false))
532             {
533                 mpContainer->InvalidatePreview(aToken);
534                 mpContainer->RequestPreview(aToken);
535                 break;
536             }
537         }
538     }
539 }
540 
UpdateAllPreviews()541 void MasterPagesSelector::UpdateAllPreviews()
542 {
543     const ::osl::MutexGuard aGuard (maMutex);
544 
545     for (size_t nIndex=1; nIndex<=PreviewValueSet::GetItemCount(); nIndex++)
546     {
547         UserData* pData = GetUserData(nIndex);
548         if (pData != nullptr)
549         {
550             MasterPageContainer::Token aToken (pData->second);
551             PreviewValueSet::SetItemImage(
552                 nIndex,
553                 mpContainer->GetPreviewForToken(aToken));
554             if (mpContainer->GetPreviewState(aToken) == MasterPageContainer::PS_CREATABLE)
555                 mpContainer->RequestPreview(aToken);
556         }
557     }
558     PreviewValueSet::Rearrange();
559 }
560 
ClearPageSet()561 void MasterPagesSelector::ClearPageSet()
562 {
563     const ::osl::MutexGuard aGuard (maMutex);
564 
565     for (size_t nIndex=1; nIndex<=PreviewValueSet::GetItemCount(); nIndex++)
566     {
567         UserData* pData = GetUserData(nIndex);
568         delete pData;
569     }
570     PreviewValueSet::Clear();
571 }
572 
SetHelpId(const OString & aId)573 void MasterPagesSelector::SetHelpId( const OString& aId )
574 {
575     const ::osl::MutexGuard aGuard (maMutex);
576 
577     PreviewValueSet::SetHelpId( aId );
578 }
579 
GetIndexForToken(MasterPageContainer::Token aToken) const580 sal_Int32 MasterPagesSelector::GetIndexForToken (MasterPageContainer::Token aToken) const
581 {
582     const ::osl::MutexGuard aGuard (maMutex);
583 
584     TokenToValueSetIndex::const_iterator iIndex (maTokenToValueSetIndex.find(aToken));
585     if (iIndex != maTokenToValueSetIndex.end())
586         return iIndex->second;
587     else
588         return -1;
589 }
590 
Clear()591 void MasterPagesSelector::Clear()
592 {
593     const ::osl::MutexGuard aGuard (maMutex);
594 
595     ClearPageSet();
596 }
597 
InvalidateItem(MasterPageContainer::Token aToken)598 void MasterPagesSelector::InvalidateItem (MasterPageContainer::Token aToken)
599 {
600     const ::osl::MutexGuard aGuard (maMutex);
601 
602     auto iItem = std::find(maCurrentItemList.begin(), maCurrentItemList.end(), aToken);
603     if (iItem != maCurrentItemList.end())
604         *iItem = MasterPageContainer::NIL_TOKEN;
605 }
606 
UpdateItemList(::std::unique_ptr<ItemList> && pNewItemList)607 void MasterPagesSelector::UpdateItemList (::std::unique_ptr<ItemList> && pNewItemList)
608 {
609     const ::osl::MutexGuard aGuard (maMutex);
610 
611     ItemList::const_iterator iNewItem (pNewItemList->begin());
612     ItemList::const_iterator iCurrentItem (maCurrentItemList.begin());
613     ItemList::const_iterator iNewEnd (pNewItemList->end());
614     ItemList::const_iterator iCurrentEnd (maCurrentItemList.end());
615     sal_uInt16 nIndex (1);
616 
617     // Update existing items.
618     for ( ; iNewItem!=iNewEnd && iCurrentItem!=iCurrentEnd; ++iNewItem, ++iCurrentItem,++nIndex)
619     {
620         if (*iNewItem != *iCurrentItem)
621         {
622             SetItem(nIndex,*iNewItem);
623         }
624     }
625 
626     // Append new items.
627     for ( ; iNewItem!=iNewEnd; ++iNewItem,++nIndex)
628     {
629         SetItem(nIndex,*iNewItem);
630     }
631 
632     // Remove trailing items.
633     for ( ; iCurrentItem!=iCurrentEnd; ++iCurrentItem,++nIndex)
634     {
635         SetItem(nIndex,MasterPageContainer::NIL_TOKEN);
636     }
637 
638     maCurrentItemList.swap(*pNewItemList);
639 
640     PreviewValueSet::Rearrange();
641     if (mxSidebar.is())
642         mxSidebar->requestLayout();
643 }
644 
GetHeightForWidth(const sal_Int32 nWidth)645 css::ui::LayoutSize MasterPagesSelector::GetHeightForWidth (const sal_Int32 nWidth)
646 {
647     const sal_Int32 nHeight (GetPreferredHeight(nWidth));
648     return css::ui::LayoutSize(nHeight,nHeight,nHeight);
649 }
650 
651 } } // end of namespace sd::sidebar
652 
653 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
654