1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sdext.hxx"
30 
31 #include "PresenterSlidePreview.hxx"
32 #include "PresenterCanvasHelper.hxx"
33 #include "PresenterGeometryHelper.hxx"
34 #include "PresenterPaintManager.hxx"
35 #include <com/sun/star/awt/XWindow.hpp>
36 #include <com/sun/star/awt/XWindowPeer.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
39 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
40 #include <com/sun/star/drawing/framework/XPane.hpp>
41 #include <com/sun/star/rendering/CompositeOperation.hpp>
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::drawing::framework;
46 using ::rtl::OUString;
47 
48 namespace
49 {
50     // Use a super sample factor greater than 1 to achive a poor mans
51     // antialiasing effect for slide previews.
52     const sal_Int16 gnSuperSampleFactor = 2;
53 }
54 
55 namespace sdext { namespace presenter {
56 
57 //===== PresenterSlidePreview =================================================
58 
59 PresenterSlidePreview::PresenterSlidePreview (
60     const Reference<XComponentContext>& rxContext,
61     const Reference<XResourceId>& rxViewId,
62     const Reference<XPane>& rxAnchorPane,
63     const ::rtl::Reference<PresenterController>& rpPresenterController)
64     : PresenterSlidePreviewInterfaceBase(m_aMutex),
65       mpPresenterController(rpPresenterController),
66       mxPane(rxAnchorPane),
67       mxViewId(rxViewId),
68       mxPreviewRenderer(),
69       mxPreview(),
70       mxCurrentSlide(),
71       mnSlideAspectRatio(28.0 / 21.0),
72       mxWindow(),
73       mxCanvas()
74 {
75     if ( ! rxContext.is()
76         || ! rxViewId.is()
77         || ! rxAnchorPane.is()
78         || ! rpPresenterController.is())
79     {
80         throw RuntimeException(
81             OUString::createFromAscii(
82                 "PresenterSlidePreview can not be constructed due to empty argument"),
83             static_cast<XWeak*>(this));
84     }
85 
86     mxWindow = rxAnchorPane->getWindow();
87     mxCanvas = rxAnchorPane->getCanvas();
88 
89     if (mxWindow.is())
90     {
91         mxWindow->addWindowListener(this);
92         mxWindow->addPaintListener(this);
93 
94         Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
95         if (xPeer.is())
96             xPeer->setBackground(util::Color(0xff000000));
97 
98         mxWindow->setVisible(sal_True);
99     }
100 
101     if (mpPresenterController.get() != NULL)
102         mnSlideAspectRatio = mpPresenterController->GetSlideAspectRatio();
103 
104     Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager(), UNO_QUERY);
105     if (xFactory.is())
106         mxPreviewRenderer = Reference<drawing::XSlideRenderer>(
107             xFactory->createInstanceWithContext(
108                 OUString::createFromAscii("com.sun.star.drawing.SlideRenderer"),
109                 rxContext),
110             UNO_QUERY);
111 
112     Resize();
113 }
114 
115 
116 
117 
118 PresenterSlidePreview::~PresenterSlidePreview (void)
119 {
120 }
121 
122 
123 
124 
125 void SAL_CALL PresenterSlidePreview::disposing (void)
126 {
127     if (mxWindow.is())
128     {
129         mxWindow->removeWindowListener(this);
130         mxWindow->removePaintListener(this);
131         mxWindow = NULL;
132         mxCanvas = NULL;
133     }
134 
135     Reference<lang::XComponent> xComponent (mxPreviewRenderer, UNO_QUERY);
136     if (xComponent.is())
137         xComponent->dispose();
138 }
139 
140 
141 
142 
143 //----- XResourceId -----------------------------------------------------------
144 
145 Reference<XResourceId> SAL_CALL PresenterSlidePreview::getResourceId (void)
146     throw (RuntimeException)
147 {
148     return mxViewId;
149 }
150 
151 
152 
153 
154 sal_Bool SAL_CALL PresenterSlidePreview::isAnchorOnly (void)
155     throw (RuntimeException)
156 {
157     return false;
158 }
159 
160 
161 
162 
163 //----- XWindowListener -------------------------------------------------------
164 
165 void SAL_CALL PresenterSlidePreview::windowResized (const awt::WindowEvent& rEvent)
166     throw (RuntimeException)
167 {
168     (void)rEvent;
169     ThrowIfDisposed();
170     ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
171     Resize();
172 }
173 
174 
175 
176 
177 
178 void SAL_CALL PresenterSlidePreview::windowMoved (const awt::WindowEvent& rEvent)
179     throw (RuntimeException)
180 {
181     (void)rEvent;
182 }
183 
184 
185 
186 
187 void SAL_CALL PresenterSlidePreview::windowShown (const lang::EventObject& rEvent)
188     throw (RuntimeException)
189 {
190     (void)rEvent;
191     ThrowIfDisposed();
192     ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
193     Resize();
194 }
195 
196 
197 
198 
199 void SAL_CALL PresenterSlidePreview::windowHidden (const lang::EventObject& rEvent)
200     throw (RuntimeException)
201 {
202     (void)rEvent;
203 }
204 
205 
206 
207 
208 //----- XPaintListener --------------------------------------------------------
209 
210 void SAL_CALL PresenterSlidePreview::windowPaint (const awt::PaintEvent& rEvent)
211     throw (RuntimeException)
212 {
213     ThrowIfDisposed();
214 
215     ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
216     if (mxWindow.is())
217         Paint(awt::Rectangle(
218             rEvent.UpdateRect.X,
219             rEvent.UpdateRect.Y,
220             rEvent.UpdateRect.Width,
221             rEvent.UpdateRect.Height));
222 }
223 
224 
225 
226 
227 //----- lang::XEventListener --------------------------------------------------
228 
229 void SAL_CALL PresenterSlidePreview::disposing (const lang::EventObject& rEvent)
230     throw (RuntimeException)
231 {
232     if (rEvent.Source == mxWindow)
233     {
234         mxWindow = NULL;
235         mxCanvas = NULL;
236         mxPreview = NULL;
237     }
238 }
239 
240 
241 
242 
243 //----- XDrawView -------------------------------------------------------------
244 
245 void SAL_CALL PresenterSlidePreview::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
246     throw (RuntimeException)
247 {
248     ThrowIfDisposed();
249     ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
250     SetSlide(rxSlide);
251 }
252 
253 
254 
255 
256 Reference<drawing::XDrawPage> SAL_CALL PresenterSlidePreview::getCurrentPage (void)
257     throw (RuntimeException)
258 {
259     ThrowIfDisposed();
260     return NULL;
261 }
262 
263 
264 
265 
266 //-----------------------------------------------------------------------------
267 
268 void PresenterSlidePreview::SetSlide (const Reference<drawing::XDrawPage>& rxPage)
269 {
270     mxCurrentSlide = rxPage;
271     mxPreview = NULL;
272 
273     Reference<beans::XPropertySet> xPropertySet (mxCurrentSlide, UNO_QUERY);
274     if (xPropertySet.is())
275     {
276         awt::Size aSlideSize;
277         try
278         {
279             xPropertySet->getPropertyValue(
280                 OUString::createFromAscii("Width")) >>= aSlideSize.Width;
281             xPropertySet->getPropertyValue(
282                 OUString::createFromAscii("Height")) >>= aSlideSize.Height;
283         }
284         catch (beans::UnknownPropertyException&)
285         {
286             OSL_ASSERT(false);
287         }
288     }
289 
290     // The preview is not transparent, therefore only this window, not its
291     // parent, has to be invalidated.
292     mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
293 }
294 
295 
296 
297 
298 void PresenterSlidePreview::Paint (const awt::Rectangle& rBoundingBox)
299 {
300     (void)rBoundingBox;
301     if ( ! mxWindow.is())
302         return;
303     if ( ! mxCanvas.is())
304         return;
305     if ( ! mxPreviewRenderer.is())
306         return;
307 
308     // Make sure that a preview in the correct size exists.
309     awt::Rectangle aWindowBox (mxWindow->getPosSize());
310 
311     if ( ! mxPreview.is() && mxCurrentSlide.is())
312     {
313         // Create a new preview bitmap.
314         mxPreview = mxPreviewRenderer->createPreviewForCanvas(
315             mxCurrentSlide,
316             awt::Size(aWindowBox.Width, aWindowBox.Height),
317             gnSuperSampleFactor,
318             mxCanvas);
319     }
320 
321     // Determine the bounding box of the preview.
322     awt::Rectangle aPreviewBox;
323     if (mxPreview.is())
324     {
325         const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize());
326         aPreviewBox = awt::Rectangle(
327             (aWindowBox.Width - aPreviewSize.Width)/2,
328             (aWindowBox.Height - aPreviewSize.Height)/2,
329             aPreviewSize.Width,
330             aPreviewSize.Height);
331     }
332     else
333     {
334         if (mnSlideAspectRatio > 0)
335         {
336             const awt::Size aPreviewSize (mxPreviewRenderer->calculatePreviewSize(
337                 mnSlideAspectRatio,awt::Size(aWindowBox.Width, aWindowBox.Height)));
338             aPreviewBox = awt::Rectangle(
339                 (aWindowBox.Width - aPreviewSize.Width)/2,
340                 (aWindowBox.Height - aPreviewSize.Height)/2,
341                 aPreviewSize.Width,
342                 aPreviewSize.Height);
343         }
344     }
345 
346     // Paint the background.
347     mpPresenterController->GetCanvasHelper()->Paint(
348         mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
349         mxCanvas,
350         rBoundingBox,
351         awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
352         aPreviewBox);
353 
354     // Paint the preview.
355     const rendering::ViewState aViewState(
356         geometry::AffineMatrix2D(1,0,0, 0,1,0),
357         NULL);
358 
359     Sequence<double> aBackgroundColor(4);
360     rendering::RenderState aRenderState (
361         geometry::AffineMatrix2D(1, 0, aPreviewBox.X, 0, 1, aPreviewBox.Y),
362         NULL,
363         aBackgroundColor,
364         rendering::CompositeOperation::SOURCE);
365     PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00000000);
366     if (mxPreview.is())
367     {
368         mxCanvas->drawBitmap(mxPreview, aViewState, aRenderState);
369     }
370     else
371     {
372         if (mnSlideAspectRatio > 0)
373         {
374             Reference<rendering::XPolyPolygon2D> xPolygon (
375                 PresenterGeometryHelper::CreatePolygon(aPreviewBox, mxCanvas->getDevice()));
376             if (xPolygon.is())
377                 mxCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState);
378         }
379     }
380 
381     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
382     if (xSpriteCanvas.is())
383         xSpriteCanvas->updateScreen(sal_False);
384 }
385 
386 
387 
388 
389 void PresenterSlidePreview::Resize (void)
390 {
391     if (mxPreviewRenderer.is() && mxPreview.is())
392     {
393         const awt::Rectangle aWindowBox (mxWindow->getPosSize());
394         const awt::Size aNewPreviewSize (mxPreviewRenderer->calculatePreviewSize(
395             mnSlideAspectRatio,
396                 awt::Size(aWindowBox.Width, aWindowBox.Height)));
397         const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize());
398         if (aNewPreviewSize.Width==aPreviewSize.Width
399             && aNewPreviewSize.Height==aPreviewSize.Height)
400         {
401             // The size of the window may have changed but the preview would
402             // be painted in the same size (but not necessarily at the same
403             // position.)
404             return;
405         }
406     }
407     SetSlide(mxCurrentSlide);
408 }
409 
410 
411 
412 
413 void PresenterSlidePreview::ThrowIfDisposed (void)
414     throw (::com::sun::star::lang::DisposedException)
415 {
416 	if (PresenterSlidePreviewInterfaceBase::rBHelper.bDisposed || PresenterSlidePreviewInterfaceBase::rBHelper.bInDispose)
417 	{
418         throw lang::DisposedException (
419             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
420                 "PresenterSlidePreview object has already been disposed")),
421             static_cast<uno::XWeak*>(this));
422     }
423 }
424 
425 
426 } } // end of namespace ::sd::presenter
427 
428