/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <config_features.h>
#include <com/sun/star/frame/theAutoRecovery.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/drawing/XMasterPageTarget.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/awt/SystemPointer.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/presentation/SlideShow.hpp>
#include <o3tl/clamp.hxx>
#include <svl/aeitem.hxx>
#include <svl/urihelper.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/request.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/app.hxx>
#include <svx/unoapi.hxx>
#include <svx/svdoole2.hxx>
#include <sfx2/templdlg.hxx>
#include <svx/f3dchild.hxx>
#include <svx/imapdlg.hxx>
#include <svx/fontwork.hxx>
#include <svx/SvxColorChildWindow.hxx>
#include <svx/bmpmask.hxx>
#include <svx/srchdlg.hxx>
#include <svx/hyperdlg.hxx>
#include <AnimationChildWindow.hxx>
#include <notifydocumentevent.hxx>
#include "slideshowimpl.hxx"
#include "slideshowviewimpl.hxx"
#include <pgjump.hxx>
#include "PaneHider.hxx"
#include <bitmaps.hlst>
#include <vcl/canvastools.hxx>
#include <vcl/commandinfoprovider.hxx>
#include <vcl/settings.hxx>
#include <comphelper/anytostring.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <rtl/ref.hxx>
#include <sal/log.hxx>
#include <canvas/elapsedtime.hxx>
#include <avmedia/mediawindow.hxx>
#include <svtools/colrdlg.hxx>
#include <RemoteServer.hxx>
#include <customshowlist.hxx>
#include <unopage.hxx>
#include <sdpage.hxx>
#define CM_SLIDES 21
using ::com::sun::star::animations::XAnimationNode;
using ::com::sun::star::animations::XAnimationListener;
using ::com::sun::star::awt::XWindow;
using namespace ::com::sun::star;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::presentation;
using namespace ::com::sun::star::beans;
namespace sd
{
/** Slots, which will be disabled in the slide show and are managed by Sfx.
Have to be sorted in the order of the SIDs */
static sal_uInt16 const pAllowed[] =
{
SID_OPENDOC , // 5501 ///< that internally jumps work
SID_JUMPTOMARK , // 5598
SID_OPENHYPERLINK , // 6676
SID_PRESENTATION_END // 27218
};
class AnimationSlideController
{
public:
enum Mode { ALL, FROM, CUSTOM, PREVIEW };
public:
AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode );
void setStartSlideNumber( sal_Int32 nSlideNumber ) { mnStartSlideNumber = nSlideNumber; }
sal_Int32 getStartSlideIndex() const;
sal_Int32 getCurrentSlideNumber() const;
sal_Int32 getCurrentSlideIndex() const;
sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); }
sal_Int32 getSlideNumberCount() const { return mnSlideCount; }
sal_Int32 getSlideNumber( sal_Int32 nSlideIndex ) const;
void insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible = true );
void setPreviewNode( const Reference< XAnimationNode >& xPreviewNode );
bool jumpToSlideIndex( sal_Int32 nNewSlideIndex );
bool jumpToSlideNumber( sal_Int32 nNewSlideIndex );
bool nextSlide();
bool previousSlide();
void displayCurrentSlide( const Reference< XSlideShow >& xShow,
const Reference< XDrawPagesSupplier>& xDrawPages,
const bool bSkipAllMainSequenceEffects );
sal_Int32 getNextSlideIndex() const;
sal_Int32 getPreviousSlideIndex() const;
bool isVisibleSlideNumber( sal_Int32 nSlideNumber ) const;
Reference< XDrawPage > getSlideByNumber( sal_Int32 nSlideNumber ) const;
sal_Int32 getNextSlideNumber() const;
bool hasSlides() const { return !maSlideNumbers.empty(); }
private:
bool getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode );
sal_Int32 findSlideIndex( sal_Int32 nSlideNumber ) const;
bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (nIndex < static_cast<sal_Int32>(maSlideNumbers.size())); }
bool isValidSlideNumber( sal_Int32 nSlideNumber ) const { return (nSlideNumber >= 0) && (nSlideNumber < mnSlideCount); }
private:
Mode meMode;
sal_Int32 mnStartSlideNumber;
std::vector< sal_Int32 > maSlideNumbers;
std::vector< bool > maSlideVisible;
std::vector< bool > maSlideVisited;
Reference< XAnimationNode > mxPreviewNode;
sal_Int32 mnSlideCount;
sal_Int32 mnCurrentSlideIndex;
sal_Int32 mnHiddenSlideNumber;
Reference< XIndexAccess > mxSlides;
};
Reference< XDrawPage > AnimationSlideController::getSlideByNumber( sal_Int32 nSlideNumber ) const
{
Reference< XDrawPage > xSlide;
if( mxSlides.is() && (nSlideNumber >= 0) && (nSlideNumber < mxSlides->getCount()) )
mxSlides->getByIndex( nSlideNumber ) >>= xSlide;
return xSlide;
}
bool AnimationSlideController::isVisibleSlideNumber( sal_Int32 nSlideNumber ) const
{
sal_Int32 nIndex = findSlideIndex( nSlideNumber );
if( nIndex != -1 )
return maSlideVisible[ nIndex ];
else
return false;
}
void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode )
{
mxPreviewNode = xPreviewNode;
}
AnimationSlideController::AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode )
: meMode( eMode )
, mnStartSlideNumber(-1)
, mnSlideCount( 0 )
, mnCurrentSlideIndex(0)
, mnHiddenSlideNumber( -1 )
, mxSlides( xSlides )
{
if( mxSlides.is() )
mnSlideCount = xSlides->getCount();
}
sal_Int32 AnimationSlideController::getStartSlideIndex() const
{
if( mnStartSlideNumber >= 0 )
{
sal_Int32 nIndex;
const sal_Int32 nCount = maSlideNumbers.size();
for( nIndex = 0; nIndex < nCount; nIndex++ )
{
if( maSlideNumbers[nIndex] == mnStartSlideNumber )
return nIndex;
}
}
return 0;
}
sal_Int32 AnimationSlideController::getCurrentSlideNumber() const
{
if( mnHiddenSlideNumber != -1 )
return mnHiddenSlideNumber;
else if( !maSlideNumbers.empty() )
return maSlideNumbers[mnCurrentSlideIndex];
else
return 0;
}
sal_Int32 AnimationSlideController::getCurrentSlideIndex() const
{
if( mnHiddenSlideNumber != -1 )
return -1;
else
return mnCurrentSlideIndex;
}
bool AnimationSlideController::jumpToSlideIndex( sal_Int32 nNewSlideIndex )
{
if( isValidIndex( nNewSlideIndex ) )
{
mnCurrentSlideIndex = nNewSlideIndex;
mnHiddenSlideNumber = -1;
maSlideVisited[mnCurrentSlideIndex] = true;
return true;
}
else
{
return false;
}
}
bool AnimationSlideController::jumpToSlideNumber( sal_Int32 nNewSlideNumber )
{
sal_Int32 nIndex = findSlideIndex( nNewSlideNumber );
if( isValidIndex( nIndex ) )
{
return jumpToSlideIndex( nIndex );
}
else if( (nNewSlideNumber >= 0) && (nNewSlideNumber < mnSlideCount) )
{
// jump to a hidden slide
mnHiddenSlideNumber = nNewSlideNumber;
return true;
}
else
{
return false;
}
}
sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const
{
if( isValidIndex( nSlideIndex ) )
return maSlideNumbers[nSlideIndex];
else
return -1;
}
void AnimationSlideController::insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible /* = true */ )
{
DBG_ASSERT( isValidSlideNumber( nSlideNumber ), "sd::AnimationSlideController::insertSlideNumber(), illegal index" );
if( isValidSlideNumber( nSlideNumber ) )
{
maSlideNumbers.push_back( nSlideNumber );
maSlideVisible.push_back( bVisible );
maSlideVisited.push_back( false );
}
}
bool AnimationSlideController::getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode )
{
if( isValidSlideNumber( nSlideNumber ) ) try
{
xSlide.set( mxSlides->getByIndex(nSlideNumber), UNO_QUERY_THROW );
if( meMode == PREVIEW )
{
xAnimNode = mxPreviewNode;
}
else
{
Reference< animations::XAnimationNodeSupplier > xAnimNodeSupplier( xSlide, UNO_QUERY_THROW );
xAnimNode = xAnimNodeSupplier->getAnimationNode();
}
return true;
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::AnimationSlideController::getSlideAPI(), "
"exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
return false;
}
sal_Int32 AnimationSlideController::findSlideIndex( sal_Int32 nSlideNumber ) const
{
sal_Int32 nIndex;
const sal_Int32 nCount = maSlideNumbers.size();
for( nIndex = 0; nIndex < nCount; nIndex++ )
{
if( maSlideNumbers[nIndex] == nSlideNumber )
return nIndex;
}
return -1;
}
sal_Int32 AnimationSlideController::getNextSlideIndex() const
{
switch( meMode )
{
case ALL:
{
sal_Int32 nNewSlideIndex = mnCurrentSlideIndex + 1;
if( isValidIndex( nNewSlideIndex ) )
{
// if the current slide is not excluded, make sure the
// next slide is also not excluded.
// if the current slide is excluded, we want to go
// to the next slide, even if this is also excluded.
if( maSlideVisible[mnCurrentSlideIndex] )
{
while( isValidIndex( nNewSlideIndex ) )
{
if( maSlideVisible[nNewSlideIndex] )
break;
nNewSlideIndex++;
}
}
}
return isValidIndex( nNewSlideIndex ) ? nNewSlideIndex : -1;
}
case FROM:
case CUSTOM:
return mnHiddenSlideNumber == -1 ? mnCurrentSlideIndex + 1 : mnCurrentSlideIndex;
default:
case PREVIEW:
return -1;
}
}
sal_Int32 AnimationSlideController::getNextSlideNumber() const
{
sal_Int32 nNextSlideIndex = getNextSlideIndex();
if( isValidIndex( nNextSlideIndex ) )
{
return maSlideNumbers[nNextSlideIndex];
}
else
{
return -1;
}
}
bool AnimationSlideController::nextSlide()
{
return jumpToSlideIndex( getNextSlideIndex() );
}
sal_Int32 AnimationSlideController::getPreviousSlideIndex() const
{
sal_Int32 nNewSlideIndex = mnCurrentSlideIndex - 1;
switch( meMode )
{
case ALL:
{
// make sure the previous slide is visible
// or was already visited
while( isValidIndex( nNewSlideIndex ) )
{
if( maSlideVisible[nNewSlideIndex] || maSlideVisited[nNewSlideIndex] )
break;
nNewSlideIndex--;
}
break;
}
case PREVIEW:
return -1;
default:
break;
}
return nNewSlideIndex;
}
bool AnimationSlideController::previousSlide()
{
return jumpToSlideIndex( getPreviousSlideIndex() );
}
void AnimationSlideController::displayCurrentSlide( const Reference< XSlideShow >& xShow,
const Reference< XDrawPagesSupplier>& xDrawPages,
const bool bSkipAllMainSequenceEffects )
{
const sal_Int32 nCurrentSlideNumber = getCurrentSlideNumber();
if( xShow.is() && (nCurrentSlideNumber != -1 ) )
{
Reference< XDrawPage > xSlide;
Reference< XAnimationNode > xAnimNode;
::std::vector<PropertyValue> aProperties;
const sal_Int32 nNextSlideNumber = getNextSlideNumber();
if( getSlideAPI( nNextSlideNumber, xSlide, xAnimNode ) )
{
Sequence< Any > aValue(2);
aValue[0] <<= xSlide;
aValue[1] <<= xAnimNode;
aProperties.emplace_back( "Prefetch" ,
-1,
Any(aValue),
PropertyState_DIRECT_VALUE);
}
if (bSkipAllMainSequenceEffects)
{
// Add one property that prevents the slide transition from being
// shown (to speed up the transition to the previous slide) and
// one to show all main sequence effects so that the user can
// continue to undo effects.
aProperties.emplace_back( "SkipAllMainSequenceEffects",
-1,
Any(true),
PropertyState_DIRECT_VALUE);
aProperties.emplace_back("SkipSlideTransition",
-1,
Any(true),
PropertyState_DIRECT_VALUE);
}
if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) )
xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) );
}
}
SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow )
: SlideshowImplBase( m_aMutex )
, mxModel(pDoc->getUnoModel(),UNO_QUERY_THROW)
, mpView(pView)
, mpViewShell(pViewSh)
, mpDocSh(pDoc->GetDocSh())
, mpDoc(pDoc)
, mpParentWindow(pParentWindow)
, mpShowWindow(nullptr)
, mpTimeButton(nullptr)
, mnRestoreSlide(0)
, maPresSize( -1, -1 )
, meAnimationMode(ANIMATIONMODE_SHOW)
, mpOldActiveWindow(nullptr)
, mnChildMask( 0 )
, mbDisposed(false)
, mbAutoSaveWasOn(false)
, mbRehearseTimings(false)
, mbIsPaused(false)
, mbWasPaused(false)
, mbInputFreeze(false)
, mbActive(false)
, maPresSettings( pDoc->getPresentationSettings() )
, mnUserPaintColor( 0x80ff0000L )
, mbUsePen(false)
, mdUserPaintStrokeWidth ( 150.0 )
, msOnClick( "OnClick" )
, msBookmark( "Bookmark" )
, msVerb( "Verb" )
, mnEndShowEvent(nullptr)
, mnContextMenuEvent(nullptr)
, mxPresentation( xPresentation )
{
if( mpViewShell )
mpOldActiveWindow = mpViewShell->GetActiveWindow();
maUpdateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, updateHdl));
// Priority must not be too high or we'll starve input handling etc.
maUpdateTimer.SetPriority(TaskPriority::REPAINT);
maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl));
maDeactivateTimer.SetTimeout( 20 );
maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) );
maInputFreezeTimer.SetTimeout( 20 );
SvtSaveOptions aOptions;
// no autosave during show
if( aOptions.IsAutoSave() )
mbAutoSaveWasOn = true;
Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
mbUsePen = maPresSettings.mbMouseAsPen;
SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
if( pOptions )
{
mnUserPaintColor = pOptions->GetPresentationPenColor();
mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
}
}
SlideshowImpl::~SlideshowImpl()
{
SdModule *pModule = SD_MOD();
//rhbz#806663 SlideshowImpl can outlive SdModule
SdOptions* pOptions = pModule ?
pModule->GetSdOptions(DocumentType::Impress) : nullptr;
if( pOptions )
{
pOptions->SetPresentationPenColor(mnUserPaintColor);
pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth);
}
Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
maDeactivateTimer.Stop();
if( !mbDisposed )
{
OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!");
disposing();
}
}
void SAL_CALL SlideshowImpl::disposing()
{
#ifdef ENABLE_SDREMOTE
RemoteServer::presentationStopped();
#endif
if( mxShow.is() && mpDoc )
NotifyDocumentEvent(
*mpDoc,
"OnEndPresentation" );
if( mbAutoSaveWasOn )
setAutoSaveState( true );
if( mnEndShowEvent )
Application::RemoveUserEvent( mnEndShowEvent );
if( mnContextMenuEvent )
Application::RemoveUserEvent( mnContextMenuEvent );
maInputFreezeTimer.Stop();
SolarMutexGuard aSolarGuard;
if( !mxShow.is() )
return;
if( mxPresentation.is() )
mxPresentation->end();
maUpdateTimer.Stop();
removeShapeEvents();
if( mxListenerProxy.is() )
mxListenerProxy->removeAsSlideShowListener();
try
{
if( mxView.is() )
mxShow->removeView( mxView.get() );
Reference< XComponent > xComponent( mxShow, UNO_QUERY );
if( xComponent.is() )
xComponent->dispose();
if( mxView.is() )
mxView->dispose();
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::stop(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
mxShow.clear();
mxView.clear();
mxListenerProxy.clear();
mpSlideController.reset();
// take DrawView from presentation window, but give the old window back
if( mpShowWindow && mpView )
mpView->DeleteWindowFromPaintView( mpShowWindow );
if( mpView )
mpView->SetAnimationPause( false );
if( mpViewShell )
{
mpViewShell->SetActiveWindow(mpOldActiveWindow);
if (mpShowWindow)
mpShowWindow->SetViewShell( nullptr );
}
if( mpView )
mpView->InvalidateAllWin();
if( maPresSettings.mbFullScreen )
{
#if HAVE_FEATURE_SCRIPTING
// restore StarBASICErrorHdl
StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl);
maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>();
#endif
}
else
{
if( mpShowWindow )
mpShowWindow->Hide();
}
if( meAnimationMode == ANIMATIONMODE_SHOW )
{
mpDocSh->SetSlotFilter();
mpDocSh->ApplySlotFilter();
Help::EnableContextHelp();
Help::EnableExtHelp();
showChildWindows();
mnChildMask = 0;
}
// show current window again
if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) == nullptr)
{
if( meAnimationMode == ANIMATIONMODE_SHOW )
{
mpViewShell->GetViewShellBase().ShowUIControls (true);
mpPaneHider.reset();
}
else if( meAnimationMode == ANIMATIONMODE_PREVIEW )
{
mpViewShell->ShowUIControls(true);
}
}
if( mpTimeButton )
mpTimeButton->Hide();
mpTimeButton.disposeAndClear();
if( mpShowWindow )
mpShowWindow->Hide();
mpShowWindow.disposeAndClear();
if ( mpViewShell )
{
if( meAnimationMode == ANIMATIONMODE_SHOW )
{
::sd::Window* pActWin = mpViewShell->GetActiveWindow();
if (pActWin)
{
Size aVisSizePixel = pActWin->GetOutputSizePixel();
::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
mpViewShell->VisAreaChanged(aVisAreaWin);
if (mpView)
mpView->VisAreaChanged(pActWin);
pActWin->GrabFocus();
}
}
// restart the custom show dialog if he started us
if( mpViewShell->IsStartShowWithDialog() && getDispatcher() )
{
mpViewShell->SetStartShowWithDialog( false );
getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
}
mpViewShell->GetViewShellBase().UpdateBorder(true);
}
if( mpShowWindow )
{
mpShowWindow.disposeAndClear();
}
setActiveXToolbarsVisible( true );
mbDisposed = true;
}
bool SlideshowImpl::startPreview(
const Reference< XDrawPage >& xDrawPage,
const Reference< XAnimationNode >& xAnimationNode,
vcl::Window * pParent )
{
bool bRet = false;
try
{
const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY );
if (xServiceInfo.is()) {
const Sequence<OUString> supportedServices(
xServiceInfo->getSupportedServiceNames() );
for ( sal_Int32 pos = supportedServices.getLength(); pos--; ) {
if ( supportedServices[pos] == "com.sun.star.drawing.MasterPage" ) {
OSL_FAIL("sd::SlideshowImpl::startPreview() "
"not allowed on master page!");
return false;
}
}
}
mxPreviewDrawPage = xDrawPage;
mxPreviewAnimationNode = xAnimationNode;
meAnimationMode = ANIMATIONMODE_PREVIEW;
maPresSettings.mbAll = false;
maPresSettings.mbEndless = false;
maPresSettings.mbCustomShow = false;
maPresSettings.mbManual = false;
maPresSettings.mbMouseVisible = false;
maPresSettings.mbMouseAsPen = false;
maPresSettings.mbLockedPages = false;
maPresSettings.mbAlwaysOnTop = false;
maPresSettings.mbFullScreen = false;
maPresSettings.mbAnimationAllowed = true;
maPresSettings.mnPauseTimeout = 0;
maPresSettings.mbShowPauseLogo = false;
Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
mpSlideController.reset( new AnimationSlideController( xSlides, AnimationSlideController::PREVIEW ) );
sal_Int32 nSlideNumber = 0;
Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW );
xSet->getPropertyValue( "Number" ) >>= nSlideNumber;
mpSlideController->insertSlideNumber( nSlideNumber-1 );
mpSlideController->setPreviewNode( xAnimationNode );
mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ? mpParentWindow.get() : pParent );
if( mpViewShell )
{
mpViewShell->SetActiveWindow( mpShowWindow );
mpShowWindow->SetViewShell (mpViewShell);
mpViewShell->ShowUIControls (false);
}
if( mpView )
{
mpView->AddWindowToPaintView( mpShowWindow, nullptr );
mpView->SetAnimationPause( true );
}
// call resize handler
if( pParent )
{
maPresSize = pParent->GetSizePixel();
}
else if( mpViewShell )
{
::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle());
if (AllSettings::GetLayoutRTL())
{
aContentRect.SetLeft( aContentRect.Right() );
aContentRect.AdjustRight(aContentRect.Right() );
}
maPresSize = aContentRect.GetSize();
mpShowWindow->SetPosPixel( aContentRect.TopLeft() );
}
else
{
OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!");
}
resize( maPresSize );
sal_Int32 nPropertyCount = 1;
if( mxPreviewAnimationNode.is() )
nPropertyCount++;
Sequence< beans::PropertyValue > aProperties(nPropertyCount);
aProperties[0].Name = "AutomaticAdvancement";
aProperties[0].Value <<= 1.0; // one second timeout
if( mxPreviewAnimationNode.is() )
{
aProperties[1].Name = "NoSlideTransitions";
aProperties[1].Value <<= true;
}
bRet = startShowImpl( aProperties );
if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW )
mpShowWindow->SetPreviewMode();
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::startPreview(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
bRet = false;
}
return bRet;
}
bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings )
{
const rtl::Reference<SlideshowImpl> this_(this);
DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" );
if( mxShow.is() )
return true;
DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" );
if (mpParentWindow == nullptr)
return false;
// Autoplay (pps/ppsx)
if (mpViewShell->GetDoc()->IsStartWithPresentation()){
mpViewShell->GetDoc()->SetExitAfterPresenting(true);
}
bool bRet = false;
try
{
if( pPresSettings )
{
maPresSettings = *pPresSettings;
mbRehearseTimings = pPresSettings->mbRehearseTimings;
}
OUString aPresSlide( maPresSettings.maPresPage );
SdPage* pStartPage = mpViewShell->GetActualPage();
bool bStartWithActualSlide = pStartPage;
// times should be measured?
if( mbRehearseTimings )
{
maPresSettings.mbEndless = false;
maPresSettings.mbManual = true;
maPresSettings.mbMouseVisible = true;
maPresSettings.mbMouseAsPen = false;
maPresSettings.mnPauseTimeout = 0;
maPresSettings.mbShowPauseLogo = false;
}
if( pStartPage )
{
if( pStartPage->GetPageKind() == PageKind::Notes )
{
// we are in notes page mode, so get
// the corresponding draw page
const sal_uInt16 nPgNum = ( pStartPage->GetPageNum() - 2 ) >> 1;
pStartPage = mpDoc->GetSdPage( nPgNum, PageKind::Standard );
}
}
if( bStartWithActualSlide )
{
if ( aPresSlide.isEmpty())
{
// no preset slide yet, so pick current on one
aPresSlide = pStartPage->GetName();
// if the starting slide is hidden, we can't set slide controller to ALL mode
maPresSettings.mbAll = !pStartPage->IsExcluded();
}
if( meAnimationMode != ANIMATIONMODE_SHOW )
{
if( pStartPage->GetPageKind() == PageKind::Standard )
{
maPresSettings.mbAll = false;
}
}
}
// build page list
createSlideList( maPresSettings.mbAll, aPresSlide );
// remember Slide number from where the show was started
if( pStartPage )
mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2;
if( mpSlideController->hasSlides() )
{
// hide child windows
hideChildWindows();
mpShowWindow = VclPtr<ShowWindow>::Create( this, mpParentWindow );
mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
mpViewShell->SetActiveWindow( mpShowWindow );
mpShowWindow->SetViewShell (mpViewShell);
mpViewShell->GetViewShellBase().ShowUIControls (false);
// Hide the side panes for in-place presentations.
if ( ! maPresSettings.mbFullScreen)
mpPaneHider.reset(new PaneHider(*mpViewShell,this));
// these Slots are forbidden in other views for this document
if( mpDocSh )
{
mpDocSh->SetSlotFilter( true, pAllowed );
mpDocSh->ApplySlotFilter();
}
Help::DisableContextHelp();
Help::DisableExtHelp();
if( maPresSettings.mbFullScreen )
{
#if HAVE_FEATURE_SCRIPTING
// disable basic ide error handling
maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl();
StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() );
#endif
}
// call resize handler
maPresSize = mpParentWindow->GetSizePixel();
if (!maPresSettings.mbFullScreen)
{
const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle();
maPresSize = aClientRect.GetSize();
mpShowWindow->SetPosPixel( aClientRect.TopLeft() );
resize( maPresSize );
}
// #i41824#
// Note: In FullScreen Mode the OS (window manager) sends a resize to
// the WorkWindow once it actually resized it to full size. The
// WorkWindow propagates the resize to the DrawViewShell which calls
// resize() at the SlideShow (this). Calling resize here results in a
// temporary display of a black window in the window's default size
if( mpView )
{
mpView->AddWindowToPaintView( mpShowWindow, nullptr );
mpView->SetAnimationPause( true );
}
SfxBindings* pBindings = getBindings();
if( pBindings )
{
pBindings->Invalidate( SID_PRESENTATION );
pBindings->Invalidate( SID_REHEARSE_TIMINGS );
}
// Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly.
//mpShowWindow->GrabFocus();
std::vector<beans::PropertyValue> aProperties;
aProperties.reserve( 4 );
aProperties.emplace_back( "AdvanceOnClick" ,
-1, Any( !maPresSettings.mbLockedPages ),
beans::PropertyState_DIRECT_VALUE );
aProperties.emplace_back( "ImageAnimationsAllowed" ,
-1, Any( maPresSettings.mbAnimationAllowed ),
beans::PropertyState_DIRECT_VALUE );
const bool bZOrderEnabled(
SD_MOD()->GetSdOptions( mpDoc->GetDocumentType() )->IsSlideshowRespectZOrder() );
aProperties.emplace_back( "DisableAnimationZOrder" ,
-1, Any( !bZOrderEnabled ),
beans::PropertyState_DIRECT_VALUE );
aProperties.emplace_back( "ForceManualAdvance" ,
-1, Any( maPresSettings.mbManual ),
beans::PropertyState_DIRECT_VALUE );
if( mbUsePen )
{
aProperties.emplace_back( "UserPaintColor" ,
// User paint color is black by default.
-1, Any( mnUserPaintColor ),
beans::PropertyState_DIRECT_VALUE );
aProperties.emplace_back( "UserPaintStrokeWidth" ,
// User paint color is black by default.
-1, Any( mdUserPaintStrokeWidth ),
beans::PropertyState_DIRECT_VALUE );
}
if (mbRehearseTimings) {
aProperties.emplace_back( "RehearseTimings" ,
-1, Any(true), beans::PropertyState_DIRECT_VALUE );
}
bRet = startShowImpl( Sequence<beans::PropertyValue>(
&aProperties[0], aProperties.size() ) );
}
setActiveXToolbarsVisible( false );
}
catch (const Exception&)
{
SAL_WARN( "sd", "sd::SlideshowImpl::startShow(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
bRet = false;
}
return bRet;
}
bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties )
{
try
{
mxShow.set( createSlideShow(), UNO_QUERY_THROW );
mxView = new SlideShowView(
*mpShowWindow,
mpDoc,
meAnimationMode,
this,
maPresSettings.mbFullScreen);
// try add wait symbol to properties:
const Reference<rendering::XSpriteCanvas> xSpriteCanvas(
mxView->getCanvas() );
if (xSpriteCanvas.is())
{
BitmapEx waitSymbolBitmap(BMP_WAIT_ICON);
const Reference<rendering::XBitmap> xBitmap(
vcl::unotools::xBitmapFromBitmapEx( waitSymbolBitmap ) );
if (xBitmap.is())
{
mxShow->setProperty(
beans::PropertyValue( "WaitSymbolBitmap" ,
-1,
makeAny( xBitmap ),
beans::PropertyState_DIRECT_VALUE ) );
}
BitmapEx pointerSymbolBitmap(BMP_POINTER_ICON);
const Reference<rendering::XBitmap> xPointerBitmap(
vcl::unotools::xBitmapFromBitmapEx( pointerSymbolBitmap ) );
if (xPointerBitmap.is())
{
mxShow->setProperty(
beans::PropertyValue( "PointerSymbolBitmap" ,
-1,
makeAny( xPointerBitmap ),
beans::PropertyState_DIRECT_VALUE ) );
}
}
const sal_Int32 nCount = aProperties.getLength();
sal_Int32 nIndex;
for( nIndex = 0; nIndex < nCount; nIndex++ )
mxShow->setProperty( aProperties[nIndex] );
mxShow->addView( mxView.get() );
mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) );
mxListenerProxy->addAsSlideShowListener();
NotifyDocumentEvent(
*mpDoc,
"OnStartPresentation");
displaySlideIndex( mpSlideController->getStartSlideIndex() );
return true;
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::startShowImpl(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
return false;
}
}
/** called only by the slideshow view when the first paint event occurs.
This actually starts the slideshow. */
void SlideshowImpl::onFirstPaint()
{
if( mpShowWindow )
{
/*
mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) );
mpShowWindow->Erase();
mpShowWindow->SetBackground();
*/
}
SolarMutexGuard aSolarGuard;
maUpdateTimer.SetTimeout( sal_uLong(100) );
maUpdateTimer.Start();
}
void SlideshowImpl::paint()
{
if( mxView.is() ) try
{
awt::PaintEvent aEvt;
// aEvt.UpdateRect = TODO
mxView->paint( aEvt );
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::paint(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener )
{
if( mxListenerProxy.is() )
mxListenerProxy->addSlideShowListener( xListener );
}
void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener )
{
if( mxListenerProxy.is() )
mxListenerProxy->removeSlideShowListener( xListener );
}
void SlideshowImpl::slideEnded(const bool bReverse)
{
if (bReverse)
gotoPreviousSlide(true);
else
gotoNextSlide();
}
bool SlideshowImpl::swipe(const CommandSwipeData &rSwipeData)
{
if (mbUsePen || mnContextMenuEvent)
return false;
double nVelocityX = rSwipeData.getVelocityX();
// tdf#108475 make it swipe only if some reasonable movement was involved
if (fabs(nVelocityX) < 50)
return false;
if (nVelocityX > 0)
{
gotoPreviousSlide();
}
else
{
gotoNextEffect();
}
//a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
//to the swipe instead
mxView->ignoreNextMouseReleased();
return true;
}
bool SlideshowImpl::longpress(const CommandLongPressData &rLongPressData)
{
if (mnContextMenuEvent)
return false;
maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY());
mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
return true;
}
void SlideshowImpl::removeShapeEvents()
{
if( mxShow.is() && mxListenerProxy.is() ) try
{
WrappedShapeEventImplMap::iterator aIter;
const WrappedShapeEventImplMap::iterator aEnd( maShapeEventMap.end() );
for( aIter = maShapeEventMap.begin(); aIter != aEnd; ++aIter )
{
mxListenerProxy->removeShapeEventListener( (*aIter).first );
mxShow->setShapeCursor( (*aIter).first, awt::SystemPointer::ARROW );
}
maShapeEventMap.clear();
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::removeShapeEvents(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber)
{
if( nSlideNumber >= 0 ) try
{
Reference< XDrawPagesSupplier > xDrawPages( mxModel, UNO_QUERY_THROW );
Reference< XIndexAccess > xPages( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
Reference< XShapes > xDrawPage;
xPages->getByIndex(nSlideNumber) >>= xDrawPage;
if( xDrawPage.is() )
{
Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
if( xMasterPageTarget.is() )
{
Reference< XShapes > xMasterPage( xMasterPageTarget->getMasterPage(), UNO_QUERY );
if( xMasterPage.is() )
registerShapeEvents( xMasterPage );
}
registerShapeEvents( xDrawPage );
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::registerShapeEvents(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes )
{
try
{
const sal_Int32 nShapeCount = xShapes->getCount();
sal_Int32 nShape;
for( nShape = 0; nShape < nShapeCount; nShape++ )
{
Reference< XShape > xShape;
xShapes->getByIndex( nShape ) >>= xShape;
if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
{
Reference< XShapes > xSubShapes( xShape, UNO_QUERY );
if( xSubShapes.is() )
registerShapeEvents( xSubShapes );
}
Reference< XPropertySet > xSet( xShape, UNO_QUERY );
if( !xSet.is() )
continue;
Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( msOnClick ) )
continue;
WrappedShapeEventImplPtr pEvent( new WrappedShapeEventImpl );
xSet->getPropertyValue( msOnClick ) >>= pEvent->meClickAction;
switch( pEvent->meClickAction )
{
case ClickAction_PREVPAGE:
case ClickAction_NEXTPAGE:
case ClickAction_FIRSTPAGE:
case ClickAction_LASTPAGE:
case ClickAction_STOPPRESENTATION:
break;
case ClickAction_BOOKMARK:
if( xSetInfo->hasPropertyByName( msBookmark ) )
xSet->getPropertyValue( msBookmark ) >>= pEvent->maStrBookmark;
if( getSlideNumberForBookmark( pEvent->maStrBookmark ) == -1 )
continue;
break;
case ClickAction_DOCUMENT:
case ClickAction_SOUND:
case ClickAction_PROGRAM:
case ClickAction_MACRO:
if( xSetInfo->hasPropertyByName( msBookmark ) )
xSet->getPropertyValue( msBookmark ) >>= pEvent->maStrBookmark;
break;
case ClickAction_VERB:
if( xSetInfo->hasPropertyByName( msVerb ) )
xSet->getPropertyValue( msVerb ) >>= pEvent->mnVerb;
break;
default:
continue; // skip all others
}
maShapeEventMap[ xShape ] = pEvent;
if( mxListenerProxy.is() )
mxListenerProxy->addShapeEventListener( xShape );
mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND );
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::registerShapeEvents(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects)
{
stopSound();
removeShapeEvents();
if( mpSlideController.get() && mxShow.is() )
{
Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(),
UNO_QUERY_THROW );
mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects );
registerShapeEvents(mpSlideController->getCurrentSlideNumber());
update();
}
// send out page change event and notify to update all acc info for current page
if (mpViewShell)
{
sal_Int32 currentPageIndex = getCurrentSlideIndex();
mpViewShell->fireSwitchCurrentPage(currentPageIndex);
mpViewShell->NotifyAccUpdate();
}
}
void SlideshowImpl::endPresentation()
{
if( maPresSettings.mbMouseAsPen)
{
Reference< XMultiServiceFactory > xDocFactory(mpDoc->getUnoModel(), UNO_QUERY );
if( xDocFactory.is() )
mxShow->registerUserPaintPolygons(xDocFactory);
}
if( !mnEndShowEvent )
mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) );
}
IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void)
{
mnEndShowEvent = nullptr;
if( mxPresentation.is() )
mxPresentation->end();
}
void SAL_CALL SlideshowImpl::pause()
{
SolarMutexGuard aSolarGuard;
if( !mbIsPaused ) try
{
mbIsPaused = true;
if( mxShow.is() )
{
mxShow->pause(true);
if( mxListenerProxy.is() )
mxListenerProxy->paused();
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::pause(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SAL_CALL SlideshowImpl::resume()
{
SolarMutexGuard aSolarGuard;
if( mbIsPaused ) try
{
if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
{
mpShowWindow->RestartShow();
}
else
{
mbIsPaused = false;
if( mxShow.is() )
{
mxShow->pause(false);
update();
if( mxListenerProxy.is() )
mxListenerProxy->resumed();
}
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::resume(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
#ifdef ENABLE_SDREMOTE
RemoteServer::presentationStarted( this );
#endif
}
sal_Bool SAL_CALL SlideshowImpl::isPaused()
{
SolarMutexGuard aSolarGuard;
return mbIsPaused;
}
void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor )
{
SolarMutexGuard aSolarGuard;
if( mpShowWindow && mpSlideController )
{
if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(nColor) ) )
{
pause();
}
}
}
// XShapeEventListener
void SlideshowImpl::click( const Reference< XShape >& xShape )
{
SolarMutexGuard aSolarGuard;
WrappedShapeEventImplPtr pEvent = maShapeEventMap[xShape];
if( !pEvent.get() )
return;
switch( pEvent->meClickAction )
{
case ClickAction_PREVPAGE: gotoPreviousSlide(); break;
case ClickAction_NEXTPAGE: gotoNextSlide(); break;
case ClickAction_FIRSTPAGE: gotoFirstSlide(); break;
case ClickAction_LASTPAGE: gotoLastSlide(); break;
case ClickAction_STOPPRESENTATION: endPresentation(); break;
case ClickAction_BOOKMARK:
{
gotoBookmark( pEvent->maStrBookmark );
}
break;
case ClickAction_SOUND:
{
#if HAVE_FEATURE_AVMEDIA
try
{
mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, ""/*TODO?*/), uno::UNO_QUERY_THROW );
mxPlayer->start();
}
catch( uno::Exception& )
{
OSL_FAIL("sd::SlideshowImpl::click(), exception caught!" );
}
#endif
}
break;
case ClickAction_DOCUMENT:
{
OUString aBookmark( pEvent->maStrBookmark );
sal_Int32 nPos = aBookmark.indexOf( '#' );
if( nPos >= 0 )
{
OUString aURL( aBookmark.copy( 0, nPos+1 ) );
OUString aName( aBookmark.copy( nPos+1 ) );
aURL += getUiNameFromPageApiNameImpl( aName );
aBookmark = aURL;
}
mpDocSh->OpenBookmark( aBookmark );
}
break;
case ClickAction_PROGRAM:
{
INetURLObject aURL(
::URIHelper::SmartRel2Abs(
INetURLObject(mpDocSh->GetMedium()->GetBaseURL()),
pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true,
false, INetURLObject::EncodeMechanism::WasEncoded,
INetURLObject::DecodeMechanism::Unambiguous ) );
if( INetProtocol::File == aURL.GetProtocol() )
{
SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
SfxBoolItem aBrowsing( SID_BROWSE, true );
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if (pViewFrm)
{
pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC,
SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
{ &aUrl, &aBrowsing });
}
}
}
break;
case presentation::ClickAction_MACRO:
{
const OUString aMacro( pEvent->maStrBookmark );
if ( SfxApplication::IsXScriptURL( aMacro ) )
{
Any aRet;
Sequence< sal_Int16 > aOutArgsIndex;
Sequence< Any > aOutArgs;
Sequence< Any >* pInArgs = new Sequence< Any >(0);
mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs);
}
else
{
// aMacro has the following syntax:
// "Macroname.Modulname.Libname.Documentname" or
// "Macroname.Modulname.Libname.Applicationname"
OUString aMacroName = aMacro.getToken(0, '.');
OUString aModulName = aMacro.getToken(1, '.');
// todo: is the limitation still given that only
// Modulname+Macroname can be used here?
OUString aExecMacro = aModulName + "." + aMacroName;
mpDocSh->GetBasic()->Call(aExecMacro);
}
}
break;
case ClickAction_VERB:
{
// todo, better do it async?
SdrObject* pObj = GetSdrObjectFromXShape( xShape );
SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj);
if (pOleObject && mpViewShell )
mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb);
}
break;
default:
break;
}
}
sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark )
{
bool bIsMasterPage;
OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark );
sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage );
if( nPgNum == SDRPAGE_NOTFOUND )
{
// Is the bookmark an object?
SdrObject* pObj = mpDoc->GetObj( aBookmark );
if( pObj )
{
nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage();
}
}
if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard )
return -1;
return ( nPgNum - 1) >> 1;
}
void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink )
{
OUString aBookmark( aHyperLink );
sal_Int32 nPos = aBookmark.indexOf( '#' );
if( nPos >= 0 )
{
OUString aURL( aBookmark.copy( 0, nPos+1 ) );
OUString aName( aBookmark.copy( nPos+1 ) );
aURL += getUiNameFromPageApiNameImpl( aName );
aBookmark = aURL;
}
mpDocSh->OpenBookmark( aBookmark );
}
void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber )
{
if( mpSlideController.get() )
{
if( mpSlideController->jumpToSlideNumber( nSlideNumber ) )
{
displayCurrentSlide();
}
}
}
/** nSlideIndex == -1 displays current slide again */
void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex )
{
if( mpSlideController.get() )
{
if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) )
{
displayCurrentSlide();
}
}
}
void SlideshowImpl::jumpToBookmark( const OUString& sBookmark )
{
sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark );
if( nSlideNumber != -1 )
displaySlideNumber( nSlideNumber );
}
sal_Int32 SlideshowImpl::getCurrentSlideNumber()
{
return mpSlideController.get() ? mpSlideController->getCurrentSlideNumber() : -1;
}
sal_Bool SAL_CALL SlideshowImpl::isEndless()
{
SolarMutexGuard aSolarGuard;
return maPresSettings.mbEndless;
}
void SlideshowImpl::update()
{
startUpdateTimer();
}
void SlideshowImpl::startUpdateTimer()
{
SolarMutexGuard aSolarGuard;
maUpdateTimer.SetTimeout( 0 );
maUpdateTimer.Start();
}
/** this timer is called 20ms after a new slide was displayed.
This is used to unfreeze user input that was disabled after
slide change to skip input that was buffered during slide
transition preparation */
IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void)
{
mbInputFreeze = false;
}
/** if I catch someone someday who calls this method by hand
and not by using the timer, I will personally punish this
person seriously, even if this person is me.
*/
IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void)
{
updateSlideShow();
}
void SlideshowImpl::updateSlideShow()
{
// prevent me from deletion when recursing (App::EnableYieldMode does)
const rtl::Reference<SlideshowImpl> this_(this);
Reference< XSlideShow > xShow( mxShow );
if ( ! xShow.is())
return;
try
{
double fUpdate = 0.0;
if( !xShow->update(fUpdate) )
fUpdate = -1.0;
if (mxShow.is() && (fUpdate >= 0.0))
{
if (!::basegfx::fTools::equalZero(fUpdate))
{
// Avoid busy loop when the previous call to update()
// returns a small positive number but not 0 (which is
// handled above). Also, make sure that calls to update()
// have a minimum frequency.
// => Allow up to 60 frames per second. Call at least once
// every 4 seconds.
const static sal_Int32 nMaximumFrameCount (60);
const static double nMinimumTimeout (1.0 / nMaximumFrameCount);
const static double nMaximumTimeout (4.0);
fUpdate = o3tl::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout);
// Make sure that the maximum frame count has not been set
// too high (only then conversion to milliseconds and long
// integer may lead to zero value.)
OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
}
// Use our high resolution timers for the asynchronous callback.
maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
maUpdateTimer.Start();
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::updateSlideShow(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
bool SlideshowImpl::keyInput(const KeyEvent& rKEvt)
{
if( !mxShow.is() || mbInputFreeze )
return false;
bool bRet = true;
try
{
const int nKeyCode = rKEvt.GetKeyCode().GetCode();
switch( nKeyCode )
{
case awt::Key::CONTEXTMENU:
if( !mnContextMenuEvent )
{
if( mpShowWindow )
maPopupMousePos = mpShowWindow->GetPointerState().maPos;
mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
}
break;
// cancel show
case KEY_ESCAPE:
case KEY_SUBTRACT:
// in case the user cancels the presentation, switch to current slide
// in edit mode
if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
{
if( mpSlideController->getCurrentSlideNumber() != -1 )
mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
}
endPresentation();
break;
// advance show
case KEY_PAGEDOWN:
if(rKEvt.GetKeyCode().IsMod2())
{
gotoNextSlide();
break;
}
SAL_FALLTHROUGH;
case KEY_SPACE:
case KEY_RIGHT:
case KEY_DOWN:
case KEY_N:
gotoNextEffect();
break;
case KEY_RETURN:
{
if( !maCharBuffer.isEmpty() )
{
if( mpSlideController.get() )
{
if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) )
displayCurrentSlide();
}
maCharBuffer.clear();
}
else
{
gotoNextEffect();
}
}
break;
// numeric: add to buffer
case KEY_0:
case KEY_1:
case KEY_2:
case KEY_3:
case KEY_4:
case KEY_5:
case KEY_6:
case KEY_7:
case KEY_8:
case KEY_9:
maCharBuffer += OUStringLiteral1( rKEvt.GetCharCode() );
break;
case KEY_PAGEUP:
if(rKEvt.GetKeyCode().IsMod2())
{
gotoPreviousSlide();
break;
}
SAL_FALLTHROUGH;
case KEY_LEFT:
case KEY_UP:
case KEY_P:
case KEY_BACKSPACE:
gotoPreviousEffect();
break;
case KEY_HOME:
gotoFirstSlide();
break;
case KEY_END:
gotoLastSlide();
break;
case KEY_B:
case KEY_W:
case KEY_POINT:
case KEY_COMMA:
{
blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 );
}
break;
default:
bRet = false;
break;
}
}
catch( Exception& )
{
bRet = false;
SAL_WARN( "sd", "sd::SlideshowImpl::keyInput(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
return bRet;
}
IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void )
{
if( !mxShow.is() || mbInputFreeze )
return;
if( (rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData() )
{
const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
if( rEvent.GetCommand() == CommandEventId::Media )
{
CommandMediaData* pMediaData = rEvent.GetMediaData();
pMediaData->SetPassThroughToOS(false);
switch (pMediaData->GetMediaId())
{
#if defined( MACOSX )
case MediaCommand::Menu:
if( !mnContextMenuEvent )
{
if( mpShowWindow )
maPopupMousePos = mpShowWindow->GetPointerState().maPos;
mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
}
break;
case MediaCommand::VolumeDown:
gotoPreviousSlide();
break;
case MediaCommand::VolumeUp:
gotoNextEffect();
break;
#endif
case MediaCommand::NextTrack:
gotoNextEffect();
break;
case MediaCommand::Pause:
if( !mbIsPaused )
blankScreen(0);
break;
case MediaCommand::Play:
if( mbIsPaused )
resume();
break;
case MediaCommand::PlayPause:
if( mbIsPaused )
resume();
else
blankScreen(0);
break;
case MediaCommand::PreviousTrack:
gotoPreviousSlide();
break;
case MediaCommand::NextTrackHold:
gotoLastSlide();
break;
case MediaCommand::Rewind:
gotoFirstSlide();
break;
case MediaCommand::Stop:
// in case the user cancels the presentation, switch to current slide
// in edit mode
if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
{
if( mpSlideController->getCurrentSlideNumber() != -1 )
mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
}
endPresentation();
break;
default:
pMediaData->SetPassThroughToOS(true);
break;
}
}
}
}
void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt)
{
if( rMEvt.IsRight() && !mnContextMenuEvent )
{
maPopupMousePos = rMEvt.GetPosPixel();
mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
}
}
IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void)
{
mnContextMenuEvent = nullptr;
if( mpSlideController.get() == nullptr )
return;
mbWasPaused = mbIsPaused;
if( !mbWasPaused )
pause();
VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/simpress/ui/slidecontextmenu.ui", "");
VclPtr<PopupMenu> pMenu(aBuilder.get_menu("menu"));
// Adding button to display if in Pen mode
pMenu->CheckItem("pen", mbUsePen);
const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
pMenu->EnableItem(pMenu->GetItemId("next"), mpSlideController->getNextSlideIndex() != -1);
pMenu->EnableItem(pMenu->GetItemId("prev"), (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK));
pMenu->EnableItem(pMenu->GetItemId("edit"), mpViewShell->GetDoc()->IsStartWithPresentation());
PopupMenu* pPageMenu = pMenu->GetPopupMenu(pMenu->GetItemId("goto"));
SfxViewFrame* pViewFrame = getViewFrame();
if( pViewFrame )
{
Reference< css::frame::XFrame > xFrame( pViewFrame->GetFrame().GetFrameInterface() );
if( xFrame.is() )
{
pMenu->SetItemImage(pMenu->GetItemId("next"), vcl::CommandInfoProvider::GetImageForCommand(".uno:NextRecord", xFrame));
pMenu->SetItemImage(pMenu->GetItemId("prev"), vcl::CommandInfoProvider::GetImageForCommand(".uno:PrevRecord", xFrame));
if( pPageMenu )
{
pPageMenu->SetItemImage(pPageMenu->GetItemId("first"), vcl::CommandInfoProvider::GetImageForCommand(".uno:FirstRecord", xFrame));
pPageMenu->SetItemImage(pPageMenu->GetItemId("last"), vcl::CommandInfoProvider::GetImageForCommand(".uno:LastRecord", xFrame));
}
}
}
// populate slide goto list
if( pPageMenu )
{
const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount();
if( nPageNumberCount <= 1 )
{
pMenu->EnableItem(pMenu->GetItemId("goto"), false);
}
else
{
sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber();
if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
nCurrentSlideNumber = -1;
pPageMenu->EnableItem(pPageMenu->GetItemId("first"), mpSlideController->getSlideNumber(0) != nCurrentSlideNumber);
pPageMenu->EnableItem(pPageMenu->GetItemId("last"), mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber);
sal_Int32 nPageNumber;
for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ )
{
if( mpSlideController->isVisibleSlideNumber( nPageNumber ) )
{
SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard);
if (pPage)
{
pPageMenu->InsertItem( static_cast<sal_uInt16>(CM_SLIDES + nPageNumber), pPage->GetName() );
if( nPageNumber == nCurrentSlideNumber )
pPageMenu->CheckItem( static_cast<sal_uInt16>(CM_SLIDES + nPageNumber) );
}
}
}
}
}
if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
{
PopupMenu* pBlankMenu = pMenu->GetPopupMenu(pMenu->GetItemId("screen"));
if( pBlankMenu )
{
pBlankMenu->CheckItem((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black");
}
}
PopupMenu* pWidthMenu = pMenu->GetPopupMenu(pMenu->GetItemId("width"));
// populate color width list
if( pWidthMenu )
{
sal_Int32 nIterator;
double nWidth;
nWidth = 4.0;
for( nIterator = 1; nIterator < 6; nIterator++)
{
switch(nIterator)
{
case 1:
nWidth = 4.0;
break;
case 2:
nWidth = 100.0;
break;
case 3:
nWidth = 150.0;
break;
case 4:
nWidth = 200.0;
break;
case 5:
nWidth = 400.0;
break;
default:
break;
}
if (nWidth == mdUserPaintStrokeWidth)
pWidthMenu->CheckItem(OString::number(nWidth));
}
}
pMenu->SetSelectHdl( LINK( this, SlideshowImpl, ContextMenuSelectHdl ) );
pMenu->Execute( mpShowWindow, maPopupMousePos );
if( mxView.is() )
mxView->ignoreNextMouseReleased();
if( !mbWasPaused )
resume();
}
IMPL_LINK( SlideshowImpl, ContextMenuSelectHdl, Menu *, pMenu, bool )
{
if (!pMenu)
return false;
OString sMenuId = pMenu->GetCurItemIdent();
if (sMenuId == "prev")
{
gotoPreviousSlide();
mbWasPaused = false;
}
else if(sMenuId == "next")
{
gotoNextSlide();
mbWasPaused = false;
}
else if (sMenuId == "first")
{
gotoFirstSlide();
mbWasPaused = false;
}
else if (sMenuId == "last")
{
gotoLastSlide();
mbWasPaused = false;
}
else if (sMenuId == "black" || sMenuId == "white")
{
const Color aBlankColor(sMenuId == "white" ? COL_WHITE : COL_BLACK);
if( mbWasPaused )
{
if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
{
if( mpShowWindow->GetBlankColor() == aBlankColor )
{
mbWasPaused = false;
mpShowWindow->RestartShow();
return false;
}
}
mpShowWindow->RestartShow();
}
if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) )
{
pause();
mbWasPaused = true;
}
}
else if (sMenuId == "color")
{
//Open a color picker based on SvColorDialog
::Color aColor( mnUserPaintColor );
SvColorDialog aColorDlg;
aColorDlg.SetColor( aColor );
if (aColorDlg.Execute(mpShowWindow->GetFrameWeld()))
{
aColor = aColorDlg.GetColor();
setPenColor(sal_Int32(aColor));
}
mbWasPaused = false;
}
else if (sMenuId == "4")
{
setPenWidth(4.0);
mbWasPaused = false;
}
else if (sMenuId == "100")
{
setPenWidth(100.0);
mbWasPaused = false;
}
else if (sMenuId == "150")
{
setPenWidth(150.0);
mbWasPaused = false;
}
else if (sMenuId == "200")
{
setPenWidth(200.0);
mbWasPaused = false;
}
else if (sMenuId == "400")
{
setPenWidth(400.0);
mbWasPaused = false;
}
else if (sMenuId == "erase")
{
setEraseAllInk(true);
mbWasPaused = false;
}
else if (sMenuId == "pen")
{
setUsePen(!mbUsePen);
mbWasPaused = false;
}
else if (sMenuId == "edit")
{
// When in autoplay mode (pps/ppsx), offer editing of the presentation
// Turn autostart off, else Impress will close when exiting the Presentation
mpViewShell->GetDoc()->SetExitAfterPresenting(false);
if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
{
if( mpSlideController->getCurrentSlideNumber() != -1 )
{
mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
}
}
endPresentation();
}
else if (sMenuId == "end")
{
// in case the user cancels the presentation, switch to current slide
// in edit mode
if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
{
if( mpSlideController->getCurrentSlideNumber() != -1 )
{
mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
}
}
endPresentation();
}
else
{
sal_Int32 nPageNumber = pMenu->GetCurItemId() - CM_SLIDES;
const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
{
mpShowWindow->RestartShow( nPageNumber );
}
else if( nPageNumber != mpSlideController->getCurrentSlideNumber() )
{
displaySlideNumber( nPageNumber );
}
mbWasPaused = false;
}
return false;
}
Reference< XSlideShow > SlideshowImpl::createSlideShow()
{
Reference< XSlideShow > xShow;
try
{
Reference< uno::XComponentContext > xContext =
::comphelper::getProcessComponentContext();
xShow.set( presentation::SlideShow::create(xContext), UNO_QUERY_THROW );
}
catch( uno::Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::createSlideShow(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
return xShow;
}
void SlideshowImpl::createSlideList( bool bAll, const OUString& rPresSlide )
{
const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard );
if( nSlideCount )
{
SdCustomShow* pCustomShow;
if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow )
pCustomShow = mpDoc->GetCustomShowList()->GetCurObject();
else
pCustomShow = nullptr;
// create animation slide controller
AnimationSlideController::Mode eMode =
( pCustomShow && pCustomShow->PagesVector().size() ) ? AnimationSlideController::CUSTOM :
(bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM);
Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
mpSlideController.reset( new AnimationSlideController( xSlides, eMode ) );
if( eMode != AnimationSlideController::CUSTOM )
{
sal_Int32 nFirstVisibleSlide = 0;
// normal presentation
if( !rPresSlide.isEmpty() )
{
sal_Int32 nSlide;
bool bTakeNextAvailable = false;
for( nSlide = 0, nFirstVisibleSlide = -1;
( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ )
{
SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard );
if( pTestSlide->GetName() == rPresSlide )
{
if( pTestSlide->IsExcluded() )
bTakeNextAvailable = true;
else
nFirstVisibleSlide = nSlide;
}
else if( bTakeNextAvailable && !pTestSlide->IsExcluded() )
nFirstVisibleSlide = nSlide;
}
if( -1 == nFirstVisibleSlide )
nFirstVisibleSlide = 0;
}
for( sal_Int32 i = 0; i < nSlideCount; i++ )
{
bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded();
if( bVisible || (eMode == AnimationSlideController::ALL) )
mpSlideController->insertSlideNumber( i, bVisible );
}
mpSlideController->setStartSlideNumber( nFirstVisibleSlide );
}
else
{
if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.isEmpty() )
{
sal_Int32 nSlide;
for( nSlide = 0; nSlide < nSlideCount; nSlide++ )
if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() )
break;
if( nSlide < nSlideCount )
mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) );
}
sal_Int32 nSlideIndex = 0;
for( SdCustomShow::PageVec::iterator it = pCustomShow->PagesVector().begin();
it != pCustomShow->PagesVector().end(); ++it, nSlideIndex++ )
{
const sal_uInt16 nSdSlide = ( (*it)->GetPageNum() - 1 ) / 2;
if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded())
mpSlideController->insertSlideNumber( nSdSlide );
}
}
}
}
typedef sal_uInt16 (*FncGetChildWindowId)();
static const FncGetChildWindowId aShowChildren[] =
{
&AnimationChildWindow::GetChildWindowId,
&Svx3DChildWindow::GetChildWindowId,
&SvxFontWorkChildWindow::GetChildWindowId,
&SvxColorChildWindow::GetChildWindowId,
&SvxSearchDialogWrapper::GetChildWindowId,
&SvxBmpMaskChildWindow::GetChildWindowId,
&SvxIMapDlgChildWindow::GetChildWindowId,
&SvxHlinkDlgWrapper::GetChildWindowId,
&SfxInfoBarContainerChild::GetChildWindowId
};
void SlideshowImpl::hideChildWindows()
{
mnChildMask = 0;
if( ANIMATIONMODE_SHOW == meAnimationMode )
{
SfxViewFrame* pViewFrame = getViewFrame();
if( pViewFrame )
{
for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ )
{
const sal_uInt16 nId = ( *aShowChildren[ i ] )();
if( pViewFrame->GetChildWindow( nId ) )
{
pViewFrame->SetChildWindow( nId, false );
mnChildMask |= 1 << i;
}
}
}
}
}
void SlideshowImpl::showChildWindows()
{
if( ANIMATIONMODE_SHOW == meAnimationMode )
{
SfxViewFrame* pViewFrame = getViewFrame();
if( pViewFrame )
{
for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ )
{
if( mnChildMask & ( 1 << i ) )
pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true );
}
}
}
}
SfxViewFrame* SlideshowImpl::getViewFrame() const
{
return mpViewShell ? mpViewShell->GetViewFrame() : nullptr;
}
SfxDispatcher* SlideshowImpl::getDispatcher() const
{
return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr;
}
SfxBindings* SlideshowImpl::getBindings() const
{
return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr;
}
void SlideshowImpl::resize( const Size& rSize )
{
maPresSize = rSize;
if(mpShowWindow)
{
mpShowWindow->SetSizePixel( maPresSize );
mpShowWindow->Show();
}
if( mxView.is() ) try
{
awt::WindowEvent aEvt;
mxView->windowResized(aEvt);
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::resize(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible )
{
// in case of ActiveX control the toolbars should not be visible if slide show runs in window mode
// actually it runs always in window mode in case of ActiveX control
if ( !maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium() )
{
const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(mpDocSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
if ( pItem && pItem->GetValue() )
{
// this is a plugin/activex mode, no toolbars should be visible during slide show
// after the end of slide show they should be visible again
SfxViewFrame* pViewFrame = getViewFrame();
if( pViewFrame )
{
try
{
Reference< frame::XLayoutManager > xLayoutManager;
Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW );
if ( ( xFrameProps->getPropertyValue( "LayoutManager" )
>>= xLayoutManager )
&& xLayoutManager.is() )
{
xLayoutManager->setVisible( bVisible );
}
}
catch( uno::Exception& )
{}
}
}
}
}
void SAL_CALL SlideshowImpl::activate()
{
SolarMutexGuard aSolarGuard;
maDeactivateTimer.Stop();
if( !mbActive && mxShow.is() )
{
mbActive = true;
if( ANIMATIONMODE_SHOW == meAnimationMode )
{
if( mbAutoSaveWasOn )
setAutoSaveState( false );
if( mpShowWindow )
{
SfxViewFrame* pViewFrame = getViewFrame();
SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
hideChildWindows();
if( pDispatcher )
{
// filter all forbidden slots
pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed );
}
if( getBindings() )
getBindings()->InvalidateAll(true);
mpShowWindow->GrabFocus();
}
}
resume();
}
}
void SAL_CALL SlideshowImpl::deactivate()
{
SolarMutexGuard aSolarGuard;
if( mbActive && mxShow.is() )
{
maDeactivateTimer.Start();
}
}
IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void)
{
if( mbActive && mxShow.is() )
{
mbActive = false;
pause();
if( ANIMATIONMODE_SHOW == meAnimationMode )
{
if( mbAutoSaveWasOn )
setAutoSaveState( true );
if( mpShowWindow )
{
showChildWindows();
}
}
}
}
sal_Bool SAL_CALL SlideshowImpl::isActive()
{
SolarMutexGuard aSolarGuard;
return mbActive;
}
void SlideshowImpl::setAutoSaveState( bool bOn)
{
try
{
uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext));
util::URL aURL;
aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState";
xParser->parseStrict(aURL);
Sequence< beans::PropertyValue > aArgs(1);
aArgs[0].Name = "AutoSaveState";
aArgs[0].Value <<= bOn;
uno::Reference< frame::XDispatch > xAutoSave = frame::theAutoRecovery::get(xContext);
xAutoSave->dispatch(aURL, aArgs);
}
catch( Exception& )
{
OSL_FAIL("sd::SlideshowImpl::setAutoSaveState(), exception caught!");
}
}
Reference< XDrawPage > SAL_CALL SlideshowImpl::getCurrentSlide()
{
SolarMutexGuard aSolarGuard;
Reference< XDrawPage > xSlide;
if( mxShow.is() && mpSlideController.get() )
{
sal_Int32 nSlide = getCurrentSlideNumber();
if( (nSlide >= 0) && (nSlide < mpSlideController->getSlideNumberCount() ) )
xSlide = mpSlideController->getSlideByNumber( nSlide );
}
return xSlide;
}
sal_Int32 SAL_CALL SlideshowImpl::getNextSlideIndex()
{
SolarMutexGuard aSolarGuard;
if( mxShow.is() )
{
return mpSlideController->getNextSlideIndex();
}
else
{
return -1;
}
}
sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex()
{
return mpSlideController.get() ? mpSlideController->getCurrentSlideIndex() : -1;
}
// css::presentation::XSlideShowController:
::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount()
{
return mpSlideController.get() ? mpSlideController->getSlideIndexCount() : 0;
}
Reference< XDrawPage > SAL_CALL SlideshowImpl::getSlideByIndex(::sal_Int32 Index)
{
if( (mpSlideController.get() == nullptr ) || (Index < 0) || (Index >= mpSlideController->getSlideIndexCount() ) )
throw IndexOutOfBoundsException();
return mpSlideController->getSlideByNumber( mpSlideController->getSlideNumber( Index ) );
}
sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop()
{
SolarMutexGuard aSolarGuard;
return maPresSettings.mbAlwaysOnTop;
}
void SAL_CALL SlideshowImpl::setAlwaysOnTop( sal_Bool bAlways )
{
SolarMutexGuard aSolarGuard;
if( maPresSettings.mbAlwaysOnTop != bool(bAlways) )
{
maPresSettings.mbAlwaysOnTop = bAlways;
// todo, can this be changed while running?
}
}
sal_Bool SAL_CALL SlideshowImpl::isFullScreen()
{
SolarMutexGuard aSolarGuard;
return maPresSettings.mbFullScreen;
}
sal_Bool SAL_CALL SlideshowImpl::getMouseVisible()
{
SolarMutexGuard aSolarGuard;
return maPresSettings.mbMouseVisible;
}
void SAL_CALL SlideshowImpl::setMouseVisible( sal_Bool bVisible )
{
SolarMutexGuard aSolarGuard;
if( maPresSettings.mbMouseVisible != bool(bVisible) )
{
maPresSettings.mbMouseVisible = bVisible;
if( mpShowWindow )
mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
}
}
sal_Bool SAL_CALL SlideshowImpl::getUsePen()
{
SolarMutexGuard aSolarGuard;
return mbUsePen;
}
void SAL_CALL SlideshowImpl::setUsePen( sal_Bool bMouseAsPen )
{
SolarMutexGuard aSolarGuard;
mbUsePen = bMouseAsPen;
if( mxShow.is() ) try
{
// For Pencolor;
Any aValue;
if( mbUsePen )
aValue <<= mnUserPaintColor;
beans::PropertyValue aPenProp;
aPenProp.Name = "UserPaintColor";
aPenProp.Value = aValue;
mxShow->setProperty( aPenProp );
//for StrokeWidth :
if( mbUsePen )
{
beans::PropertyValue aPenPropWidth;
aPenPropWidth.Name = "UserPaintStrokeWidth";
aPenPropWidth.Value <<= mdUserPaintStrokeWidth;
mxShow->setProperty( aPenPropWidth );
// for Pen Mode
beans::PropertyValue aPenPropSwitchPenMode;
aPenPropSwitchPenMode.Name = "SwitchPenMode";
aPenPropSwitchPenMode.Value <<= true;
mxShow->setProperty( aPenPropSwitchPenMode );
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::setUsePen(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
double SAL_CALL SlideshowImpl::getPenWidth()
{
SolarMutexGuard aSolarGuard;
return mdUserPaintStrokeWidth;
}
void SAL_CALL SlideshowImpl::setPenWidth( double dStrokeWidth )
{
SolarMutexGuard aSolarGuard;
mdUserPaintStrokeWidth = dStrokeWidth;
setUsePen( true ); // enable pen mode, update color and width
}
sal_Int32 SAL_CALL SlideshowImpl::getPenColor()
{
SolarMutexGuard aSolarGuard;
return mnUserPaintColor;
}
void SAL_CALL SlideshowImpl::setPenColor( sal_Int32 nColor )
{
SolarMutexGuard aSolarGuard;
mnUserPaintColor = nColor;
setUsePen( true ); // enable pen mode, update color
}
void SlideshowImpl::setEraseAllInk(bool bEraseAllInk)
{
if( bEraseAllInk )
{
SolarMutexGuard aSolarGuard;
if( mxShow.is() ) try
{
beans::PropertyValue aPenPropEraseAllInk;
aPenPropEraseAllInk.Name = "EraseAllInk";
aPenPropEraseAllInk.Value <<= bEraseAllInk;
mxShow->setProperty( aPenPropEraseAllInk );
}
catch( Exception& )
{
SAL_WARN( "sd.slideshow", "sd::SlideshowImpl::setEraseAllInk(), "
"exception caught: " << comphelper::anyToString( cppu::getCaughtException() ));
}
}
}
// XSlideShowController Methods
sal_Bool SAL_CALL SlideshowImpl::isRunning( )
{
SolarMutexGuard aSolarGuard;
return mxShow.is();
}
void SAL_CALL SlideshowImpl::gotoNextEffect( )
{
SolarMutexGuard aSolarGuard;
if( mxShow.is() && mpSlideController.get() && mpShowWindow )
{
if( mbIsPaused )
resume();
const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
if( eMode == SHOWWINDOWMODE_END )
{
endPresentation();
}
else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
{
mpShowWindow->RestartShow();
}
else
{
mxShow->nextEffect();
update();
}
}
}
void SAL_CALL SlideshowImpl::gotoPreviousEffect( )
{
SolarMutexGuard aSolarGuard;
if( mxShow.is() && mpSlideController.get() && mpShowWindow )
{
if( mbIsPaused )
resume();
const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
{
mpShowWindow->RestartShow();
}
else
{
mxShow->previousEffect();
update();
}
}
}
void SAL_CALL SlideshowImpl::gotoFirstSlide( )
{
SolarMutexGuard aSolarGuard;
if( mpShowWindow && mpSlideController.get() )
{
if( mbIsPaused )
resume();
if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
{
if( mpSlideController->getSlideIndexCount() )
mpShowWindow->RestartShow( 0);
}
else
{
displaySlideIndex( 0 );
}
}
}
void SAL_CALL SlideshowImpl::gotoNextSlide( )
{
SolarMutexGuard aSolarGuard;
if( mbIsPaused )
resume();
const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
{
mpShowWindow->RestartShow();
}
else
{
// if this is a show, ignore user inputs and
// start 20ms timer to reenable inputs to filter
// buffered inputs during slide transition
if( meAnimationMode == ANIMATIONMODE_SHOW )
{
mbInputFreeze = true;
maInputFreezeTimer.Start();
}
if( mpSlideController.get() )
{
if( mpSlideController->nextSlide() )
{
displayCurrentSlide();
}
else
{
stopSound();
if( meAnimationMode == ANIMATIONMODE_PREVIEW )
{
endPresentation();
}
else if( maPresSettings.mbEndless )
{
if( maPresSettings.mnPauseTimeout )
{
if( mpShowWindow )
{
if ( maPresSettings.mbShowPauseLogo )
{
Graphic aGraphic(SfxApplication::GetApplicationLogo(360));
mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout, &aGraphic );
}
else
mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout );
}
}
else
{
displaySlideIndex( 0 );
}
}
else
{
if( mpShowWindow )
{
mpShowWindow->SetEndMode();
if( !mpViewShell->GetDoc()->IsStartWithPresentation() )
pause();
}
}
}
}
}
}
void SAL_CALL SlideshowImpl::gotoPreviousSlide( )
{
gotoPreviousSlide(false);
}
void SlideshowImpl::gotoPreviousSlide (const bool bSkipAllMainSequenceEffects)
{
SolarMutexGuard aSolarGuard;
if( mxShow.is() && mpSlideController.get() ) try
{
if( mbIsPaused )
resume();
const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
if( eMode == SHOWWINDOWMODE_END )
{
mpShowWindow->RestartShow( mpSlideController->getCurrentSlideIndex() );
}
else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
{
mpShowWindow->RestartShow();
}
else
{
if( mpSlideController->previousSlide())
displayCurrentSlide(bSkipAllMainSequenceEffects);
else if (bSkipAllMainSequenceEffects)
{
// We could not go to the previous slide (probably because
// the current slide is already the first one). We still
// have to call displayCurrentSlide because the calling
// slideshow can not determine whether there is a previous
// slide or not and has already prepared for a slide change.
// This slide change has to be completed now, even when
// changing to the same slide.
// Note that in this special case we do NOT pass
// bSkipAllMainSequenceEffects because we display the same
// slide as before and do not want to show all its effects.
displayCurrentSlide();
}
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::gotoPreviousSlide(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
void SAL_CALL SlideshowImpl::gotoLastSlide()
{
SolarMutexGuard aSolarGuard;
if( mpSlideController.get() )
{
if( mbIsPaused )
resume();
const sal_Int32 nLastSlideIndex = mpSlideController->getSlideIndexCount() - 1;
if( nLastSlideIndex >= 0 )
{
if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
{
mpShowWindow->RestartShow( nLastSlideIndex );
}
else
{
displaySlideIndex( nLastSlideIndex );
}
}
}
}
void SAL_CALL SlideshowImpl::gotoBookmark( const OUString& rBookmark )
{
SolarMutexGuard aSolarGuard;
if( mbIsPaused )
resume();
sal_Int32 nSlideNumber = getSlideNumberForBookmark( rBookmark );
if( nSlideNumber != -1 )
displaySlideNumber( nSlideNumber );
}
void SAL_CALL SlideshowImpl::gotoSlide( const Reference< XDrawPage >& xSlide )
{
SolarMutexGuard aSolarGuard;
if( mpSlideController.get() && xSlide.is() )
{
if( mbIsPaused )
resume();
const sal_Int32 nSlideCount = mpSlideController->getSlideNumberCount();
for( sal_Int32 nSlide = 0; nSlide < nSlideCount; nSlide++ )
{
if( mpSlideController->getSlideByNumber( nSlide ) == xSlide )
{
displaySlideNumber( nSlide );
}
}
}
}
void SAL_CALL SlideshowImpl::gotoSlideIndex( sal_Int32 nIndex )
{
SolarMutexGuard aSolarGuard;
if( mbIsPaused )
resume();
displaySlideIndex( nIndex );
}
void SAL_CALL SlideshowImpl::stopSound( )
{
SolarMutexGuard aSolarGuard;
try
{
if( mxPlayer.is() )
{
mxPlayer->stop();
mxPlayer.clear();
}
}
catch( Exception& )
{
SAL_WARN( "sd", "sd::SlideshowImpl::stopSound(), exception caught: "
<< comphelper::anyToString( cppu::getCaughtException() ) );
}
}
// XIndexAccess
::sal_Int32 SAL_CALL SlideshowImpl::getCount( )
{
return getSlideCount();
}
css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index )
{
return Any( getSlideByIndex( Index ) );
}
css::uno::Type SAL_CALL SlideshowImpl::getElementType( )
{
return cppu::UnoType<XDrawPage>::get();
}
sal_Bool SAL_CALL SlideshowImpl::hasElements( )
{
return getSlideCount() != 0;
}
Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
{
return mxShow;
}
PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r )
: PresentationSettings( r )
, mbRehearseTimings(r.mbRehearseTimings)
, mbPreview(r.mbPreview)
, mpParentWindow( nullptr )
{
}
PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r )
: PresentationSettings( r )
, mbRehearseTimings(false)
, mbPreview(false)
, mpParentWindow(nullptr)
{
}
void PresentationSettingsEx::SetArguments( const Sequence< PropertyValue >& rArguments )
{
sal_Int32 nArguments = rArguments.getLength();
const PropertyValue* pValue = rArguments.getConstArray();
while( nArguments-- )
{
SetPropertyValue( pValue->Name, pValue->Value );
pValue++;
}
}
void PresentationSettingsEx::SetPropertyValue( const OUString& rProperty, const Any& rValue )
{
if ( rProperty == "RehearseTimings" )
{
if( rValue >>= mbRehearseTimings )
return;
}
else if ( rProperty == "Preview" )
{
if( rValue >>= mbPreview )
return;
}
else if ( rProperty == "AnimationNode" )
{
if( rValue >>= mxAnimationNode )
return;
}
else if ( rProperty == "ParentWindow" )
{
Reference< XWindow > xWindow;
if( rValue >>= xWindow )
{
mpParentWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow )
: VclPtr<vcl::Window>();
return;
}
}
else if ( rProperty == "AllowAnimations" )
{
if( rValue >>= mbAnimationAllowed )
return;
}
else if ( rProperty == "FirstPage" )
{
OUString aPresPage;
if( rValue >>= aPresPage )
{
maPresPage = getUiNameFromPageApiNameImpl(aPresPage);
mbCustomShow = false;
mbAll = false;
return;
}
else
{
if( rValue >>= mxStartPage )
return;
}
}
else if ( rProperty == "IsAlwaysOnTop" )
{
if( rValue >>= mbAlwaysOnTop )
return;
}
else if ( rProperty == "IsAutomatic" )
{
if( rValue >>= mbManual )
return;
}
else if ( rProperty == "IsEndless" )
{
if( rValue >>= mbEndless )
return;
}
else if ( rProperty == "IsFullScreen" )
{
if( rValue >>= mbFullScreen )
return;
}
else if ( rProperty == "IsMouseVisible" )
{
if( rValue >>= mbMouseVisible )
return;
}
else if ( rProperty == "Pause" )
{
sal_Int32 nPause = -1;
if( (rValue >>= nPause) && (nPause >= 0) )
{
mnPauseTimeout = nPause;
return;
}
}
else if ( rProperty == "UsePen" )
{
if( rValue >>= mbMouseAsPen )
return;
}
throw IllegalArgumentException();
}
// XAnimationListener
SlideShowListenerProxy::SlideShowListenerProxy( const rtl::Reference< SlideshowImpl >& xController, const css::uno::Reference< css::presentation::XSlideShow >& xSlideShow )
: maListeners( m_aMutex )
, mxController( xController )
, mxSlideShow( xSlideShow )
{
}
SlideShowListenerProxy::~SlideShowListenerProxy()
{
}
void SlideShowListenerProxy::addAsSlideShowListener()
{
if( mxSlideShow.is() )
{
Reference< XSlideShowListener > xSlideShowListener( this );
mxSlideShow->addSlideShowListener( xSlideShowListener );
}
}
void SlideShowListenerProxy::removeAsSlideShowListener()
{
if( mxSlideShow.is() )
{
Reference< XSlideShowListener > xSlideShowListener( this );
mxSlideShow->removeSlideShowListener( xSlideShowListener );
}
}
void SlideShowListenerProxy::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
{
if( mxSlideShow.is() )
{
Reference< XShapeEventListener > xListener( this );
mxSlideShow->addShapeEventListener( xListener, xShape );
}
}
void SlideShowListenerProxy::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
{
if( mxSlideShow.is() )
{
Reference< XShapeEventListener > xListener( this );
mxSlideShow->removeShapeEventListener( xListener, xShape );
}
}
void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
{
maListeners.addInterface(xListener);
}
void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
{
maListeners.removeInterface(xListener);
}
void SAL_CALL SlideShowListenerProxy::beginEvent( const Reference< XAnimationNode >& xNode )
{
::osl::MutexGuard aGuard( m_aMutex );
if( maListeners.getLength() >= 0 )
{
maListeners.forEach<XSlideShowListener>(
[&] (Reference<XAnimationListener> const& xListener) {
return xListener->beginEvent(xNode);
} );
}
}
void SAL_CALL SlideShowListenerProxy::endEvent( const Reference< XAnimationNode >& xNode )
{
::osl::MutexGuard aGuard( m_aMutex );
if( maListeners.getLength() >= 0 )
{
maListeners.forEach<XSlideShowListener>(
[&] (Reference<XAnimationListener> const& xListener) {
return xListener->endEvent(xNode);
} );
}
}
void SAL_CALL SlideShowListenerProxy::repeat( const Reference< XAnimationNode >& xNode, ::sal_Int32 nRepeat )
{
::osl::MutexGuard aGuard( m_aMutex );
if( maListeners.getLength() >= 0 )
{
maListeners.forEach<XSlideShowListener>(
[&] (Reference<XAnimationListener> const& xListener) {
return xListener->repeat(xNode, nRepeat);
} );
}
}
// css::presentation::XSlideShowListener:
void SAL_CALL SlideShowListenerProxy::paused( )
{
::osl::MutexGuard aGuard( m_aMutex );
maListeners.forEach<XSlideShowListener>(
[](uno::Reference<presentation::XSlideShowListener> const& xListener)
{
xListener->paused();
});
}
void SAL_CALL SlideShowListenerProxy::resumed( )
{
::osl::MutexGuard aGuard( m_aMutex );
maListeners.forEach<XSlideShowListener>(
[](uno::Reference<presentation::XSlideShowListener> const& xListener)
{
xListener->resumed();
});
}
void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( )
{
::osl::MutexGuard aGuard( m_aMutex );
maListeners.forEach<XSlideShowListener>(
[](uno::Reference<presentation::XSlideShowListener> const& xListener)
{
xListener->slideTransitionStarted();
});
}
void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( )
{
::osl::MutexGuard aGuard( m_aMutex );
maListeners.forEach<XSlideShowListener>(
[](uno::Reference<presentation::XSlideShowListener> const& xListener)
{
xListener->slideTransitionEnded ();
});
}
void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded( )
{
::osl::MutexGuard aGuard( m_aMutex );
maListeners.forEach<XSlideShowListener>(
[](uno::Reference<presentation::XSlideShowListener> const& xListener)
{
xListener->slideAnimationsEnded ();
});
}
void SlideShowListenerProxy::slideEnded(sal_Bool bReverse)
{
{
::osl::MutexGuard aGuard( m_aMutex );
if( maListeners.getLength() >= 0 )
{
maListeners.forEach<XSlideShowListener>(
[&] (Reference<XSlideShowListener> const& xListener) {
return xListener->slideEnded(bReverse);
} );
}
}
{
SolarMutexGuard aSolarGuard;
if( mxController.is() )
mxController->slideEnded(bReverse);
}
}
void SlideShowListenerProxy::hyperLinkClicked( OUString const& aHyperLink )
{
{
::osl::MutexGuard aGuard( m_aMutex );
if( maListeners.getLength() >= 0 )
{
maListeners.forEach<XSlideShowListener>(
[&] (Reference<XSlideShowListener> const& xListener) {
return xListener->hyperLinkClicked(aHyperLink);
} );
}
}
{
SolarMutexGuard aSolarGuard;
if( mxController.is() )
mxController->hyperLinkClicked(aHyperLink);
}
}
// XEventListener
void SAL_CALL SlideShowListenerProxy::disposing( const css::lang::EventObject& aDisposeEvent )
{
maListeners.disposeAndClear( aDisposeEvent );
mxController.clear();
mxSlideShow.clear();
}
// XShapeEventListener
void SAL_CALL SlideShowListenerProxy::click( const Reference< XShape >& xShape, const css::awt::MouseEvent& /*aOriginalEvent*/ )
{
SolarMutexGuard aSolarGuard;
if( mxController.is() )
mxController->click(xShape );
}
} // namespace ::sd
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V595 The 'pStartPage' pointer was utilized before it was verified against nullptr. Check lines: 896, 907.
↑ V773 Visibility scope of the 'pInArgs' pointer was exited without releasing the memory. A memory leak is possible.