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