1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26 
27 #include "PresenterSlideShowView.hxx"
28 
29 #include "PresenterCanvasHelper.hxx"
30 #include "PresenterGeometryHelper.hxx"
31 #include "PresenterHelper.hxx"
32 #include "PresenterPaneContainer.hxx"
33 #include <com/sun/star/awt/InvalidateStyle.hpp>
34 #include <com/sun/star/awt/PosSize.hpp>
35 #include <com/sun/star/awt/WindowAttribute.hpp>
36 #include <com/sun/star/awt/XWindow.hpp>
37 #include <com/sun/star/awt/XWindow2.hpp>
38 #include <com/sun/star/awt/XWindowPeer.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/drawing/CanvasFeature.hpp>
41 #include <com/sun/star/drawing/XPresenterHelper.hpp>
42 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
43 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
44 #include <com/sun/star/rendering/CompositeOperation.hpp>
45 #include <com/sun/star/rendering/TextDirection.hpp>
46 #include <com/sun/star/rendering/TexturingMode.hpp>
47 #include <osl/mutex.hxx>
48 
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::drawing::framework;
52 using ::rtl::OUString;
53 
54 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
55 
56 namespace sdext { namespace presenter {
57 
58 //===== PresenterSlideShowView ================================================
59 
PresenterSlideShowView(const css::uno::Reference<css::uno::XComponentContext> & rxContext,const css::uno::Reference<css::drawing::framework::XResourceId> & rxViewId,const css::uno::Reference<css::frame::XController> & rxController,const::rtl::Reference<PresenterController> & rpPresenterController)60 PresenterSlideShowView::PresenterSlideShowView (
61     const css::uno::Reference<css::uno::XComponentContext>& rxContext,
62     const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId,
63     const css::uno::Reference<css::frame::XController>& rxController,
64     const ::rtl::Reference<PresenterController>& rpPresenterController)
65     : PresenterSlideShowViewInterfaceBase(m_aMutex),
66       mxComponentContext(rxContext),
67       mpPresenterController(rpPresenterController),
68       mxViewId(rxViewId),
69       mxController(rxController),
70       mxSlideShowController(PresenterHelper::GetSlideShowController(rxController)),
71       mxSlideShow(),
72       mxCanvas(),
73       mxViewCanvas(),
74       mxPointer(),
75       mxWindow(),
76       mxViewWindow(),
77       mxTopPane(),
78       mxPresenterHelper(),
79       mxBackgroundPolygon1(),
80       mxBackgroundPolygon2(),
81       mbIsViewAdded(false),
82       mnPageAspectRatio(28.0/21.0),
83       maBroadcaster(m_aMutex),
84       mpBackground(),
85       mbIsInModifyNotification(false),
86       mbIsForcedPaintPending(false),
87       mbIsPaintPending(true),
88       msClickToExitPresentationText(),
89       msClickToExitPresentationTitle(),
90       msTitleTemplate(),
91       mbIsEndSlideVisible(false),
92       mxCurrentSlide()
93 {
94     if (mpPresenterController.get() != NULL)
95     {
96         mnPageAspectRatio = mpPresenterController->GetSlideAspectRatio();
97         mpBackground = mpPresenterController->GetViewBackground(mxViewId->getResourceURL());
98     }
99 }
100 
101 
102 
LateInit(void)103 void PresenterSlideShowView::LateInit (void)
104 {
105     mxSlideShow = Reference<presentation::XSlideShow> (
106         mxSlideShowController->getSlideShow(), UNO_QUERY_THROW);
107     Reference<lang::XComponent> xSlideShowComponent (mxSlideShow, UNO_QUERY);
108     if (xSlideShowComponent.is())
109         xSlideShowComponent->addEventListener(static_cast<awt::XWindowListener*>(this));
110 
111     Reference<lang::XMultiComponentFactory> xFactory (
112         mxComponentContext->getServiceManager(), UNO_QUERY_THROW);
113     mxPresenterHelper.set (xFactory->createInstanceWithContext(
114 			       OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
115 			       mxComponentContext),
116 			   UNO_QUERY_THROW);
117 
118     // Use view id and controller to retrieve window and canvas from
119     // configuration controller.
120     Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW);
121     Reference<XConfigurationController> xCC (xCM->getConfigurationController());
122 
123     if (xCC.is())
124     {
125 	mxTopPane.set(xCC->getResource(mxViewId->getAnchor()->getAnchor()), UNO_QUERY);
126 
127         Reference<XPane> xPane (xCC->getResource(mxViewId->getAnchor()), UNO_QUERY_THROW);
128 
129         mxWindow = xPane->getWindow();
130         mxCanvas = xPane->getCanvas();
131 
132         if (mxWindow.is())
133         {
134             mxWindow->addPaintListener(this);
135             mxWindow->addWindowListener(this);
136         }
137 
138         // The window does not have to paint a background.  We do
139         // that ourself.
140         Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
141         if (xPeer.is())
142             xPeer->setBackground(util::Color(0xff000000));
143     }
144 
145     // Create a window for the actual slide show view.  It is places
146     // centered and with maximal size inside the pane.
147     mxViewWindow = CreateViewWindow(mxWindow);
148 
149     mxViewCanvas = CreateViewCanvas(mxViewWindow);
150 
151     if (mxViewWindow.is())
152     {
153         // Register listeners at window.
154         mxViewWindow->addPaintListener(this);
155         mxViewWindow->addMouseListener(this);
156         mxViewWindow->addMouseMotionListener(this);
157     }
158 
159     if (mxViewWindow.is())
160         Resize();
161 
162     if (mxWindow.is())
163         mxWindow->setVisible(sal_True);
164 
165     // Add the new slide show view to the slide show.
166     if (mxSlideShow.is() && ! mbIsViewAdded)
167     {
168         Reference<presentation::XSlideShowView> xView (this);
169         mxSlideShow->addView(xView);
170         // Prevent embedded sounds being played twice at the same time by
171         // disabling sound for the new slide show view.
172         beans::PropertyValue aProperty;
173         aProperty.Name = A2S("IsSoundEnabled");
174         Sequence<Any> aValues (2);
175         aValues[0] <<= xView;
176         aValues[1] <<= sal_False;
177         aProperty.Value <<= aValues;
178         mxSlideShow->setProperty(aProperty);
179         mbIsViewAdded = true;
180     }
181 
182     // Read text for one past last slide.
183     PresenterConfigurationAccess aConfiguration (
184         mxComponentContext,
185         PresenterConfigurationAccess::msPresenterScreenRootName,
186         PresenterConfigurationAccess::READ_ONLY);
187     aConfiguration.GetConfigurationNode(
188         A2S("Presenter/Views/CurrentSlidePreview/"
189             "Strings/ClickToExitPresentationText/String"))
190         >>= msClickToExitPresentationText;
191     aConfiguration.GetConfigurationNode(
192         A2S("Presenter/Views/CurrentSlidePreview/"
193             "Strings/ClickToExitPresentationTitle/String"))
194         >>= msClickToExitPresentationTitle;
195 }
196 
197 
198 
199 
~PresenterSlideShowView(void)200 PresenterSlideShowView::~PresenterSlideShowView (void)
201 {
202 }
203 
204 
205 
206 
disposing(void)207 void PresenterSlideShowView::disposing (void)
208 {
209     // Tell all listeners that we are disposed.
210     lang::EventObject aEvent;
211     aEvent.Source = static_cast<XWeak*>(this);
212 
213     ::cppu::OInterfaceContainerHelper* pIterator
214           = maBroadcaster.getContainer(getCppuType((Reference<lang::XEventListener>*)NULL));
215     if (pIterator != NULL)
216         pIterator->disposeAndClear(aEvent);
217 
218     // Do this for
219     // XPaintListener, XModifyListener,XMouseListener,XMouseMotionListener,XWindowListener?
220 
221     if (mxWindow.is())
222     {
223         mxWindow->removePaintListener(this);
224         mxWindow->removeMouseListener(this);
225         mxWindow->removeMouseMotionListener(this);
226         mxWindow->removeWindowListener(this);
227         mxWindow = NULL;
228     }
229     mxSlideShowController = NULL;
230     mxSlideShow = NULL;
231     if (mxViewCanvas.is())
232     {
233         Reference<XComponent> xComponent (mxViewCanvas, UNO_QUERY);
234         mxViewCanvas = NULL;
235         if (xComponent.is())
236             xComponent->dispose();
237     }
238     if (mxViewWindow.is())
239     {
240         Reference<XComponent> xComponent (mxViewWindow, UNO_QUERY);
241         mxViewWindow = NULL;
242         if (xComponent.is())
243             xComponent->dispose();
244     }
245     if (mxPointer.is())
246     {
247         Reference<XComponent> xComponent (mxPointer, UNO_QUERY);
248         mxPointer = NULL;
249         if (xComponent.is())
250             xComponent->dispose();
251     }
252     if (mxBackgroundPolygon1.is())
253     {
254         Reference<XComponent> xComponent (mxBackgroundPolygon1, UNO_QUERY);
255         mxBackgroundPolygon1 = NULL;
256         if (xComponent.is())
257             xComponent->dispose();
258     }
259     if (mxBackgroundPolygon2.is())
260     {
261         Reference<XComponent> xComponent (mxBackgroundPolygon2, UNO_QUERY);
262         mxBackgroundPolygon2 = NULL;
263         if (xComponent.is())
264             xComponent->dispose();
265     }
266 
267     mxComponentContext = NULL;
268     mpPresenterController = NULL;
269     mxViewId = NULL;
270     mxController = NULL;
271     mxCanvas = NULL;
272     mpBackground.reset();
273     msClickToExitPresentationText = OUString();
274     msClickToExitPresentationTitle = OUString();
275     msTitleTemplate = OUString();
276     mxCurrentSlide = NULL;
277 }
278 
279 
280 
281 
282 //----- XDrawView -------------------------------------------------------------
283 
setCurrentPage(const css::uno::Reference<css::drawing::XDrawPage> & rxSlide)284 void SAL_CALL PresenterSlideShowView::setCurrentPage (
285     const css::uno::Reference<css::drawing::XDrawPage>& rxSlide)
286     throw (css::uno::RuntimeException)
287 {
288     mxCurrentSlide = rxSlide;
289     if (mpPresenterController.get() != NULL
290         && mxSlideShowController.is()
291         && ! mpPresenterController->GetCurrentSlide().is()
292         && ! mxSlideShowController->isPaused())
293     {
294         mbIsEndSlideVisible = true;
295         Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY);
296         if (xPeer.is())
297             xPeer->invalidate(awt::InvalidateStyle::NOTRANSPARENT);
298 
299         // For the end slide we use a special title, without the (n of m)
300         // part.  Save the title template for the case that the user goes
301         // backwards.
302         PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
303             mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL()));
304         if (pDescriptor.get() != NULL)
305         {
306             msTitleTemplate = pDescriptor->msTitleTemplate;
307             pDescriptor->msTitleTemplate = msClickToExitPresentationTitle;
308             mpPresenterController->UpdatePaneTitles();
309         }
310     }
311     else if (mbIsEndSlideVisible)
312     {
313         mbIsEndSlideVisible = false;
314 
315         // Restore the title template.
316         PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
317             mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL()));
318         if (pDescriptor.get() != NULL)
319         {
320             pDescriptor->msTitleTemplate = msTitleTemplate;
321             pDescriptor->msTitle = OUString();
322             mpPresenterController->UpdatePaneTitles();
323         }
324     }
325 }
326 
327 
328 
329 
getCurrentPage(void)330 css::uno::Reference<css::drawing::XDrawPage> SAL_CALL PresenterSlideShowView::getCurrentPage (void)
331     throw (css::uno::RuntimeException)
332 {
333     return mxCurrentSlide;
334 }
335 
336 
337 
338 
339 //----- CachablePresenterView -------------------------------------------------
340 
ReleaseView(void)341 void PresenterSlideShowView::ReleaseView (void)
342 {
343     if (mxSlideShow.is() && mbIsViewAdded)
344     {
345         mxSlideShow->removeView(this);
346         mbIsViewAdded = false;
347     }
348 }
349 
350 
351 
352 
353 //----- XSlideShowView --------------------------------------------------------
354 
getCanvas(void)355 Reference<rendering::XSpriteCanvas> SAL_CALL PresenterSlideShowView::getCanvas (void)
356     throw (RuntimeException)
357 {
358     ThrowIfDisposed();
359 
360     return Reference<rendering::XSpriteCanvas>(mxViewCanvas, UNO_QUERY);
361 }
362 
363 
364 
365 
clear(void)366 void SAL_CALL PresenterSlideShowView::clear (void)
367     throw (RuntimeException)
368 {
369     ThrowIfDisposed();
370     mbIsForcedPaintPending = false;
371     mbIsPaintPending = false;
372 
373     if (mxViewCanvas.is() && mxViewWindow.is())
374     {
375         // Create a polygon for the window outline.
376         awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize());
377         Reference<rendering::XPolyPolygon2D> xPolygon (PresenterGeometryHelper::CreatePolygon(
378             awt::Rectangle(0,0, aViewWindowBox.Width,aViewWindowBox.Height),
379             mxViewCanvas->getDevice()));
380 
381         rendering::ViewState aViewState (
382             geometry::AffineMatrix2D(1,0,0, 0,1,0),
383             NULL);
384         double aColor[3] = {0,0,0};
385         rendering::RenderState aRenderState(
386             geometry::AffineMatrix2D(1,0,0, 0,1,0),
387             NULL,
388             Sequence<double>(aColor,4),
389             rendering::CompositeOperation::SOURCE);
390         mxViewCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState);
391     }
392 }
393 
394 
395 
396 
getTransformation(void)397 geometry::AffineMatrix2D SAL_CALL PresenterSlideShowView::getTransformation (void)
398     throw (RuntimeException)
399 {
400     ThrowIfDisposed();
401 
402     if (mxViewWindow.is())
403     {
404         // When the mbIsInModifyNotification is set then a slightly modifed
405         // version of the transformation is returned in order to get past
406         // optimizations the avoid updates when the transformation is
407         // unchanged (when the window size changes then due to the constant
408         // aspect ratio the size of the preview may remain the same while
409         // the position changes.  The position, however, is repesented by
410         // the position of the view window.  This transformation is given
411         // relative to the view window and therefore does not contain the
412         // position.)
413         const awt::Rectangle aWindowBox = mxViewWindow->getPosSize();
414         return geometry::AffineMatrix2D(
415             aWindowBox.Width-1, 0, (mbIsInModifyNotification ? 1 : 0),
416             0, aWindowBox.Height-1, 0);
417     }
418     else
419     {
420         return geometry::AffineMatrix2D(1,0,0, 0,1,0);
421     }
422 }
423 
424 
425 
426 
addTransformationChangedListener(const Reference<util::XModifyListener> & rxListener)427 void SAL_CALL PresenterSlideShowView::addTransformationChangedListener(
428     const Reference<util::XModifyListener>& rxListener)
429     throw (RuntimeException)
430 {
431     ThrowIfDisposed();
432     maBroadcaster.addListener(
433         getCppuType((Reference<util::XModifyListener>*)NULL),
434         rxListener);
435 }
436 
437 
438 
439 
removeTransformationChangedListener(const Reference<util::XModifyListener> & rxListener)440 void SAL_CALL PresenterSlideShowView::removeTransformationChangedListener(
441     const Reference<util::XModifyListener>& rxListener)
442     throw (RuntimeException)
443 {
444     ThrowIfDisposed();
445     maBroadcaster.removeListener(
446         getCppuType((Reference<util::XModifyListener>*)NULL),
447         rxListener);
448 }
449 
450 
451 
452 
addPaintListener(const Reference<awt::XPaintListener> & rxListener)453 void SAL_CALL PresenterSlideShowView::addPaintListener(
454     const Reference<awt::XPaintListener>& rxListener)
455     throw (RuntimeException)
456 {
457     ThrowIfDisposed();
458     maBroadcaster.addListener(
459         getCppuType((Reference<awt::XPaintListener>*)NULL),
460         rxListener);
461 }
462 
463 
464 
465 
removePaintListener(const Reference<awt::XPaintListener> & rxListener)466 void SAL_CALL PresenterSlideShowView::removePaintListener(
467     const Reference<awt::XPaintListener>& rxListener)
468     throw (RuntimeException)
469 {
470     ThrowIfDisposed();
471     maBroadcaster.removeListener(
472         getCppuType((Reference<awt::XPaintListener>*)NULL),
473         rxListener);
474 }
475 
476 
477 
478 
addMouseListener(const Reference<awt::XMouseListener> & rxListener)479 void SAL_CALL PresenterSlideShowView::addMouseListener(
480     const Reference<awt::XMouseListener>& rxListener)
481     throw (RuntimeException)
482 {
483     ThrowIfDisposed();
484     maBroadcaster.addListener(
485         getCppuType((Reference<awt::XMouseListener>*)NULL),
486         rxListener);
487 }
488 
489 
490 
491 
removeMouseListener(const Reference<awt::XMouseListener> & rxListener)492 void SAL_CALL PresenterSlideShowView::removeMouseListener(
493     const Reference<awt::XMouseListener>& rxListener)
494     throw (RuntimeException)
495 {
496     ThrowIfDisposed();
497     maBroadcaster.removeListener(
498         getCppuType((Reference<awt::XMouseListener>*)NULL),
499         rxListener);
500 }
501 
502 
503 
504 
addMouseMotionListener(const Reference<awt::XMouseMotionListener> & rxListener)505 void SAL_CALL PresenterSlideShowView::addMouseMotionListener(
506     const Reference<awt::XMouseMotionListener>& rxListener)
507     throw (RuntimeException)
508 {
509     ThrowIfDisposed();
510     maBroadcaster.addListener(
511         getCppuType((Reference<awt::XMouseMotionListener>*)NULL),
512         rxListener);
513 }
514 
515 
516 
517 
removeMouseMotionListener(const Reference<awt::XMouseMotionListener> & rxListener)518 void SAL_CALL PresenterSlideShowView::removeMouseMotionListener(
519     const Reference<awt::XMouseMotionListener>& rxListener)
520     throw (RuntimeException)
521 {
522     ThrowIfDisposed();
523     maBroadcaster.removeListener(
524         getCppuType((Reference<awt::XMouseMotionListener>*)NULL),
525         rxListener);
526 }
527 
528 
529 
530 
setMouseCursor(::sal_Int16 nPointerShape)531 void SAL_CALL PresenterSlideShowView::setMouseCursor(::sal_Int16 nPointerShape)
532     throw (RuntimeException)
533 {
534     ThrowIfDisposed();
535 
536     // Create a pointer when it does not yet exist.
537     if ( ! mxPointer.is())
538     {
539         Reference<lang::XMultiServiceFactory> xFactory (
540             mxComponentContext, UNO_QUERY);
541         if (xFactory.is())
542             mxPointer = Reference<awt::XPointer>(
543                 xFactory->createInstance(OUString::createFromAscii("com.sun.star.awt.Pointer")),
544                 UNO_QUERY);
545     }
546 
547     // Set the pointer to the given shape and the window(peer) to the
548     // pointer.
549     Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY);
550     if (mxPointer.is() && xPeer.is())
551     {
552         mxPointer->setType(nPointerShape);
553         xPeer->setPointer(mxPointer);
554     }
555 }
556 
557 
558 
getCanvasArea()559 awt::Rectangle SAL_CALL PresenterSlideShowView::getCanvasArea(  ) throw (RuntimeException)
560 {
561     if( mxViewWindow.is() && mxTopPane.is() )
562 	return mxPresenterHelper->getWindowExtentsRelative( mxViewWindow, mxTopPane->getWindow() );
563 
564     awt::Rectangle aRectangle;
565 
566     aRectangle.X = aRectangle.Y = aRectangle.Width = aRectangle.Height = 0;
567 
568     return aRectangle;
569 }
570 
571 
572 
573 //----- lang::XEventListener --------------------------------------------------
574 
disposing(const lang::EventObject & rEvent)575 void SAL_CALL PresenterSlideShowView::disposing (const lang::EventObject& rEvent)
576     throw (RuntimeException)
577 {
578     if (rEvent.Source == mxViewWindow)
579         mxViewWindow = NULL;
580     else if (rEvent.Source == mxSlideShow)
581         mxSlideShow = NULL;
582 }
583 
584 
585 
586 
587 //----- XPaintListener --------------------------------------------------------
588 
windowPaint(const awt::PaintEvent & rEvent)589 void SAL_CALL PresenterSlideShowView::windowPaint (const awt::PaintEvent& rEvent)
590     throw (RuntimeException)
591 {
592     // Deactivated views must not be painted.
593     if ( ! mbIsPresenterViewActive)
594         return;
595 
596     awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize());
597     if (aViewWindowBox.Width <= 0 || aViewWindowBox.Height <= 0)
598         return;
599 
600     if (rEvent.Source == mxWindow)
601         PaintOuterWindow(rEvent.UpdateRect);
602     else if (mbIsEndSlideVisible)
603         PaintEndSlide(rEvent.UpdateRect);
604     else
605         PaintInnerWindow(rEvent);
606 }
607 
608 
609 
610 
611 //----- XMouseListener --------------------------------------------------------
612 
mousePressed(const awt::MouseEvent & rEvent)613 void SAL_CALL PresenterSlideShowView::mousePressed (const awt::MouseEvent& rEvent)
614     throw (RuntimeException)
615 {
616     awt::MouseEvent aEvent (rEvent);
617     aEvent.Source = static_cast<XWeak*>(this);
618     ::cppu::OInterfaceContainerHelper* pIterator
619         = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL));
620     if (pIterator != NULL)
621     {
622         pIterator->notifyEach(&awt::XMouseListener::mousePressed, aEvent);
623     }
624 
625     // Only when the end slide is displayed we forward the mouse event to
626     // the PresenterController so that it switches to the next slide and
627     // ends the presentation.
628     if (mbIsEndSlideVisible)
629         if (mpPresenterController.get() != NULL)
630             mpPresenterController->HandleMouseClick(rEvent);
631 }
632 
633 
634 
635 
mouseReleased(const awt::MouseEvent & rEvent)636 void SAL_CALL PresenterSlideShowView::mouseReleased (const awt::MouseEvent& rEvent)
637     throw (RuntimeException)
638 {
639     awt::MouseEvent aEvent (rEvent);
640     aEvent.Source = static_cast<XWeak*>(this);
641     ::cppu::OInterfaceContainerHelper* pIterator
642         = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL));
643     if (pIterator != NULL)
644     {
645         pIterator->notifyEach(&awt::XMouseListener::mouseReleased, aEvent);
646     }
647 }
648 
649 
650 
651 
mouseEntered(const awt::MouseEvent & rEvent)652 void SAL_CALL PresenterSlideShowView::mouseEntered (const awt::MouseEvent& rEvent)
653     throw (RuntimeException)
654 {
655     awt::MouseEvent aEvent (rEvent);
656     aEvent.Source = static_cast<XWeak*>(this);
657     ::cppu::OInterfaceContainerHelper* pIterator
658         = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL));
659     if (pIterator != NULL)
660     {
661         pIterator->notifyEach(&awt::XMouseListener::mouseEntered, aEvent);
662     }
663 }
664 
665 
666 
667 
mouseExited(const awt::MouseEvent & rEvent)668 void SAL_CALL PresenterSlideShowView::mouseExited (const awt::MouseEvent& rEvent)
669     throw (RuntimeException)
670 {
671     awt::MouseEvent aEvent (rEvent);
672     aEvent.Source = static_cast<XWeak*>(this);
673     ::cppu::OInterfaceContainerHelper* pIterator
674         = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL));
675     if (pIterator != NULL)
676     {
677         pIterator->notifyEach(&awt::XMouseListener::mouseExited, aEvent);
678     }
679 }
680 
681 
682 
683 
684 //----- XMouseMotionListener --------------------------------------------------
685 
mouseDragged(const awt::MouseEvent & rEvent)686 void SAL_CALL PresenterSlideShowView::mouseDragged (const awt::MouseEvent& rEvent)
687     throw (RuntimeException)
688 {
689     awt::MouseEvent aEvent (rEvent);
690     aEvent.Source = static_cast<XWeak*>(this);
691     ::cppu::OInterfaceContainerHelper* pIterator
692         = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseMotionListener>*)NULL));
693     if (pIterator != NULL)
694     {
695         pIterator->notifyEach(&awt::XMouseMotionListener::mouseDragged, aEvent);
696     }
697 }
698 
699 
700 
701 
mouseMoved(const awt::MouseEvent & rEvent)702 void SAL_CALL PresenterSlideShowView::mouseMoved (const awt::MouseEvent& rEvent)
703     throw (RuntimeException)
704 {
705     awt::MouseEvent aEvent (rEvent);
706     aEvent.Source = static_cast<XWeak*>(this);
707     ::cppu::OInterfaceContainerHelper* pIterator
708         = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseMotionListener>*)NULL));
709     if (pIterator != NULL)
710     {
711         pIterator->notifyEach(&awt::XMouseMotionListener::mouseMoved, aEvent);
712     }
713 }
714 
715 
716 
717 
718 //----- XWindowListener -------------------------------------------------------
719 
windowResized(const awt::WindowEvent & rEvent)720 void SAL_CALL PresenterSlideShowView::windowResized (const awt::WindowEvent& rEvent)
721     throw (RuntimeException)
722 {
723     (void)rEvent;
724 
725     ThrowIfDisposed();
726 	::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
727 
728     Resize();
729 }
730 
731 
732 
733 
734 
windowMoved(const awt::WindowEvent & rEvent)735 void SAL_CALL PresenterSlideShowView::windowMoved (const awt::WindowEvent& rEvent)
736     throw (RuntimeException)
737 {
738     (void)rEvent;
739     if ( ! mbIsPaintPending)
740         mbIsForcedPaintPending = true;
741 }
742 
743 
744 
745 
windowShown(const lang::EventObject & rEvent)746 void SAL_CALL PresenterSlideShowView::windowShown (const lang::EventObject& rEvent)
747     throw (RuntimeException)
748 {
749     (void)rEvent;
750     Resize();
751 }
752 
753 
754 
755 
windowHidden(const lang::EventObject & rEvent)756 void SAL_CALL PresenterSlideShowView::windowHidden (const lang::EventObject& rEvent)
757     throw (RuntimeException)
758 {
759     (void)rEvent;
760 }
761 
762 
763 
764 
765 //----- XView -----------------------------------------------------------------
766 
getResourceId(void)767 Reference<XResourceId> SAL_CALL PresenterSlideShowView::getResourceId (void)
768     throw(RuntimeException)
769 {
770     return mxViewId;
771 }
772 
773 
774 
775 
isAnchorOnly(void)776 sal_Bool SAL_CALL PresenterSlideShowView::isAnchorOnly (void)
777     throw (RuntimeException)
778 {
779     return false;
780 }
781 
782 
783 
784 
785 //----- CachablePresenterView -------------------------------------------------
786 
ActivatePresenterView(void)787 void PresenterSlideShowView::ActivatePresenterView (void)
788 {
789     if (mxSlideShow.is() && ! mbIsViewAdded)
790     {
791         mxSlideShow->addView(this);
792         mbIsViewAdded = true;
793     }
794 }
795 
796 
797 
798 
DeactivatePresenterView(void)799 void PresenterSlideShowView::DeactivatePresenterView (void)
800 {
801     if (mxSlideShow.is() && mbIsViewAdded)
802     {
803         mxSlideShow->removeView(this);
804         mbIsViewAdded = false;
805     }
806 }
807 
808 
809 
810 
811 //-----------------------------------------------------------------------------
812 
PaintOuterWindow(const awt::Rectangle & rRepaintBox)813 void PresenterSlideShowView::PaintOuterWindow (const awt::Rectangle& rRepaintBox)
814 {
815     if ( ! mxCanvas.is())
816         return;
817 
818     if (mpBackground.get() == NULL)
819         return;
820 
821     const rendering::ViewState aViewState(
822         geometry::AffineMatrix2D(1,0,0, 0,1,0),
823         PresenterGeometryHelper::CreatePolygon(rRepaintBox, mxCanvas->getDevice()));
824 
825     rendering::RenderState aRenderState (
826         geometry::AffineMatrix2D(1,0,0, 0,1,0),
827         NULL,
828         Sequence<double>(4),
829         rendering::CompositeOperation::SOURCE);
830 
831     Reference<rendering::XBitmap> xBackgroundBitmap (mpBackground->GetNormalBitmap());
832     if (xBackgroundBitmap.is())
833     {
834         Sequence<rendering::Texture> aTextures (1);
835         const geometry::IntegerSize2D aBitmapSize(xBackgroundBitmap->getSize());
836         aTextures[0] = rendering::Texture (
837             geometry::AffineMatrix2D(
838                 aBitmapSize.Width,0,0,
839                 0,aBitmapSize.Height,0),
840             1,
841             0,
842             xBackgroundBitmap,
843             NULL,
844             NULL,
845             rendering::StrokeAttributes(),
846             rendering::TexturingMode::REPEAT,
847             rendering::TexturingMode::REPEAT);
848 
849         if (mxBackgroundPolygon1.is())
850             mxCanvas->fillTexturedPolyPolygon(
851                 mxBackgroundPolygon1,
852                 aViewState,
853                 aRenderState,
854                 aTextures);
855         if (mxBackgroundPolygon2.is())
856             mxCanvas->fillTexturedPolyPolygon(
857                 mxBackgroundPolygon2,
858                 aViewState,
859                 aRenderState,
860                 aTextures);
861     }
862     else
863     {
864         PresenterCanvasHelper::SetDeviceColor(aRenderState, mpBackground->maReplacementColor);
865 
866         if (mxBackgroundPolygon1.is())
867             mxCanvas->fillPolyPolygon(mxBackgroundPolygon1, aViewState, aRenderState);
868         if (mxBackgroundPolygon2.is())
869             mxCanvas->fillPolyPolygon(mxBackgroundPolygon2, aViewState, aRenderState);
870     }
871 }
872 
873 
874 
875 
PaintEndSlide(const awt::Rectangle & rRepaintBox)876 void PresenterSlideShowView::PaintEndSlide (const awt::Rectangle& rRepaintBox)
877 {
878     if ( ! mxCanvas.is())
879         return;
880 
881     const rendering::ViewState aViewState(
882         geometry::AffineMatrix2D(1,0,0, 0,1,0),
883         PresenterGeometryHelper::CreatePolygon(rRepaintBox, mxCanvas->getDevice()));
884 
885     rendering::RenderState aRenderState (
886         geometry::AffineMatrix2D(1,0,0, 0,1,0),
887         NULL,
888         Sequence<double>(4),
889         rendering::CompositeOperation::SOURCE);
890     PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00000000));
891     mxCanvas->fillPolyPolygon(
892         PresenterGeometryHelper::CreatePolygon(mxViewWindow->getPosSize(), mxCanvas->getDevice()),
893         aViewState,
894         aRenderState);
895 
896     do
897     {
898         if (mpPresenterController.get() == NULL)
899             break;
900         ::boost::shared_ptr<PresenterTheme> pTheme (mpPresenterController->GetTheme());
901         if (pTheme.get() == NULL)
902             break;
903 
904         const OUString sViewStyle (pTheme->GetStyleName(mxViewId->getResourceURL()));
905         PresenterTheme::SharedFontDescriptor pFont (pTheme->GetFont(sViewStyle));
906         if (pFont.get() == NULL)
907             break;
908 
909         PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff));
910         aRenderState.AffineTransform.m02 = 20;
911         aRenderState.AffineTransform.m12 = 40;
912         const rendering::StringContext aContext (
913             msClickToExitPresentationText, 0, msClickToExitPresentationText.getLength());
914         pFont->PrepareFont(mxCanvas);
915         mxCanvas->drawText(
916             aContext,
917             pFont->mxFont,
918             aViewState,
919             aRenderState,
920             rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
921     }
922     while (false);
923 
924     // Finally, in double buffered environments, request the changes to be
925     // made visible.
926     Reference<rendering::XSpriteCanvas> mxSpriteCanvas (mxCanvas, UNO_QUERY);
927     if (mxSpriteCanvas.is())
928         mxSpriteCanvas->updateScreen(sal_True);
929 }
930 
931 
932 
933 
PaintInnerWindow(const awt::PaintEvent & rEvent)934 void PresenterSlideShowView::PaintInnerWindow (const awt::PaintEvent& rEvent)
935 {
936     // Forward window paint to listeners.
937     awt::PaintEvent aEvent (rEvent);
938     aEvent.Source = static_cast<XWeak*>(this);
939     ::cppu::OInterfaceContainerHelper* pIterator
940         = maBroadcaster.getContainer(getCppuType((Reference<awt::XPaintListener>*)NULL));
941     if (pIterator != NULL)
942     {
943         pIterator->notifyEach(&awt::XPaintListener::windowPaint, aEvent);
944     }
945 
946     if (mbIsForcedPaintPending)
947         ForceRepaint();
948 
949     // Finally, in double buffered environments, request the changes to be
950     // made visible.
951     Reference<rendering::XSpriteCanvas> mxSpriteCanvas (mxCanvas, UNO_QUERY);
952     if (mxSpriteCanvas.is())
953         mxSpriteCanvas->updateScreen(sal_True);
954 }
955 
956 
957 
958 
CreateViewWindow(const Reference<awt::XWindow> & rxParentWindow) const959 Reference<awt::XWindow> PresenterSlideShowView::CreateViewWindow (
960     const Reference<awt::XWindow>& rxParentWindow) const
961 {
962     Reference<awt::XWindow> xViewWindow;
963     try
964     {
965         Reference<lang::XMultiComponentFactory> xFactory (mxComponentContext->getServiceManager());
966         if ( ! xFactory.is())
967             return xViewWindow;
968 
969         Reference<awt::XToolkit> xToolkit (
970             xFactory->createInstanceWithContext(
971                 OUString::createFromAscii("com.sun.star.awt.Toolkit"),
972                 mxComponentContext),
973             UNO_QUERY_THROW);
974         awt::WindowDescriptor aWindowDescriptor (
975             awt::WindowClass_CONTAINER,
976             OUString(),
977             Reference<awt::XWindowPeer>(rxParentWindow,UNO_QUERY_THROW),
978             -1, // parent index not available
979             awt::Rectangle(0,0,10,10),
980             awt::WindowAttribute::SIZEABLE
981                 | awt::WindowAttribute::MOVEABLE
982                 | awt::WindowAttribute::NODECORATION);
983         xViewWindow = Reference<awt::XWindow>(
984             xToolkit->createWindow(aWindowDescriptor),UNO_QUERY_THROW);
985 
986         // Make the background transparent.  The slide show paints its own background.
987         Reference<awt::XWindowPeer> xPeer (xViewWindow, UNO_QUERY_THROW);
988         if (xPeer.is())
989         {
990             xPeer->setBackground(0xff000000);
991         }
992 
993         xViewWindow->setVisible(sal_True);
994     }
995     catch (RuntimeException&)
996     {
997     }
998     return xViewWindow;
999 }
1000 
1001 
1002 
1003 
CreateViewCanvas(const Reference<awt::XWindow> & rxViewWindow) const1004 Reference<rendering::XCanvas> PresenterSlideShowView::CreateViewCanvas (
1005     const Reference<awt::XWindow>& rxViewWindow) const
1006 {
1007     // Create a canvas for the view window.
1008     return mxPresenterHelper->createSharedCanvas(
1009         Reference<rendering::XSpriteCanvas>(mxTopPane->getCanvas(), UNO_QUERY),
1010         mxTopPane->getWindow(),
1011         mxTopPane->getCanvas(),
1012         mxTopPane->getWindow(),
1013         rxViewWindow);
1014 }
1015 
1016 
1017 
1018 
Resize(void)1019 void PresenterSlideShowView::Resize (void)
1020 {
1021     if ( ! mxWindow.is() || ! mxViewWindow.is())
1022         return;
1023 
1024     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1025     awt::Rectangle aViewWindowBox;
1026     if (aWindowBox.Height > 0)
1027     {
1028         const double nWindowAspectRatio (
1029             double(aWindowBox.Width) / double(aWindowBox.Height));
1030         if (nWindowAspectRatio > mnPageAspectRatio)
1031         {
1032             // Slides will be painted with the full parent window height.
1033             aViewWindowBox.Width = sal_Int32(aWindowBox.Height * mnPageAspectRatio + 0.5);
1034             aViewWindowBox.Height = aWindowBox.Height;
1035             aViewWindowBox.X = (aWindowBox.Width - aViewWindowBox.Width) / 2;
1036             aViewWindowBox.Y = 0;
1037         }
1038         else
1039         {
1040             // Slides will be painted with the full parent window width.
1041             aViewWindowBox.Width = aWindowBox.Width;
1042             aViewWindowBox.Height = sal_Int32(aWindowBox.Width / mnPageAspectRatio + 0.5);
1043             aViewWindowBox.X = 0;
1044             aViewWindowBox.Y = (aWindowBox.Height - aViewWindowBox.Height) / 2;
1045         }
1046         mxViewWindow->setPosSize(
1047             aViewWindowBox.X,
1048             aViewWindowBox.Y,
1049             aViewWindowBox.Width,
1050             aViewWindowBox.Height,
1051             awt::PosSize::POSSIZE);
1052     }
1053 
1054     // Clear the background polygon so that on the next paint it is created
1055     // for the new size.
1056     CreateBackgroundPolygons();
1057 
1058     // Notify listeners that the transformation that maps the view into the
1059     // window has changed.
1060     lang::EventObject aEvent (static_cast<XWeak*>(this));
1061     ::cppu::OInterfaceContainerHelper* pIterator
1062         = maBroadcaster.getContainer(getCppuType((Reference<util::XModifyListener>*)NULL));
1063     if (pIterator != NULL)
1064     {
1065         pIterator->notifyEach(&util::XModifyListener::modified, aEvent);
1066     }
1067 
1068     // Due to constant aspect ratio resizing may lead a preview that changes
1069     // its position but not its size.  This invalidates the back buffer and
1070     // we have to enforce a complete repaint.
1071     if ( ! mbIsPaintPending)
1072         mbIsForcedPaintPending = true;
1073 }
1074 
1075 
1076 
1077 
ForceRepaint(void)1078 void PresenterSlideShowView::ForceRepaint (void)
1079 {
1080     if (mxSlideShow.is() && mbIsViewAdded)
1081     {
1082         mxSlideShow->removeView(this);
1083         mxSlideShow->addView(this);
1084     }
1085 }
1086 
1087 
1088 
1089 
CreateBackgroundPolygons(void)1090 void PresenterSlideShowView::CreateBackgroundPolygons (void)
1091 {
1092     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1093     const awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize());
1094     if (aWindowBox.Height == aViewWindowBox.Height && aWindowBox.Width == aViewWindowBox.Width)
1095     {
1096         mxBackgroundPolygon1 = NULL;
1097         mxBackgroundPolygon2 = NULL;
1098     }
1099     else if (aWindowBox.Height == aViewWindowBox.Height)
1100     {
1101         // Paint two boxes to the left and right of the view window.
1102         mxBackgroundPolygon1 = PresenterGeometryHelper::CreatePolygon(
1103             awt::Rectangle(
1104                 0,
1105                 0,
1106                 aViewWindowBox.X,
1107                 aWindowBox.Height),
1108             mxCanvas->getDevice());
1109         mxBackgroundPolygon2 = PresenterGeometryHelper::CreatePolygon(
1110             awt::Rectangle(
1111                 aViewWindowBox.X + aViewWindowBox.Width,
1112                 0,
1113                 aWindowBox.Width - aViewWindowBox.X - aViewWindowBox.Width,
1114                 aWindowBox.Height),
1115             mxCanvas->getDevice());
1116     }
1117     else
1118     {
1119         // Paint two boxes above and below the view window.
1120         mxBackgroundPolygon1 = PresenterGeometryHelper::CreatePolygon(
1121             awt::Rectangle(
1122                 0,
1123                 0,
1124                 aWindowBox.Width,
1125                 aViewWindowBox.Y),
1126             mxCanvas->getDevice());
1127         mxBackgroundPolygon2 = PresenterGeometryHelper::CreatePolygon(
1128             awt::Rectangle(
1129                 0,
1130                 aViewWindowBox.Y + aViewWindowBox.Height,
1131                 aWindowBox.Width,
1132                 aWindowBox.Height - aViewWindowBox.Y - aViewWindowBox.Height),
1133             mxCanvas->getDevice());
1134     }
1135 }
1136 
1137 
1138 
1139 
ThrowIfDisposed(void)1140 void PresenterSlideShowView::ThrowIfDisposed (void)
1141     throw (::com::sun::star::lang::DisposedException)
1142 {
1143 	if (rBHelper.bDisposed || rBHelper.bInDispose)
1144 	{
1145         throw lang::DisposedException (
1146             OUString::createFromAscii("PresenterSlideShowView object has already been disposed"),
1147             static_cast<uno::XWeak*>(this));
1148     }
1149 }
1150 
1151 
1152 } } // end of namespace ::sd::presenter
1153