vcl: allow for overriding the default PDF rendering resolution
[LibreOffice.git] / sdext / source / presenter / PresenterWindowManager.cxx
blobb4b262c1f761387a5caa1ae8c89ec52c91d0d42e
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 <vcl/settings.hxx>
21 #include "PresenterWindowManager.hxx"
22 #include "PresenterController.hxx"
23 #include "PresenterGeometryHelper.hxx"
24 #include "PresenterPaintManager.hxx"
25 #include "PresenterPaneBorderPainter.hxx"
26 #include "PresenterPaneContainer.hxx"
27 #include "PresenterPaneFactory.hxx"
28 #include "PresenterToolBar.hxx"
29 #include "PresenterViewFactory.hxx"
30 #include "PresenterTheme.hxx"
31 #include <com/sun/star/awt/InvalidateStyle.hpp>
32 #include <com/sun/star/awt/PosSize.hpp>
33 #include <com/sun/star/awt/XWindow2.hpp>
34 #include <com/sun/star/awt/XWindowPeer.hpp>
35 #include <com/sun/star/rendering/CompositeOperation.hpp>
36 #include <com/sun/star/rendering/FillRule.hpp>
37 #include <com/sun/star/rendering/Texture.hpp>
38 #include <com/sun/star/rendering/TexturingMode.hpp>
39 #include <math.h>
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::drawing::framework;
45 namespace sdext { namespace presenter {
47 //===== PresenterWindowManager ================================================
49 PresenterWindowManager::PresenterWindowManager (
50 const Reference<XComponentContext>& rxContext,
51 const ::rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
52 const ::rtl::Reference<PresenterController>& rpPresenterController)
53 : PresenterWindowManagerInterfaceBase(m_aMutex),
54 mxComponentContext(rxContext),
55 mpPresenterController(rpPresenterController),
56 mxParentWindow(),
57 mxParentCanvas(),
58 mxPaneBorderManager(),
59 mpPaneBorderPainter(),
60 mpPaneContainer(rpPaneContainer),
61 mbIsLayoutPending(true),
62 mbIsLayouting(false),
63 mpTheme(),
64 mpBackgroundBitmap(),
65 mxScaledBackgroundBitmap(),
66 mxClipPolygon(),
67 meLayoutMode(LM_Generic),
68 mbIsSlideSorterActive(false),
69 mbIsHelpViewActive(false),
70 maLayoutListeners(),
71 mbIsMouseClickPending(false)
76 PresenterWindowManager::~PresenterWindowManager()
80 void SAL_CALL PresenterWindowManager::disposing()
82 NotifyDisposing();
84 SetParentPane(nullptr);
86 Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY);
87 if (xComponent.is())
88 xComponent->dispose();
89 mxPaneBorderManager = nullptr;
91 for (const auto& rxPane : mpPaneContainer->maPanes)
93 if (rxPane->mxBorderWindow.is())
95 rxPane->mxBorderWindow->removeWindowListener(this);
96 rxPane->mxBorderWindow->removeFocusListener(this);
97 rxPane->mxBorderWindow->removeMouseListener(this);
102 void PresenterWindowManager::SetParentPane (
103 const Reference<drawing::framework::XPane>& rxPane)
105 if (mxParentWindow.is())
107 mxParentWindow->removeWindowListener(this);
108 mxParentWindow->removePaintListener(this);
109 mxParentWindow->removeMouseListener(this);
110 mxParentWindow->removeFocusListener(this);
112 mxParentWindow = nullptr;
113 mxParentCanvas = nullptr;
115 if (rxPane.is())
117 mxParentWindow = rxPane->getWindow();
118 mxParentCanvas = rxPane->getCanvas();
120 else
122 mxParentWindow = nullptr;
125 if (mxParentWindow.is())
127 mxParentWindow->addWindowListener(this);
128 mxParentWindow->addPaintListener(this);
129 mxParentWindow->addMouseListener(this);
130 mxParentWindow->addFocusListener(this);
132 // We paint our own background, make that of the parent window transparent.
133 Reference<awt::XWindowPeer> xPeer (mxParentWindow, UNO_QUERY);
134 if (xPeer.is())
135 xPeer->setBackground(util::Color(0xff000000));
139 void PresenterWindowManager::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
141 mpTheme = rpTheme;
143 // Get background bitmap or background color from the theme.
145 if (mpTheme != nullptr)
147 mpBackgroundBitmap = mpTheme->GetBitmap(OUString(), "Background");
151 void PresenterWindowManager::NotifyViewCreation (const Reference<XView>& rxView)
153 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
154 mpPaneContainer->FindPaneId(rxView->getResourceId()->getAnchor()));
155 OSL_ASSERT(pDescriptor.get() != nullptr);
156 if (pDescriptor.get() != nullptr)
158 Layout();
160 mpPresenterController->GetPaintManager()->Invalidate(
161 pDescriptor->mxContentWindow,
162 sal_Int16(awt::InvalidateStyle::TRANSPARENT
163 | awt::InvalidateStyle::CHILDREN));
167 void PresenterWindowManager::SetPanePosSizeAbsolute (
168 const OUString& rsPaneURL,
169 const double nX,
170 const double nY,
171 const double nWidth,
172 const double nHeight)
174 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
175 mpPaneContainer->FindPaneURL(rsPaneURL));
176 if (pDescriptor.get() != nullptr)
178 if (pDescriptor->mxBorderWindow.is())
179 pDescriptor->mxBorderWindow->setPosSize(
180 ::sal::static_int_cast<sal_Int32>(nX),
181 ::sal::static_int_cast<sal_Int32>(nY),
182 ::sal::static_int_cast<sal_Int32>(nWidth),
183 ::sal::static_int_cast<sal_Int32>(nHeight),
184 awt::PosSize::POSSIZE);
188 void PresenterWindowManager::SetPaneBorderPainter (
189 const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter)
191 mpPaneBorderPainter = rPainter;
194 //----- XWindowListener -------------------------------------------------------
196 void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent)
198 ThrowIfDisposed();
199 if (rEvent.Source == mxParentWindow)
201 Layout();
203 else
205 Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
206 if (xWindow.is())
208 UpdateWindowSize(xWindow);
210 // Make sure the background of a transparent window is painted.
211 mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
216 void SAL_CALL PresenterWindowManager::windowMoved (const awt::WindowEvent& rEvent)
218 ThrowIfDisposed();
219 if (rEvent.Source != mxParentWindow)
221 Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
222 UpdateWindowSize(xWindow);
224 // Make sure the background of a transparent window is painted.
225 mpPresenterController->GetPaintManager()->Invalidate(xWindow);
229 void SAL_CALL PresenterWindowManager::windowShown (const lang::EventObject&) {}
231 void SAL_CALL PresenterWindowManager::windowHidden (const lang::EventObject&) {}
233 //----- XPaintListener --------------------------------------------------------
235 void SAL_CALL PresenterWindowManager::windowPaint (const awt::PaintEvent& rEvent)
237 ThrowIfDisposed();
239 if ( ! mxParentWindow.is())
240 return;
241 if ( ! mxParentCanvas.is())
242 return;
244 if (mpTheme == nullptr)
245 return;
249 if (mbIsLayoutPending)
250 Layout();
251 PaintBackground(rEvent.UpdateRect);
252 PaintChildren(rEvent);
254 catch (RuntimeException&)
256 OSL_FAIL("paint failed!");
260 //----- XMouseListener --------------------------------------------------------
262 void SAL_CALL PresenterWindowManager::mousePressed (const css::awt::MouseEvent&)
264 if (!mbIsSlideSorterActive) // tdf#127921
265 mbIsMouseClickPending = true;
268 void SAL_CALL PresenterWindowManager::mouseReleased (const css::awt::MouseEvent& rEvent)
270 if (mbIsMouseClickPending)
272 mbIsMouseClickPending = false;
273 mpPresenterController->HandleMouseClick(rEvent);
277 void SAL_CALL PresenterWindowManager::mouseEntered (const css::awt::MouseEvent&)
279 mbIsMouseClickPending = false;
282 void SAL_CALL PresenterWindowManager::mouseExited (const css::awt::MouseEvent&)
284 mbIsMouseClickPending = false;
287 //----- XFocusListener --------------------------------------------------------
289 void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& /*rEvent*/)
291 ThrowIfDisposed();
294 void SAL_CALL PresenterWindowManager::focusLost (const css::awt::FocusEvent&)
296 ThrowIfDisposed();
299 //----- XEventListener --------------------------------------------------------
301 void SAL_CALL PresenterWindowManager::disposing (const lang::EventObject& rEvent)
303 if (rEvent.Source == mxParentWindow)
304 mxParentWindow = nullptr;
308 void PresenterWindowManager::PaintChildren (const awt::PaintEvent& rEvent) const
310 // Call windowPaint on all children that lie in or touch the
311 // update rectangle.
312 for (const auto& rxPane : mpPaneContainer->maPanes)
316 // Make sure that the pane shall and can be painted.
317 if ( ! rxPane->mbIsActive)
318 continue;
319 if (rxPane->mbIsSprite)
320 continue;
321 if ( ! rxPane->mxPane.is())
322 continue;
323 if ( ! rxPane->mxBorderWindow.is())
324 continue;
325 Reference<awt::XWindow> xBorderWindow (rxPane->mxBorderWindow);
326 if ( ! xBorderWindow.is())
327 continue;
329 // Get the area in which the border of the pane has to be painted.
330 const awt::Rectangle aBorderBox (xBorderWindow->getPosSize());
331 const awt::Rectangle aBorderUpdateBox(
332 PresenterGeometryHelper::Intersection(
333 rEvent.UpdateRect,
334 aBorderBox));
335 if (aBorderUpdateBox.Width<=0 || aBorderUpdateBox.Height<=0)
336 continue;
338 const awt::Rectangle aLocalBorderUpdateBox(
339 PresenterGeometryHelper::TranslateRectangle(
340 aBorderUpdateBox,
341 -aBorderBox.X,
342 -aBorderBox.Y));
344 // Invalidate the area of the content window.
345 mpPresenterController->GetPaintManager()->Invalidate(
346 xBorderWindow,
347 aLocalBorderUpdateBox,
348 sal_Int16(awt::InvalidateStyle::CHILDREN
349 | awt::InvalidateStyle::NOTRANSPARENT));
351 catch (RuntimeException&)
353 OSL_FAIL("paint children failed!");
358 void PresenterWindowManager::SetLayoutMode (const LayoutMode eMode)
360 OSL_ASSERT(mpPresenterController.get() != nullptr);
362 if (meLayoutMode == eMode
363 && !mbIsSlideSorterActive
364 && !mbIsHelpViewActive)
365 return;
367 meLayoutMode = eMode;
368 mbIsSlideSorterActive = false;
369 mbIsHelpViewActive = false;
371 mpPresenterController->RequestViews(
372 mbIsSlideSorterActive,
373 meLayoutMode==LM_Notes,
374 mbIsHelpViewActive);
375 Layout();
376 NotifyLayoutModeChange();
379 void PresenterWindowManager::SetSlideSorterState (bool bIsActive)
381 if (mbIsSlideSorterActive == bIsActive)
382 return;
384 mbIsSlideSorterActive = bIsActive;
385 if (mbIsSlideSorterActive)
386 mbIsHelpViewActive = false;
387 StoreViewMode(GetViewMode());
389 mpPresenterController->RequestViews(
390 mbIsSlideSorterActive,
391 meLayoutMode==LM_Notes,
392 mbIsHelpViewActive);
393 Layout();
394 NotifyLayoutModeChange();
397 void PresenterWindowManager::SetHelpViewState (bool bIsActive)
399 if (mbIsHelpViewActive == bIsActive)
400 return;
402 mbIsHelpViewActive = bIsActive;
403 if (mbIsHelpViewActive)
404 mbIsSlideSorterActive = false;
405 StoreViewMode(GetViewMode());
407 mpPresenterController->RequestViews(
408 mbIsSlideSorterActive,
409 meLayoutMode==LM_Notes,
410 mbIsHelpViewActive);
411 Layout();
412 NotifyLayoutModeChange();
415 void PresenterWindowManager::SetViewMode (const ViewMode eMode)
417 switch (eMode)
419 case VM_Standard:
420 SetSlideSorterState(false);
421 SetHelpViewState(false);
422 SetLayoutMode(LM_Standard);
423 break;
425 case VM_Notes:
426 SetSlideSorterState(false);
427 SetHelpViewState(false);
428 SetLayoutMode(LM_Notes);
429 break;
431 case VM_SlideOverview:
432 SetHelpViewState(false);
433 SetSlideSorterState(true);
434 break;
436 case VM_Help:
437 SetHelpViewState(true);
438 SetSlideSorterState(false);
439 break;
442 StoreViewMode(eMode);
445 PresenterWindowManager::ViewMode PresenterWindowManager::GetViewMode() const
447 if (mbIsHelpViewActive)
448 return VM_Help;
449 else if (mbIsSlideSorterActive)
450 return VM_SlideOverview;
451 else if (meLayoutMode == LM_Notes)
452 return VM_Notes;
453 else
454 return VM_Standard;
457 void PresenterWindowManager::RestoreViewMode()
459 sal_Int32 nMode (0);
460 PresenterConfigurationAccess aConfiguration (
461 mxComponentContext,
462 "/org.openoffice.Office.PresenterScreen/",
463 PresenterConfigurationAccess::READ_ONLY);
464 aConfiguration.GetConfigurationNode("Presenter/InitialViewMode") >>= nMode;
465 switch (nMode)
467 default:
468 case 0:
469 SetViewMode(VM_Standard);
470 break;
472 case 1:
473 SetViewMode(VM_Notes);
474 break;
476 case 2:
477 SetViewMode(VM_SlideOverview);
478 break;
482 void PresenterWindowManager::StoreViewMode (const ViewMode eViewMode)
486 PresenterConfigurationAccess aConfiguration (
487 mxComponentContext,
488 "/org.openoffice.Office.PresenterScreen/",
489 PresenterConfigurationAccess::READ_WRITE);
490 aConfiguration.GoToChild("Presenter");
491 Any aValue;
492 switch (eViewMode)
494 default:
495 case VM_Standard:
496 aValue <<= sal_Int32(0);
497 break;
499 case VM_Notes:
500 aValue <<= sal_Int32(1);
501 break;
503 case VM_SlideOverview:
504 aValue <<= sal_Int32(2);
505 break;
508 aConfiguration.SetProperty ("InitialViewMode", aValue);
509 aConfiguration.CommitChanges();
511 catch (Exception&)
516 void PresenterWindowManager::AddLayoutListener (
517 const Reference<document::XEventListener>& rxListener)
519 maLayoutListeners.push_back(rxListener);
522 void PresenterWindowManager::RemoveLayoutListener (
523 const Reference<document::XEventListener>& rxListener)
525 // Assume that there are no multiple entries.
526 auto iListener = std::find(maLayoutListeners.begin(), maLayoutListeners.end(), rxListener);
527 if (iListener != maLayoutListeners.end())
528 maLayoutListeners.erase(iListener);
531 void PresenterWindowManager::Layout()
533 if (!mxParentWindow.is() || mbIsLayouting)
534 return;
536 mbIsLayoutPending = false;
537 mbIsLayouting = true;
538 mxScaledBackgroundBitmap = nullptr;
539 mxClipPolygon = nullptr;
543 if (mbIsSlideSorterActive)
544 LayoutSlideSorterMode();
545 else if (mbIsHelpViewActive)
546 LayoutHelpMode();
547 else
548 switch (meLayoutMode)
550 case LM_Standard:
551 default:
552 LayoutStandardMode();
553 break;
555 case LM_Notes:
556 LayoutNotesMode();
557 break;
560 catch (Exception&)
562 OSL_ASSERT(false);
563 throw;
566 mbIsLayouting = false;
569 void PresenterWindowManager::LayoutStandardMode()
571 awt::Rectangle aBox = mxParentWindow->getPosSize();
573 const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
574 const double nGap (20);
575 const double nHorizontalSlideDivide (aBox.Width / nGoldenRatio);
576 double nSlidePreviewTop (0);
579 // For the current slide view calculate the outer height from the outer
580 // width. This takes into account the slide aspect ratio and thus has to
581 // go over the inner pane size.
582 PresenterPaneContainer::SharedPaneDescriptor pPane (
583 mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
584 if (pPane.get() != nullptr)
586 const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
587 nHorizontalSlideDivide - 1.5*nGap,
588 PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
589 nSlidePreviewTop = (aBox.Height - aCurrentSlideOuterBox.Height) / 2;
590 double Temp=nGap;
591 /// check whether RTL interface or not
592 if(AllSettings::GetLayoutRTL())
593 Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
594 SetPanePosSizeAbsolute (
595 PresenterPaneFactory::msCurrentSlidePreviewPaneURL,
596 Temp,
597 nSlidePreviewTop,
598 aCurrentSlideOuterBox.Width,
599 aCurrentSlideOuterBox.Height);
602 // For the next slide view calculate the outer height from the outer
603 // width. This takes into account the slide aspect ratio and thus has to
604 // go over the inner pane size.
605 pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL);
606 if (pPane.get() != nullptr)
608 const awt::Size aNextSlideOuterBox (CalculatePaneSize(
609 aBox.Width - nHorizontalSlideDivide - 1.5*nGap,
610 PresenterPaneFactory::msNextSlidePreviewPaneURL));
611 double Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
612 /// check whether RTL interface or not
613 if(AllSettings::GetLayoutRTL())
614 Temp=nGap;
615 SetPanePosSizeAbsolute (
616 PresenterPaneFactory::msNextSlidePreviewPaneURL,
617 Temp,
618 nSlidePreviewTop,
619 aNextSlideOuterBox.Width,
620 aNextSlideOuterBox.Height);
623 LayoutToolBar();
626 void PresenterWindowManager::LayoutNotesMode()
628 awt::Rectangle aBox = mxParentWindow->getPosSize();
630 const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
632 const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
633 const double nGap (20);
634 const double nPrimaryWidth (aBox.Width / nGoldenRatio);
635 const double nSecondaryWidth (aBox.Width - nPrimaryWidth);
636 const double nTertiaryWidth (nSecondaryWidth / nGoldenRatio);
637 double nSlidePreviewTop (0);
638 double nNotesViewBottom (aToolBarBox.Y1 - nGap);
639 /// check whether RTL interface or not
642 // The notes view has no fixed aspect ratio.
643 PresenterPaneContainer::SharedPaneDescriptor pPane (
644 mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
645 if (pPane.get() != nullptr)
647 const geometry::RealSize2D aNotesViewOuterSize(
648 nPrimaryWidth - 1.5*nGap + 0.5,
649 nNotesViewBottom);
650 nSlidePreviewTop = (aBox.Height
651 - aToolBarBox.Y2 + aToolBarBox.Y1 - aNotesViewOuterSize.Height) / 2;
652 /// check whether RTL interface or not
653 double Temp=aBox.Width - aNotesViewOuterSize.Width - nGap;
654 if(AllSettings::GetLayoutRTL())
655 Temp=nGap;
656 SetPanePosSizeAbsolute (
657 PresenterPaneFactory::msNotesPaneURL,
658 Temp,
659 nSlidePreviewTop,
660 aNotesViewOuterSize.Width,
661 aNotesViewOuterSize.Height);
662 nNotesViewBottom = nSlidePreviewTop + aNotesViewOuterSize.Height;
665 // For the current slide view calculate the outer height from the outer
666 // width. This takes into account the slide aspect ratio and thus has to
667 // go over the inner pane size.
668 pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
669 if (pPane.get() != nullptr)
671 const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
672 nSecondaryWidth - 1.5*nGap,
673 PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
674 /// check whether RTL interface or not
675 double Temp=nGap;
676 if(AllSettings::GetLayoutRTL())
677 Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
678 SetPanePosSizeAbsolute (
679 PresenterPaneFactory::msCurrentSlidePreviewPaneURL,
680 Temp,
681 nSlidePreviewTop,
682 aCurrentSlideOuterBox.Width,
683 aCurrentSlideOuterBox.Height);
686 // For the next slide view calculate the outer height from the outer
687 // width. This takes into account the slide aspect ratio and thus has to
688 // go over the inner pane size.
689 pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL);
690 if (pPane.get() == nullptr)
691 return;
693 const awt::Size aNextSlideOuterBox (CalculatePaneSize(
694 nTertiaryWidth,
695 PresenterPaneFactory::msNextSlidePreviewPaneURL));
696 /// check whether RTL interface or not
697 double Temp=nGap;
698 if(AllSettings::GetLayoutRTL())
699 Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
700 SetPanePosSizeAbsolute (
701 PresenterPaneFactory::msNextSlidePreviewPaneURL,
702 Temp,
703 nNotesViewBottom - aNextSlideOuterBox.Height,
704 aNextSlideOuterBox.Width,
705 aNextSlideOuterBox.Height);
710 void PresenterWindowManager::LayoutSlideSorterMode()
712 const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
714 awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
715 const double nGap (20);
716 SetPanePosSizeAbsolute(
717 mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msSlideSorterURL),
718 nGap,
719 nGap,
720 aWindowBox.Width - 2*nGap,
721 aToolBarBox.Y1 - 2*nGap);
724 void PresenterWindowManager::LayoutHelpMode()
726 const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
728 awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
729 const double nGap (20);
730 const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
731 const double nWidth = ::std::min(aWindowBox.Width - 2*nGap, aWindowBox.Width/nGoldenRatio);
732 SetPanePosSizeAbsolute(
733 mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msHelpViewURL),
734 (aWindowBox.Width - nWidth)/2,
735 nGap,
736 nWidth,
737 aToolBarBox.Y1 - 2*nGap);
740 geometry::RealRectangle2D PresenterWindowManager::LayoutToolBar()
742 double nToolBarWidth (400);
743 double nToolBarHeight (80);
745 // Get access to the tool bar.
746 PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
747 mpPaneContainer->FindPaneURL(PresenterPaneFactory::msToolBarPaneURL));
748 if (pDescriptor.get() != nullptr)
750 PresenterToolBarView* pToolBarView
751 = dynamic_cast<PresenterToolBarView*>(pDescriptor->mxView.get());
752 if (pToolBarView != nullptr && pToolBarView->GetPresenterToolBar().is())
754 geometry::RealSize2D aSize (pToolBarView->GetPresenterToolBar()->GetMinimalSize());
756 if (mpPaneBorderPainter.is())
758 const awt::Rectangle aBox (mpPaneBorderPainter->addBorder (
759 PresenterPaneFactory::msToolBarPaneURL,
760 awt::Rectangle(
763 PresenterGeometryHelper::Round(aSize.Width),
764 PresenterGeometryHelper::Round(aSize.Height)),
765 css::drawing::framework::BorderType_TOTAL_BORDER));
767 nToolBarWidth = aBox.Width;
768 nToolBarHeight = aBox.Height;
770 else
772 nToolBarWidth = aSize.Width + 20;
773 nToolBarHeight = aSize.Height + 10;
778 const awt::Rectangle aBox = mxParentWindow->getPosSize();
779 const double nToolBarX ((aBox.Width - nToolBarWidth) / 2);
780 const double nToolBarY (aBox.Height - nToolBarHeight);
781 SetPanePosSizeAbsolute(
782 PresenterPaneFactory::msToolBarPaneURL,
783 nToolBarX,
784 nToolBarY,
785 nToolBarWidth,
786 nToolBarHeight);
788 return geometry::RealRectangle2D(
789 nToolBarX,
790 nToolBarY,
791 nToolBarX + nToolBarWidth - 1,
792 nToolBarY + nToolBarHeight - 1);
795 awt::Size PresenterWindowManager::CalculatePaneSize (
796 const double nOuterWidth,
797 const OUString& rsPaneURL)
799 // Calculate the inner width by removing the pane border.
800 awt::Rectangle aInnerBox (mpPaneBorderPainter->RemoveBorder (
801 rsPaneURL,
802 awt::Rectangle(0,0,
803 sal_Int32(nOuterWidth+0.5),sal_Int32(nOuterWidth)),
804 drawing::framework::BorderType_TOTAL_BORDER));
806 // Calculate the inner height with the help of the slide aspect ratio.
807 const double nCurrentSlideInnerHeight (
808 aInnerBox.Width / mpPresenterController->GetSlideAspectRatio());
810 // Add the pane border to get the outer box.
811 awt::Rectangle aOuterBox (mpPaneBorderPainter->AddBorder (
812 rsPaneURL,
813 awt::Rectangle(0,0,
814 aInnerBox.Width,sal_Int32(nCurrentSlideInnerHeight+0.5)),
815 drawing::framework::BorderType_TOTAL_BORDER));
817 return awt::Size(aOuterBox.Width, aOuterBox.Height);
820 void PresenterWindowManager::NotifyLayoutModeChange()
822 document::EventObject aEvent;
823 aEvent.Source = Reference<XInterface>(static_cast<XWeak*>(this));
825 LayoutListenerContainer aContainerCopy (maLayoutListeners);
826 for (const auto& rxListener : aContainerCopy)
828 if (rxListener.is())
832 rxListener->notifyEvent(aEvent);
834 catch (lang::DisposedException&)
836 RemoveLayoutListener(rxListener);
838 catch (RuntimeException&)
845 void PresenterWindowManager::NotifyDisposing()
847 lang::EventObject aEvent;
848 aEvent.Source = static_cast<XWeak*>(this);
850 LayoutListenerContainer aContainer;
851 aContainer.swap(maLayoutListeners);
852 for (auto& rxListener : aContainer)
854 if (rxListener.is())
858 rxListener->disposing(aEvent);
860 catch (lang::DisposedException&)
863 catch (RuntimeException&)
870 void PresenterWindowManager::UpdateWindowSize (const Reference<awt::XWindow>& rxBorderWindow)
872 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
873 mpPaneContainer->FindBorderWindow(rxBorderWindow));
874 if (pDescriptor.get() != nullptr)
876 mxClipPolygon = nullptr;
878 // ToTop is called last because it may invalidate the iterator.
879 if ( ! mbIsLayouting)
880 mpPaneContainer->ToTop(pDescriptor);
884 void PresenterWindowManager::PaintBackground (const awt::Rectangle& rUpdateBox)
886 if ( ! mxParentWindow.is())
887 return;
889 Reference<rendering::XGraphicDevice> xDevice (mxParentCanvas->getDevice());
890 if ( ! xDevice.is())
891 return;
893 // Create a polygon for the background and for clipping.
894 Reference<rendering::XPolyPolygon2D> xBackgroundPolygon (
895 PresenterGeometryHelper::CreatePolygon(mxParentWindow->getPosSize(), xDevice));
896 if ( ! mxClipPolygon.is())
897 mxClipPolygon = CreateClipPolyPolygon();
899 // Create View- and RenderState structs.
900 const rendering::ViewState aViewState(
901 geometry::AffineMatrix2D(1,0,0, 0,1,0),
902 PresenterGeometryHelper::CreatePolygon(rUpdateBox, xDevice));
903 rendering::RenderState aRenderState (
904 geometry::AffineMatrix2D(1,0,0, 0,1,0),
905 mxClipPolygon,
906 Sequence<double>(4),
907 rendering::CompositeOperation::SOURCE);
909 // Paint the background.
910 if (mpBackgroundBitmap.get() == nullptr)
911 return;
913 ProvideBackgroundBitmap();
915 if (mxScaledBackgroundBitmap.is())
917 Sequence<rendering::Texture> aTextures (1);
918 const geometry::IntegerSize2D aBitmapSize(mxScaledBackgroundBitmap->getSize());
919 aTextures[0] = rendering::Texture (
920 geometry::AffineMatrix2D(
921 aBitmapSize.Width,0,0,
922 0,aBitmapSize.Height,0),
925 mxScaledBackgroundBitmap,
926 nullptr,
927 nullptr,
928 rendering::StrokeAttributes(),
929 rendering::TexturingMode::REPEAT,
930 rendering::TexturingMode::REPEAT);
932 mxParentCanvas->fillTexturedPolyPolygon(
933 xBackgroundPolygon,
934 aViewState,
935 aRenderState,
936 aTextures);
938 else
940 const util::Color aBackgroundColor (mpBackgroundBitmap->maReplacementColor);
941 aRenderState.DeviceColor[0] = ((aBackgroundColor >> 16) & 0x0ff) / 255.0;
942 aRenderState.DeviceColor[1] = ((aBackgroundColor >> 8) & 0x0ff) / 255.0;
943 aRenderState.DeviceColor[2] = ((aBackgroundColor >> 0) & 0x0ff) / 255.0;
944 aRenderState.DeviceColor[3] = ((aBackgroundColor >> 24) & 0x0ff) / 255.0;
945 mxParentCanvas->fillPolyPolygon(
946 xBackgroundPolygon,
947 aViewState,
948 aRenderState);
952 void PresenterWindowManager::ProvideBackgroundBitmap()
954 if ( mxScaledBackgroundBitmap.is())
955 return;
957 Reference<rendering::XBitmap> xBitmap (mpBackgroundBitmap->GetNormalBitmap());
958 if (!xBitmap.is())
959 return;
961 const bool bStretchVertical (mpBackgroundBitmap->meVerticalTexturingMode
962 == PresenterBitmapDescriptor::Stretch);
963 const bool bStretchHorizontal (mpBackgroundBitmap->meHorizontalTexturingMode
964 == PresenterBitmapDescriptor::Stretch);
965 if (bStretchHorizontal || bStretchVertical)
967 geometry::RealSize2D aSize;
968 if (bStretchVertical)
969 aSize.Height = mxParentWindow->getPosSize().Height;
970 else
971 aSize.Height = xBitmap->getSize().Height;
972 if (bStretchHorizontal)
973 aSize.Width = mxParentWindow->getPosSize().Width;
974 else
975 aSize.Width = xBitmap->getSize().Width;
976 mxScaledBackgroundBitmap = xBitmap->getScaledBitmap(aSize, false);
978 else
980 mxScaledBackgroundBitmap = xBitmap;
984 Reference<rendering::XPolyPolygon2D> PresenterWindowManager::CreateClipPolyPolygon() const
986 // Create a clip polygon that includes the whole update area but has the
987 // content windows as holes.
988 const sal_Int32 nPaneCount (mpPaneContainer->maPanes.size());
989 ::std::vector<awt::Rectangle> aRectangles;
990 aRectangles.reserve(1+nPaneCount);
991 aRectangles.push_back(mxParentWindow->getPosSize());
992 for (const auto& pDescriptor : mpPaneContainer->maPanes)
994 if ( ! pDescriptor->mbIsActive)
995 continue;
996 if ( ! pDescriptor->mbIsOpaque)
997 continue;
998 if ( ! pDescriptor->mxBorderWindow.is() || ! pDescriptor->mxContentWindow.is())
999 continue;
1000 Reference<awt::XWindow2> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY);
1001 if (xWindow.is() && ! xWindow->isVisible())
1002 continue;
1004 const awt::Rectangle aOuterBorderBox (pDescriptor->mxBorderWindow->getPosSize());
1005 awt::Rectangle aInnerBorderBox (pDescriptor->mxContentWindow->getPosSize());
1006 aInnerBorderBox.X += aOuterBorderBox.X;
1007 aInnerBorderBox.Y += aOuterBorderBox.Y;
1008 aRectangles.push_back(aInnerBorderBox);
1010 Reference<rendering::XPolyPolygon2D> xPolyPolygon (
1011 PresenterGeometryHelper::CreatePolygon(
1012 aRectangles,
1013 mxParentCanvas->getDevice()));
1014 if (xPolyPolygon.is())
1015 xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD);
1016 return xPolyPolygon;
1019 void PresenterWindowManager::Update()
1021 mxClipPolygon = nullptr;
1022 mbIsLayoutPending = true;
1024 mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
1027 void PresenterWindowManager::ThrowIfDisposed() const
1029 if (rBHelper.bDisposed || rBHelper.bInDispose)
1031 throw lang::DisposedException (
1032 "PresenterWindowManager has already been disposed",
1033 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1037 } } // end of namespace ::sdext::presenter
1039 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */