1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MasterPagesSelector.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "MasterPagesSelector.hxx"
36 #include "MasterPageContainer.hxx"
37 #include "DocumentHelper.hxx"
39 #include "drawdoc.hxx"
40 #include "DrawDocShell.hxx"
45 #include "res_bmp.hrc"
46 #include "strings.hrc"
47 #include "showview.hxx"
48 #include "DrawViewShell.hxx"
49 #include "DrawController.hxx"
50 #include "SlideSorterViewShell.hxx"
51 #include "PreviewValueSet.hxx"
52 #include "ViewShellBase.hxx"
53 #include "../TaskPaneShellManager.hxx"
54 #include "taskpane/TitledControl.hxx"
55 #include "taskpane/ControlContainer.hxx"
56 #include "controller/SlideSorterController.hxx"
57 #include "controller/SlsPageSelector.hxx"
58 #include <sfx2/objface.hxx>
59 #include "sdresid.hxx"
60 #include "TemplateScanner.hxx"
61 #ifndef _SD_DRAWVIEW_HXX
62 #include "drawview.hxx"
64 #include <vcl/image.hxx>
65 #include <svtools/languageoptions.hxx>
66 #include <sfx2/app.hxx>
67 #include <sfx2/dispatch.hxx>
68 #include <sfx2/mnumgr.hxx>
69 #include <svtools/itemset.hxx>
70 #include <svtools/eitem.hxx>
71 #include <svx/dlgutil.hxx>
72 #include <svx/svdpagv.hxx>
73 #include <svx/svxids.hrc>
74 #include "FrameView.hxx"
76 #include "stlpool.hxx"
77 #include "unmovss.hxx"
78 #include <sfx2/request.hxx>
79 #include <svtools/itempool.hxx>
81 using namespace ::sd::toolpanel::controls
;
82 #define MasterPagesSelector
83 #include "sdslots.hxx"
85 using namespace ::com::sun::star::text
;
89 namespace sd
{ namespace toolpanel
{ namespace controls
{
92 SFX_IMPL_INTERFACE(MasterPagesSelector
, SfxShell
,
93 SdResId(STR_MASTERPAGESSELECTOR
))
95 SFX_POPUPMENU_REGISTRATION( SdResId(RID_TASKPANE_MASTERPAGESSELECTOR_POPUP
) );
98 TYPEINIT1(MasterPagesSelector
, SfxShell
);
102 MasterPagesSelector::MasterPagesSelector (
104 SdDrawDocument
& rDocument
,
105 ViewShellBase
& rBase
,
106 const ::boost::shared_ptr
<MasterPageContainer
>& rpContainer
)
107 : TreeNode (pParent
),
110 mpContainer(rpContainer
),
111 mrDocument(rDocument
),
112 mpPageSet (new PreviewValueSet(pParent
)),
114 mnDefaultClickAction(SID_TP_APPLY_TO_ALL_SLIDES
),
115 maPreviewUpdateQueue(),
117 maTokenToValueSetIndex(),
118 maLockedMasterPages()
120 SetPool (&rDocument
.GetPool());
122 mpPageSet
->SetSelectHdl (
123 LINK(this, MasterPagesSelector
, ClickHandler
));
124 mpPageSet
->SetRightMouseClickHandler (
125 LINK(this, MasterPagesSelector
, RightClickHandler
));
126 mpPageSet
->SetContextMenuCallback (
127 LINK(this, MasterPagesSelector
, ContextMenuCallback
));
128 mpPageSet
->SetStyle(mpPageSet
->GetStyle() | WB_NO_DIRECTSELECT
);
129 mpPageSet
->SetPreviewSize(mpContainer
->GetPreviewSizePixel());
132 Link
aChangeListener (LINK(this,MasterPagesSelector
,ContainerChangeListener
));
133 mpContainer
->AddChangeListener(aChangeListener
);
139 MasterPagesSelector::~MasterPagesSelector (void)
143 UpdateLocks(ItemList());
145 if (GetShellManager() != NULL
)
146 GetShellManager()->RemoveSubShell (this);
148 Link
aChangeListener (LINK(this,MasterPagesSelector
,ContainerChangeListener
));
149 mpContainer
->RemoveChangeListener(aChangeListener
);
155 void MasterPagesSelector::LateInit (void)
162 sal_Int32
MasterPagesSelector::GetPreferredWidth (sal_Int32 nHeight
)
164 const ::osl::MutexGuard
aGuard (maMutex
);
166 return mpPageSet
->GetPreferredWidth (nHeight
);
172 sal_Int32
MasterPagesSelector::GetPreferredHeight (sal_Int32 nWidth
)
174 const ::osl::MutexGuard
aGuard (maMutex
);
176 return mpPageSet
->GetPreferredHeight (nWidth
);
182 Size
MasterPagesSelector::GetPreferredSize (void)
184 int nPreferredWidth
= GetPreferredWidth(
185 mpPageSet
->GetOutputSizePixel().Height());
186 int nPreferredHeight
= GetPreferredHeight(nPreferredWidth
);
187 return Size (nPreferredWidth
, nPreferredHeight
);
194 void MasterPagesSelector::UpdateLocks (const ItemList
& rItemList
)
196 ItemList aNewLockList
;
198 // In here we first lock the master pages in the given list and then
199 // release the locks acquired in a previous call to this method. When
200 // this were done the other way round the lock count of some master
201 // pages might drop temporarily to 0 and would lead to unnecessary
202 // deletion and re-creation of MasterPageDescriptor objects.
204 // Lock the master pages in the given list.
205 ItemList::const_iterator iItem
;
206 for (iItem
=rItemList
.begin(); iItem
!=rItemList
.end(); ++iItem
)
208 mpContainer
->AcquireToken(*iItem
);
209 aNewLockList
.push_back(*iItem
);
212 // Release the previously locked master pages.
213 ItemList::const_iterator iPage
;
214 ItemList::const_iterator
iEnd (maLockedMasterPages
.end());
215 for (iPage
=maLockedMasterPages
.begin(); iPage
!=iEnd
; ++iPage
)
216 mpContainer
->ReleaseToken(*iPage
);
218 maLockedMasterPages
.swap(aNewLockList
);
224 void MasterPagesSelector::Fill (void)
226 ::std::auto_ptr
<ItemList
> pItemList (new ItemList());
230 UpdateLocks(*pItemList
);
231 UpdateItemList(pItemList
);
237 ResId
MasterPagesSelector::GetContextMenuResId (void) const
239 return SdResId(RID_TASKPANE_MASTERPAGESSELECTOR_POPUP
);
245 IMPL_LINK(MasterPagesSelector
, ClickHandler
, PreviewValueSet
*, EMPTYARG
)
247 // We use the framework to assign the clicked-on master page because we
248 // so use the same mechanism as the context menu does (where we do not
249 // have the option to call the assignment method directly.)
250 if (GetShellManager() != NULL
)
251 GetShellManager()->MoveToTop (this);
253 SfxViewFrame
* pViewFrame
= mrBase
.GetViewFrame();
254 if (pViewFrame
!= NULL
)
256 SfxDispatcher
* pDispatcher
= pViewFrame
->GetDispatcher();
257 if (pDispatcher
!= NULL
)
258 pDispatcher
->Execute(mnDefaultClickAction
);
267 IMPL_LINK(MasterPagesSelector
, RightClickHandler
, MouseEvent
*, pEvent
)
269 // Here we only prepare the display of the context menu: the item under
270 // the mouse is selected. The actual display of the context menu is
271 // done in ContextMenuCallback which is called indirectly through
272 // PreviewValueSet::Command().
273 mpPageSet
->GrabFocus ();
274 mpPageSet
->ReleaseMouse();
275 if (GetDispatcher() != NULL
&& pEvent
!= NULL
)
277 USHORT nIndex
= mpPageSet
->GetItemId (pEvent
->GetPosPixel());
279 mpPageSet
->SelectItem (nIndex
);
287 IMPL_LINK(MasterPagesSelector
, ContextMenuCallback
, CommandEvent
*, pEvent
)
289 // Use the currently selected item and show the popup menu in its
291 if (GetShellManager() != NULL
)
292 GetShellManager()->MoveToTop (this);
293 const USHORT nIndex
= mpPageSet
->GetSelectItemId();
294 if (nIndex
> 0 && pEvent
!=NULL
)
296 // The position of the upper left corner of the context menu is
297 // taken either from the mouse position (when the command was sent
298 // as reaction to a right click) or in the center of the selected
299 // item (when the command was sent as reaction to Shift+F10.)
300 Point
aPosition (pEvent
->GetMousePosPixel());
301 if ( ! pEvent
->IsMouseEvent())
303 Rectangle
aBBox (mpPageSet
->GetItemRect(nIndex
));
304 aPosition
= aBBox
.Center();
307 const ResId
aPopupResId (GetContextMenuResId());
308 mrBase
.GetViewFrame()->GetDispatcher()->ExecutePopup(
320 IMPL_LINK(MasterPagesSelector
, ContainerChangeListener
, MasterPageContainerChangeEvent
*, pEvent
)
323 NotifyContainerChangeEvent(*pEvent
);
330 SdPage
* MasterPagesSelector::GetSelectedMasterPage (void)
332 const ::osl::MutexGuard
aGuard (maMutex
);
334 SdPage
* pMasterPage
= NULL
;
335 USHORT nIndex
= mpPageSet
->GetSelectItemId();
336 UserData
* pData
= GetUserData(nIndex
);
339 pMasterPage
= mpContainer
->GetPageObjectForToken(pData
->second
);
347 /** Assemble a list of all slides of the document and pass it to
348 AssignMasterPageToPageList().
350 void MasterPagesSelector::AssignMasterPageToAllSlides (SdPage
* pMasterPage
)
354 if (pMasterPage
== NULL
)
357 USHORT nPageCount
= mrDocument
.GetSdPageCount(PK_STANDARD
);
361 // Get a list of all pages. As a little optimization we only
362 // include pages that do not already have the given master page
364 String
sFullLayoutName (pMasterPage
->GetLayoutName());
365 ::sd::slidesorter::SharedPageSelection
pPageList (
366 new ::sd::slidesorter::SlideSorterViewShell::PageSelection());
367 for (USHORT nPageIndex
=0; nPageIndex
<nPageCount
; nPageIndex
++)
369 SdPage
* pPage
= mrDocument
.GetSdPage (nPageIndex
, PK_STANDARD
);
371 && pPage
->GetLayoutName().CompareTo(sFullLayoutName
)!=0)
373 pPageList
->push_back (pPage
);
377 AssignMasterPageToPageList(pMasterPage
, pPageList
);
385 /** Assemble a list of the currently selected slides (selected in a visible
386 slide sorter) and pass it to AssignMasterPageToPageList().
388 void MasterPagesSelector::AssignMasterPageToSelectedSlides (
393 using namespace ::std
;
394 using namespace ::sd::slidesorter
;
395 using namespace ::sd::slidesorter::controller
;
397 if (pMasterPage
== NULL
)
400 // Find a visible slide sorter.
401 SlideSorterViewShell
* pSlideSorter
= SlideSorterViewShell::GetSlideSorter(mrBase
);
402 if (pSlideSorter
== NULL
)
405 // Get a list of selected pages.
406 ::sd::slidesorter::SharedPageSelection pPageSelection
= pSlideSorter
->GetPageSelection();
407 if (pPageSelection
->empty())
410 AssignMasterPageToPageList(pMasterPage
, pPageSelection
);
412 // Restore the previous selection.
413 pSlideSorter
->SetPageSelection(pPageSelection
);
421 void MasterPagesSelector::AssignMasterPageToPageList (
423 const ::sd::slidesorter::SharedPageSelection
& rPageList
)
425 DocumentHelper::AssignMasterPageToPageList(mrDocument
, pMasterPage
, rPageList
);
431 void MasterPagesSelector::NotifyContainerChangeEvent (const MasterPageContainerChangeEvent
& rEvent
)
433 const ::osl::MutexGuard
aGuard (maMutex
);
435 switch (rEvent
.meEventType
)
437 case MasterPageContainerChangeEvent::SIZE_CHANGED
:
438 mpPageSet
->SetPreviewSize(mpContainer
->GetPreviewSizePixel());
442 case MasterPageContainerChangeEvent::PREVIEW_CHANGED
:
444 int nIndex (GetIndexForToken(rEvent
.maChildToken
));
447 mpPageSet
->SetItemImage (
449 mpContainer
->GetPreviewForToken(rEvent
.maChildToken
));
450 mpPageSet
->Invalidate(mpPageSet
->GetItemRect((USHORT
)nIndex
));
455 case MasterPageContainerChangeEvent::DATA_CHANGED
:
457 InvalidateItem(rEvent
.maChildToken
);
470 MasterPagesSelector::UserData
* MasterPagesSelector::CreateUserData (
472 MasterPageContainer::Token aToken
) const
474 return new UserData(nIndex
,aToken
);
480 MasterPagesSelector::UserData
* MasterPagesSelector::GetUserData (int nIndex
) const
482 const ::osl::MutexGuard
aGuard (maMutex
);
484 if (nIndex
>0 && nIndex
<=mpPageSet
->GetItemCount())
485 return reinterpret_cast<UserData
*>(mpPageSet
->GetItemData((USHORT
)nIndex
));
493 void MasterPagesSelector::SetUserData (int nIndex
, UserData
* pData
)
495 const ::osl::MutexGuard
aGuard (maMutex
);
497 if (nIndex
>0 && nIndex
<=mpPageSet
->GetItemCount())
499 UserData
* pOldData
= GetUserData(nIndex
);
500 if (pOldData
!=NULL
&& pOldData
!=pData
)
502 mpPageSet
->SetItemData((USHORT
)nIndex
, pData
);
509 bool MasterPagesSelector::IsResizable (void)
517 ::Window
* MasterPagesSelector::GetWindow (void)
519 return mpPageSet
.get();
525 sal_Int32
MasterPagesSelector::GetMinimumWidth (void)
527 return mpContainer
->GetPreviewSizePixel().Width() + 2*3;
533 void MasterPagesSelector::UpdateSelection (void)
540 void MasterPagesSelector::Execute (SfxRequest
& rRequest
)
542 switch (rRequest
.GetSlot())
544 case SID_TP_APPLY_TO_ALL_SLIDES
:
545 mrBase
.SetBusyState (true);
546 AssignMasterPageToAllSlides (GetSelectedMasterPage());
547 mrBase
.SetBusyState (false);
550 case SID_TP_APPLY_TO_SELECTED_SLIDES
:
551 mrBase
.SetBusyState (true);
552 AssignMasterPageToSelectedSlides (GetSelectedMasterPage());
553 mrBase
.SetBusyState (false);
556 case SID_TP_USE_FOR_NEW_PRESENTATIONS
:
558 "Using slides as default for new presentations"
559 " is not yet implemented");
562 case SID_TP_SHOW_SMALL_PREVIEW
:
563 case SID_TP_SHOW_LARGE_PREVIEW
:
565 mrBase
.SetBusyState (true);
566 mpContainer
->SetPreviewSize(
567 rRequest
.GetSlot()==SID_TP_SHOW_SMALL_PREVIEW
568 ? MasterPageContainer::SMALL
569 : MasterPageContainer::LARGE
);
570 mrBase
.SetBusyState (false);
574 case SID_TP_EDIT_MASTER
:
576 using namespace ::com::sun::star
;
577 uno::Reference
<drawing::XDrawPage
> xSelectedMaster (
578 GetSelectedMasterPage()->getUnoPage(), uno::UNO_QUERY
);
579 SfxViewFrame
* pViewFrame
= mrBase
.GetViewFrame();
580 if (pViewFrame
!= NULL
&& xSelectedMaster
.is())
582 SfxDispatcher
* pDispatcher
= pViewFrame
->GetDispatcher();
583 if (pDispatcher
!= NULL
)
585 USHORT nIndex
= mpPageSet
->GetSelectItemId();
586 pDispatcher
->Execute(SID_MASTERPAGE
, SFX_CALLMODE_SYNCHRON
);
587 mpPageSet
->SelectItem (nIndex
);
588 mrBase
.GetDrawController().setCurrentPage(xSelectedMaster
);
597 // Cut, copy, and paste are not supported and thus are ignored.
605 void MasterPagesSelector::GetState (SfxItemSet
& rItemSet
)
607 if (mpContainer
->GetPreviewSize() == MasterPageContainer::SMALL
)
608 rItemSet
.DisableItem (SID_TP_SHOW_SMALL_PREVIEW
);
610 rItemSet
.DisableItem (SID_TP_SHOW_LARGE_PREVIEW
);
612 // Cut and paste is not supported so do not show the menu entries.
613 rItemSet
.DisableItem (SID_CUT
);
614 rItemSet
.DisableItem (SID_COPY
);
615 rItemSet
.DisableItem (SID_PASTE
);
621 void MasterPagesSelector::SetItem (
623 MasterPageContainer::Token aToken
)
625 const ::osl::MutexGuard
aGuard (maMutex
);
627 RemoveTokenToIndexEntry(nIndex
,aToken
);
631 if (aToken
!= MasterPageContainer::NIL_TOKEN
)
633 Image
aPreview (mpContainer
->GetPreviewForToken(aToken
));
634 MasterPageContainer::PreviewState
eState (mpContainer
->GetPreviewState(aToken
));
636 if (aPreview
.GetSizePixel().Width()>0)
638 if (mpPageSet
->GetItemPos(nIndex
) != VALUESET_ITEM_NOTFOUND
)
640 mpPageSet
->SetItemImage(nIndex
,aPreview
);
641 mpPageSet
->SetItemText(nIndex
, mpContainer
->GetPageNameForToken(aToken
));
645 mpPageSet
->InsertItem (
648 mpContainer
->GetPageNameForToken(aToken
),
651 SetUserData(nIndex
, CreateUserData(nIndex
,aToken
));
653 AddTokenToIndexEntry(nIndex
,aToken
);
656 if (eState
== MasterPageContainer::PS_CREATABLE
)
657 mpContainer
->RequestPreview(aToken
);
661 mpPageSet
->RemoveItem(nIndex
);
670 void MasterPagesSelector::AddTokenToIndexEntry (
672 MasterPageContainer::Token aToken
)
674 const ::osl::MutexGuard
aGuard (maMutex
);
676 maTokenToValueSetIndex
[aToken
] = nIndex
;
682 void MasterPagesSelector::RemoveTokenToIndexEntry (
684 MasterPageContainer::Token aNewToken
)
686 const ::osl::MutexGuard
aGuard (maMutex
);
688 UserData
* pData
= GetUserData(nIndex
);
691 // Get the token that the index pointed to previously.
692 MasterPageContainer::Token
aOldToken (pData
->second
);
694 if (aNewToken
!= aOldToken
695 && nIndex
== GetIndexForToken(aOldToken
))
697 maTokenToValueSetIndex
[aOldToken
] = 0;
705 void MasterPagesSelector::InvalidatePreview (MasterPageContainer::Token aToken
)
707 const ::osl::MutexGuard
aGuard (maMutex
);
709 int nIndex (GetIndexForToken(aToken
));
712 mpContainer
->InvalidatePreview(aToken
);
713 mpContainer
->RequestPreview(aToken
);
720 void MasterPagesSelector::InvalidatePreview (const SdPage
* pPage
)
722 const ::osl::MutexGuard
aGuard (maMutex
);
724 for (USHORT nIndex
=1; nIndex
<=mpPageSet
->GetItemCount(); nIndex
++)
726 UserData
* pData
= GetUserData(nIndex
);
729 MasterPageContainer::Token
aToken (pData
->second
);
730 if (pPage
== mpContainer
->GetPageObjectForToken(aToken
,false))
732 mpContainer
->InvalidatePreview(aToken
);
733 mpContainer
->RequestPreview(aToken
);
743 void MasterPagesSelector::InvalidateAllPreviews (void)
745 const ::osl::MutexGuard
aGuard (maMutex
);
747 for (USHORT nIndex
=1; nIndex
<=mpPageSet
->GetItemCount(); nIndex
++)
748 InvalidatePreview(nIndex
);
754 void MasterPagesSelector::UpdateAllPreviews (void)
756 const ::osl::MutexGuard
aGuard (maMutex
);
758 for (USHORT nIndex
=1; nIndex
<=mpPageSet
->GetItemCount(); nIndex
++)
760 UserData
* pData
= GetUserData(nIndex
);
763 MasterPageContainer::Token
aToken (pData
->second
);
764 mpPageSet
->SetItemImage(
766 mpContainer
->GetPreviewForToken(aToken
));
767 if (mpContainer
->GetPreviewState(aToken
) == MasterPageContainer::PS_CREATABLE
)
768 mpContainer
->RequestPreview(aToken
);
771 mpPageSet
->Rearrange(true);
777 void MasterPagesSelector::ClearPageSet (void)
779 const ::osl::MutexGuard
aGuard (maMutex
);
781 for (USHORT nIndex
=1; nIndex
<=mpPageSet
->GetItemCount(); nIndex
++)
783 UserData
* pData
= GetUserData(nIndex
);
793 void MasterPagesSelector::SetSmartHelpId( const SmartId
& aId
, SmartIdUpdateMode aMode
)
795 const ::osl::MutexGuard
aGuard (maMutex
);
797 mpPageSet
->SetSmartHelpId( aId
, aMode
);
803 sal_Int32
MasterPagesSelector::GetIndexForToken (MasterPageContainer::Token aToken
) const
805 const ::osl::MutexGuard
aGuard (maMutex
);
807 TokenToValueSetIndex::const_iterator
iIndex (maTokenToValueSetIndex
.find(aToken
));
808 if (iIndex
!= maTokenToValueSetIndex
.end())
809 return iIndex
->second
;
817 void MasterPagesSelector::Clear (void)
819 const ::osl::MutexGuard
aGuard (maMutex
);
827 void MasterPagesSelector::InvalidateItem (MasterPageContainer::Token aToken
)
829 const ::osl::MutexGuard
aGuard (maMutex
);
831 ItemList::iterator iItem
;
832 for (iItem
=maCurrentItemList
.begin(); iItem
!=maCurrentItemList
.end(); ++iItem
)
834 if (*iItem
== aToken
)
836 *iItem
= MasterPageContainer::NIL_TOKEN
;
845 void MasterPagesSelector::UpdateItemList (::std::auto_ptr
<ItemList
> pNewItemList
)
847 const ::osl::MutexGuard
aGuard (maMutex
);
849 ItemList::const_iterator
iNewItem (pNewItemList
->begin());
850 ItemList::const_iterator
iCurrentItem (maCurrentItemList
.begin());
851 ItemList::const_iterator
iNewEnd (pNewItemList
->end());
852 ItemList::const_iterator
iCurrentEnd (maCurrentItemList
.end());
855 // Update existing items.
856 for ( ; iNewItem
!=iNewEnd
&& iCurrentItem
!=iCurrentEnd
; ++iNewItem
, ++iCurrentItem
,++nIndex
)
858 if (*iNewItem
!= *iCurrentItem
)
860 SetItem(nIndex
,*iNewItem
);
865 for ( ; iNewItem
!=iNewEnd
; ++iNewItem
,++nIndex
)
867 SetItem(nIndex
,*iNewItem
);
870 // Remove trailing items.
871 for ( ; iCurrentItem
!=iCurrentEnd
; ++iCurrentItem
,++nIndex
)
873 SetItem(nIndex
,MasterPageContainer::NIL_TOKEN
);
876 maCurrentItemList
.swap(*pNewItemList
);
878 mpPageSet
->Rearrange();
879 if (GetParentNode() != NULL
)
880 GetParentNode()->RequestResize();
887 } } } // end of namespace ::sd::toolpanel::controls