Get the style color and number just once
[LibreOffice.git] / sd / source / ui / slideshow / slideshowviewimpl.cxx
blob7db8594e4e08941b8304b5f10390b14f3e67dcb0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "slideshowviewimpl.hxx"
21 #include "slideshowimpl.hxx"
22 #include <sdpage.hxx>
24 #include <vcl/svapp.hxx>
26 #include <com/sun/star/awt/Pointer.hpp>
27 #include <com/sun/star/awt/XWindow.hpp>
28 #include <com/sun/star/awt/XWindowPeer.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <basegfx/polygon/b2dpolygon.hxx>
32 #include <basegfx/polygon/b2dpolygontools.hxx>
33 #include <basegfx/matrix/b2dhommatrixtools.hxx>
34 #include <basegfx/matrix/b2dhommatrix.hxx>
36 #include <cppcanvas/vclfactory.hxx>
37 #include <cppcanvas/basegfxfactory.hxx>
38 #include <basegfx/utils/canvastools.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <comphelper/processfactory.hxx>
43 using ::com::sun::star::uno::Reference;
44 using ::com::sun::star::uno::WeakReference;
45 using ::com::sun::star::uno::Exception;
47 using namespace ::com::sun::star;
49 namespace sd
52 void SlideShowViewMouseListeners::notify( std::unique_lock<std::mutex>& rGuard, const WrappedMouseEvent& rEvent )
54 forEach(rGuard,
55 [&rEvent] (const Reference<css::awt::XMouseListener>& rListener)
57 switch( rEvent.meType )
59 case WrappedMouseEvent::PRESSED:
60 rListener->mousePressed( rEvent.maEvent );
61 break;
63 case WrappedMouseEvent::RELEASED:
64 rListener->mouseReleased( rEvent.maEvent );
65 break;
67 case WrappedMouseEvent::ENTERED:
68 rListener->mouseEntered( rEvent.maEvent );
69 break;
71 case WrappedMouseEvent::EXITED:
72 rListener->mouseExited( rEvent.maEvent );
73 break;
75 });
79 void SlideShowViewMouseMotionListeners::notify( std::unique_lock<std::mutex>& rGuard,const WrappedMouseMotionEvent& rEvent )
81 forEach(rGuard,
82 [&rEvent] (const Reference< awt::XMouseMotionListener >& rListener)
84 switch( rEvent.meType )
86 case WrappedMouseMotionEvent::DRAGGED:
87 rListener->mouseDragged( rEvent.maEvent );
88 break;
90 case WrappedMouseMotionEvent::MOVED:
91 rListener->mouseMoved( rEvent.maEvent );
92 break;
94 });
97 // SlideShowView
98 SlideShowView::SlideShowView( ShowWindow& rOutputWindow,
99 SdDrawDocument* pDoc,
100 AnimationMode eAnimationMode,
101 SlideshowImpl* pSlideShow,
102 bool bFullScreen )
103 : mpCanvas( ::cppcanvas::VCLFactory::createSpriteCanvas( rOutputWindow ) ),
104 mxWindow( VCLUnoHelper::GetInterface( &rOutputWindow ), uno::UNO_SET_THROW ),
105 mxWindowPeer( mxWindow, uno::UNO_QUERY_THROW ),
106 mpSlideShow( pSlideShow ),
107 mrOutputWindow( rOutputWindow ),
108 mpDoc( pDoc ),
109 mbIsMouseMotionListener( false ),
110 meAnimationMode( eAnimationMode ),
111 mbFirstPaint( true ),
112 mbMousePressedEaten( false )
114 mxWindow->addWindowListener( this );
115 mxWindow->addMouseListener( this );
117 mxPointer = awt::Pointer::create( ::comphelper::getProcessComponentContext() );
119 getTransformation();
121 // #i48939# only switch on kind of hacky scroll optimization, when
122 // running fullscreen. this minimizes the probability that other
123 // windows partially cover the show.
124 if( bFullScreen )
128 Reference< beans::XPropertySet > xCanvasProps( getCanvas(),
129 uno::UNO_QUERY_THROW );
130 xCanvasProps->setPropertyValue(u"UnsafeScrolling"_ustr,
131 uno::Any( true ) );
133 catch( uno::Exception& )
138 mTranslationOffset.Width = 0;
139 mTranslationOffset.Height = 0;
142 // Dispose all internal references
143 void SlideShowView::disposing(std::unique_lock<std::mutex>& rGuard)
145 mpSlideShow = nullptr;
147 // deregister listeners
148 if( mxWindow.is() )
150 mxWindow->removeWindowListener( this );
151 mxWindow->removeMouseListener( this );
153 if( mbIsMouseMotionListener )
154 mxWindow->removeMouseMotionListener( this );
157 mpCanvas.reset();
158 mxWindow.clear();
160 // clear all listener containers
161 disposingImpl(rGuard);
164 // Disposing our broadcaster
165 void SAL_CALL SlideShowView::disposing( const lang::EventObject& )
167 std::unique_lock aGuard( m_aMutex );
169 disposingImpl(aGuard);
172 // Disposing our broadcaster
173 void SlideShowView::disposingImpl(std::unique_lock<std::mutex>& rGuard)
175 // notify all listeners that _we_ are going down (send a disposing()),
176 // then delete listener containers:
177 lang::EventObject const evt( static_cast<OWeakObject *>(this) );
178 if (!maViewListeners.empty())
180 auto tmp = std::move(maViewListeners);
181 rGuard.unlock();
182 for( const auto& rxListener : tmp )
184 Reference< util::XModifyListener > xListener( rxListener );
185 if( xListener.is() )
186 xListener->disposing( evt );
188 rGuard.lock();
190 if (maPaintListeners.getLength(rGuard))
192 maPaintListeners.disposeAndClear( rGuard, evt );
193 rGuard.lock();
195 if (maMouseListeners.getLength(rGuard))
197 maMouseListeners.disposeAndClear( rGuard, evt );
198 rGuard.lock();
200 if (maMouseMotionListeners.getLength(rGuard))
202 maMouseMotionListeners.disposeAndClear( rGuard, evt );
203 rGuard.lock();
207 void SlideShowView::paint( const awt::PaintEvent& e )
209 std::unique_lock aGuard( m_aMutex );
211 if( mbFirstPaint )
213 mbFirstPaint = false;
214 SlideshowImpl* pSlideShow = mpSlideShow;
215 aGuard.unlock();
216 if( pSlideShow )
217 pSlideShow->onFirstPaint();
219 else
221 // Change event source, to enable listeners to match event
222 // with view
223 awt::PaintEvent aEvent( e );
224 aEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
225 maPaintListeners.notifyEach( aGuard, &css::awt::XPaintListener::windowPaint, aEvent );
226 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
230 // XSlideShowView methods
231 Reference< rendering::XSpriteCanvas > SAL_CALL SlideShowView::getCanvas( )
233 std::unique_lock aGuard( m_aMutex );
235 return mpCanvas ? mpCanvas->getUNOSpriteCanvas() : Reference< rendering::XSpriteCanvas >();
238 void SAL_CALL SlideShowView::clear()
240 // paint background in black
241 std::unique_lock aGuard( m_aMutex );
242 SolarMutexGuard aSolarGuard;
244 // fill the bounds rectangle in black
246 const Size aWindowSize( mrOutputWindow.GetSizePixel() );
248 ::basegfx::B2DPolygon aPoly( ::basegfx::utils::createPolygonFromRect(
249 ::basegfx::B2DRectangle(0.0,0.0,
250 aWindowSize.Width(),
251 aWindowSize.Height() ) ) );
252 ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
253 ::cppcanvas::BaseGfxFactory::createPolyPolygon( mpCanvas, aPoly ) );
255 if( pPolyPoly )
257 pPolyPoly->setRGBAFillColor( 0x000000FFU );
258 pPolyPoly->draw();
262 geometry::IntegerSize2D SAL_CALL SlideShowView::getTranslationOffset( )
264 return mTranslationOffset;
267 geometry::AffineMatrix2D SAL_CALL SlideShowView::getTransformation( )
269 std::unique_lock aGuard( m_aMutex );
270 SolarMutexGuard aSolarGuard;
272 const Size aTmpSize( mrOutputWindow.GetSizePixel() );
274 if (aTmpSize.IsEmpty())
276 return geometry::AffineMatrix2D (1,0,0,0,1,0);
279 const Size aWindowSize( mrOutputWindow.GetSizePixel() );
280 Size aOutputSize( aWindowSize );
282 if( meAnimationMode != ANIMATIONMODE_SHOW )
284 aOutputSize.setWidth( static_cast<::tools::Long>( aOutputSize.Width() / 1.03 ) );
285 aOutputSize.setHeight( static_cast<::tools::Long>( aOutputSize.Height() / 1.03 ) );
288 SdPage* pP = mpDoc->GetSdPage( 0, PageKind::Standard );
289 Size aPageSize( pP->GetSize() );
291 const double page_ratio = static_cast<double>(aPageSize.Width()) / static_cast<double>(aPageSize.Height());
292 const double output_ratio = static_cast<double>(aOutputSize.Width()) / static_cast<double>(aOutputSize.Height());
294 if( page_ratio > output_ratio )
296 aOutputSize.setHeight( ( aOutputSize.Width() * aPageSize.Height() ) / aPageSize.Width() );
298 else if( page_ratio < output_ratio )
300 aOutputSize.setWidth( ( aOutputSize.Height() * aPageSize.Width() ) / aPageSize.Height() );
303 Point aOutputOffset( ( aWindowSize.Width() - aOutputSize.Width() ) >> 1,
304 ( aWindowSize.Height() - aOutputSize.Height() ) >> 1 );
306 // Reduce available width by one, as the slides might actually
307 // render one pixel wider and higher as aPageSize below specifies
308 // (when shapes of page size have visible border lines)
309 aOutputSize.AdjustWidth( -1 );
310 aOutputSize.AdjustHeight( -1 );
312 // Record mTranslationOffset
313 mTranslationOffset.Height = aOutputOffset.Y();
314 mTranslationOffset.Width = aOutputOffset.X();
316 // scale presentation into available window rect (minus 10%); center in the window
317 const basegfx::B2DHomMatrix aMatrix(basegfx::utils::createScaleTranslateB2DHomMatrix(
318 aOutputSize.Width(), aOutputSize.Height(), aOutputOffset.X(), aOutputOffset.Y()));
320 geometry::AffineMatrix2D aRes;
322 return ::basegfx::unotools::affineMatrixFromHomMatrix( aRes, aMatrix );
325 void SAL_CALL SlideShowView::addTransformationChangedListener( const Reference< util::XModifyListener >& xListener )
327 std::unique_lock aGuard( m_aMutex );
329 if (m_bDisposed)
330 return;
331 WeakReference< util::XModifyListener > xWeak( xListener );
332 if( std::find( maViewListeners.begin(), maViewListeners.end(), xWeak ) == maViewListeners.end() )
333 maViewListeners.push_back( xWeak );
336 void SAL_CALL SlideShowView::removeTransformationChangedListener( const Reference< util::XModifyListener >& xListener )
338 std::unique_lock aGuard( m_aMutex );
340 if (m_bDisposed)
341 return;
342 WeakReference< util::XModifyListener > xWeak( xListener );
343 auto aIter( std::find( maViewListeners.begin(), maViewListeners.end(), xWeak ) );
344 if( aIter != maViewListeners.end() )
345 maViewListeners.erase( aIter );
348 void SAL_CALL SlideShowView::addPaintListener( const Reference< awt::XPaintListener >& xListener )
350 std::unique_lock aGuard( m_aMutex );
352 if (!m_bDisposed)
353 maPaintListeners.addInterface( aGuard, xListener );
356 void SAL_CALL SlideShowView::removePaintListener( const Reference< awt::XPaintListener >& xListener )
358 std::unique_lock aGuard( m_aMutex );
360 if (!m_bDisposed)
361 maPaintListeners.removeInterface( aGuard, xListener );
364 void SAL_CALL SlideShowView::addMouseListener( const Reference< awt::XMouseListener >& xListener )
366 std::unique_lock aGuard( m_aMutex );
368 if (!m_bDisposed)
369 maMouseListeners.addInterface( aGuard, xListener );
372 void SAL_CALL SlideShowView::removeMouseListener( const Reference< awt::XMouseListener >& xListener )
374 std::unique_lock aGuard( m_aMutex );
376 if (!m_bDisposed)
377 maMouseListeners.removeInterface( aGuard, xListener );
380 void SAL_CALL SlideShowView::addMouseMotionListener( const Reference< awt::XMouseMotionListener >& xListener )
382 std::unique_lock aGuard( m_aMutex );
384 if (m_bDisposed)
385 return;
387 if( !mbIsMouseMotionListener && mxWindow.is() )
389 // delay motion event registration, until we really
390 // need it
391 mbIsMouseMotionListener = true;
392 mxWindow->addMouseMotionListener( this );
395 maMouseMotionListeners.addInterface( aGuard, xListener );
398 void SAL_CALL SlideShowView::removeMouseMotionListener( const Reference< awt::XMouseMotionListener >& xListener )
400 std::unique_lock aGuard( m_aMutex );
402 if (!m_bDisposed)
403 maMouseMotionListeners.removeInterface( aGuard, xListener );
405 // TODO(P1): Might be nice to deregister for mouse motion
406 // events, when the last listener is gone.
409 void SAL_CALL SlideShowView::setMouseCursor( sal_Int16 nPointerShape )
411 std::unique_lock aGuard( m_aMutex );
413 // forward to window
414 if( mxPointer.is() )
415 mxPointer->setType( nPointerShape );
417 if( mxWindowPeer.is() )
418 mxWindowPeer->setPointer( mxPointer );
421 awt::Rectangle SAL_CALL SlideShowView::getCanvasArea( )
423 awt::Rectangle aRectangle;
425 if( mxWindow.is() )
426 return mxWindow->getPosSize();
428 aRectangle.X = aRectangle.Y = aRectangle.Width = aRectangle.Height = 0;
430 return aRectangle;
433 void SlideShowView::updateimpl( std::unique_lock<std::mutex>& rGuard, SlideshowImpl* pSlideShow )
435 if( !pSlideShow )
436 return;
438 ::rtl::Reference< SlideshowImpl > xKeepAlive( pSlideShow );
440 if( mbFirstPaint )
442 mbFirstPaint = false;
443 SlideshowImpl* pTmpSlideShow = mpSlideShow;
444 rGuard.unlock();
445 if( pTmpSlideShow )
446 pTmpSlideShow->onFirstPaint();
447 } else
448 rGuard.unlock();
450 pSlideShow->startUpdateTimer();
453 // XWindowListener methods
454 void SAL_CALL SlideShowView::windowResized( const awt::WindowEvent& e )
456 std::unique_lock aGuard( m_aMutex );
458 if (m_bDisposed)
459 return;
461 if (!maViewListeners.empty())
463 // Change event source, to enable listeners to match event
464 // with view
465 awt::WindowEvent aEvent( e );
466 aEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
467 auto aIter( maViewListeners.begin() );
468 while( aIter != maViewListeners.end() )
470 Reference< util::XModifyListener > xListener( *aIter );
471 if( xListener.is() )
473 aGuard.unlock();
474 xListener->modified( aEvent );
475 aGuard.lock();
476 ++aIter;
478 else
480 aIter = maViewListeners.erase( aIter );
485 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
488 void SAL_CALL SlideShowView::windowMoved( const awt::WindowEvent& )
490 // ignored
493 void SAL_CALL SlideShowView::windowShown( const lang::EventObject& )
495 // ignored
498 void SAL_CALL SlideShowView::windowHidden( const lang::EventObject& )
500 // ignored
503 // XMouseListener implementation
504 void SAL_CALL SlideShowView::mousePressed( const awt::MouseEvent& e )
506 std::unique_lock aGuard( m_aMutex );
507 if (m_bDisposed)
508 return;
510 if( mpSlideShow && mpSlideShow->isInputFreezed() )
512 mbMousePressedEaten = true;
514 else
516 mbMousePressedEaten = false;
518 // Change event source, to enable listeners to match event
519 // with view
520 WrappedMouseEvent aEvent;
521 aEvent.meType = WrappedMouseEvent::PRESSED;
522 aEvent.maEvent = e;
523 aEvent.maEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
525 maMouseListeners.notify( aGuard, aEvent );
526 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
530 void SAL_CALL SlideShowView::mouseReleased( const awt::MouseEvent& e )
532 std::unique_lock aGuard( m_aMutex );
533 if (m_bDisposed)
534 return;
536 if( mbMousePressedEaten )
538 // if mouse button down was ignored, also ignore mouse button up
539 mbMousePressedEaten = false;
541 else if( mpSlideShow && !mpSlideShow->isInputFreezed() )
543 // Change event source, to enable listeners to match event
544 // with view
545 WrappedMouseEvent aEvent;
546 aEvent.meType = WrappedMouseEvent::RELEASED;
547 aEvent.maEvent = e;
548 aEvent.maEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
550 maMouseListeners.notify( aGuard, aEvent );
551 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
555 void SlideShowView::ignoreNextMouseReleased()
557 std::unique_lock aGuard( m_aMutex );
558 mbMousePressedEaten = true;
561 void SAL_CALL SlideShowView::mouseEntered( const awt::MouseEvent& e )
563 std::unique_lock aGuard( m_aMutex );
564 if (m_bDisposed)
565 return;
567 // Change event source, to enable listeners to match event
568 // with view
569 WrappedMouseEvent aEvent;
570 aEvent.meType = WrappedMouseEvent::ENTERED;
571 aEvent.maEvent = e;
572 aEvent.maEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
574 maMouseListeners.notify( aGuard, aEvent );
575 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
578 void SAL_CALL SlideShowView::mouseExited( const awt::MouseEvent& e )
580 std::unique_lock aGuard( m_aMutex );
581 if (m_bDisposed)
582 return;
584 // Change event source, to enable listeners to match event
585 // with view
586 WrappedMouseEvent aEvent;
587 aEvent.meType = WrappedMouseEvent::EXITED;
588 aEvent.maEvent = e;
589 aEvent.maEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
591 maMouseListeners.notify( aGuard, aEvent );
592 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
595 // XMouseMotionListener implementation
596 void SAL_CALL SlideShowView::mouseDragged( const awt::MouseEvent& e )
598 std::unique_lock aGuard( m_aMutex );
599 if (m_bDisposed)
600 return;
602 // Change event source, to enable listeners to match event
603 // with view
604 WrappedMouseMotionEvent aEvent;
605 aEvent.meType = WrappedMouseMotionEvent::DRAGGED;
606 aEvent.maEvent = e;
607 aEvent.maEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
609 maMouseMotionListeners.notify( aGuard, aEvent );
610 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
613 void SAL_CALL SlideShowView::mouseMoved( const awt::MouseEvent& e )
615 std::unique_lock aGuard( m_aMutex );
616 if (m_bDisposed)
617 return;
619 // Change event source, to enable listeners to match event
620 // with view
621 WrappedMouseMotionEvent aEvent;
622 aEvent.meType = WrappedMouseMotionEvent::MOVED;
623 aEvent.maEvent = e;
624 aEvent.maEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
626 maMouseMotionListeners.notify( aGuard, aEvent );
627 updateimpl( aGuard, mpSlideShow ); // warning: clears guard!
630 } // namespace ::sd
632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */