Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sdext / source / presenter / PresenterWindowManager.cxx
blob2830c444df970e390bc35839ed61955512e78c35
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/svapp.hxx>
21 #include <vcl/settings.hxx>
22 #include "PresenterWindowManager.hxx"
23 #include "PresenterController.hxx"
24 #include "PresenterGeometryHelper.hxx"
25 #include "PresenterHelper.hxx"
26 #include "PresenterPaintManager.hxx"
27 #include "PresenterPaneBase.hxx"
28 #include "PresenterPaneBorderPainter.hxx"
29 #include "PresenterPaneContainer.hxx"
30 #include "PresenterPaneFactory.hxx"
31 #include "PresenterSprite.hxx"
32 #include "PresenterToolBar.hxx"
33 #include "PresenterViewFactory.hxx"
34 #include "PresenterTheme.hxx"
35 #include <com/sun/star/awt/InvalidateStyle.hpp>
36 #include <com/sun/star/awt/PosSize.hpp>
37 #include <com/sun/star/awt/SystemPointer.hpp>
38 #include <com/sun/star/awt/XDevice.hpp>
39 #include <com/sun/star/awt/XWindow2.hpp>
40 #include <com/sun/star/awt/XWindowPeer.hpp>
41 #include <com/sun/star/awt/WindowAttribute.hpp>
42 #include <com/sun/star/container/XChild.hpp>
43 #include <com/sun/star/drawing/framework/ResourceId.hpp>
44 #include <com/sun/star/rendering/CompositeOperation.hpp>
45 #include <com/sun/star/rendering/FillRule.hpp>
46 #include <com/sun/star/rendering/PathCapType.hpp>
47 #include <com/sun/star/rendering/PathJoinType.hpp>
48 #include <com/sun/star/rendering/Texture.hpp>
49 #include <com/sun/star/rendering/TexturingMode.hpp>
50 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
51 #include <math.h>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::drawing::framework;
57 namespace sdext { namespace presenter {
59 //===== PresenterWindowManager ================================================
61 PresenterWindowManager::PresenterWindowManager (
62 const Reference<XComponentContext>& rxContext,
63 const ::rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
64 const ::rtl::Reference<PresenterController>& rpPresenterController)
65 : PresenterWindowManagerInterfaceBase(m_aMutex),
66 mxComponentContext(rxContext),
67 mpPresenterController(rpPresenterController),
68 mxParentWindow(),
69 mxParentCanvas(),
70 mxPaneBorderManager(),
71 mpPaneBorderPainter(),
72 mpPaneContainer(rpPaneContainer),
73 mbIsLayoutPending(true),
74 mbIsLayouting(false),
75 mpTheme(),
76 mpBackgroundBitmap(),
77 mxScaledBackgroundBitmap(),
78 mxClipPolygon(),
79 meLayoutMode(LM_Generic),
80 mbIsSlideSorterActive(false),
81 mbIsHelpViewActive(false),
82 maLayoutListeners(),
83 mbIsMouseClickPending(false)
88 PresenterWindowManager::~PresenterWindowManager()
92 void SAL_CALL PresenterWindowManager::disposing()
94 NotifyDisposing();
96 SetParentPane(nullptr);
98 Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY);
99 if (xComponent.is())
100 xComponent->dispose();
101 mxPaneBorderManager = nullptr;
103 PresenterPaneContainer::PaneList::const_iterator iPane;
104 PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
105 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
107 if ((*iPane)->mxBorderWindow.is())
109 (*iPane)->mxBorderWindow->removeWindowListener(this);
110 (*iPane)->mxBorderWindow->removeFocusListener(this);
111 (*iPane)->mxBorderWindow->removeMouseListener(this);
116 void PresenterWindowManager::SetParentPane (
117 const Reference<drawing::framework::XPane>& rxPane)
119 if (mxParentWindow.is())
121 mxParentWindow->removeWindowListener(this);
122 mxParentWindow->removePaintListener(this);
123 mxParentWindow->removeMouseListener(this);
124 mxParentWindow->removeFocusListener(this);
126 mxParentWindow = nullptr;
127 mxParentCanvas = nullptr;
129 if (rxPane.is())
131 mxParentWindow = rxPane->getWindow();
132 mxParentCanvas = rxPane->getCanvas();
134 else
136 mxParentWindow = nullptr;
139 if (mxParentWindow.is())
141 mxParentWindow->addWindowListener(this);
142 mxParentWindow->addPaintListener(this);
143 mxParentWindow->addMouseListener(this);
144 mxParentWindow->addFocusListener(this);
146 // We paint our own background, make that of the parent window transparent.
147 Reference<awt::XWindowPeer> xPeer (mxParentWindow, UNO_QUERY);
148 if (xPeer.is())
149 xPeer->setBackground(util::Color(0xff000000));
153 void PresenterWindowManager::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
155 mpTheme = rpTheme;
157 // Get background bitmap or background color from the theme.
159 if (mpTheme.get() != nullptr)
161 mpBackgroundBitmap = mpTheme->GetBitmap(OUString(), "Background");
165 void PresenterWindowManager::NotifyViewCreation (const Reference<XView>& rxView)
167 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
168 mpPaneContainer->FindPaneId(rxView->getResourceId()->getAnchor()));
169 OSL_ASSERT(pDescriptor.get() != nullptr);
170 if (pDescriptor.get() != nullptr)
172 Layout();
174 mpPresenterController->GetPaintManager()->Invalidate(
175 pDescriptor->mxContentWindow,
176 sal_Int16(awt::InvalidateStyle::TRANSPARENT
177 | awt::InvalidateStyle::CHILDREN));
181 void PresenterWindowManager::SetPanePosSizeAbsolute (
182 const OUString& rsPaneURL,
183 const double nX,
184 const double nY,
185 const double nWidth,
186 const double nHeight)
188 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
189 mpPaneContainer->FindPaneURL(rsPaneURL));
190 if (pDescriptor.get() != nullptr)
192 if (pDescriptor->mxBorderWindow.is())
193 pDescriptor->mxBorderWindow->setPosSize(
194 ::sal::static_int_cast<sal_Int32>(nX),
195 ::sal::static_int_cast<sal_Int32>(nY),
196 ::sal::static_int_cast<sal_Int32>(nWidth),
197 ::sal::static_int_cast<sal_Int32>(nHeight),
198 awt::PosSize::POSSIZE);
202 void PresenterWindowManager::SetPaneBorderPainter (
203 const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter)
205 mpPaneBorderPainter = rPainter;
208 //----- XWindowListener -------------------------------------------------------
210 void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent)
212 ThrowIfDisposed();
213 if (rEvent.Source == mxParentWindow)
215 Layout();
217 else
219 Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
220 if (xWindow.is())
222 UpdateWindowSize(xWindow);
224 // Make sure the background of a transparent window is painted.
225 mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
230 void SAL_CALL PresenterWindowManager::windowMoved (const awt::WindowEvent& rEvent)
232 ThrowIfDisposed();
233 if (rEvent.Source != mxParentWindow)
235 Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
236 UpdateWindowSize(xWindow);
238 // Make sure the background of a transparent window is painted.
239 mpPresenterController->GetPaintManager()->Invalidate(xWindow);
243 void SAL_CALL PresenterWindowManager::windowShown (const lang::EventObject&) {}
245 void SAL_CALL PresenterWindowManager::windowHidden (const lang::EventObject&) {}
247 //----- XPaintListener --------------------------------------------------------
249 void SAL_CALL PresenterWindowManager::windowPaint (const awt::PaintEvent& rEvent)
251 ThrowIfDisposed();
253 if ( ! mxParentWindow.is())
254 return;
255 if ( ! mxParentCanvas.is())
256 return;
258 if (mpTheme.get()!=nullptr)
262 if (mbIsLayoutPending)
263 Layout();
264 PaintBackground(rEvent.UpdateRect);
265 PaintChildren(rEvent);
267 catch (RuntimeException&)
269 OSL_FAIL("paint failed!");
274 //----- XMouseListener --------------------------------------------------------
276 void SAL_CALL PresenterWindowManager::mousePressed (const css::awt::MouseEvent&)
278 mbIsMouseClickPending = true;
281 void SAL_CALL PresenterWindowManager::mouseReleased (const css::awt::MouseEvent& rEvent)
283 if (mbIsMouseClickPending)
285 mbIsMouseClickPending = false;
286 mpPresenterController->HandleMouseClick(rEvent);
290 void SAL_CALL PresenterWindowManager::mouseEntered (const css::awt::MouseEvent&)
292 mbIsMouseClickPending = false;
295 void SAL_CALL PresenterWindowManager::mouseExited (const css::awt::MouseEvent&)
297 mbIsMouseClickPending = false;
300 //----- XFocusListener --------------------------------------------------------
302 void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& /*rEvent*/)
304 ThrowIfDisposed();
307 void SAL_CALL PresenterWindowManager::focusLost (const css::awt::FocusEvent&)
309 ThrowIfDisposed();
312 //----- XEventListener --------------------------------------------------------
314 void SAL_CALL PresenterWindowManager::disposing (const lang::EventObject& rEvent)
316 if (rEvent.Source == mxParentWindow)
317 mxParentWindow = nullptr;
321 void PresenterWindowManager::PaintChildren (const awt::PaintEvent& rEvent) const
323 // Call windowPaint on all children that lie in or touch the
324 // update rectangle.
325 PresenterPaneContainer::PaneList::const_iterator iPane;
326 PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
327 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
331 // Make sure that the pane shall and can be painted.
332 if ( ! (*iPane)->mbIsActive)
333 continue;
334 if ((*iPane)->mbIsSprite)
335 continue;
336 if ( ! (*iPane)->mxPane.is())
337 continue;
338 if ( ! (*iPane)->mxBorderWindow.is())
339 continue;
340 Reference<awt::XWindow> xBorderWindow ((*iPane)->mxBorderWindow);
341 if ( ! xBorderWindow.is())
342 continue;
344 // Get the area in which the border of the pane has to be painted.
345 const awt::Rectangle aBorderBox (xBorderWindow->getPosSize());
346 const awt::Rectangle aBorderUpdateBox(
347 PresenterGeometryHelper::Intersection(
348 rEvent.UpdateRect,
349 aBorderBox));
350 if (aBorderUpdateBox.Width<=0 || aBorderUpdateBox.Height<=0)
351 continue;
353 const awt::Rectangle aLocalBorderUpdateBox(
354 PresenterGeometryHelper::TranslateRectangle(
355 aBorderUpdateBox,
356 -aBorderBox.X,
357 -aBorderBox.Y));
359 // Invalidate the area of the content window.
360 mpPresenterController->GetPaintManager()->Invalidate(
361 xBorderWindow,
362 aLocalBorderUpdateBox,
363 sal_Int16(awt::InvalidateStyle::CHILDREN
364 | awt::InvalidateStyle::NOTRANSPARENT));
366 catch (RuntimeException&)
368 OSL_FAIL("paint children failed!");
373 void PresenterWindowManager::SetLayoutMode (const LayoutMode eMode)
375 OSL_ASSERT(mpPresenterController.get() != nullptr);
377 if (meLayoutMode != eMode
378 || mbIsSlideSorterActive
379 || mbIsHelpViewActive)
381 meLayoutMode = eMode;
382 mbIsSlideSorterActive = false;
383 mbIsHelpViewActive = false;
385 mpPresenterController->RequestViews(
386 mbIsSlideSorterActive,
387 meLayoutMode==LM_Notes,
388 mbIsHelpViewActive);
389 Layout();
390 NotifyLayoutModeChange();
394 void PresenterWindowManager::SetSlideSorterState (bool bIsActive)
396 if (mbIsSlideSorterActive != bIsActive)
398 mbIsSlideSorterActive = bIsActive;
399 if (mbIsSlideSorterActive)
400 mbIsHelpViewActive = false;
401 StoreViewMode(GetViewMode());
403 mpPresenterController->RequestViews(
404 mbIsSlideSorterActive,
405 meLayoutMode==LM_Notes,
406 mbIsHelpViewActive);
407 Layout();
408 NotifyLayoutModeChange();
412 void PresenterWindowManager::SetHelpViewState (bool bIsActive)
414 if (mbIsHelpViewActive != bIsActive)
416 mbIsHelpViewActive = bIsActive;
417 if (mbIsHelpViewActive)
418 mbIsSlideSorterActive = false;
419 StoreViewMode(GetViewMode());
421 mpPresenterController->RequestViews(
422 mbIsSlideSorterActive,
423 meLayoutMode==LM_Notes,
424 mbIsHelpViewActive);
425 Layout();
426 NotifyLayoutModeChange();
430 void PresenterWindowManager::SetViewMode (const ViewMode eMode)
432 switch (eMode)
434 case VM_Standard:
435 SetSlideSorterState(false);
436 SetHelpViewState(false);
437 SetLayoutMode(LM_Standard);
438 break;
440 case VM_Notes:
441 SetSlideSorterState(false);
442 SetHelpViewState(false);
443 SetLayoutMode(LM_Notes);
444 break;
446 case VM_SlideOverview:
447 SetHelpViewState(false);
448 SetSlideSorterState(true);
449 break;
451 case VM_Help:
452 SetHelpViewState(true);
453 SetSlideSorterState(false);
454 break;
457 StoreViewMode(eMode);
460 PresenterWindowManager::ViewMode PresenterWindowManager::GetViewMode() const
462 if (mbIsHelpViewActive)
463 return VM_Help;
464 else if (mbIsSlideSorterActive)
465 return VM_SlideOverview;
466 else if (meLayoutMode == LM_Notes)
467 return VM_Notes;
468 else
469 return VM_Standard;
472 void PresenterWindowManager::RestoreViewMode()
474 sal_Int32 nMode (0);
475 PresenterConfigurationAccess aConfiguration (
476 mxComponentContext,
477 "/org.openoffice.Office.PresenterScreen/",
478 PresenterConfigurationAccess::READ_ONLY);
479 aConfiguration.GetConfigurationNode("Presenter/InitialViewMode") >>= nMode;
480 switch (nMode)
482 default:
483 case 0:
484 SetViewMode(VM_Standard);
485 break;
487 case 1:
488 SetViewMode(VM_Notes);
489 break;
491 case 2:
492 SetViewMode(VM_SlideOverview);
493 break;
497 void PresenterWindowManager::StoreViewMode (const ViewMode eViewMode)
501 PresenterConfigurationAccess aConfiguration (
502 mxComponentContext,
503 "/org.openoffice.Office.PresenterScreen/",
504 PresenterConfigurationAccess::READ_WRITE);
505 aConfiguration.GoToChild(OUString("Presenter"));
506 Any aValue;
507 switch (eViewMode)
509 default:
510 case VM_Standard:
511 aValue <<= sal_Int32(0);
512 break;
514 case VM_Notes:
515 aValue <<= sal_Int32(1);
516 break;
518 case VM_SlideOverview:
519 aValue <<= sal_Int32(2);
520 break;
523 aConfiguration.SetProperty ("InitialViewMode", aValue);
524 aConfiguration.CommitChanges();
526 catch (Exception&)
531 void PresenterWindowManager::AddLayoutListener (
532 const Reference<document::XEventListener>& rxListener)
534 maLayoutListeners.push_back(rxListener);
537 void PresenterWindowManager::RemoveLayoutListener (
538 const Reference<document::XEventListener>& rxListener)
540 LayoutListenerContainer::iterator iListener (maLayoutListeners.begin());
541 LayoutListenerContainer::iterator iEnd (maLayoutListeners.end());
542 for ( ; iListener!=iEnd; ++iListener)
544 if (*iListener == rxListener)
546 maLayoutListeners.erase(iListener);
547 // Assume that there are no multiple entries.
548 break;
553 void PresenterWindowManager::Layout()
555 if (mxParentWindow.is() && ! mbIsLayouting)
557 mbIsLayoutPending = false;
558 mbIsLayouting = true;
559 mxScaledBackgroundBitmap = nullptr;
560 mxClipPolygon = nullptr;
564 if (mbIsSlideSorterActive)
565 LayoutSlideSorterMode();
566 else if (mbIsHelpViewActive)
567 LayoutHelpMode();
568 else
569 switch (meLayoutMode)
571 case LM_Standard:
572 default:
573 LayoutStandardMode();
574 break;
576 case LM_Notes:
577 LayoutNotesMode();
578 break;
581 catch (Exception&)
583 OSL_ASSERT(false);
584 throw;
587 mbIsLayouting = false;
591 void PresenterWindowManager::LayoutStandardMode()
593 awt::Rectangle aBox = mxParentWindow->getPosSize();
595 const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
596 const double nGap (20);
597 const double nHorizontalSlideDivide (aBox.Width / nGoldenRatio);
598 double nSlidePreviewTop (0);
601 // For the current slide view calculate the outer height from the outer
602 // width. This takes into account the slide aspect ratio and thus has to
603 // go over the inner pane size.
604 PresenterPaneContainer::SharedPaneDescriptor pPane (
605 mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
606 if (pPane.get() != nullptr)
608 const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
609 nHorizontalSlideDivide - 1.5*nGap,
610 PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
611 nSlidePreviewTop = (aBox.Height - aCurrentSlideOuterBox.Height) / 2;
612 double Temp=nGap;
613 /// check whether RTL interface or not
614 if(AllSettings::GetLayoutRTL())
615 Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
616 SetPanePosSizeAbsolute (
617 PresenterPaneFactory::msCurrentSlidePreviewPaneURL,
618 Temp,
619 nSlidePreviewTop,
620 aCurrentSlideOuterBox.Width,
621 aCurrentSlideOuterBox.Height);
624 // For the next slide view calculate the outer height from the outer
625 // width. This takes into account the slide aspect ratio and thus has to
626 // go over the inner pane size.
627 pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL);
628 if (pPane.get() != nullptr)
630 const awt::Size aNextSlideOuterBox (CalculatePaneSize(
631 aBox.Width - nHorizontalSlideDivide - 1.5*nGap,
632 PresenterPaneFactory::msNextSlidePreviewPaneURL));
633 double Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
634 /// check whether RTL interface or not
635 if(AllSettings::GetLayoutRTL())
636 Temp=nGap;
637 SetPanePosSizeAbsolute (
638 PresenterPaneFactory::msNextSlidePreviewPaneURL,
639 Temp,
640 nSlidePreviewTop,
641 aNextSlideOuterBox.Width,
642 aNextSlideOuterBox.Height);
645 LayoutToolBar();
648 void PresenterWindowManager::LayoutNotesMode()
650 awt::Rectangle aBox = mxParentWindow->getPosSize();
652 const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
654 const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
655 const double nGap (20);
656 const double nPrimaryWidth (aBox.Width / nGoldenRatio);
657 const double nSecondaryWidth (aBox.Width - nPrimaryWidth);
658 const double nTertiaryWidth (nSecondaryWidth / nGoldenRatio);
659 double nSlidePreviewTop (0);
660 double nNotesViewBottom (aToolBarBox.Y1 - nGap);
661 /// check whether RTL interface or not
664 // The notes view has no fixed aspect ratio.
665 PresenterPaneContainer::SharedPaneDescriptor pPane (
666 mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
667 if (pPane.get() != nullptr)
669 const geometry::RealSize2D aNotesViewOuterSize(
670 nPrimaryWidth - 1.5*nGap + 0.5,
671 nNotesViewBottom);
672 nSlidePreviewTop = (aBox.Height
673 - aToolBarBox.Y2 + aToolBarBox.Y1 - aNotesViewOuterSize.Height) / 2;
674 /// check whether RTL interface or not
675 double Temp=aBox.Width - aNotesViewOuterSize.Width - nGap;
676 if(AllSettings::GetLayoutRTL())
677 Temp=nGap;
678 SetPanePosSizeAbsolute (
679 PresenterPaneFactory::msNotesPaneURL,
680 Temp,
681 nSlidePreviewTop,
682 aNotesViewOuterSize.Width,
683 aNotesViewOuterSize.Height);
684 nNotesViewBottom = nSlidePreviewTop + aNotesViewOuterSize.Height;
687 // For the current slide view calculate the outer height from the outer
688 // width. This takes into account the slide aspect ratio and thus has to
689 // go over the inner pane size.
690 pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
691 if (pPane.get() != nullptr)
693 const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
694 nSecondaryWidth - 1.5*nGap,
695 PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
696 /// check whether RTL interface or not
697 double Temp=nGap;
698 if(AllSettings::GetLayoutRTL())
699 Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
700 SetPanePosSizeAbsolute (
701 PresenterPaneFactory::msCurrentSlidePreviewPaneURL,
702 Temp,
703 nSlidePreviewTop,
704 aCurrentSlideOuterBox.Width,
705 aCurrentSlideOuterBox.Height);
708 // For the next slide view calculate the outer height from the outer
709 // width. This takes into account the slide aspect ratio and thus has to
710 // go over the inner pane size.
711 pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL);
712 if (pPane.get() != nullptr)
714 const awt::Size aNextSlideOuterBox (CalculatePaneSize(
715 nTertiaryWidth,
716 PresenterPaneFactory::msNextSlidePreviewPaneURL));
717 /// check whether RTL interface or not
718 double Temp=nGap;
719 if(AllSettings::GetLayoutRTL())
720 Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
721 SetPanePosSizeAbsolute (
722 PresenterPaneFactory::msNextSlidePreviewPaneURL,
723 Temp,
724 nNotesViewBottom - aNextSlideOuterBox.Height,
725 aNextSlideOuterBox.Width,
726 aNextSlideOuterBox.Height);
732 void PresenterWindowManager::LayoutSlideSorterMode()
734 const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
736 awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
737 const double nGap (20);
738 SetPanePosSizeAbsolute(
739 mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msSlideSorterURL),
740 nGap,
741 nGap,
742 aWindowBox.Width - 2*nGap,
743 aToolBarBox.Y1 - 2*nGap);
746 void PresenterWindowManager::LayoutHelpMode()
748 const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
750 awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
751 const double nGap (20);
752 const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
753 const double nWidth = ::std::min(aWindowBox.Width - 2*nGap, aWindowBox.Width/nGoldenRatio);
754 SetPanePosSizeAbsolute(
755 mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msHelpViewURL),
756 (aWindowBox.Width - nWidth)/2,
757 nGap,
758 nWidth,
759 aToolBarBox.Y1 - 2*nGap);
762 geometry::RealRectangle2D PresenterWindowManager::LayoutToolBar()
764 double nToolBarWidth (400);
765 double nToolBarHeight (80);
767 // Get access to the tool bar.
768 PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
769 mpPaneContainer->FindPaneURL(PresenterPaneFactory::msToolBarPaneURL));
770 if (pDescriptor.get() != nullptr)
772 PresenterToolBarView* pToolBarView
773 = dynamic_cast<PresenterToolBarView*>(pDescriptor->mxView.get());
774 if (pToolBarView != nullptr && pToolBarView->GetPresenterToolBar().is())
776 geometry::RealSize2D aSize (pToolBarView->GetPresenterToolBar()->GetMinimalSize());
778 if (mpPaneBorderPainter.is())
780 const awt::Rectangle aBox (mpPaneBorderPainter->addBorder (
781 PresenterPaneFactory::msToolBarPaneURL,
782 awt::Rectangle(
785 PresenterGeometryHelper::Round(aSize.Width),
786 PresenterGeometryHelper::Round(aSize.Height)),
787 css::drawing::framework::BorderType_TOTAL_BORDER));
789 nToolBarWidth = aBox.Width;
790 nToolBarHeight = aBox.Height;
792 else
794 nToolBarWidth = aSize.Width + 20;
795 nToolBarHeight = aSize.Height + 10;
800 const awt::Rectangle aBox = mxParentWindow->getPosSize();
801 const double nToolBarX ((aBox.Width - nToolBarWidth) / 2);
802 const double nToolBarY (aBox.Height - nToolBarHeight);
803 SetPanePosSizeAbsolute(
804 PresenterPaneFactory::msToolBarPaneURL,
805 nToolBarX,
806 nToolBarY,
807 nToolBarWidth,
808 nToolBarHeight);
810 return geometry::RealRectangle2D(
811 nToolBarX,
812 nToolBarY,
813 nToolBarX + nToolBarWidth - 1,
814 nToolBarY + nToolBarHeight - 1);
817 awt::Size PresenterWindowManager::CalculatePaneSize (
818 const double nOuterWidth,
819 const OUString& rsPaneURL)
821 // Calculate the inner width by removing the pane border.
822 awt::Rectangle aInnerBox (mpPaneBorderPainter->RemoveBorder (
823 rsPaneURL,
824 awt::Rectangle(0,0,
825 sal_Int32(nOuterWidth+0.5),sal_Int32(nOuterWidth)),
826 drawing::framework::BorderType_TOTAL_BORDER));
828 // Calculate the inner height with the help of the slide aspect ratio.
829 const double nCurrentSlideInnerHeight (
830 aInnerBox.Width / mpPresenterController->GetSlideAspectRatio());
832 // Add the pane border to get the outer box.
833 awt::Rectangle aOuterBox (mpPaneBorderPainter->AddBorder (
834 rsPaneURL,
835 awt::Rectangle(0,0,
836 aInnerBox.Width,sal_Int32(nCurrentSlideInnerHeight+0.5)),
837 drawing::framework::BorderType_TOTAL_BORDER));
839 return awt::Size(aOuterBox.Width, aOuterBox.Height);
842 void PresenterWindowManager::NotifyLayoutModeChange()
844 document::EventObject aEvent;
845 aEvent.Source = Reference<XInterface>(static_cast<XWeak*>(this));
847 LayoutListenerContainer aContainerCopy (maLayoutListeners);
848 LayoutListenerContainer::iterator iListener (aContainerCopy.begin());
849 LayoutListenerContainer::iterator iEnd (aContainerCopy.end());
850 for ( ; iListener!=iEnd; ++iListener)
852 if (iListener->is())
856 (*iListener)->notifyEvent(aEvent);
858 catch (lang::DisposedException&)
860 RemoveLayoutListener(*iListener);
862 catch (RuntimeException&)
869 void PresenterWindowManager::NotifyDisposing()
871 lang::EventObject aEvent;
872 aEvent.Source = static_cast<XWeak*>(this);
874 LayoutListenerContainer aContainer;
875 aContainer.swap(maLayoutListeners);
876 LayoutListenerContainer::iterator iListener (aContainer.begin());
877 LayoutListenerContainer::iterator iEnd (aContainer.end());
878 for ( ; iListener!=iEnd; ++iListener)
880 if (iListener->is())
884 (*iListener)->disposing(aEvent);
886 catch (lang::DisposedException&)
889 catch (RuntimeException&)
896 void PresenterWindowManager::UpdateWindowSize (const Reference<awt::XWindow>& rxBorderWindow)
898 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
899 mpPaneContainer->FindBorderWindow(rxBorderWindow));
900 if (pDescriptor.get() != nullptr)
902 mxClipPolygon = nullptr;
904 // ToTop is called last because it may invalidate the iterator.
905 if ( ! mbIsLayouting)
906 mpPaneContainer->ToTop(pDescriptor);
910 void PresenterWindowManager::PaintBackground (const awt::Rectangle& rUpdateBox)
912 if ( ! mxParentWindow.is())
913 return;
915 Reference<rendering::XGraphicDevice> xDevice (mxParentCanvas->getDevice());
916 if ( ! xDevice.is())
917 return;
919 // Create a polygon for the background and for clipping.
920 Reference<rendering::XPolyPolygon2D> xBackgroundPolygon (
921 PresenterGeometryHelper::CreatePolygon(mxParentWindow->getPosSize(), xDevice));
922 if ( ! mxClipPolygon.is())
923 mxClipPolygon = CreateClipPolyPolygon();
925 // Create View- and RenderState structs.
926 const rendering::ViewState aViewState(
927 geometry::AffineMatrix2D(1,0,0, 0,1,0),
928 PresenterGeometryHelper::CreatePolygon(rUpdateBox, xDevice));
929 rendering::RenderState aRenderState (
930 geometry::AffineMatrix2D(1,0,0, 0,1,0),
931 mxClipPolygon,
932 Sequence<double>(4),
933 rendering::CompositeOperation::SOURCE);
935 // Paint the background.
936 if (mpBackgroundBitmap.get() != nullptr)
938 ProvideBackgroundBitmap();
940 if (mxScaledBackgroundBitmap.is())
942 Sequence<rendering::Texture> aTextures (1);
943 const geometry::IntegerSize2D aBitmapSize(mxScaledBackgroundBitmap->getSize());
944 aTextures[0] = rendering::Texture (
945 geometry::AffineMatrix2D(
946 aBitmapSize.Width,0,0,
947 0,aBitmapSize.Height,0),
950 mxScaledBackgroundBitmap,
951 nullptr,
952 nullptr,
953 rendering::StrokeAttributes(),
954 rendering::TexturingMode::REPEAT,
955 rendering::TexturingMode::REPEAT);
957 mxParentCanvas->fillTexturedPolyPolygon(
958 xBackgroundPolygon,
959 aViewState,
960 aRenderState,
961 aTextures);
963 else
965 const util::Color aBackgroundColor (mpBackgroundBitmap->maReplacementColor);
966 aRenderState.DeviceColor[0] = ((aBackgroundColor >> 16) & 0x0ff) / 255.0;
967 aRenderState.DeviceColor[1] = ((aBackgroundColor >> 8) & 0x0ff) / 255.0;
968 aRenderState.DeviceColor[2] = ((aBackgroundColor >> 0) & 0x0ff) / 255.0;
969 aRenderState.DeviceColor[3] = ((aBackgroundColor >> 24) & 0x0ff) / 255.0;
970 mxParentCanvas->fillPolyPolygon(
971 xBackgroundPolygon,
972 aViewState,
973 aRenderState);
978 void PresenterWindowManager::ProvideBackgroundBitmap()
980 if ( ! mxScaledBackgroundBitmap.is())
982 Reference<rendering::XBitmap> xBitmap (mpBackgroundBitmap->GetNormalBitmap());
983 if (xBitmap.is())
985 const bool bStretchVertical (mpBackgroundBitmap->meVerticalTexturingMode
986 == PresenterBitmapDescriptor::Stretch);
987 const bool bStretchHorizontal (mpBackgroundBitmap->meHorizontalTexturingMode
988 == PresenterBitmapDescriptor::Stretch);
989 if (bStretchHorizontal || bStretchVertical)
991 geometry::RealSize2D aSize;
992 if (bStretchVertical)
993 aSize.Height = mxParentWindow->getPosSize().Height;
994 else
995 aSize.Height = xBitmap->getSize().Height;
996 if (bStretchHorizontal)
997 aSize.Width = mxParentWindow->getPosSize().Width;
998 else
999 aSize.Width = xBitmap->getSize().Width;
1000 mxScaledBackgroundBitmap = xBitmap->getScaledBitmap(aSize, false);
1002 else
1004 mxScaledBackgroundBitmap.set(xBitmap, UNO_QUERY);
1010 Reference<rendering::XPolyPolygon2D> PresenterWindowManager::CreateClipPolyPolygon() const
1012 // Create a clip polygon that includes the whole update area but has the
1013 // content windows as holes.
1014 const sal_Int32 nPaneCount (mpPaneContainer->maPanes.size());
1015 ::std::vector<awt::Rectangle> aRectangles;
1016 aRectangles.reserve(1+nPaneCount);
1017 aRectangles.push_back(mxParentWindow->getPosSize());
1018 PresenterPaneContainer::PaneList::const_iterator iPane;
1019 PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
1020 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
1022 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (*iPane);
1023 if ( ! pDescriptor->mbIsActive)
1024 continue;
1025 if ( ! pDescriptor->mbIsOpaque)
1026 continue;
1027 if ( ! pDescriptor->mxBorderWindow.is() || ! pDescriptor->mxContentWindow.is())
1028 continue;
1029 Reference<awt::XWindow2> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY);
1030 if (xWindow.is() && ! xWindow->isVisible())
1031 continue;
1033 const awt::Rectangle aOuterBorderBox (pDescriptor->mxBorderWindow->getPosSize());
1034 awt::Rectangle aInnerBorderBox (pDescriptor->mxContentWindow->getPosSize());
1035 aInnerBorderBox.X += aOuterBorderBox.X;
1036 aInnerBorderBox.Y += aOuterBorderBox.Y;
1037 aRectangles.push_back(aInnerBorderBox);
1039 Reference<rendering::XPolyPolygon2D> xPolyPolygon (
1040 PresenterGeometryHelper::CreatePolygon(
1041 aRectangles,
1042 mxParentCanvas->getDevice()));
1043 if (xPolyPolygon.is())
1044 xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD);
1045 return xPolyPolygon;
1048 void PresenterWindowManager::Update()
1050 mxClipPolygon = nullptr;
1051 mbIsLayoutPending = true;
1053 mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
1056 void PresenterWindowManager::ThrowIfDisposed() const
1058 if (rBHelper.bDisposed || rBHelper.bInDispose)
1060 throw lang::DisposedException (
1061 "PresenterWindowManager has already been disposed",
1062 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1066 } } // end of namespace ::sdext::presenter
1068 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */