/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
namespace { /** Return the slide show controller of a running presentation that has the same document as the given framework controller. @return When no presentation is running this method returns an empty reference.
*/
Reference<presentation::XSlideShowController> lcl_GetSlideShowController ( const Reference<frame::XController>& rxController)
{
Reference<presentation::XSlideShowController> xSlideShowController;
// Use view id and controller to retrieve window and canvas from // configuration controller.
Reference<XConfigurationController> xCC (mxController->getConfigurationController());
if (xCC.is())
{
mxTopPane.set(xCC->getResource(mxViewId->getAnchor()->getAnchor()), UNO_QUERY);
if (mxWindow.is())
{
mxWindow->addPaintListener(this);
mxWindow->addWindowListener(this);
}
// The window does not have to paint a background. We do // that ourself.
Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); if (xPeer.is())
xPeer->setBackground(util::Color(0xff000000));
}
// Create a window for the actual slide show view. It is places // centered and with maximal size inside the pane.
mxViewWindow = CreateViewWindow(mxWindow);
mxViewCanvas = CreateViewCanvas(mxViewWindow);
if (mxViewWindow.is())
{ // Register listeners at window.
mxViewWindow->addPaintListener(this);
mxViewWindow->addMouseListener(this);
mxViewWindow->addMouseMotionListener(this);
}
if (mxViewWindow.is())
Resize();
if (mxWindow.is())
mxWindow->setVisible(true);
// Add the new slide show view to the slide show. if (mxSlideShow.is() && ! mbIsViewAdded)
{
impl_addAndConfigureView();
mbIsViewAdded = true;
}
// Read text for one past last slide.
PresenterConfigurationAccess aConfiguration (
mxComponentContext,
PresenterConfigurationAccess::msPresenterScreenRootName,
PresenterConfigurationAccess::READ_ONLY);
aConfiguration.GetConfigurationNode(
u"Presenter/Views/CurrentSlidePreview/" "Strings/ClickToExitPresentationText/String"_ustr)
>>= msClickToExitPresentationText;
aConfiguration.GetConfigurationNode(
u"Presenter/Views/CurrentSlidePreview/" "Strings/ClickToExitPresentationTitle/String"_ustr)
>>= msClickToExitPresentationTitle;
}
void PresenterSlideShowView::disposing()
{ // Tell all listeners that we are disposed.
lang::EventObject aEvent;
aEvent.Source = static_cast<XWeak*>(this);
::cppu::OInterfaceContainerHelper* pIterator
= maBroadcaster.getContainer(cppu::UnoType<lang::XEventListener>::get()); if (pIterator != nullptr)
pIterator->disposeAndClear(aEvent);
// Do this for // XPaintListener, XModifyListener,XMouseListener,XMouseMotionListener,XWindowListener?
if (mxWindow.is())
{
mxWindow->removePaintListener(this);
mxWindow->removeMouseListener(this);
mxWindow->removeMouseMotionListener(this);
mxWindow->removeWindowListener(this);
mxWindow = nullptr;
}
mxSlideShowController = nullptr;
mxSlideShow = nullptr; if (mxViewCanvas.is())
{
Reference<XComponent> xComponent (mxViewCanvas, UNO_QUERY);
mxViewCanvas = nullptr; if (xComponent.is())
xComponent->dispose();
} if (mxViewWindow.is())
{
Reference<XComponent> xComponent = mxViewWindow;
mxViewWindow = nullptr; if (xComponent.is())
xComponent->dispose();
} if (mxPointer.is())
{
Reference<XComponent> xComponent (mxPointer, UNO_QUERY);
mxPointer = nullptr; if (xComponent.is())
xComponent->dispose();
} if (mxBackgroundPolygon1.is())
{
Reference<XComponent> xComponent (mxBackgroundPolygon1, UNO_QUERY);
mxBackgroundPolygon1 = nullptr; if (xComponent.is())
xComponent->dispose();
} if (mxBackgroundPolygon2.is())
{
Reference<XComponent> xComponent (mxBackgroundPolygon2, UNO_QUERY);
mxBackgroundPolygon2 = nullptr; if (xComponent.is())
xComponent->dispose();
}
// For the end slide we use a special title, without the (n of m) // part. Save the title template for the case that the user goes // backwards.
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL())); if (pDescriptor)
{
msTitleTemplate = pDescriptor->msTitleTemplate;
pDescriptor->msTitleTemplate = msClickToExitPresentationTitle;
mpPresenterController->UpdatePaneTitles();
}
} elseif (mbIsEndSlideVisible)
{
mbIsEndSlideVisible = false;
// Restore the title template.
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL())); if (pDescriptor)
{
pDescriptor->msTitleTemplate = msTitleTemplate;
pDescriptor->msTitle.clear();
mpPresenterController->UpdatePaneTitles();
}
}
}
if (mxViewWindow.is())
{ // When the mbIsInModifyNotification is set then a slightly modified // version of the transformation is returned in order to get past // optimizations the avoid updates when the transformation is // unchanged (when the window size changes then due to the constant // aspect ratio the size of the preview may remain the same while // the position changes. The position, however, is represented by // the position of the view window. This transformation is given // relative to the view window and therefore does not contain the // position.) const awt::Rectangle aWindowBox = mxViewWindow->getPosSize(); return geometry::AffineMatrix2D(
aWindowBox.Width-1, 0, 0,
0, aWindowBox.Height-1, 0);
} else
{ return geometry::AffineMatrix2D(1,0,0, 0,1,0);
}
}
// Create a pointer when it does not yet exist. if ( ! mxPointer.is())
{
mxPointer = awt::Pointer::create(mxComponentContext);
}
// Set the pointer to the given shape and the window(peer) to the // pointer.
Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY); if (mxPointer.is() && xPeer.is())
{
mxPointer->setType(nPointerShape);
xPeer->setPointer(mxPointer);
}
}
void SAL_CALL PresenterSlideShowView::windowPaint (const awt::PaintEvent& rEvent)
{ // Deactivated views must not be painted. if ( ! mbIsPresenterViewActive) return;
// Only when the end slide is displayed we forward the mouse event to // the PresenterController so that it switches to the next slide and // ends the presentation. if (mbIsEndSlideVisible) if (mpPresenterController)
mpPresenterController->HandleMouseClick(rEvent);
}
do
{ if (!mpPresenterController) break;
std::shared_ptr<PresenterTheme> pTheme (mpPresenterController->GetTheme()); if (pTheme == nullptr) break;
const OUString sViewStyle (pTheme->GetStyleName(mxViewId->getResourceURL()));
PresenterTheme::SharedFontDescriptor pFont (pTheme->GetFont(sViewStyle)); if (!pFont) break;
/// this is responsible of the " presentation exit " text inside the slide windows
PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff));
aRenderState.AffineTransform.m02 = 20;
aRenderState.AffineTransform.m12 = 40; const rendering::StringContext aContext (
msClickToExitPresentationText, 0, msClickToExitPresentationText.getLength());
pFont->PrepareFont(mxCanvas); const Reference<rendering::XTextLayout> xLayout (
pFont->mxFont->createTextLayout(aContext,rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
mxCanvas->drawTextLayout(
xLayout,
aViewState,
aRenderState);
} while (false);
// Finally, in double buffered environments, request the changes to be // made visible.
Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); if (xSpriteCanvas.is())
xSpriteCanvas->updateScreen(true);
}
/** The slide show relies on the back buffer of the canvas not being modified. With a shared canvas there are times when that can not be guaranteed.
*/ if (mbIsForcedPaintPending && mxSlideShow.is() && mbIsViewAdded)
{
mxSlideShow->removeView(this);
impl_addAndConfigureView();
}
// Finally, in double buffered environments, request the changes to be // made visible.
Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); if (xSpriteCanvas.is())
xSpriteCanvas->updateScreen(true);
}
Reference<awt::XToolkit2> xToolkit = awt::Toolkit::create(mxComponentContext);
awt::WindowDescriptor aWindowDescriptor (
awt::WindowClass_CONTAINER,
OUString(),
Reference<awt::XWindowPeer>(rxParentWindow,UNO_QUERY_THROW),
-1, // parent index not available
awt::Rectangle(0,0,10,10),
awt::WindowAttribute::SIZEABLE
| awt::WindowAttribute::MOVEABLE
| awt::WindowAttribute::NODECORATION);
xViewWindow.set( xToolkit->createWindow(aWindowDescriptor),UNO_QUERY_THROW);
// Make the background transparent. The slide show paints its own background.
Reference<awt::XWindowPeer> xPeer (xViewWindow, UNO_QUERY_THROW);
xPeer->setBackground(0xff000000);
const awt::Rectangle aWindowBox (mxWindow->getPosSize()); if (aWindowBox.Height > 0)
{
awt::Rectangle aViewWindowBox; constdouble nWindowAspectRatio ( double(aWindowBox.Width) / double(aWindowBox.Height)); if (nWindowAspectRatio > mnPageAspectRatio)
{ // Slides will be painted with the full parent window height.
aViewWindowBox.Width = sal_Int32(aWindowBox.Height * mnPageAspectRatio + 0.5);
aViewWindowBox.Height = aWindowBox.Height;
aViewWindowBox.X = (aWindowBox.Width - aViewWindowBox.Width) / 2;
aViewWindowBox.Y = 0;
} else
{ // Slides will be painted with the full parent window width.
aViewWindowBox.Width = aWindowBox.Width;
aViewWindowBox.Height = sal_Int32(aWindowBox.Width / mnPageAspectRatio + 0.5);
aViewWindowBox.X = 0;
aViewWindowBox.Y = (aWindowBox.Height - aViewWindowBox.Height) / 2;
}
mxViewWindow->setPosSize(
aViewWindowBox.X,
aViewWindowBox.Y,
aViewWindowBox.Width,
aViewWindowBox.Height,
awt::PosSize::POSSIZE);
}
// Clear the background polygon so that on the next paint it is created // for the new size.
CreateBackgroundPolygons();
// Notify listeners that the transformation that maps the view into the // window has changed.
lang::EventObject aEvent (static_cast<XWeak*>(this));
::cppu::OInterfaceContainerHelper* pIterator
= maBroadcaster.getContainer(cppu::UnoType<util::XModifyListener>::get()); if (pIterator != nullptr)
{
pIterator->notifyEach(&util::XModifyListener::modified, aEvent);
}
// Due to constant aspect ratio resizing may lead a preview that changes // its position but not its size. This invalidates the back buffer and // we have to enforce a complete repaint. if ( ! mbIsPaintPending)
mbIsForcedPaintPending = true;
}
void PresenterSlideShowView::CreateBackgroundPolygons()
{ const awt::Rectangle aWindowBox (mxWindow->getPosSize()); const awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize()); if (aWindowBox.Height == aViewWindowBox.Height && aWindowBox.Width == aViewWindowBox.Width)
{
mxBackgroundPolygon1 = nullptr;
mxBackgroundPolygon2 = nullptr;
} elseif (aWindowBox.Height == aViewWindowBox.Height)
{ // Paint two boxes to the left and right of the view window.
mxBackgroundPolygon1 = PresenterGeometryHelper::CreatePolygon(
awt::Rectangle(
0,
0,
aViewWindowBox.X,
aWindowBox.Height),
mxCanvas->getDevice());
mxBackgroundPolygon2 = PresenterGeometryHelper::CreatePolygon(
awt::Rectangle(
aViewWindowBox.X + aViewWindowBox.Width,
0,
aWindowBox.Width - aViewWindowBox.X - aViewWindowBox.Width,
aWindowBox.Height),
mxCanvas->getDevice());
} else
{ // Paint two boxes above and below the view window.
mxBackgroundPolygon1 = PresenterGeometryHelper::CreatePolygon(
awt::Rectangle(
0,
0,
aWindowBox.Width,
aViewWindowBox.Y),
mxCanvas->getDevice());
mxBackgroundPolygon2 = PresenterGeometryHelper::CreatePolygon(
awt::Rectangle(
0,
aViewWindowBox.Y + aViewWindowBox.Height,
aWindowBox.Width,
aWindowBox.Height - aViewWindowBox.Y - aViewWindowBox.Height),
mxCanvas->getDevice());
}
}
void PresenterSlideShowView::ThrowIfDisposed()
{ if (rBHelper.bDisposed || rBHelper.bInDispose)
{ throw lang::DisposedException (
u"PresenterSlideShowView object has already been disposed"_ustr, static_cast<uno::XWeak*>(this));
}
}
void PresenterSlideShowView::impl_addAndConfigureView()
{
Reference<presentation::XSlideShowView> xView (this);
mxSlideShow->addView(xView); // Prevent embedded sounds being played twice at the same time by // disabling sound for the new slide show view.
beans::PropertyValue aProperty;
aProperty.Name = "IsSoundEnabled";
Sequence<Any> aValues{ Any(xView), Any(false) };
aProperty.Value <<= aValues;
mxSlideShow->setProperty(aProperty);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.