/* -*- 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 .
*/
#include <memory>
#include <com/sun/star/presentation/XPresentation2.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/awt/XDevice.hpp>
#include <com/sun/star/document/IndexedPropertyValues.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/util/XTheme.hpp>
#include <com/sun/star/animations/AnimationFill.hpp>
#include <com/sun/star/animations/AnimationRestart.hpp>
#include <com/sun/star/animations/AnimationEndSync.hpp>
#include <com/sun/star/animations/AnimationCalcMode.hpp>
#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
#include <com/sun/star/animations/AnimationNodeType.hpp>
#include <com/sun/star/animations/AnimationTransformType.hpp>
#include <com/sun/star/animations/AnimationColorSpace.hpp>
#include <com/sun/star/animations/Event.hpp>
#include <com/sun/star/animations/EventTrigger.hpp>
#include <com/sun/star/animations/Timing.hpp>
#include <com/sun/star/animations/TransitionType.hpp>
#include <com/sun/star/animations/TransitionSubType.hpp>
#include <com/sun/star/animations/ValuePair.hpp>
#include <com/sun/star/animations/XAnimate.hpp>
#include <com/sun/star/animations/XAnimateMotion.hpp>
#include <com/sun/star/animations/XAnimateColor.hpp>
#include <com/sun/star/animations/XAnimateTransform.hpp>
#include <com/sun/star/animations/XIterateContainer.hpp>
#include <com/sun/star/animations/XTimeContainer.hpp>
#include <com/sun/star/animations/XTransitionFilter.hpp>
#include <com/sun/star/presentation/EffectNodeType.hpp>
#include <com/sun/star/presentation/EffectPresetClass.hpp>
#include <com/sun/star/presentation/ParagraphTarget.hpp>
#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
#include <com/sun/star/presentation/TextAnimationType.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <officecfg/Office/Common.hxx>
#include <officecfg/Office/Impress.hxx>
#include <comphelper/dispatchcommand.hxx>
#include <comphelper/indexedpropertyvalues.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/propertysequence.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/servicehelper.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/profilezone.hxx>
#include <sal/log.hxx>
#include <editeng/unofield.hxx>
#include <notifydocumentevent.hxx>
#include <tpaction.hxx>
#include <unomodel.hxx>
#include "unopool.hxx"
#include <sfx2/lokhelper.hxx>
#include <sfx2/dispatch.hxx>
#include <vcl/svapp.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <editeng/UnoForbiddenCharsTable.hxx>
#include <svx/svdoutl.hxx>
#include <o3tl/any.hxx>
#include <o3tl/safeint.hxx>
#include <o3tl/string_view.hxx>
#include <o3tl/test_info.hxx>
#include <o3tl/unit_conversion.hxx>
#include <svx/UnoNamespaceMap.hxx>
#include <svx/svdlayer.hxx>
#include <svx/svdsob.hxx>
#include <svx/svdundo.hxx>
#include <svx/svdomedia.hxx>
#include <svx/unoapi.hxx>
#include <svx/unofill.hxx>
#include <svx/sdrpagewindow.hxx>
#include <svx/sdrpaintwindow.hxx>
#include <editeng/fontitem.hxx>
#include <toolkit/awt/vclxdevice.hxx>
#include <svx/svdpool.hxx>
#include <svx/svdpagv.hxx>
#include <svtools/unoimap.hxx>
#include <svx/unoshape.hxx>
#include <editeng/unonrule.hxx>
#include <editeng/eeitem.hxx>
#include <unotools/datetime.hxx>
#include <sax/tools/converter.hxx>
#include <xmloff/autolayout.hxx>
#include <xmloff/xmltoken.hxx>
#include <rtl/math.hxx>
#include <tools/helpers.hxx>
#include <tools/json_writer.hxx>
// Support creation of GraphicStorageHandler and EmbeddedObjectResolver
#include <svx/xmleohlp.hxx>
#include <svx/xmlgrhlp.hxx>
#include <DrawDocShell.hxx>
#include <ViewShellBase.hxx>
#include "UnoDocumentSettings.hxx"
#include <Annotation.hxx>
#include <drawdoc.hxx>
#include <sdmod.hxx>
#include <sdresid.hxx>
#include <sdpage.hxx>
#include <strings.hrc>
#include <strings.hxx>
#include "unolayer.hxx"
#include <unopage.hxx>
#include "unocpres.hxx"
#include "unoobj.hxx"
#include <stlpool.hxx>
#include "unopback.hxx"
#include <unokywds.hxx>
#include <FrameView.hxx>
#include <ClientView.hxx>
#include <DrawViewShell.hxx>
#include <ViewShell.hxx>
#include <Window.hxx>
#include <optsitem.hxx>
#include <vcl/pdfextoutdevdata.hxx>
#include <vcl/pdf/PDFNote.hxx>
#include <com/sun/star/presentation/AnimationSpeed.hpp>
#include <com/sun/star/presentation/ClickAction.hpp>
#include <svx/sdr/contact/viewobjectcontact.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <com/sun/star/office/XAnnotation.hpp>
#include <com/sun/star/office/XAnnotationAccess.hpp>
#include <com/sun/star/office/XAnnotationEnumeration.hpp>
#include <com/sun/star/geometry/RealPoint2D.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
#include <sfx2/lokcomponenthelpers.hxx>
#include <sfx2/LokControlHandler.hxx>
#include <tools/gen.hxx>
#include <tools/debug.hxx>
#include <tools/urlobj.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <tools/UnitConversion.hxx>
#include <svx/ColorSets.hxx>
#include <docmodel/theme/Theme.hxx>
#include <frozen/bits/defines.h>
#include <frozen/bits/elsa_std.h>
#include <frozen/unordered_map.h>
#include <app.hrc>
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::sd;
const TranslateId aTypeResIds[SdLinkTargetType::Count] =
{
STR_SD_PAGE, // SdLinkTargetType::Page
STR_NOTES_MODE, // SdLinkTargetType::Notes
STR_HANDOUT, // SdLinkTargetType::Handout
STR_MASTERPAGE_NAME, // SdLinkTargetType::MasterPage
};
TranslateId SdTPAction::GetClickActionSdResId( presentation::ClickAction eCA )
{
switch( eCA )
{
case presentation::ClickAction_NONE: return STR_CLICK_ACTION_NONE;
case presentation::ClickAction_PREVPAGE: return STR_CLICK_ACTION_PREVPAGE;
case presentation::ClickAction_NEXTPAGE: return STR_CLICK_ACTION_NEXTPAGE;
case presentation::ClickAction_FIRSTPAGE: return STR_CLICK_ACTION_FIRSTPAGE;
case presentation::ClickAction_LASTPAGE: return STR_CLICK_ACTION_LASTPAGE;
case presentation::ClickAction_BOOKMARK: return STR_CLICK_ACTION_BOOKMARK;
case presentation::ClickAction_DOCUMENT: return STR_CLICK_ACTION_DOCUMENT;
case presentation::ClickAction_PROGRAM: return STR_CLICK_ACTION_PROGRAM;
case presentation::ClickAction_MACRO: return STR_CLICK_ACTION_MACRO;
case presentation::ClickAction_SOUND: return STR_CLICK_ACTION_SOUND;
case presentation::ClickAction_VERB: return STR_CLICK_ACTION_VERB;
case presentation::ClickAction_STOPPRESENTATION: return STR_CLICK_ACTION_STOPPRESENTATION;
default: OSL_FAIL( "No StringResource for ClickAction available!" );
}
return {};
}
class SdUnoForbiddenCharsTable : public SvxUnoForbiddenCharsTable,
public SfxListener
{
public:
explicit SdUnoForbiddenCharsTable(SdrModel* pModel);
virtual ~SdUnoForbiddenCharsTable() override;
// SfxListener
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override;
protected:
virtual void onChange() override;
private:
SdrModel* mpModel;
};
namespace {
class SlideBackgroundInfo
{
public:
SlideBackgroundInfo(const uno::Reference<drawing::XDrawPage>& xDrawPage,
const uno::Reference<drawing::XDrawPage>& xMasterPage);
bool slideHasOwnBackground() const { return mbIsCustom; }
bool hasBackground() const { return bHasBackground; }
bool isSolidColor() const { return mbIsSolidColor; }
::Color getFillColor() const;
sal_Int32 getFillTransparency() const;
OString getFillColorAsRGBA() const;
private:
bool getFillStyleImpl(const uno::Reference<drawing::XDrawPage>& xDrawPage);
private:
uno::Reference<beans::XPropertySet> mxBackground;
bool mbIsCustom;
bool bHasBackground;
bool mbIsSolidColor;
drawing::FillStyle maFillStyle;
};
SlideBackgroundInfo::SlideBackgroundInfo(
const uno::Reference<drawing::XDrawPage>& xDrawPage,
const uno::Reference<drawing::XDrawPage>& xMasterPage)
: mbIsCustom(false)
, bHasBackground(false)
, mbIsSolidColor(false)
, maFillStyle(drawing::FillStyle_NONE)
{
mbIsCustom = getFillStyleImpl(xDrawPage);
bHasBackground = mbIsCustom;
if (!bHasBackground)
{
bHasBackground = getFillStyleImpl(xMasterPage);
}
if (bHasBackground)
{
if (maFillStyle == drawing::FillStyle_SOLID)
{
OUString sGradientName;
mxBackground->getPropertyValue("FillTransparenceGradientName") >>= sGradientName;
if (sGradientName.isEmpty())
{
mbIsSolidColor = true;
}
}
}
}
sal_Int32 SlideBackgroundInfo::getFillTransparency() const
{
if (!mxBackground.is())
return 0;
sal_Int32 nFillTransparency = 0;
mxBackground->getPropertyValue("FillTransparence") >>= nFillTransparency;
return nFillTransparency;
}
::Color SlideBackgroundInfo::getFillColor() const
{
if (!mxBackground.is())
return {};
if (sal_Int32 nFillColor; mxBackground->getPropertyValue("FillColor") >>= nFillColor)
{
return ::Color(ColorTransparency, nFillColor & 0xffffff);
}
return {};
}
OString SlideBackgroundInfo::getFillColorAsRGBA() const
{
::Color aColor = getFillColor();
OString sColor = aColor.AsRGBHEXString().toUtf8();
sal_uInt32 nAlpha = std::round((100 - getFillTransparency()) * 255 / 100.0);
std::stringstream ss;
ss << std::hex << std::uppercase << std::setfill ('0') << std::setw(2) << nAlpha;
sColor += ss.str().c_str();
return sColor;
}
bool SlideBackgroundInfo::getFillStyleImpl(const uno::Reference<drawing::XDrawPage>& xDrawPage)
{
if( xDrawPage.is() )
{
uno::Reference< beans::XPropertySet > xPropSet( xDrawPage, uno::UNO_QUERY );
if( xPropSet.is() )
{
uno::Reference< beans::XPropertySet > xBackground;
if (xPropSet->getPropertySetInfo()->hasPropertyByName("Background"))
xPropSet->getPropertyValue( "Background" ) >>= xBackground;
if( xBackground.is() )
{
drawing::FillStyle aFillStyle;
if( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle )
{
maFillStyle = aFillStyle;
if (aFillStyle != drawing::FillStyle_NONE)
{
mxBackground = std::move(xBackground);
return true;
}
}
}
}
}
return false;
}
using namespace ::css::animations;
using namespace ::css::beans;
using namespace ::css::container;
using namespace ::css::uno;
using namespace ::xmloff::token;
using namespace ::css::presentation;
template <typename T, std::size_t N>
constexpr auto mapEnumToString(std::pair<T, std::string_view> const (&items)[N])
{
return frozen::make_unordered_map<T, std::string_view, N>(items);
}
constexpr auto constTransitionTypeToString = mapEnumToString<sal_Int16>({
{ animations::TransitionType::BARWIPE, "BarWipe" }, // Wipe
{ animations::TransitionType::PINWHEELWIPE, "PineWheelWipe" }, // Wheel
{ animations::TransitionType::SLIDEWIPE, "SlideWipe" }, // Cover, Uncover
{ animations::TransitionType::RANDOMBARWIPE, "RandomBarWipe" }, // Bars
{ animations::TransitionType::CHECKERBOARDWIPE, "CheckerBoardWipe" }, // Checkers
{ animations::TransitionType::FOURBOXWIPE, "FourBoxWipe" }, // Shape
{ animations::TransitionType::IRISWIPE, "IrisWipe" }, // Box
{ animations::TransitionType::FANWIPE, "FanWipe" }, // Wedge
{ animations::TransitionType::BLINDSWIPE, "BlindWipe"}, // Venetian
{ animations::TransitionType::FADE, "Fade"},
{ animations::TransitionType::DISSOLVE, "Dissolve"},
{ animations::TransitionType::PUSHWIPE, "PushWipe"}, // Comb
{ animations::TransitionType::ELLIPSEWIPE, "EllipseWipe"}, // Shape
{ animations::TransitionType::BARNDOORWIPE, "BarnDoorWipe"}, // Split
{ animations::TransitionType::WATERFALLWIPE, "WaterfallWipe"}, // Diagonal
{ animations::TransitionType::MISCSHAPEWIPE, "MiscShapeWipe"},
{ animations::TransitionType::ZOOM, "Zoom"}
});
constexpr auto constTransitionSubTypeToString = mapEnumToString<sal_Int16>({
{ animations::TransitionSubType::LEFTTORIGHT, "LeftToRight" },
{ animations::TransitionSubType::TOPTOBOTTOM, "TopToBottom" },
{ animations::TransitionSubType::EIGHTBLADE, "8Blade" },
{ animations::TransitionSubType::FOURBLADE, "4Blade" },
{ animations::TransitionSubType::THREEBLADE, "3Blade" },
{ animations::TransitionSubType::TWOBLADEVERTICAL, "2BladeVertical" },
{ animations::TransitionSubType::ONEBLADE, "1Blade" },
{ animations::TransitionSubType::FROMTOPLEFT, "FromTopLeft" },
{ animations::TransitionSubType::FROMTOPRIGHT, "FromTopRight"},
{ animations::TransitionSubType::FROMBOTTOMLEFT, "FromBottomLeft"},
{ animations::TransitionSubType::FROMBOTTOMRIGHT, "FromBottomRight"},
{ animations::TransitionSubType::VERTICAL, "Vertical"},
{ animations::TransitionSubType::HORIZONTAL, "Horizontal"},
{ animations::TransitionSubType::DOWN, "Down"},
{ animations::TransitionSubType::ACROSS, "Across"},
{ animations::TransitionSubType::CORNERSOUT, "CornersOut"},
{ animations::TransitionSubType::DIAMOND, "Diamond"},
{ animations::TransitionSubType::CIRCLE, "Circle"},
{ animations::TransitionSubType::RECTANGLE, "Rectangle"},
{ animations::TransitionSubType::CENTERTOP, "CenterTop"},
{ animations::TransitionSubType::CROSSFADE, "CrossFade"},
{ animations::TransitionSubType::FADEOVERCOLOR, "FadeOverColor"},
{ animations::TransitionSubType::FROMLEFT, "FromLeft"},
{ animations::TransitionSubType::FROMRIGHT, "FromRight"},
{ animations::TransitionSubType::FROMTOP, "FromTop"},
{ animations::TransitionSubType::HORIZONTALLEFT, "HorizontalLeft"},
{ animations::TransitionSubType::HORIZONTALRIGHT, "HorizontalRight"},
{ animations::TransitionSubType::COMBVERTICAL, "CombVertical"},
{ animations::TransitionSubType::COMBHORIZONTAL, "CombHorizontal"},
{ animations::TransitionSubType::TOPLEFT, "TopLeft"},
{ animations::TransitionSubType::TOPRIGHT, "TopRight"},
{ animations::TransitionSubType::BOTTOMRIGHT, "BottomRight"},
{ animations::TransitionSubType::BOTTOMLEFT, "BottomLeft"},
{ animations::TransitionSubType::TOPCENTER, "TopCenter"},
{ animations::TransitionSubType::RIGHTCENTER, "RightCenter"},
{ animations::TransitionSubType::BOTTOMCENTER, "BottomCenter"},
{ animations::TransitionSubType::FANOUTHORIZONTAL, "FanOutHorizontal"},
{ animations::TransitionSubType::CORNERSIN, "CornersIn"},
{ animations::TransitionSubType::HEART, "Heart"},
{ animations::TransitionSubType::ROTATEIN, "RotateIn"}
});
constexpr auto constAnimationNodeTypeToString = mapEnumToString<sal_Int16>({
{ AnimationNodeType::ANIMATE, "Animate" },
{ AnimationNodeType::ANIMATECOLOR, "AnimateColor" },
{ AnimationNodeType::ANIMATEMOTION, "Animate" },
{ AnimationNodeType::ANIMATEPHYSICS, "Animate" },
{ AnimationNodeType::ANIMATETRANSFORM, "AnimateTransform" },
{ AnimationNodeType::AUDIO, "Audio" },
{ AnimationNodeType::COMMAND, "Command" },
{ AnimationNodeType::CUSTOM, "Custom" },
{ AnimationNodeType::ITERATE, "Iterate" },
{ AnimationNodeType::PAR, "Par" },
{ AnimationNodeType::SEQ, "Seq" },
{ AnimationNodeType::SET, "Set" },
{ AnimationNodeType::TRANSITIONFILTER, "TransitionFilter" },
});
constexpr auto constFillToString = mapEnumToString<sal_Int16>({
{ AnimationFill::DEFAULT, "Default" },
{ AnimationFill::REMOVE, "Remove" },
{ AnimationFill::FREEZE, "Freeze" },
{ AnimationFill::HOLD, "Hold" },
{ AnimationFill::TRANSITION, "Transition" },
{ AnimationFill::AUTO, "Auto" },
});
constexpr auto constRestartToString = mapEnumToString<sal_Int16>({
{ AnimationRestart::DEFAULT, "Default" },
{ AnimationRestart::ALWAYS, "Always" },
{ AnimationRestart::WHEN_NOT_ACTIVE, "WhenNotActive" },
{ AnimationRestart::NEVER, "Never" },
});
constexpr auto constEndSyncToString = mapEnumToString<sal_Int16>({
{ AnimationEndSync::FIRST, "First" },
{ AnimationEndSync::LAST, "Last" },
{ AnimationEndSync::ALL, "All" },
{ AnimationEndSync::MEDIA, "Media" },
});
constexpr auto constCalcModeToString = mapEnumToString<sal_Int16>({
{ AnimationCalcMode::DISCRETE, "Discrete" },
{ AnimationCalcMode::LINEAR, "Linear" },
{ AnimationCalcMode::PACED, "Paced" },
{ AnimationCalcMode::SPLINE, "Spline" },
});
constexpr auto constAdditiveModeToString = mapEnumToString<sal_Int16>({
{ AnimationAdditiveMode::BASE, "Base" },
{ AnimationAdditiveMode::SUM, "Sum" },
{ AnimationAdditiveMode::REPLACE, "Replace" },
{ AnimationAdditiveMode::MULTIPLY, "Multiply" },
{ AnimationAdditiveMode::NONE, "None" },
});
constexpr auto constEffectPresetClassToString = mapEnumToString<sal_Int16>({
{ EffectPresetClass::CUSTOM, "Custom" },
{ EffectPresetClass::ENTRANCE, "Entrance" },
{ EffectPresetClass::EXIT, "Exit" },
{ EffectPresetClass::EMPHASIS, "Emphasis" },
{ EffectPresetClass::MOTIONPATH, "MotionPath" },
{ EffectPresetClass::OLEACTION, "OleAction" },
{ EffectPresetClass::MEDIACALL, "MediaCall" },
});
constexpr auto constEffectNodeTypeToString = mapEnumToString<sal_Int16>({
{ EffectNodeType::DEFAULT, "Default" },
{ EffectNodeType::ON_CLICK, "OnClick" },
{ EffectNodeType::WITH_PREVIOUS, "WithPrevious" },
{ EffectNodeType::AFTER_PREVIOUS, "AfterPrevious" },
{ EffectNodeType::MAIN_SEQUENCE, "MainSequence" },
{ EffectNodeType::TIMING_ROOT, "TimingRoot" },
{ EffectNodeType::INTERACTIVE_SEQUENCE, "InteractiveSequence" },
});
constexpr auto constEventTriggerToString = mapEnumToString<sal_Int16>({
{ EventTrigger::BEGIN_EVENT, "BeginEvent" },
{ EventTrigger::END_EVENT, "EndEvent" },
{ EventTrigger::NONE, "None" },
{ EventTrigger::ON_BEGIN, "OnBegin" },
{ EventTrigger::ON_CLICK, "OnClick" },
{ EventTrigger::ON_DBL_CLICK, "OnDblClick" },
{ EventTrigger::ON_END, "OnEnd" },
{ EventTrigger::ON_MOUSE_ENTER, "OnMouseEnter" },
{ EventTrigger::ON_MOUSE_LEAVE, "OnMouseLeave" },
{ EventTrigger::ON_NEXT, "OnNext" },
{ EventTrigger::ON_PREV, "OnPrev" },
{ EventTrigger::ON_STOP_AUDIO, "OnStopAudio" },
{ EventTrigger::REPEAT, "Repeat" },
});
constexpr auto constTimingToString = mapEnumToString<Timing>({
{ Timing_INDEFINITE, "indefinite" },
{ Timing_MEDIA, "media" },
});
constexpr auto constTransformTypeToString = mapEnumToString<sal_Int16>({
{ AnimationTransformType::TRANSLATE, "Translate" },
{ AnimationTransformType::SCALE, "Scale" },
{ AnimationTransformType::ROTATE, "Rotate" },
{ AnimationTransformType::SKEWX, "SkewX" },
{ AnimationTransformType::SKEWY, "SkewY" },
});
constexpr auto constSubItemToString = mapEnumToString<sal_Int16>({
{ ShapeAnimationSubType::AS_WHOLE, "AsWhole" },
{ ShapeAnimationSubType::ONLY_BACKGROUND, "OnlyBackground" },
{ ShapeAnimationSubType::ONLY_TEXT, "OnlyText" },
});
constexpr auto constIterateTypeToString = mapEnumToString<sal_Int16>({
{ TextAnimationType::BY_PARAGRAPH, "ByParagraph" },
{ TextAnimationType::BY_WORD, "ByWord" },
{ TextAnimationType::BY_LETTER, "ByLetter" },
});
constexpr auto constFillStyleToString = mapEnumToString<drawing::FillStyle>({
{ drawing::FillStyle_NONE, "None" },
{ drawing::FillStyle_SOLID, "Solid" },
{ drawing::FillStyle_BITMAP, "Bitmap" },
{ drawing::FillStyle_GRADIENT, "Gradient" },
{ drawing::FillStyle_HATCH, "Hatch" },
});
constexpr auto constLineStyleToString = mapEnumToString<drawing::LineStyle>({
{ drawing::LineStyle_NONE, "None" },
{ drawing::LineStyle_SOLID, "Solid" },
{ drawing::LineStyle_DASH, "Dash" },
});
constexpr auto constAttributeNameToXMLEnum
= frozen::make_unordered_map<std::string_view, XMLTokenEnum>({
{ "X", XML_X },
{ "Y", XML_Y },
{ "Width", XML_WIDTH },
{ "Height", XML_HEIGHT },
{ "Rotate", XML_ROTATE },
{ "SkewX", XML_SKEWX },
{ "FillColor", XML_FILL_COLOR },
{ "FillStyle", XML_FILL },
{ "LineColor", XML_STROKE_COLOR },
{ "LineStyle",XML_STROKE },
{ "CharColor", XML_COLOR },
{ "CharRotation", XML_TEXT_ROTATION_ANGLE },
{ "CharWeight", XML_FONT_WEIGHT },
{ "CharUnderline", XML_TEXT_UNDERLINE },
{ "CharFontName", XML_FONT_FAMILY },
{ "CharHeight", XML_FONT_SIZE },
{ "CharPosture", XML_FONT_STYLE },
{ "Visibility", XML_VISIBILITY },
{ "Opacity", XML_OPACITY },
{ "DimColor", XML_DIM },
});
class AnimationsExporter
{
public:
AnimationsExporter(::tools::JsonWriter& rWriter,
const Reference<drawing::XDrawPage>& xDrawPage);
void exportAnimations();
[[nodiscard]] bool hasEffects() const { return mbHasEffects; }
private:
void exportNode(const Reference<XAnimationNode>& xNode);
void exportNodeImpl(const Reference<XAnimationNode>& xNode);
void exportContainer(const Reference<XTimeContainer>& xContainer);
void exportAnimate(const Reference<XAnimate>& xAnimate);
void convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp, const Any& rValue) const;
static void convertTarget(OStringBuffer& sTmp, const Any& rTarget);
static Reference<XInterface> getParagraphTarget( const ParagraphTarget& pTarget );
void convertTiming(OStringBuffer& sTmp, const Any& rValue) const;
private:
::tools::JsonWriter& mrWriter;
Reference<drawing::XDrawPage> mxDrawPage;
Reference<XPropertySet> mxPageProps;
Reference<XAnimationNode> mxRootNode;
bool mbHasEffects;
};
AnimationsExporter::AnimationsExporter(::tools::JsonWriter& rWriter,
const Reference<drawing::XDrawPage>& xDrawPage)
: mrWriter(rWriter)
, mxDrawPage(xDrawPage)
, mbHasEffects(false)
{
if (!mxDrawPage.is())
return;
try
{
mxPageProps = Reference<XPropertySet>(xDrawPage, UNO_QUERY);
if (!mxPageProps.is())
return;
Reference<XAnimationNodeSupplier> xAnimNodeSupplier(mxDrawPage, UNO_QUERY);
if (!xAnimNodeSupplier.is())
return;
Reference<XAnimationNode> xRootNode = xAnimNodeSupplier->getAnimationNode();
if (xRootNode.is())
{
// first check if there are no animations
Reference<XEnumerationAccess> xEnumerationAccess(xRootNode, UNO_QUERY_THROW);
Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(),
css::uno::UNO_SET_THROW);
if (xEnumeration->hasMoreElements())
{
// first child node may be an empty main sequence, check this
Reference<XAnimationNode> xMainNode(xEnumeration->nextElement(), UNO_QUERY_THROW);
Reference<XEnumerationAccess> xMainEnumerationAccess(xMainNode, UNO_QUERY_THROW);
Reference<XEnumeration> xMainEnumeration(
xMainEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW);
// only export if the main sequence is not empty or if there are additional
// trigger sequences
mbHasEffects
= xMainEnumeration->hasMoreElements() || xEnumeration->hasMoreElements();
}
}
if (mbHasEffects)
mxRootNode = std::move(xRootNode);
}
catch (const RuntimeException&)
{
TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
}
}
template <typename EnumT, size_t N>
constexpr bool convertEnum(OStringBuffer& rBuffer, EnumT nValue,
const frozen::unordered_map<EnumT, std::string_view, N>& rMap)
{
auto iterator = rMap.find(nValue);
if (iterator == rMap.end())
return false;
rBuffer.append(iterator->second);
return true;
}
void convertDouble(OStringBuffer& rBuffer, double fValue)
{
::rtl::math::doubleToStringBuffer(rBuffer, fValue, rtl_math_StringFormat_Automatic,
rtl_math_DecimalPlaces_Max, '.', true);
}
void convertBool(OStringBuffer& rBuffer, bool bValue)
{
rBuffer.append( bValue );
}
void convertPath(OStringBuffer& sTmp, const Any& rPath)
{
OUString aStr;
rPath >>= aStr;
sTmp = aStr.toUtf8();
}
void convertColor(OStringBuffer& rBuffer, sal_Int32 nColor)
{
OUStringBuffer aUBuffer;
::sax::Converter::convertColor(aUBuffer, nColor);
rBuffer.append(aUBuffer.makeStringAndClear().toUtf8());
}
void convertColor(OStringBuffer& rBuffer, const Any& rValue)
{
sal_Int32 nColor = 0;
if (rValue >>= nColor)
{
convertColor(rBuffer, nColor);
}
else
{
Sequence<double> aHSL;
if ((rValue >>= aHSL) && (aHSL.getLength() == 3))
{
rBuffer.append("hsl(" + OString::number(aHSL[0]) + ","
+ OString::number(aHSL[1] * 100.0) + "%,"
+ OString::number(aHSL[2] * 100.0) + "%)");
}
}
}
bool isValidNode(const Reference<XAnimationNode>& xNode)
{
if (xNode.is())
{
sal_Int16 nNodeType = xNode->getType();
auto iterator = constAnimationNodeTypeToString.find(nNodeType);
return iterator != constAnimationNodeTypeToString.end();
}
return false;
}
void AnimationsExporter::exportAnimations()
{
if (!mxDrawPage.is() || !mxPageProps.is() || !mxRootNode.is() || !hasEffects())
return;
if (isValidNode(mxRootNode))
{
auto aNode = mrWriter.startNode("root");
exportNodeImpl(mxRootNode);
}
}
void AnimationsExporter::exportNode(const Reference<XAnimationNode>& xNode)
{
if (!isValidNode(xNode))
return;
auto aStruct = mrWriter.startStruct();
exportNodeImpl(xNode);
}
void AnimationsExporter::exportNodeImpl(const Reference<XAnimationNode>& xNode)
{
try
{
std::string sId = GetInterfaceHash(xNode);
mrWriter.put("id", sId);
sal_Int16 nNodeType = xNode->getType();
auto iterator = constAnimationNodeTypeToString.find(nNodeType);
assert(iterator != constAnimationNodeTypeToString.end() && "must be previously checked with isValidNode");
mrWriter.put("nodeName", iterator->second);
// common properties
OStringBuffer sTmp;
Any aTemp;
double fTemp = 0;
sal_Int16 nTemp;
aTemp = xNode->getBegin();
if (aTemp.hasValue())
{
convertTiming(sTmp, aTemp);
mrWriter.put("begin", sTmp.makeStringAndClear());
}
aTemp = xNode->getDuration();
if (aTemp.hasValue())
{
if (aTemp >>= fTemp)
{
convertDouble(sTmp, fTemp);
sTmp.append('s');
mrWriter.put("dur", sTmp.makeStringAndClear());
}
else
{
Timing eTiming;
if (aTemp >>= eTiming)
{
mrWriter.put("dur", eTiming == Timing_INDEFINITE ? "indefinite" : "media");
}
}
}
aTemp = xNode->getEnd();
if (aTemp.hasValue())
{
convertTiming(sTmp, aTemp);
mrWriter.put("end", sTmp.makeStringAndClear());
}
nTemp = xNode->getFill();
if (nTemp != AnimationFill::DEFAULT)
{
convertEnum(sTmp, nTemp, constFillToString);
mrWriter.put("fill", sTmp.makeStringAndClear());
}
nTemp = xNode->getFillDefault();
if (nTemp != AnimationFill::INHERIT)
{
convertEnum(sTmp, nTemp, constFillToString);
mrWriter.put("fillDefault", sTmp.makeStringAndClear());
}
nTemp = xNode->getRestart();
if (nTemp != AnimationRestart::DEFAULT)
{
convertEnum(sTmp, nTemp, constRestartToString);
mrWriter.put("restart", sTmp.makeStringAndClear());
}
nTemp = xNode->getRestartDefault();
if (nTemp != AnimationRestart::INHERIT)
{
convertEnum(sTmp, nTemp, constRestartToString);
mrWriter.put("restartDefault", sTmp.makeStringAndClear());
}
fTemp = xNode->getAcceleration();
if (fTemp != 0.0)
{
convertDouble(sTmp, fTemp);
mrWriter.put("accelerate", sTmp.makeStringAndClear());
}
fTemp = xNode->getDecelerate();
if (fTemp != 0.0)
{
convertDouble(sTmp, fTemp);
mrWriter.put("decelerate", sTmp.makeStringAndClear());
}
bool bTemp = xNode->getAutoReverse();
if (bTemp)
{
convertBool(sTmp, bTemp);
mrWriter.put("autoreverse", sTmp.makeStringAndClear());
}
aTemp = xNode->getRepeatCount();
if (aTemp.hasValue())
{
Timing eTiming;
if ((aTemp >>= eTiming) && (eTiming == Timing_INDEFINITE))
{
mrWriter.put("repeatCount", "indefinite");
}
else if (aTemp >>= fTemp)
{
convertDouble(sTmp, fTemp);
mrWriter.put("repeatCount", sTmp.makeStringAndClear());
}
}
aTemp = xNode->getRepeatDuration();
if (aTemp.hasValue())
{
Timing eTiming;
if ((aTemp >>= eTiming) && (eTiming == Timing_INDEFINITE))
{
mrWriter.put("repeatDur", "indefinite");
}
else if (aTemp >>= fTemp)
{
convertDouble(sTmp, fTemp);
mrWriter.put("repeatDur", sTmp.makeStringAndClear());
}
}
aTemp = xNode->getEndSync();
if (aTemp.hasValue() && (aTemp >>= nTemp))
{
convertEnum(sTmp, nTemp, constEndSyncToString);
mrWriter.put("endSync", sTmp.makeStringAndClear());
}
sal_Int16 nContainerNodeType = EffectNodeType::DEFAULT;
const Sequence<NamedValue> aUserData(xNode->getUserData());
for (const auto& rValue : aUserData)
{
if (IsXMLToken(rValue.Name, XML_NODE_TYPE))
{
if ((rValue.Value >>= nContainerNodeType)
&& (nContainerNodeType != EffectNodeType::DEFAULT))
{
convertEnum(sTmp, nContainerNodeType, constEffectNodeTypeToString);
mrWriter.put("nodeType", sTmp.makeStringAndClear());
}
}
else if (IsXMLToken(rValue.Name, XML_PRESET_ID))
{
OUString aPresetId;
if (rValue.Value >>= aPresetId)
{
mrWriter.put("presetId", aPresetId);
}
}
else if (IsXMLToken(rValue.Name, XML_PRESET_SUB_TYPE))
{
OUString aPresetSubType;
if (rValue.Value >>= aPresetSubType)
{
mrWriter.put("presetSubType", aPresetSubType);
}
}
else if (IsXMLToken(rValue.Name, XML_PRESET_CLASS))
{
sal_Int16 nEffectPresetClass = sal_uInt16(0);
if (rValue.Value >>= nEffectPresetClass)
{
convertEnum(sTmp, nEffectPresetClass, constEffectPresetClassToString);
mrWriter.put("presetClass", sTmp.makeStringAndClear());
}
}
else if (IsXMLToken(rValue.Name, XML_MASTER_ELEMENT))
{
Reference<XInterface> xMaster;
rValue.Value >>= xMaster;
if (xMaster.is())
{
const std::string aIdentifier(GetInterfaceHash(xMaster));
if (!aIdentifier.empty())
mrWriter.put("masterElement", aIdentifier);
}
}
else if (IsXMLToken(rValue.Name, XML_GROUP_ID))
{
sal_Int32 nGroupId = 0;
if (rValue.Value >>= nGroupId)
mrWriter.put("groupId", nGroupId);
}
else
{
OUString aTmp;
if (rValue.Value >>= aTmp)
mrWriter.put(rValue.Name, aTmp);
}
}
switch (nNodeType)
{
case AnimationNodeType::PAR:
case AnimationNodeType::SEQ:
case AnimationNodeType::ITERATE:
{
Reference<XTimeContainer> xContainer(xNode, UNO_QUERY_THROW);
exportContainer(xContainer);
}
break;
case AnimationNodeType::ANIMATE:
case AnimationNodeType::SET:
case AnimationNodeType::ANIMATEMOTION:
case AnimationNodeType::ANIMATEPHYSICS:
case AnimationNodeType::ANIMATECOLOR:
case AnimationNodeType::ANIMATETRANSFORM:
case AnimationNodeType::TRANSITIONFILTER:
{
Reference<XAnimate> xAnimate(xNode, UNO_QUERY_THROW);
exportAnimate(xAnimate);
}
break;
case AnimationNodeType::AUDIO:
{
SAL_WARN("sd", "AnimationsExporter::exportNode(): Audio Node not supported.");
}
break;
case AnimationNodeType::COMMAND:
{
SAL_WARN("sd", "AnimationsExporter::exportNode(): Command Node not supported.");
}
break;
default:
{
OSL_FAIL(
"sd unomodel: AnimationsExporter::exportNode(), invalid AnimationNodeType!");
}
}
}
catch (const RuntimeException&)
{
TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
}
}
Reference<XInterface> AnimationsExporter::getParagraphTarget(const ParagraphTarget& pTarget)
{
try
{
Reference<XEnumerationAccess> xParaEnumAccess(pTarget.Shape, UNO_QUERY_THROW);
Reference<XEnumeration> xEnumeration(xParaEnumAccess->createEnumeration(),
css::uno::UNO_SET_THROW);
sal_Int32 nParagraph = pTarget.Paragraph;
while (xEnumeration->hasMoreElements())
{
Reference<XInterface> xRef(xEnumeration->nextElement(), UNO_QUERY);
if (nParagraph-- == 0)
return xRef;
}
}
catch (const RuntimeException&)
{
TOOLS_WARN_EXCEPTION("sd", "AnimationsExporter::getParagraphTarget");
}
Reference<XInterface> xRef;
return xRef;
}
void AnimationsExporter::convertTarget(OStringBuffer& sTmp, const Any& rTarget)
{
if (!rTarget.hasValue())
return;
Reference<XInterface> xRef;
if (!(rTarget >>= xRef))
{
if (auto pt = o3tl::tryAccess<ParagraphTarget>(rTarget))
{
xRef = getParagraphTarget(*pt);
}
}
SAL_WARN_IF(!xRef.is(), "sd", "AnimationsExporter::convertTarget(), invalid target type!");
if (xRef.is())
{
const std::string aIdentifier(GetInterfaceHash(xRef));
if (!aIdentifier.empty())
sTmp.append(aIdentifier);
}
}
void AnimationsExporter::convertTiming(OStringBuffer& sTmp, const Any& rValue) const
{
if (!rValue.hasValue())
return;
if (auto pSequence = o3tl::tryAccess<Sequence<Any>>(rValue))
{
const sal_Int32 nLength = pSequence->getLength();
sal_Int32 nElement;
const Any* pAny = pSequence->getConstArray();
OStringBuffer sTmp2;
for (nElement = 0; nElement < nLength; nElement++, pAny++)
{
if (!sTmp.isEmpty())
sTmp.append(';');
convertTiming(sTmp2, *pAny);
sTmp.append(sTmp2);
sTmp2.setLength(0);
}
}
else if (auto x = o3tl::tryAccess<double>(rValue))
{
sTmp.append(*x);
sTmp.append('s');
}
else if (auto pTiming = o3tl::tryAccess<Timing>(rValue))
{
const auto svTiming = (*pTiming == Timing_MEDIA)
? constTimingToString.at(Timing_MEDIA)
: constTimingToString.at(Timing_INDEFINITE);
sTmp.append(svTiming);
}
else if (auto pEvent = o3tl::tryAccess<Event>(rValue))
{
OStringBuffer sTmp2;
if (pEvent->Trigger != EventTrigger::NONE)
{
if (pEvent->Source.hasValue())
{
convertTarget(sTmp, pEvent->Source);
sTmp.append('.');
}
convertEnum(sTmp2, pEvent->Trigger, constEventTriggerToString);
sTmp.append(sTmp2);
sTmp2.setLength(0);
}
if (pEvent->Offset.hasValue())
{
convertTiming(sTmp2, pEvent->Offset);
if (!sTmp.isEmpty())
sTmp.append('+');
sTmp.append(sTmp2);
sTmp2.setLength(0);
}
}
else
{
OSL_FAIL("sd.unomodel: AnimationsExporter::convertTiming, invalid value type!");
}
}
void AnimationsExporter::convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp,
const Any& rValue) const
{
if (!rValue.hasValue())
return;
if (auto pValuePair = o3tl::tryAccess<ValuePair>(rValue))
{
OStringBuffer sTmp2;
convertValue(eAttributeName, sTmp, pValuePair->First);
sTmp.append(',');
convertValue(eAttributeName, sTmp2, pValuePair->Second);
sTmp.append(sTmp2);
}
else if (auto pSequence = o3tl::tryAccess<Sequence<Any>>(rValue))
{
const sal_Int32 nLength = pSequence->getLength();
sal_Int32 nElement;
const Any* pAny = pSequence->getConstArray();
OStringBuffer sTmp2;
for (nElement = 0; nElement < nLength; nElement++, pAny++)
{
if (!sTmp.isEmpty())
sTmp.append(';');
convertValue(eAttributeName, sTmp2, *pAny);
sTmp.append(sTmp2);
sTmp2.setLength(0);
}
}
else
{
switch (eAttributeName)
{
case XML_X:
case XML_Y:
case XML_WIDTH:
case XML_HEIGHT:
case XML_ANIMATETRANSFORM:
case XML_ANIMATEMOTION:
case XML_ANIMATEPHYSICS:
{
if (auto sValue = o3tl::tryAccess<OUString>(rValue))
{
sTmp.append(sValue->toUtf8());
}
else if (auto aValue = o3tl::tryAccess<double>(rValue))
{
sTmp.append(*aValue);
}
else
{
OSL_FAIL("sd::AnimationsExporter::convertValue(), invalid value type!");
}
return;
}
case XML_SKEWX:
case XML_ROTATE:
case XML_OPACITY:
case XML_TRANSITIONFILTER:
if (auto aValue = o3tl::tryAccess<double>(rValue))
{
sTmp.append(*aValue);
}
break;
case XML_TEXT_ROTATION_ANGLE:
if (auto aValue = o3tl::tryAccess<sal_Int16>(rValue))
{
// on win and armv7 platforms compiler complains
// that append(sal_Int16) is ambiguous
sTmp.append(static_cast<sal_Int32>(*aValue));
}
break;
case XML_FILL_COLOR:
case XML_STROKE_COLOR:
case XML_DIM:
case XML_COLOR:
{
convertColor(sTmp, rValue);
}
break;
case XML_FILL:
if (auto aValue = o3tl::tryAccess<drawing::FillStyle>(rValue))
{
convertEnum(sTmp, *aValue, constFillStyleToString);
}
break;
case XML_STROKE:
if (auto aValue = o3tl::tryAccess<drawing::LineStyle>(rValue))
{
convertEnum(sTmp, *aValue, constLineStyleToString);
}
break;
case XML_FONTSIZE:
if (auto aValue = o3tl::tryAccess<double>(rValue))
{
double fValue = *aValue * 100;
fValue += fValue > 0 ? 0.5 : -0.5;
auto nValue = static_cast<sal_Int32>(fValue);
sTmp.append(nValue); // percent
}
break;
case XML_FONT_WEIGHT:
case XML_FONT_STYLE:
case XML_TEXT_UNDERLINE:
SAL_WARN("sd", "AnimationsExporter::convertValue(): value type "
<< GetXMLToken(eAttributeName) << " not supported");
break;
case XML_VISIBILITY:
if (auto aValue = o3tl::tryAccess<bool>(rValue))
{
OUString sValue = *aValue ? GetXMLToken(XML_VISIBLE) : GetXMLToken(XML_HIDDEN);
sTmp.append(sValue.toUtf8());
}
break;
default:
OSL_FAIL("unomodel: AnimationsExporter::convertValue(), invalid AttributeName!");
}
}
}
void AnimationsExporter::exportContainer(const Reference<XTimeContainer>& xContainer)
{
try
{
const sal_Int32 nNodeType = xContainer->getType();
if (nNodeType == AnimationNodeType::ITERATE)
{
OStringBuffer sTmp;
Reference<XIterateContainer> xIter(xContainer, UNO_QUERY_THROW);
Any aTemp(xIter->getTarget());
if (aTemp.hasValue())
{
convertTarget(sTmp, aTemp);
mrWriter.put("targetElement", sTmp.makeStringAndClear());
}
sal_Int16 nTemp = xIter->getSubItem();
if (nTemp)
{
convertEnum(sTmp, nTemp, constSubItemToString);
mrWriter.put("subItem", sTmp.makeStringAndClear());
}
nTemp = xIter->getIterateType();
if (nTemp)
{
convertEnum(sTmp, nTemp, constIterateTypeToString);
mrWriter.put("iterateType", sTmp.makeStringAndClear());
}
double fTemp = xIter->getIterateInterval();
if (fTemp != 0)
{
OUStringBuffer buf;
::sax::Converter::convertDuration(buf, fTemp / (24 * 60 * 60));
mrWriter.put("iterateInterval", sTmp.makeStringAndClear());
}
}
auto anArray = mrWriter.startArray("children");
Reference<XEnumerationAccess> xEnumerationAccess(xContainer, UNO_QUERY_THROW);
Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(),
css::uno::UNO_SET_THROW);
while (xEnumeration->hasMoreElements())
{
Reference<XAnimationNode> xChildNode(xEnumeration->nextElement(), UNO_QUERY_THROW);
exportNode(xChildNode);
}
}
catch (const RuntimeException&)
{
TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
}
}
void AnimationsExporter::exportAnimate(const Reference<XAnimate>& xAnimate)
{
try
{
const sal_Int16 nNodeType = xAnimate->getType();
OStringBuffer sTmp;
sal_Int16 nTemp;
bool bTemp;
Any aTemp(xAnimate->getTarget());
if (aTemp.hasValue())
{
convertTarget(sTmp, aTemp);
mrWriter.put("targetElement", sTmp.makeStringAndClear());
}
nTemp = xAnimate->getSubItem();
if (nTemp)
{
convertEnum(sTmp, nTemp, constSubItemToString);
mrWriter.put("subItem", sTmp.makeStringAndClear());
}
XMLTokenEnum eAttributeName = XML_TOKEN_INVALID;
if (nNodeType == AnimationNodeType::TRANSITIONFILTER)
{
eAttributeName = XML_TRANSITIONFILTER;
}
else if (nNodeType == AnimationNodeType::ANIMATETRANSFORM)
{
eAttributeName = XML_ANIMATETRANSFORM;
}
else if (nNodeType == AnimationNodeType::ANIMATEMOTION)
{
eAttributeName = XML_ANIMATEMOTION;
}
else if (nNodeType == AnimationNodeType::ANIMATEPHYSICS)
{
eAttributeName = XML_ANIMATEPHYSICS;
}
else
{
OString sTemp(xAnimate->getAttributeName().toUtf8());
if (!sTemp.isEmpty())
{
auto iterator = constAttributeNameToXMLEnum.find(sTemp);
if (iterator != constAttributeNameToXMLEnum.end())
{
eAttributeName = iterator->second;
mrWriter.put("attributeName", sTemp);
}
else
{
mrWriter.put("attributeName", "invalid");
}
}
}
Sequence<Any> aValues(xAnimate->getValues());
if (aValues.hasElements())
{
aTemp <<= aValues;
convertValue(eAttributeName, sTmp, aTemp);
mrWriter.put("values", sTmp.makeStringAndClear());
}
else
{
aTemp = xAnimate->getFrom();
if (aTemp.hasValue())
{
convertValue(eAttributeName, sTmp, aTemp);
mrWriter.put("from", sTmp.makeStringAndClear());
}
aTemp = xAnimate->getBy();
if (aTemp.hasValue())
{
convertValue(eAttributeName, sTmp, aTemp);
mrWriter.put("by", sTmp.makeStringAndClear());
}
aTemp = xAnimate->getTo();
if (aTemp.hasValue())
{
convertValue(eAttributeName, sTmp, aTemp);
mrWriter.put("to", sTmp.makeStringAndClear());
}
}
if (nNodeType != AnimationNodeType::SET)
{
const Sequence<double> aKeyTimes(xAnimate->getKeyTimes());
if (aKeyTimes.hasElements())
{
for (const auto& rKeyTime : aKeyTimes)
{
if (!sTmp.isEmpty())
sTmp.append(';');
sTmp.append(rKeyTime);
}
mrWriter.put("keyTimes", sTmp.makeStringAndClear());
}
OUString sTemp(xAnimate->getFormula());
if (!sTemp.isEmpty())
{
mrWriter.put("formula", sTemp);
}
if ((nNodeType != AnimationNodeType::TRANSITIONFILTER)
&& (nNodeType != AnimationNodeType::AUDIO))
{
// calcMode = "discrete | linear | paced | spline"
nTemp = xAnimate->getCalcMode();
if (((nNodeType == AnimationNodeType::ANIMATEMOTION)
&& (nTemp != AnimationCalcMode::PACED))
|| ((nNodeType != AnimationNodeType::ANIMATEMOTION)
&& (nTemp != AnimationCalcMode::LINEAR)))
{
convertEnum(sTmp, nTemp, constCalcModeToString);
mrWriter.put("calcMode", sTmp.makeStringAndClear());
}
bTemp = xAnimate->getAccumulate();
if (bTemp)
{
mrWriter.put("accumulate", "sum");
}
nTemp = xAnimate->getAdditive();
if (nTemp != AnimationAdditiveMode::REPLACE)
{
convertEnum(sTmp, nTemp, constAdditiveModeToString);
mrWriter.put("additive", sTmp.makeStringAndClear());
}
}
const Sequence<TimeFilterPair> aTimeFilter(xAnimate->getTimeFilter());
if (aTimeFilter.hasElements())
{
for (const auto& rPair : aTimeFilter)
{
if (!sTmp.isEmpty())
sTmp.append(';');
sTmp.append(OString::number(rPair.Time) + ","
+ OString::number(rPair.Progress));
}
mrWriter.put("keySplines", sTmp.makeStringAndClear());
}
}
switch (nNodeType)
{
case AnimationNodeType::ANIMATEMOTION:
{
Reference<XAnimateMotion> xAnimateMotion(xAnimate, UNO_QUERY_THROW);
aTemp = xAnimateMotion->getPath();
if (aTemp.hasValue())
{
convertPath(sTmp, aTemp);
mrWriter.put("path", sTmp.makeStringAndClear());
}
}
break;
case AnimationNodeType::ANIMATEPHYSICS:
{
SAL_WARN(
"sd",
"unomodel: AnimationsExporter::exportAnimate(): AnimatePhysics not supported");
}
break;
case AnimationNodeType::ANIMATECOLOR:
{
Reference<XAnimateColor> xAnimateColor(xAnimate, UNO_QUERY_THROW);
nTemp = xAnimateColor->getColorInterpolation();
mrWriter.put("colorInterpolation",
(nTemp == AnimationColorSpace::RGB) ? "rgb" : "hsl");
bTemp = xAnimateColor->getDirection();
mrWriter.put("colorInterpolationDirection",
bTemp ? "clockwise" : "counterClockwise");
}
break;
case AnimationNodeType::ANIMATETRANSFORM:
{
mrWriter.put("attributeName", "transform");
Reference<XAnimateTransform> xTransform(xAnimate, UNO_QUERY_THROW);
nTemp = xTransform->getTransformType();
convertEnum(sTmp, nTemp, constTransformTypeToString);
mrWriter.put("transformType", sTmp.makeStringAndClear());
}
break;
case AnimationNodeType::TRANSITIONFILTER:
{
Reference<XTransitionFilter> xTransitionFilter(xAnimate, UNO_QUERY);
sal_Int16 nTransition = xTransitionFilter->getTransition();
convertEnum(sTmp, nTransition, constTransitionTypeToString);
mrWriter.put("transitionType", sTmp.makeStringAndClear());
sal_Int16 nSubtype = xTransitionFilter->getSubtype();
if (nSubtype != TransitionSubType::DEFAULT)
{
convertEnum(sTmp, nSubtype, constTransitionSubTypeToString);
mrWriter.put("transitionSubType", sTmp.makeStringAndClear());
}
bTemp = xTransitionFilter->getMode();
if (!bTemp)
mrWriter.put("transitionMode", "out");
bTemp = xTransitionFilter->getDirection();
if (!bTemp)
mrWriter.put("transitionDirection", "reverse");
if ((nTransition == TransitionType::FADE)
&& ((nSubtype == TransitionSubType::FADETOCOLOR)
|| (nSubtype == TransitionSubType::FADEFROMCOLOR)))
{
sal_Int32 nColor = xTransitionFilter->getFadeColor();
convertColor(sTmp, nColor);
mrWriter.put("transitionFadeColor", sTmp.makeStringAndClear());
}
}
break;
default:
{
SAL_WARN("sd",
"unomodel: AnimationsExporter::exportAnimate(): not supported node type: "
<< nNodeType);
}
}
}
catch (const Exception&)
{
TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
}
}
} // end anonymous namespace
SdUnoForbiddenCharsTable::SdUnoForbiddenCharsTable( SdrModel* pModel )
: SvxUnoForbiddenCharsTable( pModel->GetForbiddenCharsTable() ), mpModel( pModel )
{
StartListening( *pModel );
}
void SdUnoForbiddenCharsTable::onChange()
{
if( mpModel )
{
mpModel->ReformatAllTextObjects();
}
}
SdUnoForbiddenCharsTable::~SdUnoForbiddenCharsTable()
{
SolarMutexGuard g;
if( mpModel )
EndListening( *mpModel );
}
void SdUnoForbiddenCharsTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept
{
if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
return;
const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint );
if( SdrHintKind::ModelCleared == pSdrHint->GetKind() )
{
mpModel = nullptr;
}
}
const sal_uInt16 WID_MODEL_LANGUAGE = 1;
const sal_uInt16 WID_MODEL_TABSTOP = 2;
const sal_uInt16 WID_MODEL_VISAREA = 3;
const sal_uInt16 WID_MODEL_MAPUNIT = 4;
const sal_uInt16 WID_MODEL_FORBCHARS = 5;
const sal_uInt16 WID_MODEL_CONTFOCUS = 6;
const sal_uInt16 WID_MODEL_DSGNMODE = 7;
const sal_uInt16 WID_MODEL_BASICLIBS = 8;
const sal_uInt16 WID_MODEL_RUNTIMEUID = 9;
const sal_uInt16 WID_MODEL_BUILDID = 10;
const sal_uInt16 WID_MODEL_HASVALIDSIGNATURES = 11;
const sal_uInt16 WID_MODEL_DIALOGLIBS = 12;
const sal_uInt16 WID_MODEL_FONTS = 13;
const sal_uInt16 WID_MODEL_INTEROPGRABBAG = 14;
const sal_uInt16 WID_MODEL_THEME = 15;
const sal_uInt16 WID_MODEL_ALLOWLINKUPDATE = 16;
static const SvxItemPropertySet* ImplGetDrawModelPropertySet()
{
// Attention: the first parameter HAS TO BE sorted!!!
const static SfxItemPropertyMapEntry aDrawModelPropertyMap_Impl[] =
{
{ u"BuildId"_ustr, WID_MODEL_BUILDID, ::cppu::UnoType<OUString>::get(), 0, 0},
{ sUNO_Prop_CharLocale, WID_MODEL_LANGUAGE, ::cppu::UnoType<lang::Locale>::get(), 0, 0},
{ sUNO_Prop_TabStop, WID_MODEL_TABSTOP, ::cppu::UnoType<sal_Int32>::get(), 0, 0},
{ sUNO_Prop_VisibleArea, WID_MODEL_VISAREA, ::cppu::UnoType<awt::Rectangle>::get(), 0, 0},
{ sUNO_Prop_MapUnit, WID_MODEL_MAPUNIT, ::cppu::UnoType<sal_Int16>::get(), beans::PropertyAttribute::READONLY, 0},
{ sUNO_Prop_ForbiddenCharacters, WID_MODEL_FORBCHARS, cppu::UnoType<i18n::XForbiddenCharacters>::get(), beans::PropertyAttribute::READONLY, 0},
{ sUNO_Prop_AutomContFocus, WID_MODEL_CONTFOCUS, cppu::UnoType<bool>::get(), 0, 0},
{ sUNO_Prop_ApplyFrmDsgnMode, WID_MODEL_DSGNMODE, cppu::UnoType<bool>::get(), 0, 0},
{ u"BasicLibraries"_ustr, WID_MODEL_BASICLIBS, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
{ u"DialogLibraries"_ustr, WID_MODEL_DIALOGLIBS, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
{ sUNO_Prop_RuntimeUID, WID_MODEL_RUNTIMEUID, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
{ sUNO_Prop_HasValidSignatures, WID_MODEL_HASVALIDSIGNATURES, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY, 0},
{ sUNO_Prop_AllowLinkUpdate, WID_MODEL_ALLOWLINKUPDATE, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY, 0},
{ u"Fonts"_ustr, WID_MODEL_FONTS, cppu::UnoType<uno::Sequence<uno::Any>>::get(), beans::PropertyAttribute::READONLY, 0},
{ sUNO_Prop_InteropGrabBag, WID_MODEL_INTEROPGRABBAG, cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get(), 0, 0},
{ sUNO_Prop_Theme, WID_MODEL_THEME, cppu::UnoType<util::XTheme>::get(), 0, 0},
};
static SvxItemPropertySet aDrawModelPropertySet_Impl( aDrawModelPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
return &aDrawModelPropertySet_Impl;
}
// this ctor is used from the DocShell
SdXImpressDocument::SdXImpressDocument(::sd::DrawDocShell* pShell, bool bClipBoard)
: SfxBaseModel( pShell ),
mpDocShell( pShell ),
mpDoc( pShell ? pShell->GetDoc() : nullptr ),
mbDisposed(false),
mbImpressDoc( pShell && pShell->GetDoc() && pShell->GetDoc()->GetDocumentType() == DocumentType::Impress ),
mbClipBoard( bClipBoard ),
mpPropSet( ImplGetDrawModelPropertySet() ),
mbPaintTextEdit( true )
{
if( mpDoc )
{
StartListening( *mpDoc );
}
else
{
OSL_FAIL("DocShell is invalid");
}
}
SdXImpressDocument::SdXImpressDocument(SdDrawDocument* pDoc, bool bClipBoard)
: SfxBaseModel( nullptr ),
mpDocShell( nullptr ),
mpDoc( pDoc ),
mbDisposed(false),
mbImpressDoc( pDoc && pDoc->GetDocumentType() == DocumentType::Impress ),
mbClipBoard( bClipBoard ),
mpPropSet( ImplGetDrawModelPropertySet() ),
mbPaintTextEdit( true )
{
if( mpDoc )
{
StartListening( *mpDoc );
}
else
{
OSL_FAIL("SdDrawDocument is invalid");
}
}
/***********************************************************************
* *
***********************************************************************/
SdXImpressDocument::~SdXImpressDocument() noexcept
{
}
// XInterface
uno::Any SAL_CALL SdXImpressDocument::queryInterface( const uno::Type & rType )
{
uno::Any aAny;
if (rType == cppu::UnoType<lang::XServiceInfo>::get())
aAny <<= uno::Reference<lang::XServiceInfo>(this);
else if (rType == cppu::UnoType<beans::XPropertySet>::get())
aAny <<= uno::Reference<beans::XPropertySet>(this);
else if (rType == cppu::UnoType<lang::XMultiServiceFactory>::get())
aAny <<= uno::Reference<lang::XMultiServiceFactory>(this);
else if (rType == cppu::UnoType<drawing::XDrawPageDuplicator>::get())
aAny <<= uno::Reference<drawing::XDrawPageDuplicator>(this);
else if (rType == cppu::UnoType<drawing::XLayerSupplier>::get())
aAny <<= uno::Reference<drawing::XLayerSupplier>(this);
else if (rType == cppu::UnoType<drawing::XMasterPagesSupplier>::get())
aAny <<= uno::Reference<drawing::XMasterPagesSupplier>(this);
else if (rType == cppu::UnoType<drawing::XDrawPagesSupplier>::get())
aAny <<= uno::Reference<drawing::XDrawPagesSupplier>(this);
else if (rType == cppu::UnoType<presentation::XHandoutMasterSupplier>::get())
aAny <<= uno::Reference<presentation::XHandoutMasterSupplier>(this);
else if (rType == cppu::UnoType<document::XLinkTargetSupplier>::get())
aAny <<= uno::Reference<document::XLinkTargetSupplier>(this);
else if (rType == cppu::UnoType<style::XStyleFamiliesSupplier>::get())
aAny <<= uno::Reference<style::XStyleFamiliesSupplier>(this);
else if (rType == cppu::UnoType<css::ucb::XAnyCompareFactory>::get())
aAny <<= uno::Reference<css::ucb::XAnyCompareFactory>(this);
else if (rType == cppu::UnoType<view::XRenderable>::get())
aAny <<= uno::Reference<view::XRenderable>(this);
else if (mbImpressDoc && rType == cppu::UnoType<presentation::XPresentationSupplier>::get())
aAny <<= uno::Reference< presentation::XPresentationSupplier >(this);
else if (mbImpressDoc && rType == cppu::UnoType<presentation::XCustomPresentationSupplier>::get())
aAny <<= uno::Reference< presentation::XCustomPresentationSupplier >(this);
else
return SfxBaseModel::queryInterface(rType);
return aAny;
}
void SAL_CALL SdXImpressDocument::acquire() noexcept
{
SfxBaseModel::acquire();
}
void SAL_CALL SdXImpressDocument::release() noexcept
{
if (osl_atomic_decrement( &m_refCount ) != 0)
return;
// restore reference count:
osl_atomic_increment( &m_refCount );
if(!mbDisposed)
{
try
{
dispose();
}
catch (const uno::RuntimeException&)
{
// don't break throw ()
TOOLS_WARN_EXCEPTION( "sd", "" );
}
}
SfxBaseModel::release();
}
// XUnoTunnel
const css::uno::Sequence< sal_Int8 > & SdXImpressDocument::getUnoTunnelId() noexcept
{
static const comphelper::UnoIdInit theSdXImpressDocumentUnoTunnelId;
return theSdXImpressDocumentUnoTunnelId.getSeq();
}
sal_Int64 SAL_CALL SdXImpressDocument::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
{
if (comphelper::isUnoTunnelId<SdrModel>(rIdentifier))
return comphelper::getSomething_cast(mpDoc);
return comphelper::getSomethingImpl(rIdentifier, this,
comphelper::FallbackToGetSomethingOf<SfxBaseModel>{});
}
// XTypeProvider
uno::Sequence< uno::Type > SAL_CALL SdXImpressDocument::getTypes( )
{
::SolarMutexGuard aGuard;
if( !maTypeSequence.hasElements() )
{
uno::Sequence< uno::Type > aTypes( SfxBaseModel::getTypes() );
aTypes = comphelper::concatSequences(aTypes,
uno::Sequence {
cppu::UnoType<beans::XPropertySet>::get(),
cppu::UnoType<lang::XServiceInfo>::get(),
cppu::UnoType<lang::XMultiServiceFactory>::get(),
cppu::UnoType<drawing::XDrawPageDuplicator>::get(),
cppu::UnoType<drawing::XLayerSupplier>::get(),
cppu::UnoType<drawing::XMasterPagesSupplier>::get(),
cppu::UnoType<drawing::XDrawPagesSupplier>::get(),
cppu::UnoType<document::XLinkTargetSupplier>::get(),
cppu::UnoType<style::XStyleFamiliesSupplier>::get(),
cppu::UnoType<css::ucb::XAnyCompareFactory>::get(),
cppu::UnoType<view::XRenderable>::get() });
if( mbImpressDoc )
{
aTypes = comphelper::concatSequences(aTypes,
uno::Sequence {
cppu::UnoType<presentation::XPresentationSupplier>::get(),
cppu::UnoType<presentation::XCustomPresentationSupplier>::get(),
cppu::UnoType<presentation::XHandoutMasterSupplier>::get() });
}
maTypeSequence = std::move(aTypes);
}
return maTypeSequence;
}
uno::Sequence< sal_Int8 > SAL_CALL SdXImpressDocument::getImplementationId( )
{
return css::uno::Sequence<sal_Int8>();
}
/***********************************************************************
* *
***********************************************************************/
void SdXImpressDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
if( mpDoc )
{
if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
{
const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint );
if( hasEventListeners() )
{
document::EventObject aEvent;
if( SvxUnoDrawMSFactory::createEvent( mpDoc, pSdrHint, aEvent ) )
notifyEvent( aEvent );
}
if( pSdrHint->GetKind() == SdrHintKind::ModelCleared )
{
if( mpDoc )
EndListening( *mpDoc );
mpDoc = nullptr;
mpDocShell = nullptr;
}
}
else
{
// did our SdDrawDocument just died?
if(rHint.GetId() == SfxHintId::Dying)
{
// yes, so we ask for a new one
if( mpDocShell )
{
SdDrawDocument *pNewDoc = mpDocShell->GetDoc();
// is there a new one?
if( pNewDoc != mpDoc )
{
mpDoc = pNewDoc;
if(mpDoc)
StartListening( *mpDoc );
}
}
}
}
}
SfxBaseModel::Notify( rBC, rHint );
}
/******************************************************************************
* *
******************************************************************************/
SdPage* SdXImpressDocument::InsertSdPage( sal_uInt16 nPage, bool bDuplicate )
{
sal_uInt16 nPageCount = mpDoc->GetSdPageCount( PageKind::Standard );
SdrLayerAdmin& rLayerAdmin = mpDoc->GetLayerAdmin();
SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
rtl::Reference<SdPage> pStandardPage;
if( 0 == nPageCount )
{
// this is only used for clipboard where we only have one page
pStandardPage = mpDoc->AllocSdPage(false);
Size aDefSize(21000, 29700); // A4 portrait orientation
pStandardPage->SetSize( aDefSize );
mpDoc->InsertPage(pStandardPage.get(), 0);
}
else
{
// here we determine the page after which we should insert
SdPage* pPreviousStandardPage = mpDoc->GetSdPage( std::min( static_cast<sal_uInt16>(nPageCount - 1), nPage ), PageKind::Standard );
SdrLayerIDSet aVisibleLayers = pPreviousStandardPage->TRG_GetMasterPageVisibleLayers();
bool bIsPageBack = aVisibleLayers.IsSet( aBckgrnd );
bool bIsPageObj = aVisibleLayers.IsSet( aBckgrndObj );
// AutoLayouts must be ready
mpDoc->StopWorkStartupDelay();
/* First we create a standard page and then a notes page. It is
guaranteed, that after a standard page the corresponding notes page
follows. */
sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
SdPage* pPreviousNotesPage = static_cast<SdPage*>( mpDoc->GetPage( nStandardPageNum - 1 ) );
sal_uInt16 nNotesPageNum = nStandardPageNum + 1;
/**************************************************************
* standard page
**************************************************************/
if( bDuplicate )
pStandardPage = static_cast<SdPage*>( pPreviousStandardPage->CloneSdrPage(*mpDoc).get() );
else
pStandardPage = mpDoc->AllocSdPage(false);
pStandardPage->SetSize( pPreviousStandardPage->GetSize() );
pStandardPage->SetBorder( pPreviousStandardPage->GetLeftBorder(),
pPreviousStandardPage->GetUpperBorder(),
pPreviousStandardPage->GetRightBorder(),
pPreviousStandardPage->GetLowerBorder() );
pStandardPage->SetOrientation( pPreviousStandardPage->GetOrientation() );
pStandardPage->SetName(OUString());
// insert page after current page
mpDoc->InsertPage(pStandardPage.get(), nStandardPageNum);
if( !bDuplicate )
{
// use MasterPage of the current page
pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage());
pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() );
pStandardPage->SetAutoLayout(AUTOLAYOUT_NONE, true );
}
aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
aVisibleLayers.Set(aBckgrnd, bIsPageBack);
aVisibleLayers.Set(aBckgrndObj, bIsPageObj);
pStandardPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
/**************************************************************
* notes page
**************************************************************/
rtl::Reference<SdPage> pNotesPage;
if( bDuplicate )
pNotesPage = static_cast<SdPage*>( pPreviousNotesPage->CloneSdrPage(*mpDoc).get() );
else
pNotesPage = mpDoc->AllocSdPage(false);
pNotesPage->SetSize( pPreviousNotesPage->GetSize() );
pNotesPage->SetBorder( pPreviousNotesPage->GetLeftBorder(),
pPreviousNotesPage->GetUpperBorder(),
pPreviousNotesPage->GetRightBorder(),
pPreviousNotesPage->GetLowerBorder() );
pNotesPage->SetOrientation( pPreviousNotesPage->GetOrientation() );
pNotesPage->SetName(OUString());
pNotesPage->SetPageKind(PageKind::Notes);
// insert page after current page
mpDoc->InsertPage(pNotesPage.get(), nNotesPageNum);
if( !bDuplicate )
{
// use MasterPage of the current page
pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage());
pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() );
pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true );
}
}
SetModified();
return pStandardPage.get();
}
void SdXImpressDocument::SetModified() noexcept
{
if( mpDoc )
mpDoc->SetChanged();
}
// XModel
void SAL_CALL SdXImpressDocument::lockControllers( )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
mpDoc->setLock(true);
}
void SAL_CALL SdXImpressDocument::unlockControllers( )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
if( mpDoc->isLocked() )
{
mpDoc->setLock(false);
}
}
sal_Bool SAL_CALL SdXImpressDocument::hasControllersLocked( )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
return mpDoc->isLocked();
}
uno::Reference < container::XIndexAccess > SAL_CALL SdXImpressDocument::getViewData()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() );
if( !xRet.is() )
{
const std::vector<std::unique_ptr<sd::FrameView>> &rList = mpDoc->GetFrameViewList();
if( !rList.empty() )
{
xRet = new comphelper::IndexedPropertyValuesContainer();
uno::Reference < container::XIndexContainer > xCont( xRet, uno::UNO_QUERY );
DBG_ASSERT( xCont.is(), "SdXImpressDocument::getViewData() failed for OLE object" );
if( xCont.is() )
{
for( sal_uInt32 i = 0, n = rList.size(); i < n; i++ )
{
::sd::FrameView* pFrameView = rList[ i ].get();
uno::Sequence< beans::PropertyValue > aSeq;
pFrameView->WriteUserDataSequence( aSeq );
xCont->insertByIndex( i, uno::Any( aSeq ) );
}
}
}
}
return xRet;
}
void SAL_CALL SdXImpressDocument::setViewData( const uno::Reference < container::XIndexAccess >& xData )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
SfxBaseModel::setViewData( xData );
if( !(mpDocShell && (mpDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED) && xData.is()) )
return;
const sal_Int32 nCount = xData->getCount();
std::vector<std::unique_ptr<sd::FrameView>> &rViews = mpDoc->GetFrameViewList();
rViews.clear();
uno::Sequence< beans::PropertyValue > aSeq;
for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
{
if( xData->getByIndex( nIndex ) >>= aSeq )
{
std::unique_ptr<::sd::FrameView> pFrameView(new ::sd::FrameView( mpDoc ));
pFrameView->ReadUserDataSequence( aSeq );
rViews.push_back( std::move(pFrameView) );
}
}
}
// XDrawPageDuplicator
uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::duplicate( const uno::Reference< drawing::XDrawPage >& xPage )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
// get pPage from xPage and determine the Id (nPos ) afterwards
SvxDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage );
if( pSvxPage )
{
SdPage* pPage = static_cast<SdPage*>( pSvxPage->GetSdrPage() );
sal_uInt16 nPos = pPage->GetPageNum();
nPos = ( nPos - 1 ) / 2;
pPage = InsertSdPage( nPos, true );
if( pPage )
{
uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
return xDrawPage;
}
}
uno::Reference< drawing::XDrawPage > xDrawPage;
return xDrawPage;
}
// XDrawPagesSupplier
uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getDrawPages()
{
::SolarMutexGuard aGuard;
return getSdDrawPages();
}
rtl::Reference< SdDrawPagesAccess > SdXImpressDocument::getSdDrawPages()
{
if( nullptr == mpDoc )
throw lang::DisposedException();
rtl::Reference< SdDrawPagesAccess > xDrawPages( mxDrawPagesAccess );
if( !xDrawPages.is() )
{
initializeDocument();
xDrawPages = new SdDrawPagesAccess(*this);
mxDrawPagesAccess = xDrawPages.get();
}
return xDrawPages;
}
// XMasterPagesSupplier
uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getMasterPages()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
rtl::Reference< SdMasterPagesAccess > xMasterPages( mxMasterPagesAccess );
if( !xMasterPages.is() )
{
if ( !hasControllersLocked() )
initializeDocument();
xMasterPages = new SdMasterPagesAccess(*this);
mxMasterPagesAccess = xMasterPages.get();
}
return xMasterPages;
}
// XLayerManagerSupplier
uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLayerManager( )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
rtl::Reference< SdLayerManager > xLayerManager( mxLayerManager );
if( !xLayerManager.is() )
{
xLayerManager = new SdLayerManager(*this);
mxLayerManager = xLayerManager.get();
}
return xLayerManager;
}
// XCustomPresentationSupplier
uno::Reference< container::XNameContainer > SAL_CALL SdXImpressDocument::getCustomPresentations()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
rtl::Reference< SdXCustomPresentationAccess > xCustomPres( mxCustomPresentationAccess );
if( !xCustomPres.is() )
{
xCustomPres = new SdXCustomPresentationAccess(*this);
mxCustomPresentationAccess = xCustomPres.get();
}
return xCustomPres;
}
// XPresentationSupplier
uno::Reference< presentation::XPresentation > SAL_CALL SdXImpressDocument::getPresentation()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
return mpDoc->getPresentation();
}
// XHandoutMasterSupplier
uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::getHandoutMasterPage()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
uno::Reference< drawing::XDrawPage > xPage;
initializeDocument();
SdPage* pPage = mpDoc->GetMasterSdPage(0, PageKind::Handout);
if (pPage)
xPage.set(pPage->getUnoPage(), uno::UNO_QUERY);
return xPage;
}
// XMultiServiceFactory ( SvxFmMSFactory )
css::uno::Reference<css::uno::XInterface> SdXImpressDocument::create(
OUString const & aServiceSpecifier, OUString const & referer)
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
if( aServiceSpecifier == "com.sun.star.drawing.DashTable" )
{
if( !mxDashTable.is() )
mxDashTable = SvxUnoDashTable_createInstance( mpDoc );
return mxDashTable;
}
if( aServiceSpecifier == "com.sun.star.drawing.GradientTable" )
{
if( !mxGradientTable.is() )
mxGradientTable = SvxUnoGradientTable_createInstance( mpDoc );
return mxGradientTable;
}
if( aServiceSpecifier == "com.sun.star.drawing.HatchTable" )
{
if( !mxHatchTable.is() )
mxHatchTable = SvxUnoHatchTable_createInstance( mpDoc );
return mxHatchTable;
}
if( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" )
{
if( !mxBitmapTable.is() )
mxBitmapTable = SvxUnoBitmapTable_createInstance( mpDoc );
return mxBitmapTable;
}
if( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" )
{
if( !mxTransGradientTable.is() )
mxTransGradientTable = SvxUnoTransGradientTable_createInstance( mpDoc );
return mxTransGradientTable;
}
if( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" )
{
if( !mxMarkerTable.is() )
mxMarkerTable = SvxUnoMarkerTable_createInstance( mpDoc );
return mxMarkerTable;
}
if( aServiceSpecifier == "com.sun.star.text.NumberingRules" )
{
return uno::Reference< uno::XInterface >( SvxCreateNumRule( mpDoc ), uno::UNO_QUERY );
}
if( aServiceSpecifier == "com.sun.star.drawing.Background" )
{
return uno::Reference< uno::XInterface >(
static_cast<uno::XWeak*>(new SdUnoPageBackground( mpDoc )));
}
if( aServiceSpecifier == "com.sun.star.drawing.Defaults" )
{
if( !mxDrawingPool.is() )
mxDrawingPool = SdUnoCreatePool( mpDoc );
return mxDrawingPool;
}
if ( aServiceSpecifier == sUNO_Service_ImageMapRectangleObject )
{
return SvUnoImageMapRectangleObject_createInstance( ImplGetSupportedMacroItems() );
}
if ( aServiceSpecifier == sUNO_Service_ImageMapCircleObject )
{
return SvUnoImageMapCircleObject_createInstance( ImplGetSupportedMacroItems() );
}
if ( aServiceSpecifier == sUNO_Service_ImageMapPolygonObject )
{
return SvUnoImageMapPolygonObject_createInstance( ImplGetSupportedMacroItems() );
}
if( aServiceSpecifier == "com.sun.star.document.Settings" ||
( !mbImpressDoc && ( aServiceSpecifier == "com.sun.star.drawing.DocumentSettings" ) ) ||
( mbImpressDoc && ( aServiceSpecifier == "com.sun.star.presentation.DocumentSettings" ) ) )
{
return sd::DocumentSettings_createInstance( this );
}
if( aServiceSpecifier == "com.sun.star.text.TextField.DateTime" ||
aServiceSpecifier == "com.sun.star.text.textfield.DateTime" )
{
return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::DATE ));
}
if( aServiceSpecifier == "com.sun.star.presentation.TextField.Header" ||
aServiceSpecifier == "com.sun.star.presentation.textfield.Header" )
{
return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_HEADER ));
}
if( aServiceSpecifier == "com.sun.star.presentation.TextField.Footer" ||
aServiceSpecifier == "com.sun.star.presentation.textfield.Footer" )
{
return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_FOOTER ));
}
if( aServiceSpecifier == "com.sun.star.presentation.TextField.DateTime" ||
aServiceSpecifier == "com.sun.star.presentation.textfield.DateTime" )
{
return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_DATE_TIME ));
}
if( aServiceSpecifier == "com.sun.star.text.TextField.PageName" ||
aServiceSpecifier == "com.sun.star.text.textfield.PageName" )
{
return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PAGE_NAME ));
}
if (aServiceSpecifier == "com.sun.star.text.TextField.DocInfo.Custom" ||
aServiceSpecifier == "com.sun.star.text.textfield.DocInfo.Custom")
{
return static_cast<cppu::OWeakObject *>(new SvxUnoTextField(text::textfield::Type::DOCINFO_CUSTOM));
}
if( aServiceSpecifier == "com.sun.star.xml.NamespaceMap" )
{
static sal_uInt16 aWhichIds[] = { SDRATTR_XMLATTRIBUTES, EE_CHAR_XMLATTRIBS, EE_PARA_XMLATTRIBS, 0 };
return svx::NamespaceMap_createInstance( aWhichIds, &mpDoc->GetItemPool() );
}
// Support creation of GraphicStorageHandler and EmbeddedObjectResolver
if (aServiceSpecifier == "com.sun.star.document.ExportGraphicStorageHandler")
{
return static_cast<cppu::OWeakObject *>(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Write ));
}
if (aServiceSpecifier == "com.sun.star.document.ImportGraphicStorageHandler")
{
return static_cast<cppu::OWeakObject *>(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Read ));
}
if( aServiceSpecifier == "com.sun.star.document.ExportEmbeddedObjectResolver" )
{
comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist();
if( nullptr == pPersist )
throw lang::DisposedException();
return static_cast<cppu::OWeakObject *>(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Write ));
}
if( aServiceSpecifier == "com.sun.star.document.ImportEmbeddedObjectResolver" )
{
comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist();
if( nullptr == pPersist )
throw lang::DisposedException();
return static_cast<cppu::OWeakObject *>(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Read ));
}
uno::Reference< uno::XInterface > xRet;
if( aServiceSpecifier.startsWith( "com.sun.star.presentation.") )
{
const std::u16string_view aType( aServiceSpecifier.subView(26) );
rtl::Reference<SvxShape> pShape;
SdrObjKind nType = SdrObjKind::Text;
// create a shape wrapper
if( o3tl::starts_with(aType, u"TitleTextShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"OutlinerShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"SubtitleShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"GraphicObjectShape" ) )
{
nType = SdrObjKind::Graphic;
}
else if( o3tl::starts_with(aType, u"PageShape" ) )
{
nType = SdrObjKind::Page;
}
else if( o3tl::starts_with(aType, u"OLE2Shape" ) )
{
nType = SdrObjKind::OLE2;
}
else if( o3tl::starts_with(aType, u"ChartShape" ) )
{
nType = SdrObjKind::OLE2;
}
else if( o3tl::starts_with(aType, u"CalcShape" ) )
{
nType = SdrObjKind::OLE2;
}
else if( o3tl::starts_with(aType, u"TableShape" ) )
{
nType = SdrObjKind::Table;
}
else if( o3tl::starts_with(aType, u"OrgChartShape" ) )
{
nType = SdrObjKind::OLE2;
}
else if( o3tl::starts_with(aType, u"NotesShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"HandoutShape" ) )
{
nType = SdrObjKind::Page;
}
else if( o3tl::starts_with(aType, u"FooterShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"HeaderShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"SlideNumberShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"DateTimeShape" ) )
{
nType = SdrObjKind::Text;
}
else if( o3tl::starts_with(aType, u"MediaShape" ) )
{
nType = SdrObjKind::Media;
}
else
{
throw lang::ServiceNotRegisteredException();
}
// create the API wrapper
pShape = CreateSvxShapeByTypeAndInventor( nType, SdrInventor::Default, referer );
// set shape type
if( pShape && !mbClipBoard )
pShape->SetShapeType(aServiceSpecifier);
xRet = static_cast<uno::XWeak*>(pShape.get());
}
else if ( aServiceSpecifier == "com.sun.star.drawing.TableShape" )
{
rtl::Reference<SvxShape> pShape = CreateSvxShapeByTypeAndInventor( SdrObjKind::Table, SdrInventor::Default, referer );
if( pShape && !mbClipBoard )
pShape->SetShapeType(aServiceSpecifier);
xRet = static_cast<uno::XWeak*>(pShape.get());
}
else
{
xRet = SvxFmMSFactory::createInstance( aServiceSpecifier );
}
uno::Reference< drawing::XShape > xShape( xRet, uno::UNO_QUERY );
SvxShape* pShape = xShape.is() ? comphelper::getFromUnoTunnel<SvxShape>(xShape) : nullptr;
if (pShape)
{
xRet.clear();
new SdXShape( pShape, this );
xRet = xShape;
xShape.clear();
}
return xRet;
}
uno::Reference< uno::XInterface > SAL_CALL SdXImpressDocument::createInstance( const OUString& aServiceSpecifier )
{
return create(aServiceSpecifier, u""_ustr);
}
css::uno::Reference<css::uno::XInterface>
SdXImpressDocument::createInstanceWithArguments(
OUString const & ServiceSpecifier,
css::uno::Sequence<css::uno::Any> const & Arguments)
{
OUString arg;
if ((ServiceSpecifier == "com.sun.star.drawing.GraphicObjectShape"
|| ServiceSpecifier == "com.sun.star.drawing.AppletShape"
|| ServiceSpecifier == "com.sun.star.drawing.FrameShape"
|| ServiceSpecifier == "com.sun.star.drawing.OLE2Shape"
|| ServiceSpecifier == "com.sun.star.drawing.MediaShape"
|| ServiceSpecifier == "com.sun.star.drawing.PluginShape"
|| ServiceSpecifier == "com.sun.star.presentation.MediaShape")
&& Arguments.getLength() == 1 && (Arguments[0] >>= arg))
{
return create(ServiceSpecifier, arg);
}
return SvxFmMSFactory::createInstanceWithArguments(
ServiceSpecifier, Arguments);
}
uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getAvailableServiceNames()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
const uno::Sequence< OUString > aSNS_ORG( SvxFmMSFactory::getAvailableServiceNames() );
uno::Sequence< OUString > aSNS_Common{ u"com.sun.star.drawing.DashTable"_ustr,
u"com.sun.star.drawing.GradientTable"_ustr,
u"com.sun.star.drawing.HatchTable"_ustr,
u"com.sun.star.drawing.BitmapTable"_ustr,
u"com.sun.star.drawing.TransparencyGradientTable"_ustr,
u"com.sun.star.drawing.MarkerTable"_ustr,
u"com.sun.star.text.NumberingRules"_ustr,
u"com.sun.star.drawing.Background"_ustr,
u"com.sun.star.document.Settings"_ustr,
sUNO_Service_ImageMapRectangleObject,
sUNO_Service_ImageMapCircleObject,
sUNO_Service_ImageMapPolygonObject,
u"com.sun.star.xml.NamespaceMap"_ustr,
// Support creation of GraphicStorageHandler and EmbeddedObjectResolver
u"com.sun.star.document.ExportGraphicStorageHandler"_ustr,
u"com.sun.star.document.ImportGraphicStorageHandler"_ustr,
u"com.sun.star.document.ExportEmbeddedObjectResolver"_ustr,
u"com.sun.star.document.ImportEmbeddedObjectResolver"_ustr,
u"com.sun.star.drawing.TableShape"_ustr };
uno::Sequence< OUString > aSNS_Specific;
if(mbImpressDoc)
aSNS_Specific = { u"com.sun.star.presentation.TitleTextShape"_ustr,
u"com.sun.star.presentation.OutlinerShape"_ustr,
u"com.sun.star.presentation.SubtitleShape"_ustr,
u"com.sun.star.presentation.GraphicObjectShape"_ustr,
u"com.sun.star.presentation.ChartShape"_ustr,
u"com.sun.star.presentation.PageShape"_ustr,
u"com.sun.star.presentation.OLE2Shape"_ustr,
u"com.sun.star.presentation.TableShape"_ustr,
u"com.sun.star.presentation.OrgChartShape"_ustr,
u"com.sun.star.presentation.NotesShape"_ustr,
u"com.sun.star.presentation.HandoutShape"_ustr,
u"com.sun.star.presentation.DocumentSettings"_ustr,
u"com.sun.star.presentation.FooterShape"_ustr,
u"com.sun.star.presentation.HeaderShape"_ustr,
u"com.sun.star.presentation.SlideNumberShape"_ustr,
u"com.sun.star.presentation.DateTimeShape"_ustr,
u"com.sun.star.presentation.CalcShape"_ustr,
u"com.sun.star.presentation.MediaShape"_ustr };
else
aSNS_Specific = { u"com.sun.star.drawing.DocumentSettings"_ustr };
return comphelper::concatSequences( aSNS_ORG, aSNS_Common, aSNS_Specific );
}
// lang::XServiceInfo
OUString SAL_CALL SdXImpressDocument::getImplementationName()
{
return u"SdXImpressDocument"_ustr;
/* // Matching the .component information:
return mbImpressDoc
? OUString("com.sun.star.comp.Draw.PresentationDocument")
: OUString("com.sun.star.comp.Draw.DrawingDocument");
*/
}
sal_Bool SAL_CALL SdXImpressDocument::supportsService( const OUString& ServiceName )
{
return cppu::supportsService(this, ServiceName);
}
uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getSupportedServiceNames()
{
::SolarMutexGuard aGuard;
return { u"com.sun.star.document.OfficeDocument"_ustr,
u"com.sun.star.drawing.GenericDrawingDocument"_ustr,
u"com.sun.star.drawing.DrawingDocumentFactory"_ustr,
mbImpressDoc?u"com.sun.star.presentation.PresentationDocument"_ustr:u"com.sun.star.drawing.DrawingDocument"_ustr };
}
// XPropertySet
uno::Reference< beans::XPropertySetInfo > SAL_CALL SdXImpressDocument::getPropertySetInfo( )
{
::SolarMutexGuard aGuard;
return mpPropSet->getPropertySetInfo();
}
void SAL_CALL SdXImpressDocument::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName);
switch( pEntry ? pEntry->nWID : -1 )
{
case WID_MODEL_LANGUAGE:
{
lang::Locale aLocale;
if(!(aValue >>= aLocale))
throw lang::IllegalArgumentException();
mpDoc->SetLanguage( LanguageTag::convertToLanguageType(aLocale), EE_CHAR_LANGUAGE );
break;
}
case WID_MODEL_TABSTOP:
{
sal_Int32 nValue = 0;
if(!(aValue >>= nValue) || nValue < 0 )
throw lang::IllegalArgumentException();
mpDoc->SetDefaultTabulator(static_cast<sal_uInt16>(nValue));
break;
}
case WID_MODEL_VISAREA:
{
SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh();
if( !pEmbeddedObj )
break;
awt::Rectangle aVisArea;
if( !(aValue >>= aVisArea) || (aVisArea.Width < 0) || (aVisArea.Height < 0) )
throw lang::IllegalArgumentException();
sal_Int32 nRight, nTop;
if (o3tl::checked_add(aVisArea.X, aVisArea.Width, nRight) || o3tl::checked_add(aVisArea.Y, aVisArea.Height, nTop))
throw lang::IllegalArgumentException();
pEmbeddedObj->SetVisArea(::tools::Rectangle(aVisArea.X, aVisArea.Y, nRight, nTop));
}
break;
case WID_MODEL_CONTFOCUS:
{
bool bFocus = false;
if( !(aValue >>= bFocus ) )
throw lang::IllegalArgumentException();
mpDoc->SetAutoControlFocus( bFocus );
}
break;
case WID_MODEL_DSGNMODE:
{
bool bMode = false;
if( !(aValue >>= bMode ) )
throw lang::IllegalArgumentException();
mpDoc->SetOpenInDesignMode( bMode );
}
break;
case WID_MODEL_BUILDID:
aValue >>= maBuildId;
return;
case WID_MODEL_MAPUNIT:
case WID_MODEL_BASICLIBS:
case WID_MODEL_RUNTIMEUID: // is read-only
case WID_MODEL_DIALOGLIBS:
case WID_MODEL_FONTS:
throw beans::PropertyVetoException();
case WID_MODEL_INTEROPGRABBAG:
setGrabBagItem(aValue);
break;
case WID_MODEL_THEME:
{
SdrModel& rModel = getSdrModelFromUnoModel();
std::shared_ptr<model::Theme> pTheme = model::Theme::FromAny(aValue);
rModel.setTheme(pTheme);
}
break;
default:
throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
}
SetModified();
}
uno::Any SAL_CALL SdXImpressDocument::getPropertyValue( const OUString& PropertyName )
{
::SolarMutexGuard aGuard;
uno::Any aAny;
if( nullptr == mpDoc )
throw lang::DisposedException();
const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName);
switch( pEntry ? pEntry->nWID : -1 )
{
case WID_MODEL_LANGUAGE:
{
LanguageType eLang = mpDoc->GetLanguage( EE_CHAR_LANGUAGE );
aAny <<= LanguageTag::convertToLocale( eLang);
break;
}
case WID_MODEL_TABSTOP:
aAny <<= static_cast<sal_Int32>(mpDoc->GetDefaultTabulator());
break;
case WID_MODEL_VISAREA:
{
SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh();
if( !pEmbeddedObj )
break;
const ::tools::Rectangle& aRect = pEmbeddedObj->GetVisArea();
awt::Rectangle aVisArea( aRect.Left(), aRect.Top(), aRect.getOpenWidth(), aRect.getOpenHeight() );
aAny <<= aVisArea;
}
break;
case WID_MODEL_MAPUNIT:
{
SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh();
if( !pEmbeddedObj )
break;
sal_Int16 nMeasureUnit = 0;
SvxMapUnitToMeasureUnit( pEmbeddedObj->GetMapUnit(), nMeasureUnit );
aAny <<= nMeasureUnit;
}
break;
case WID_MODEL_FORBCHARS:
{
aAny <<= getForbiddenCharsTable();
}
break;
case WID_MODEL_CONTFOCUS:
aAny <<= mpDoc->GetAutoControlFocus();
break;
case WID_MODEL_DSGNMODE:
aAny <<= mpDoc->GetOpenInDesignMode();
break;
case WID_MODEL_BASICLIBS:
aAny <<= mpDocShell->GetBasicContainer();
break;
case WID_MODEL_DIALOGLIBS:
aAny <<= mpDocShell->GetDialogContainer();
break;
case WID_MODEL_RUNTIMEUID:
aAny <<= getRuntimeUID();
break;
case WID_MODEL_BUILDID:
return uno::Any( maBuildId );
case WID_MODEL_HASVALIDSIGNATURES:
aAny <<= hasValidSignatures();
break;
case WID_MODEL_ALLOWLINKUPDATE:
{
comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mpDocShell->getEmbeddedObjectContainer();
aAny <<= rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
break;
}
case WID_MODEL_FONTS:
{
uno::Sequence<uno::Any> aSeq;
int nSeqIndex = 0;
sal_uInt16 const aWhichIds[] { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK,
EE_CHAR_FONTINFO_CTL };
const SfxItemPool& rPool = mpDoc->GetPool();
for(sal_uInt16 nWhichId : aWhichIds)
{
ItemSurrogates aSurrogates;
rPool.GetItemSurrogates(aSurrogates, nWhichId);
const sal_uInt32 nItems(aSurrogates.size());
aSeq.realloc( aSeq.getLength() + nItems*5 + 5 );
auto pSeq = aSeq.getArray();
for (const SfxPoolItem* pItem : aSurrogates)
{
const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem);
pSeq[nSeqIndex++] <<= pFont->GetFamilyName();
pSeq[nSeqIndex++] <<= pFont->GetStyleName();
pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetFamily());
pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetPitch());
pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetCharSet());
}
const SvxFontItem& rFont = static_cast<const SvxFontItem&>(rPool.GetUserOrPoolDefaultItem( nWhichId ));
pSeq[nSeqIndex++] <<= rFont.GetFamilyName();
pSeq[nSeqIndex++] <<= rFont.GetStyleName();
pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetFamily());
pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetPitch());
pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetCharSet());
}
aSeq.realloc( nSeqIndex );
aAny <<= aSeq;
break;
}
case WID_MODEL_INTEROPGRABBAG:
getGrabBagItem(aAny);
break;
case WID_MODEL_THEME:
{
SdrModel& rModel = getSdrModelFromUnoModel();
auto const& pTheme = rModel.getTheme();
if (pTheme)
{
pTheme->ToAny(aAny);
}
else
{
beans::PropertyValues aValues;
aAny <<= aValues;
}
break;
}
default:
throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
}
return aAny;
}
void SAL_CALL SdXImpressDocument::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
void SAL_CALL SdXImpressDocument::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
void SAL_CALL SdXImpressDocument::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
void SAL_CALL SdXImpressDocument::removeVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
// XLinkTargetSupplier
uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLinks()
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
rtl::Reference< SdDocLinkTargets > xLinks( mxLinks );
if( !xLinks.is() )
{
xLinks = new SdDocLinkTargets( *this );
mxLinks = xLinks.get();
}
return xLinks;
}
// XStyleFamiliesSupplier
uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getStyleFamilies( )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
uno::Reference< container::XNameAccess > xStyles( static_cast< OWeakObject* >( mpDoc->GetStyleSheetPool() ), css::uno::UNO_QUERY );
return xStyles;
}
// XAnyCompareFactory
uno::Reference< css::ucb::XAnyCompare > SAL_CALL SdXImpressDocument::createAnyCompareByName( const OUString& )
{
return SvxCreateNumRuleCompare();
}
// XRenderable
sal_Int32 SAL_CALL SdXImpressDocument::getRendererCount( const uno::Any& rSelection,
const uno::Sequence< beans::PropertyValue >& )
{
::SolarMutexGuard aGuard;
sal_Int32 nRet = 0;
if( nullptr == mpDoc )
throw lang::DisposedException();
if (mpDocShell)
{
uno::Reference< frame::XModel > xModel;
rSelection >>= xModel;
if( xModel == mpDocShell->GetModel() )
nRet = mpDoc->GetSdPageCount( PageKind::Standard );
else
{
uno::Reference< drawing::XShapes > xShapes;
rSelection >>= xShapes;
if( xShapes.is() && xShapes->getCount() )
nRet = 1;
}
}
return nRet;
}
uno::Sequence< beans::PropertyValue > SAL_CALL SdXImpressDocument::getRenderer( sal_Int32 , const uno::Any& ,
const uno::Sequence< beans::PropertyValue >& rxOptions )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
bool bExportNotesPages = false;
for( const auto& rOption : rxOptions )
{
if ( rOption.Name == "ExportNotesPages" )
rOption.Value >>= bExportNotesPages;
}
uno::Sequence< beans::PropertyValue > aRenderer;
if (mpDocShell)
{
awt::Size aPageSize;
if ( bExportNotesPages )
{
Size aNotesPageSize = mpDoc->GetSdPage( 0, PageKind::Notes )->GetSize();
aPageSize = awt::Size( aNotesPageSize.Width(), aNotesPageSize.Height() );
}
else
{
const ::tools::Rectangle aVisArea( mpDocShell->GetVisArea( embed::Aspects::MSOLE_DOCPRINT ) );
aPageSize = awt::Size( aVisArea.GetWidth(), aVisArea.GetHeight() );
}
aRenderer = { comphelper::makePropertyValue(u"PageSize"_ustr, aPageSize) };
}
return aRenderer;
}
namespace {
class ImplRenderPaintProc : public sdr::contact::ViewObjectContactRedirector
{
const SdrLayerAdmin& rLayerAdmin;
SdrPageView* pSdrPageView;
public:
bool IsVisible ( const SdrObject* pObj ) const;
bool IsPrintable( const SdrObject* pObj ) const;
ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView* pView);
// all default implementations just call the same methods at the original. To do something
// different, override the method and at least do what the method does.
virtual void createRedirectedPrimitive2DSequence(
const sdr::contact::ViewObjectContact& rOriginal,
const sdr::contact::DisplayInfo& rDisplayInfo,
drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) override;
};
}
ImplRenderPaintProc::ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView *const pView)
: rLayerAdmin(rLA)
, pSdrPageView(pView)
{
}
static sal_Int32 ImplPDFGetBookmarkPage( const OUString& rBookmark, SdDrawDocument const & rDoc )
{
sal_Int32 nPage = -1;
OUString aBookmark( rBookmark );
if( rBookmark.startsWith("#") )
aBookmark = rBookmark.copy( 1 );
// is the bookmark a page ?
bool bIsMasterPage;
sal_uInt16 nPgNum = rDoc.GetPageByName( aBookmark, bIsMasterPage );
if ( nPgNum == SDRPAGE_NOTFOUND )
{
// is the bookmark an object ?
SdrObject* pObj = rDoc.GetObj( aBookmark );
if (pObj)
nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
}
if ( nPgNum != SDRPAGE_NOTFOUND )
nPage = ( nPgNum - 1 ) / 2;
return nPage;
}
static void ImplPDFExportComments( const uno::Reference< drawing::XDrawPage >& xPage, vcl::PDFExtOutDevData& rPDFExtOutDevData )
{
try
{
uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xPage, uno::UNO_QUERY_THROW );
uno::Reference< office::XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() );
while( xAnnotationEnumeration->hasMoreElements() )
{
uno::Reference<office::XAnnotation> xAnnotation(xAnnotationEnumeration->nextElement());
geometry::RealPoint2D aRealPoint2D(xAnnotation->getPosition());
geometry::RealSize2D aRealSize2D(xAnnotation->getSize());
Point aPoint(aRealPoint2D.X * 100.0, aRealPoint2D.Y * 100.0);
Size aSize(aRealSize2D.Width * 100.0, aRealSize2D.Height * 100.0);
Point aPopupPoint(aPoint.X(), aPoint.Y());
Size aPopupSize(aSize.Width() * 10.0, aSize.Height() * 10.0);
uno::Reference<text::XText> xText(xAnnotation->getTextRange());
vcl::pdf::PDFNote aNote;
aNote.maTitle = xAnnotation->getAuthor();
aNote.maContents = xText->getString();
aNote.maModificationDate = xAnnotation->getDateTime();
auto* pAnnotation = dynamic_cast<sd::Annotation*>(xAnnotation.get());
if (pAnnotation && pAnnotation->getCreationInfo().meType != sdr::annotation::AnnotationType::None)
{
sdr::annotation::CreationInfo const& rCreation = pAnnotation->getCreationInfo();
aNote.maPolygons = rCreation.maPolygons;
aNote.maAnnotationColor = rCreation.maColor;
aNote.maInteriorColor = rCreation.maFillColor;
aNote.mfWidth = rCreation.mnWidth;
switch (rCreation.meType)
{
case sdr::annotation::AnnotationType::Square:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Square; break;
case sdr::annotation::AnnotationType::Circle:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Circle; break;
case sdr::annotation::AnnotationType::Polygon:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Polygon; break;
case sdr::annotation::AnnotationType::Ink:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Ink; break;
case sdr::annotation::AnnotationType::Highlight:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Highlight; break;
case sdr::annotation::AnnotationType::Line:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Line; break;
case sdr::annotation::AnnotationType::FreeText:
aNote.meType = vcl::pdf::PDFAnnotationSubType::FreeText; break;
default:
aNote.meType = vcl::pdf::PDFAnnotationSubType::Text;
break;
}
}
rPDFExtOutDevData.CreateNote(::tools::Rectangle(aPoint, aSize), aNote,
::tools::Rectangle(aPopupPoint, aPopupSize));
}
}
catch (const uno::Exception&)
{
}
}
static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape >& xShape, SdDrawDocument& rDoc, vcl::PDFExtOutDevData& rPDFExtOutDevData )
{
if ( xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
{
uno::Reference< container::XIndexAccess > xIndexAccess( xShape, uno::UNO_QUERY );
if ( xIndexAccess.is() )
{
sal_Int32 i, nCount = xIndexAccess->getCount();
for ( i = 0; i < nCount; i++ )
{
uno::Reference< drawing::XShape > xSubShape( xIndexAccess->getByIndex( i ), uno::UNO_QUERY );
if ( xSubShape.is() )
ImplPDFExportShapeInteraction( xSubShape, rDoc, rPDFExtOutDevData );
}
}
}
else
{
uno::Reference< beans::XPropertySet > xShapePropSet( xShape, uno::UNO_QUERY );
if( xShapePropSet.is() )
{
Size aPageSize( rDoc.GetSdPage( 0, PageKind::Standard )->GetSize() );
Point aPoint( 0, 0 );
::tools::Rectangle aPageRect( aPoint, aPageSize );
awt::Point aShapePos( xShape->getPosition() );
awt::Size aShapeSize( xShape->getSize() );
::tools::Rectangle aLinkRect( Point( aShapePos.X, aShapePos.Y ), Size( aShapeSize.Width, aShapeSize.Height ) );
// Handle linked videos.
if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape" || xShape->getShapeType() == "com.sun.star.presentation.MediaShape")
{
OUString title;
xShapePropSet->getPropertyValue(u"Title"_ustr) >>= title;
OUString description;
xShapePropSet->getPropertyValue(u"Description"_ustr) >>= description;
OUString const altText(title.isEmpty()
? description
: description.isEmpty()
? title
: OUString::Concat(title) + OUString::Concat("\n") + OUString::Concat(description));
OUString aMediaURL;
xShapePropSet->getPropertyValue(u"MediaURL"_ustr) >>= aMediaURL;
if (!aMediaURL.isEmpty())
{
SdrObject const*const pSdrObj(SdrObject::getSdrObjectFromXShape(xShape));
OUString const mimeType(xShapePropSet->getPropertyValue(u"MediaMimeType"_ustr).get<OUString>());
sal_Int32 nScreenId = rPDFExtOutDevData.CreateScreen(aLinkRect, altText, mimeType, rPDFExtOutDevData.GetCurrentPageNumber(), pSdrObj);
if (aMediaURL.startsWith("vnd.sun.star.Package:"))
{
OUString aTempFileURL;
xShapePropSet->getPropertyValue(u"PrivateTempFileURL"_ustr) >>= aTempFileURL;
rPDFExtOutDevData.SetScreenStream(nScreenId, aTempFileURL);
}
else
rPDFExtOutDevData.SetScreenURL(nScreenId, aMediaURL);
}
}
presentation::ClickAction eCa;
uno::Any aAny( xShapePropSet->getPropertyValue( u"OnClick"_ustr ) );
if ( aAny >>= eCa )
{
OUString const actionName(SdResId(SdTPAction::GetClickActionSdResId(eCa)));
switch ( eCa )
{
case presentation::ClickAction_LASTPAGE :
{
sal_Int32 nCount = rDoc.GetSdPageCount( PageKind::Standard );
sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nCount - 1, vcl::PDFWriter::DestAreaType::FitRectangle );
sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
}
break;
case presentation::ClickAction_FIRSTPAGE :
{
sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, 0, vcl::PDFWriter::DestAreaType::FitRectangle );
sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
}
break;
case presentation::ClickAction_PREVPAGE :
{
sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber();
if ( nDestPage )
nDestPage--;
sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle );
sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
}
break;
case presentation::ClickAction_NEXTPAGE :
{
sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber() + 1;
sal_Int32 nLastPage = rDoc.GetSdPageCount( PageKind::Standard ) - 1;
if ( nDestPage > nLastPage )
nDestPage = nLastPage;
sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle );
sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
}
break;
case presentation::ClickAction_PROGRAM :
case presentation::ClickAction_BOOKMARK :
case presentation::ClickAction_DOCUMENT :
{
OUString aBookmark;
xShapePropSet->getPropertyValue( u"Bookmark"_ustr ) >>= aBookmark;
if( !aBookmark.isEmpty() )
{
switch( eCa )
{
case presentation::ClickAction_DOCUMENT :
case presentation::ClickAction_PROGRAM :
{
sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
rPDFExtOutDevData.SetLinkURL( nLinkId, aBookmark );
}
break;
case presentation::ClickAction_BOOKMARK :
{
sal_Int32 nPage = ImplPDFGetBookmarkPage( aBookmark, rDoc );
if ( nPage != -1 )
{
sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle );
sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
}
}
break;
default:
break;
}
}
}
break;
case presentation::ClickAction_STOPPRESENTATION :
case presentation::ClickAction_SOUND :
case presentation::ClickAction_INVISIBLE :
case presentation::ClickAction_VERB :
case presentation::ClickAction_VANISH :
case presentation::ClickAction_MACRO :
default :
break;
}
}
}
}
}
void ImplRenderPaintProc::createRedirectedPrimitive2DSequence(
const sdr::contact::ViewObjectContact& rOriginal,
const sdr::contact::DisplayInfo& rDisplayInfo,
drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor)
{
SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
if(!pObject)
{
// not an object, maybe a page
sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor);
return;
}
SdrPage* pSdrPage(pObject->getSdrPageFromSdrObject());
if(!pSdrPage)
return;
if(!pSdrPage->checkVisibility(rOriginal, rDisplayInfo, false))
return;
if(!IsVisible(pObject) || !IsPrintable(pObject))
return;
sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor);
}
bool ImplRenderPaintProc::IsVisible( const SdrObject* pObj ) const
{
bool bVisible = true;
SdrLayerID nLayerId = pObj->GetLayer();
if( pSdrPageView )
{
const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId );
if ( pSdrLayer )
{
const OUString& aLayerName = pSdrLayer->GetName();
bVisible = pSdrPageView->IsLayerVisible( aLayerName );
}
}
return bVisible;
}
bool ImplRenderPaintProc::IsPrintable( const SdrObject* pObj ) const
{
bool bPrintable = true;
SdrLayerID nLayerId = pObj->GetLayer();
if( pSdrPageView )
{
const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId );
if ( pSdrLayer )
{
const OUString& aLayerName = pSdrLayer->GetName();
bPrintable = pSdrPageView->IsLayerPrintable( aLayerName );
}
}
return bPrintable;
}
namespace
{
sal_Int16 CalcOutputPageNum(vcl::PDFExtOutDevData const * pPDFExtOutDevData, SdDrawDocument const *pDoc, sal_Int16 nPageNumber)
{
//export all pages, simple one to one case
if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides())
return nPageNumber-1;
//check all preceding pages, and only count non-hidden ones
sal_Int16 nRet = 0;
for (sal_Int16 i = 0; i < nPageNumber-1; ++i)
{
if (!pDoc->GetSdPage(i, PageKind::Standard)->IsExcluded())
++nRet;
}
return nRet;
}
}
void SAL_CALL SdXImpressDocument::render( sal_Int32 nRenderer, const uno::Any& rSelection,
const uno::Sequence< beans::PropertyValue >& rxOptions )
{
::SolarMutexGuard aGuard;
if( nullptr == mpDoc )
throw lang::DisposedException();
if (!mpDocShell)
return;
uno::Reference< awt::XDevice > xRenderDevice;
const sal_Int32 nPageNumber = nRenderer + 1;
PageKind ePageKind = PageKind::Standard;
bool bExportNotesPages = false;
for( const auto& rOption : rxOptions )
{
if ( rOption.Name == "RenderDevice" )
rOption.Value >>= xRenderDevice;
else if ( rOption.Name == "ExportNotesPages" )
{
rOption.Value >>= bExportNotesPages;
if ( bExportNotesPages )
ePageKind = PageKind::Notes;
}
}
if( !(xRenderDevice.is() && nPageNumber && ( nPageNumber <= mpDoc->GetSdPageCount( ePageKind ) )) )
return;
VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>( xRenderDevice.get() );
VclPtr< OutputDevice> pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >();
if( !pOut )
return;
vcl::PDFExtOutDevData* pPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData* >( pOut->GetExtOutDevData() );
if ( mpDoc->GetSdPage(static_cast<sal_Int16>(nPageNumber)-1, PageKind::Standard)->IsExcluded() &&
!(pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides()) )
return;
if (pPDFExtOutDevData)
{
css::lang::Locale const docLocale(Application::GetSettings().GetLanguageTag().getLocale());
pPDFExtOutDevData->SetDocumentLocale(docLocale);
}
::sd::ClientView aView( mpDocShell, pOut );
::tools::Rectangle aVisArea( Point(), mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1, ePageKind )->GetSize() );
vcl::Region aRegion( aVisArea );
::sd::ViewShell* pOldViewSh = mpDocShell->GetViewShell();
::sd::View* pOldSdView = pOldViewSh ? pOldViewSh->GetView() : nullptr;
if ( pOldSdView )
pOldSdView->SdrEndTextEdit();
aView.SetHlplVisible( false );
aView.SetGridVisible( false );
aView.SetBordVisible( false );
aView.SetPageVisible( false );
aView.SetGlueVisible( false );
pOut->SetMapMode(MapMode(MapUnit::Map100thMM));
pOut->IntersectClipRegion( aVisArea );
uno::Reference< frame::XModel > xModel;
rSelection >>= xModel;
if( xModel == mpDocShell->GetModel() )
{
aView.ShowSdrPage( mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1, ePageKind ));
SdrPageView* pPV = aView.GetSdrPageView();
if( pOldSdView )
{
SdrPageView* pOldPV = pOldSdView->GetSdrPageView();
if( pPV && pOldPV )
{
pPV->SetVisibleLayers( pOldPV->GetVisibleLayers() );
pPV->SetPrintableLayers( pOldPV->GetPrintableLayers() );
}
}
ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(),
pPV);
// background color for outliner :o
SdPage* pPage = pPV ? static_cast<SdPage*>(pPV->GetPage()) : nullptr;
if( pPage )
{
SdrOutliner& rOutl = mpDoc->GetDrawOutliner();
bool bScreenDisplay(true);
// #i75566# printing; suppress AutoColor BackgroundColor generation
// for visibility reasons by giving GetPageBackgroundColor()
// the needed hint
// #i75566# PDF export; suppress AutoColor BackgroundColor generation (see printing)
if (pOut && ((OUTDEV_PRINTER == pOut->GetOutDevType())
|| (OUTDEV_PDF == pOut->GetOutDevType())))
bScreenDisplay = false;
// #i75566# Name change GetBackgroundColor -> GetPageBackgroundColor and
// hint value if screen display. Only then the AutoColor mechanisms shall be applied
rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor( pPV, bScreenDisplay ) );
}
// produce link annots for media shapes before painting them
if ( pPDFExtOutDevData && pPage )
{
try
{
uno::Any aAny;
uno::Reference< drawing::XDrawPage > xPage( uno::Reference< drawing::XDrawPage >::query( pPage->getUnoPage() ) );
if ( xPage.is() )
{
if ( pPDFExtOutDevData->GetIsExportNotes() )
ImplPDFExportComments( xPage, *pPDFExtOutDevData );
uno::Reference< beans::XPropertySet > xPagePropSet( xPage, uno::UNO_QUERY );
if( xPagePropSet.is() )
{
// exporting object interactions to pdf
// if necessary, the master page interactions will be exported first
bool bIsBackgroundObjectsVisible = false; // #i39428# IsBackgroundObjectsVisible not available for Draw
if ( mbImpressDoc && xPagePropSet->getPropertySetInfo()->hasPropertyByName( u"IsBackgroundObjectsVisible"_ustr ) )
xPagePropSet->getPropertyValue( u"IsBackgroundObjectsVisible"_ustr ) >>= bIsBackgroundObjectsVisible;
if ( bIsBackgroundObjectsVisible && !pPDFExtOutDevData->GetIsExportNotesPages() )
{
uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( xPage, uno::UNO_QUERY );
if ( xMasterPageTarget.is() )
{
uno::Reference< drawing::XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage();
if ( xMasterPage.is() )
{
sal_Int32 i, nCount = xMasterPage->getCount();
for ( i = 0; i < nCount; i++ )
{
aAny = xMasterPage->getByIndex( i );
uno::Reference< drawing::XShape > xShape;
if ( aAny >>= xShape )
ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData );
}
}
}
}
// exporting slide page object interactions
sal_Int32 i, nCount = xPage->getCount();
for ( i = 0; i < nCount; i++ )
{
aAny = xPage->getByIndex( i );
uno::Reference< drawing::XShape > xShape;
if ( aAny >>= xShape )
ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData );
}
// exporting transition effects to pdf
if ( mbImpressDoc && !pPDFExtOutDevData->GetIsExportNotesPages() && pPDFExtOutDevData->GetIsExportTransitionEffects() )
{
static constexpr OUString sEffect( u"Effect"_ustr );
static constexpr OUString sSpeed ( u"Speed"_ustr );
sal_Int32 nTime = 800;
presentation::AnimationSpeed aAs;
if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) )
{
aAny = xPagePropSet->getPropertyValue( sSpeed );
if ( aAny >>= aAs )
{
switch( aAs )
{
case presentation::AnimationSpeed_SLOW : nTime = 1500; break;
case presentation::AnimationSpeed_FAST : nTime = 300; break;
default:
case presentation::AnimationSpeed_MEDIUM : nTime = 800;
}
}
}
presentation::FadeEffect eFe;
vcl::PDFWriter::PageTransition eType = vcl::PDFWriter::PageTransition::Regular;
if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) )
{
aAny = xPagePropSet->getPropertyValue( sEffect );
if ( aAny >>= eFe )
{
switch( eFe )
{
case presentation::FadeEffect_HORIZONTAL_LINES :
case presentation::FadeEffect_HORIZONTAL_CHECKERBOARD :
case presentation::FadeEffect_HORIZONTAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsHorizontal; break;
case presentation::FadeEffect_VERTICAL_LINES :
case presentation::FadeEffect_VERTICAL_CHECKERBOARD :
case presentation::FadeEffect_VERTICAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsVertical; break;
case presentation::FadeEffect_UNCOVER_TO_RIGHT :
case presentation::FadeEffect_UNCOVER_TO_UPPERRIGHT :
case presentation::FadeEffect_ROLL_FROM_LEFT :
case presentation::FadeEffect_FADE_FROM_UPPERLEFT :
case presentation::FadeEffect_MOVE_FROM_UPPERLEFT :
case presentation::FadeEffect_FADE_FROM_LEFT :
case presentation::FadeEffect_MOVE_FROM_LEFT : eType = vcl::PDFWriter::PageTransition::WipeLeftToRight; break;
case presentation::FadeEffect_UNCOVER_TO_BOTTOM :
case presentation::FadeEffect_UNCOVER_TO_LOWERRIGHT :
case presentation::FadeEffect_ROLL_FROM_TOP :
case presentation::FadeEffect_FADE_FROM_UPPERRIGHT :
case presentation::FadeEffect_MOVE_FROM_UPPERRIGHT :
case presentation::FadeEffect_FADE_FROM_TOP :
case presentation::FadeEffect_MOVE_FROM_TOP : eType = vcl::PDFWriter::PageTransition::WipeTopToBottom; break;
case presentation::FadeEffect_UNCOVER_TO_LEFT :
case presentation::FadeEffect_UNCOVER_TO_LOWERLEFT :
case presentation::FadeEffect_ROLL_FROM_RIGHT :
case presentation::FadeEffect_FADE_FROM_LOWERRIGHT :
case presentation::FadeEffect_MOVE_FROM_LOWERRIGHT :
case presentation::FadeEffect_FADE_FROM_RIGHT :
case presentation::FadeEffect_MOVE_FROM_RIGHT : eType = vcl::PDFWriter::PageTransition::WipeRightToLeft; break;
case presentation::FadeEffect_UNCOVER_TO_TOP :
case presentation::FadeEffect_UNCOVER_TO_UPPERLEFT :
case presentation::FadeEffect_ROLL_FROM_BOTTOM :
case presentation::FadeEffect_FADE_FROM_LOWERLEFT :
case presentation::FadeEffect_MOVE_FROM_LOWERLEFT :
case presentation::FadeEffect_FADE_FROM_BOTTOM :
case presentation::FadeEffect_MOVE_FROM_BOTTOM : eType = vcl::PDFWriter::PageTransition::WipeBottomToTop; break;
case presentation::FadeEffect_OPEN_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalInward; break;
case presentation::FadeEffect_CLOSE_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalOutward; break;
case presentation::FadeEffect_OPEN_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalInward; break;
case presentation::FadeEffect_CLOSE_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalOutward; break;
case presentation::FadeEffect_FADE_TO_CENTER : eType = vcl::PDFWriter::PageTransition::BoxInward; break;
case presentation::FadeEffect_FADE_FROM_CENTER : eType = vcl::PDFWriter::PageTransition::BoxOutward; break;
case presentation::FadeEffect_NONE : eType = vcl::PDFWriter::PageTransition::Regular; break;
case presentation::FadeEffect_RANDOM :
case presentation::FadeEffect_DISSOLVE :
default: eType = vcl::PDFWriter::PageTransition::Dissolve; break;
}
}
}
if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) ||
xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) )
{
pPDFExtOutDevData->SetPageTransition( eType, nTime );
}
}
}
}
}
catch (const uno::Exception&)
{
}
}
aView.SdrPaintView::CompleteRedraw(pOut, aRegion, &aImplRenderPaintProc);
if (pPDFExtOutDevData && pPage)
{
try
{
Size aPageSize( mpDoc->GetSdPage( 0, PageKind::Standard )->GetSize() );
Point aPoint( 0, 0 );
::tools::Rectangle aPageRect( aPoint, aPageSize );
// resolving links found in this page by the method ImpEditEngine::Paint
std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks();
for ( const auto& rBookmark : rBookmarks )
{
sal_Int32 nPage = ImplPDFGetBookmarkPage( rBookmark.aBookmark, *mpDoc );
if ( nPage != -1 )
{
if ( rBookmark.nLinkId != -1 )
pPDFExtOutDevData->SetLinkDest( rBookmark.nLinkId, pPDFExtOutDevData->CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ) );
else
pPDFExtOutDevData->DescribeRegisteredDest( rBookmark.nDestId, aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle );
}
else
pPDFExtOutDevData->SetLinkURL( rBookmark.nLinkId, rBookmark.aBookmark );
}
rBookmarks.clear();
//---> #i56629, #i40318
//get the page name, will be used as outline element in PDF bookmark pane
OUString aPageName = mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1 , PageKind::Standard )->GetName();
if( !aPageName.isEmpty() )
{
// Destination PageNum
const sal_Int32 nDestPageNum = CalcOutputPageNum(pPDFExtOutDevData, mpDoc, nPageNumber);
// insert the bookmark to this page into the NamedDestinations
if( pPDFExtOutDevData->GetIsExportNamedDestinations() )
pPDFExtOutDevData->CreateNamedDest(aPageName, aPageRect, nDestPageNum);
// add the name to the outline, (almost) same code as in sc/source/ui/unoobj/docuno.cxx
// issue #i40318.
if( pPDFExtOutDevData->GetIsExportBookmarks() )
{
// Destination Export
const sal_Int32 nDestId =
pPDFExtOutDevData->CreateDest(aPageRect , nDestPageNum);
// Create a new outline item:
pPDFExtOutDevData->CreateOutlineItem( -1 , aPageName, nDestId );
}
}
//<--- #i56629, #i40318
}
catch (const uno::Exception&)
{
}
}
}
else
{
uno::Reference< drawing::XShapes > xShapes;
rSelection >>= xShapes;
if( xShapes.is() && xShapes->getCount() )
{
SdrPageView* pPV = nullptr;
ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(),
pOldSdView ? pOldSdView->GetSdrPageView() : nullptr);
for( sal_uInt32 i = 0, nCount = xShapes->getCount(); i < nCount; i++ )
{
uno::Reference< drawing::XShape > xShape;
xShapes->getByIndex( i ) >>= xShape;
if( xShape.is() )
{
SdrObject* pObj = SdrObject::getSdrObjectFromXShape( xShape );
if( pObj && pObj->getSdrPageFromSdrObject()
&& aImplRenderPaintProc.IsVisible( pObj )
&& aImplRenderPaintProc.IsPrintable( pObj ) )
{
if( !pPV )
pPV = aView.ShowSdrPage( pObj->getSdrPageFromSdrObject() );
if( pPV )
aView.MarkObj( pObj, pPV );
}
}
}
aView.DrawMarkedObj(*pOut);
}
}
}
DrawViewShell* SdXImpressDocument::GetViewShell()
{
DrawViewShell* pViewSh = dynamic_cast<DrawViewShell*>(mpDocShell->GetViewShell());
if (!pViewSh)
{
SAL_WARN("sd", "DrawViewShell not available!");
return nullptr;
}
return pViewSh;
}
void SdXImpressDocument::paintTile( VirtualDevice& rDevice,
int nOutputWidth, int nOutputHeight,
int nTilePosX, int nTilePosY,
::tools::Long nTileWidth, ::tools::Long nTileHeight )
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
// we need to skip tile invalidation for controls on rendering
comphelper::LibreOfficeKit::setTiledPainting(true);
// Setup drawing layer to work properly. Since we use a custom VirtualDevice
// for the drawing, SdrPaintView::BeginCompleteRedraw() will call FindPaintWindow()
// unsuccessfully and use a temporary window that doesn't keep state. So patch
// the existing SdrPageWindow to use a temporary, and this way the state will be kept.
// Well, at least that's how I understand it based on Writer's RenderContextGuard,
// as the drawing layer classes lack documentation.
SdrPageWindow* patchedPageWindow = nullptr;
SdrPaintWindow* previousPaintWindow = nullptr;
std::unique_ptr<SdrPaintWindow> temporaryPaintWindow;
if(SdrView* pDrawView = pViewSh->GetDrawView())
{
if(SdrPageView* pSdrPageView = pDrawView->GetSdrPageView())
{
pSdrPageView->SetApplicationDocumentColor(pViewSh->GetViewOptions().mnDocBackgroundColor);
patchedPageWindow = pSdrPageView->FindPageWindow(*getDocWindow()->GetOutDev());
temporaryPaintWindow.reset(new SdrPaintWindow(*pDrawView, rDevice));
if (patchedPageWindow)
previousPaintWindow = patchedPageWindow->patchPaintWindow(*temporaryPaintWindow);
}
}
// Scaling. Must convert from pixels to twips. We know
// that VirtualDevices use a DPI of 96.
// We specifically calculate these scales first as we're still
// in TWIPs, and might as well minimize the number of conversions.
const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale;
Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale;
// svx seems to be the only component that works natively in
// 100th mm rather than TWIP. It makes most sense just to
// convert here and in getDocumentSize, and leave the tiled
// rendering API working in TWIPs.
::tools::Long nTileWidthHMM = convertTwipToMm100( nTileWidth );
::tools::Long nTileHeightHMM = convertTwipToMm100( nTileHeight );
int nTilePosXHMM = convertTwipToMm100( nTilePosX );
int nTilePosYHMM = convertTwipToMm100( nTilePosY );
MapMode aMapMode = rDevice.GetMapMode();
aMapMode.SetMapUnit( MapUnit::Map100thMM );
aMapMode.SetOrigin( Point( -nTilePosXHMM,
-nTilePosYHMM) );
aMapMode.SetScaleX( scaleX );
aMapMode.SetScaleY( scaleY );
rDevice.SetMapMode( aMapMode );
rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight) );
Point aPoint(nTilePosXHMM, nTilePosYHMM);
Size aSize(nTileWidthHMM, nTileHeightHMM);
::tools::Rectangle aRect(aPoint, aSize);
SdrView* pView = pViewSh->GetDrawView();
if (comphelper::LibreOfficeKit::isActive())
pView->SetPaintTextEdit(mbPaintTextEdit);
pViewSh->GetView()->CompleteRedraw(&rDevice, vcl::Region(aRect));
if (comphelper::LibreOfficeKit::isActive())
pView->SetPaintTextEdit(true);
LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
nTilePosX, nTilePosY, nTileWidth, nTileHeight);
LokStarMathHelper::PaintAllInPlaceOnTile(rDevice, nOutputWidth, nOutputHeight, nTilePosX,
nTilePosY, nTileWidth, nTileHeight);
if(patchedPageWindow != nullptr)
patchedPageWindow->unpatchPaintWindow(previousPaintWindow);
// Draw Form controls
SdrView* pDrawView = pViewSh->GetDrawView();
SdrPageView* pPageView = pDrawView->GetSdrPageView();
if (pPageView != nullptr)
{
SdrPage* pPage = pPageView->GetPage();
::sd::Window* pActiveWin = pViewSh->GetActiveWindow();
::tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
Size aOutputSize(nOutputWidth, nOutputHeight);
LokControlHandler::paintControlTile(pPage, pDrawView, *pActiveWin, rDevice, aOutputSize, aTileRect);
}
comphelper::LibreOfficeKit::setTiledPainting(false);
}
OString SdXImpressDocument::getViewRenderState(SfxViewShell* pViewShell)
{
OStringBuffer aState;
DrawViewShell* pView = nullptr;
if (ViewShellBase* pShellBase = dynamic_cast<ViewShellBase*>(pViewShell))
pView = dynamic_cast<DrawViewShell*>(pShellBase->GetMainViewShell().get());
else
pView = GetViewShell();
if (pView)
{
const SdViewOptions& pVOpt = pView->GetViewOptions();
if (mpDoc->GetOnlineSpell())
aState.append('S');
if (pVOpt.mnDocBackgroundColor == svtools::ColorConfig::GetDefaultColor(svtools::DOCCOLOR, 1))
aState.append('D');
aState.append(';');
OString aThemeName = OUStringToOString(pVOpt.msColorSchemeName, RTL_TEXTENCODING_UTF8);
aState.append(aThemeName);
}
return aState.makeStringAndClear();
}
void SdXImpressDocument::selectPart(int nPart, int nSelect)
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
pViewSh->SelectPage(nPart, nSelect);
}
void SdXImpressDocument::moveSelectedParts(int nPosition, bool bDuplicate)
{
// Duplicating is currently unsupported.
if (!bDuplicate)
mpDoc->MovePages(nPosition);
}
OUString SdXImpressDocument::getPartInfo(int nPart)
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return OUString();
const SdPage* pSdPage = mpDoc->GetSdPage(nPart, pViewSh->GetPageKind());
const bool bIsVisible = pSdPage && !pSdPage->IsExcluded();
const bool bIsSelected = pViewSh->IsSelected(nPart);
const sal_Int16 nMasterPageCount= pViewSh->GetDoc()->GetMasterSdPageCount(pViewSh->GetPageKind());
OUString aPartInfo = "{ \"visible\": \"" +
OUString::number(static_cast<unsigned int>(bIsVisible)) +
"\", \"selected\": \"" +
OUString::number(static_cast<unsigned int>(bIsSelected)) +
"\", \"masterPageCount\": \"" +
OUString::number(nMasterPageCount) +
"\", \"mode\": \"" +
OUString::number(getEditMode()) +
"\" }";
return aPartInfo;
}
void SdXImpressDocument::setPart( int nPart, bool bAllowChangeFocus )
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
pViewSh->SwitchPage( nPart, bAllowChangeFocus );
}
int SdXImpressDocument::getParts()
{
if (!mpDoc)
return 0;
if (isMasterViewMode())
return mpDoc->GetMasterSdPageCount(PageKind::Standard);
return mpDoc->GetSdPageCount(PageKind::Standard);
}
int SdXImpressDocument::getPart()
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return 0;
return pViewSh->GetViewShellBase().getPart();
}
OUString SdXImpressDocument::getPartName(int nPart)
{
SdPage* pPage;
if (isMasterViewMode())
pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard);
else
pPage = mpDoc->GetSdPage(nPart, PageKind::Standard);
if (!pPage)
{
SAL_WARN("sd", "DrawViewShell not available!");
return OUString();
}
return pPage->GetName();
}
OUString SdXImpressDocument::getPartHash(int nPart)
{
SdPage* pPage;
if (isMasterViewMode())
pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard);
else
pPage = mpDoc->GetSdPage(nPart, PageKind::Standard);
if (!pPage)
{
SAL_WARN("sd", "DrawViewShell not available!");
return OUString();
}
uno::Reference<drawing::XDrawPage> xDrawPage(pPage->getUnoPage(), uno::UNO_QUERY);
return OUString::fromUtf8(GetInterfaceHash(xDrawPage));
}
bool SdXImpressDocument::isMasterViewMode()
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return false;
if (pViewSh->GetDispatcher())
{
SfxPoolItemHolder aResult;
pViewSh->GetDispatcher()->QueryState(SID_SLIDE_MASTER_MODE, aResult);
const SfxBoolItem* isMasterViewMode(static_cast<const SfxBoolItem*>(aResult.getItem()));
if (isMasterViewMode && isMasterViewMode->GetValue())
return true;
}
return false;
}
VclPtr<vcl::Window> SdXImpressDocument::getDocWindow()
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return {};
if (VclPtr<vcl::Window> pWindow = SfxLokHelper::getInPlaceDocWindow(pViewShell->GetViewShell()))
return pWindow;
return pViewShell->GetActiveWindow();
}
void SdXImpressDocument::setPartMode( int nPartMode )
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
PageKind aPageKind( PageKind::Standard );
switch ( nPartMode )
{
case LOK_PARTMODE_SLIDES:
break;
case LOK_PARTMODE_NOTES:
aPageKind = PageKind::Notes;
break;
}
pViewSh->SetPageKind( aPageKind );
}
int SdXImpressDocument::getEditMode()
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return 0;
return pViewSh->GetViewShellBase().getEditMode();
}
void SdXImpressDocument::setEditMode(int nMode)
{
SolarMutexGuard aGuard;
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
pViewSh->GetViewShellBase().setEditMode(nMode);
}
Size SdXImpressDocument::getDocumentSize()
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return Size();
SdrView *pSdrView = pViewSh->GetView();
if (!pSdrView)
return Size();
SdrPageView* pCurPageView = pSdrView->GetSdrPageView();
if (!pCurPageView)
return Size();
Size aSize = pCurPageView->GetPageRect().GetSize();
// Convert the size in 100th mm to TWIP
// See paintTile above for further info.
return o3tl::convert(aSize, o3tl::Length::mm100, o3tl::Length::twip);
}
void SdXImpressDocument::getPostIts(::tools::JsonWriter& rJsonWriter)
{
auto commentsNode = rJsonWriter.startNode("comments");
if (!mpDoc)
return;
// Return annotations on master pages too ?
const sal_uInt16 nMaxPages = mpDoc->GetPageCount();
for (sal_uInt16 nPage = 0; nPage < nMaxPages; ++nPage)
{
SdrPage* pPage = mpDoc->GetPage(nPage);
for (auto const& xAnnotation : pPage->getAnnotations())
{
sal_uInt32 nID = xAnnotation->GetId();
OString nodeName = "comment" + OString::number(nID);
auto commentNode = rJsonWriter.startNode(nodeName);
rJsonWriter.put("id", nID);
rJsonWriter.put("author", xAnnotation->getAuthor());
rJsonWriter.put("dateTime", utl::toISO8601(xAnnotation->getDateTime()));
uno::Reference<text::XText> xText(xAnnotation->getTextRange());
rJsonWriter.put("text", xText->getString());
rJsonWriter.put("parthash", pPage->GetUniqueID());
geometry::RealPoint2D const aPoint = xAnnotation->getPosition();
geometry::RealSize2D const aSize = xAnnotation->getSize();
::tools::Rectangle aRectangle(Point(aPoint.X * 100.0, aPoint.Y * 100.0), Size(aSize.Width * 100.0, aSize.Height * 100.0));
aRectangle = o3tl::toTwips(aRectangle, o3tl::Length::mm100);
OString sRectangle = aRectangle.toString();
rJsonWriter.put("rectangle", sRectangle.getStr());
}
}
}
void SdXImpressDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
{
SolarMutexGuard aGuard;
OUString sThemeName;
OUString sBackgroundThemeName;
if (DrawViewShell* pViewShell = GetViewShell())
{
DrawView* pDrawView = pViewShell->GetDrawView();
for (const beans::PropertyValue& rValue : rArguments)
{
if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>())
pDrawView->SetPageShadowVisible(rValue.Value.get<bool>());
else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>())
pDrawView->SetAuthor(rValue.Value.get<OUString>());
else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
mpDoc->SetOnlineSpell(rValue.Value.get<bool>());
else if (rValue.Name == ".uno:ChangeTheme" && rValue.Value.has<OUString>())
sThemeName = rValue.Value.get<OUString>();
else if (rValue.Name == ".uno:InvertBackground" && rValue.Value.has<OUString>())
sBackgroundThemeName = rValue.Value.get<OUString>();
}
// Disable comments if requested
SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
pOptions->SetShowComments(comphelper::LibreOfficeKit::isTiledAnnotations());
pViewShell->SetRuler(false);
pViewShell->SetScrollBarsVisible(false);
if (sd::Window* pWindow = pViewShell->GetActiveWindow())
{
// get the full page size in pixels
pWindow->EnableMapMode();
Size aSize(pWindow->LogicToPixel(pDrawView->GetSdrPageView()->GetPage()->GetSize()));
// Disable map mode, so that it's possible to send mouse event
// coordinates in logic units
pWindow->EnableMapMode(false);
// arrange UI elements again with new view size
pViewShell->GetParentWindow()->SetSizePixel(aSize);
pViewShell->Resize();
}
// Forces all images to be swapped in synchronously, this
// ensures that images are available when paintTile is called
// (whereas with async loading images start being loaded after
// we have painted the tile, resulting in an invalidate, followed
// by the tile being rerendered - which is wasteful and ugly).
pDrawView->SetSwapAsynchron(false);
}
// when the "This document may contain formatting or content that cannot
// be saved..." dialog appears, it is auto-cancelled with tiled rendering,
// causing 'Save' being disabled; so let's always save to the original
// format
auto xChanges = comphelper::ConfigurationChanges::create();
officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
if (!o3tl::IsRunningUnitTest() || !comphelper::LibreOfficeKit::isActive())
officecfg::Office::Impress::MultiPaneGUI::SlideSorterBar::Visible::ImpressView::set(true,xChanges);
xChanges->commit();
// if we know what theme the user wants, then we can dispatch that now early
if (!sThemeName.isEmpty())
{
css::uno::Sequence<css::beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
{
{ "NewTheme", uno::Any(sThemeName) }
}));
comphelper::dispatchCommand(u".uno:ChangeTheme"_ustr, aPropertyValues);
}
if (!sBackgroundThemeName.isEmpty())
{
css::uno::Sequence<css::beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
{
{ "NewTheme", uno::Any(sBackgroundThemeName) }
}));
comphelper::dispatchCommand(".uno:InvertBackground", aPropertyValues);
}
}
void SdXImpressDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode)
{
SolarMutexGuard aGuard;
SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
}
void SdXImpressDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px);
if (SfxLokHelper::testInPlaceComponentMouseEventHit(
pViewShell->GetViewShell(), nType, nX, nY, nCount, nButtons, nModifier, fScale, fScale))
return;
// try to forward mouse event to control
const Point aPointTwip(nX, nY);
const Point aPointHMM = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100);
SdrView* pDrawView = pViewShell->GetDrawView();
SdrPageView* pPageView = pDrawView->GetSdrPageView();
SdrPage* pPage = pPageView->GetPage();
::sd::Window* pActiveWin = pViewShell->GetActiveWindow();
if (!pActiveWin)
{
return;
}
if (LokControlHandler::postMouseEvent(pPage, pDrawView, *pActiveWin, nType, aPointHMM, nCount, nButtons, nModifier))
return;
LokMouseEventData aMouseEventData(nType, aPointHMM, nCount, MouseEventModifiers::SIMPLECLICK,
nButtons, nModifier);
SfxLokHelper::postMouseEventAsync(pViewShell->GetActiveWindow(), aMouseEventData);
}
void SdXImpressDocument::setTextSelection(int nType, int nX, int nY)
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
LokChartHelper aChartHelper(pViewShell->GetViewShell());
if (aChartHelper.setTextSelection(nType, nX, nY))
return;
Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
switch (nType)
{
case LOK_SETTEXTSELECTION_START:
pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
break;
case LOK_SETTEXTSELECTION_END:
pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
break;
case LOK_SETTEXTSELECTION_RESET:
pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
break;
default:
assert(false);
break;
}
}
uno::Reference<datatransfer::XTransferable> SdXImpressDocument::getSelection()
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return uno::Reference<datatransfer::XTransferable>();
return pViewShell->GetSelectionTransferable();
}
void SdXImpressDocument::setGraphicSelection(int nType, int nX, int nY)
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px);
LokChartHelper aChartHelper(pViewShell->GetViewShell());
if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale))
return;
Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
switch (nType)
{
case LOK_SETGRAPHICSELECTION_START:
pViewShell->SetGraphicMm100Position(/*bStart=*/true, aPoint);
break;
case LOK_SETGRAPHICSELECTION_END:
pViewShell->SetGraphicMm100Position(/*bStart=*/false, aPoint);
break;
default:
assert(false);
break;
}
}
void SdXImpressDocument::resetSelection()
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
SdrView* pSdrView = pViewShell->GetView();
if (!pSdrView)
return;
if (pSdrView->IsTextEdit())
{
// Reset the editeng selection.
pSdrView->UnmarkAll();
// Finish editing.
pSdrView->SdrEndTextEdit();
}
// Reset graphic selection.
pSdrView->UnmarkAll();
}
void SdXImpressDocument::setClientVisibleArea(const ::tools::Rectangle& rRectangle)
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
pViewShell->GetViewShellBase().setLOKVisibleArea(rRectangle);
}
void SdXImpressDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
pViewShell->GetActiveWindow()->SetClipboard(xClipboard);
}
bool SdXImpressDocument::isMimeTypeSupported()
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return false;
TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(pViewShell->GetActiveWindow()));
return EditEngine::HasValidData(aDataHelper.GetTransferable());
}
PointerStyle SdXImpressDocument::getPointer()
{
SolarMutexGuard aGuard;
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return PointerStyle::Arrow;
Window* pWindow = pViewShell->GetActiveWindow();
if (!pWindow)
return PointerStyle::Arrow;
return pWindow->GetPointer();
}
uno::Reference< i18n::XForbiddenCharacters > SdXImpressDocument::getForbiddenCharsTable()
{
rtl::Reference<SdUnoForbiddenCharsTable> xRef = mxForbiddenCharacters.get();
if( !xRef )
{
xRef = new SdUnoForbiddenCharsTable( mpDoc );
mxForbiddenCharacters = xRef.get();
}
return xRef;
}
void SdXImpressDocument::initializeDocument()
{
if( mbClipBoard )
return;
switch( mpDoc->GetPageCount() )
{
case 1:
{
// nasty hack to detect clipboard document
mbClipBoard = true;
break;
}
case 0:
{
mpDoc->CreateFirstPages();
mpDoc->StopWorkStartupDelay();
break;
}
}
}
OString SdXImpressDocument::getPresentationInfo() const
{
::tools::JsonWriter aJsonWriter;
try
{
rtl::Reference<SdDrawPagesAccess> xDrawPages = const_cast<SdXImpressDocument*>(this)->getSdDrawPages();
// size in twips
Size aDocSize = const_cast<SdXImpressDocument*>(this)->getDocumentSize();
aJsonWriter.put("docWidth", aDocSize.getWidth());
aJsonWriter.put("docHeight", aDocSize.getHeight());
sd::PresentationSettings const& rSettings = mpDoc->getPresentationSettings();
const bool bIsEndless = rSettings.mbEndless;
aJsonWriter.put("isEndless", bIsEndless);
if (bIsEndless) {
const sal_Int32 nPauseTimeout = rSettings.mnPauseTimeout;
aJsonWriter.put("loopAndRepeatDuration", nPauseTimeout);
}
auto aSlideList = aJsonWriter.startArray("slides");
sal_Int32 nSlideCount = xDrawPages->getCount();
for (sal_Int32 i = 0; i < nSlideCount; ++i)
{
SdGenericDrawPage* pSlide(xDrawPages->getDrawPageByIndex(i));
bool bIsVisible = true; // default visible
pSlide->getPropertyValue("Visible") >>= bIsVisible;
if (bIsVisible)
{
SdrPage* pPage = pSlide->GetSdrPage();
auto aSlideNode = aJsonWriter.startStruct();
std::string sSlideHash = GetInterfaceHash(cppu::getXWeak(pSlide));
aJsonWriter.put("hash", sSlideHash);
aJsonWriter.put("index", i);
bool bIsDrawPageEmpty = pSlide->getCount() == 0;
aJsonWriter.put("empty", bIsDrawPageEmpty);
// Notes
SdPage* pNotesPage = mpDoc->GetSdPage((pPage->GetPageNum() - 1) >> 1, PageKind::Notes);
if (pNotesPage)
{
SdrObject* pNotes = pNotesPage->GetPresObj(PresObjKind::Notes);
if (pNotes)
{
OUStringBuffer strNotes;
OutlinerParaObject* pPara = pNotes->GetOutlinerParaObject();
if (pPara)
{
const EditTextObject& rText = pPara->GetTextObject();
for (sal_Int32 nNote = 0; nNote < rText.GetParagraphCount(); nNote++)
{
strNotes.append(rText.GetText(nNote));
}
aJsonWriter.put("notes", strNotes.makeStringAndClear());
}
}
}
SdMasterPage* pMasterPage = nullptr;
SdDrawPage* pMasterPageTarget(dynamic_cast<SdDrawPage*>(pSlide));
if (pMasterPageTarget)
{
pMasterPage = pMasterPageTarget->getSdMasterPage();
if (pMasterPage)
{
std::string sMPHash = GetInterfaceHash(cppu::getXWeak(pMasterPage));
aJsonWriter.put("masterPage", sMPHash);
bool bBackgroundObjectsVisibility = true; // default visible
pSlide->getPropertyValue("IsBackgroundObjectsVisible") >>= bBackgroundObjectsVisibility;
aJsonWriter.put("masterPageObjectsVisibility", bBackgroundObjectsVisibility);
}
}
bool bBackgroundVisibility = true; // default visible
pSlide->getPropertyValue("IsBackgroundVisible") >>= bBackgroundVisibility;
if (bBackgroundVisibility)
{
SlideBackgroundInfo aSlideBackgroundInfo(pSlide, static_cast<SvxDrawPage*>(pMasterPage));
if (aSlideBackgroundInfo.hasBackground())
{
auto aBackgroundNode = aJsonWriter.startNode("background");
aJsonWriter.put("isCustom", aSlideBackgroundInfo.slideHasOwnBackground());
if (aSlideBackgroundInfo.isSolidColor())
{
aJsonWriter.put("fillColor", aSlideBackgroundInfo.getFillColorAsRGBA());
}
}
}
{
auto aVideoList = aJsonWriter.startArray("videos");
SdrObjListIter aIterator(pPage, SdrIterMode::DeepWithGroups);
while (aIterator.IsMore())
{
auto* pObject = aIterator.Next();
if (pObject->GetObjIdentifier() == SdrObjKind::Media)
{
auto aVideosNode = aJsonWriter.startStruct();
auto* pMediaObject = static_cast<SdrMediaObj*>(pObject);
auto const& rRectangle = pMediaObject->GetLogicRect();
auto aRectangle = o3tl::convert(rRectangle, o3tl::Length::mm100, o3tl::Length::twip);
aJsonWriter.put("id", reinterpret_cast<sal_uInt64>(pMediaObject));
aJsonWriter.put("url", pMediaObject->getTempURL());
aJsonWriter.put("x", aRectangle.Left());
aJsonWriter.put("y", aRectangle.Top());
aJsonWriter.put("width", aRectangle.GetWidth());
aJsonWriter.put("height", aRectangle.GetHeight());
}
}
}
sal_Int32 nTransitionType = 0;
pSlide->getPropertyValue("TransitionType") >>= nTransitionType;
if (nTransitionType != 0)
{
auto iterator = constTransitionTypeToString.find(nTransitionType);
if (iterator != constTransitionTypeToString.end())
{
aJsonWriter.put("transitionType", iterator->second);
sal_Int32 nTransitionSubtype = 0;
pSlide->getPropertyValue("TransitionSubtype") >>= nTransitionSubtype;
auto iteratorSubType = constTransitionSubTypeToString.find(nTransitionSubtype);
if (iteratorSubType != constTransitionSubTypeToString.end())
{
aJsonWriter.put("transitionSubtype", iteratorSubType->second);
}
else
{
SAL_WARN("sd", "Transition sub-type unknown: " << nTransitionSubtype);
}
bool nTransitionDirection = false;
pSlide->getPropertyValue("TransitionDirection") >>= nTransitionDirection;
aJsonWriter.put("transitionDirection", nTransitionDirection);
// fade color
if ((nTransitionType == TransitionType::FADE)
&& ((nTransitionSubtype == TransitionSubType::FADETOCOLOR)
|| (nTransitionSubtype == TransitionSubType::FADEFROMCOLOR)
|| (nTransitionSubtype == TransitionSubType::FADEOVERCOLOR)))
{
sal_Int32 nFadeColor = 0;
pSlide->getPropertyValue("TransitionFadeColor") >>= nFadeColor;
OUStringBuffer sTmpBuf;
::sax::Converter::convertColor(sTmpBuf, nFadeColor);
aJsonWriter.put("transitionFadeColor", sTmpBuf.makeStringAndClear());
}
}
double nTransitionDuration(0.0);
if( pSlide->getPropertySetInfo()->hasPropertyByName( "TransitionDuration" ) &&
(pSlide->getPropertyValue( "TransitionDuration" ) >>= nTransitionDuration ) && nTransitionDuration != 0.0 )
{
// convert transitionDuration time to ms
aJsonWriter.put("transitionDuration", nTransitionDuration * 1000);
}
sal_Int32 nChange(0);
if( pSlide->getPropertySetInfo()->hasPropertyByName( "Change" ) &&
(pSlide->getPropertyValue( "Change" ) >>= nChange ) && nChange == 1 )
{
double fSlideDuration(0);
if( pSlide->getPropertySetInfo()->hasPropertyByName( "HighResDuration" ) &&
(pSlide->getPropertyValue( "HighResDuration" ) >>= fSlideDuration) )
{
// convert slide duration time to ms
aJsonWriter.put("nextSlideDuration", fSlideDuration * 1000);
}
}
}
AnimationsExporter aAnimationExporter(aJsonWriter, pSlide);
if (aAnimationExporter.hasEffects())
{
auto aAnimationsNode = aJsonWriter.startNode("animations");
aAnimationExporter.exportAnimations();
}
}
}
}
catch (uno::Exception& )
{
TOOLS_WARN_EXCEPTION("sd", "SdXImpressDocument::getSlideShowInfo ... maybe some property can't be retrieved");
}
return aJsonWriter.finishAndGetAsOString();
}
bool SdXImpressDocument::createSlideRenderer(
sal_Int32 nSlideNumber, sal_Int32& nViewWidth, sal_Int32& nViewHeight,
bool bRenderBackground, bool bRenderMasterPage)
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return false;
uno::Reference<presentation::XSlideShow> xSlideShow = pViewSh->getXSlideShowInstance();
if (!xSlideShow.is())
return false;
bool bSuccess = false;
try
{
rtl::Reference<SdXImpressDocument> xDrawPages(mpDoc->getUnoModel());
uno::Reference<container::XIndexAccess> xSlides(xDrawPages->getDrawPages(), uno::UNO_QUERY_THROW);
uno::Reference<drawing::XDrawPage> xSlide(xSlides->getByIndex(nSlideNumber), uno::UNO_QUERY_THROW);
uno::Reference<animations::XAnimationNodeSupplier> xAnimNodeSupplier(xSlide, uno::UNO_QUERY_THROW);
uno::Reference<animations::XAnimationNode> xAnimNode = xAnimNodeSupplier->getAnimationNode();
bSuccess = xSlideShow->createLOKSlideRenderer(nViewWidth, nViewHeight,
bRenderMasterPage, bRenderBackground,
xSlide, xDrawPages, xAnimNode);
}
catch (uno::Exception&)
{
TOOLS_WARN_EXCEPTION( "sd", "SdXImpressDocument::createLOKSlideRenderer: failed" );
}
return bSuccess;
}
void SdXImpressDocument::postSlideshowCleanup()
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
pViewSh->destroyXSlideShowInstance();
}
bool SdXImpressDocument::renderNextSlideLayer(unsigned char* pBuffer, bool& bIsBitmapLayer, OUString& rJsonMsg)
{
DrawViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return true;
uno::Reference<presentation::XSlideShow> xSlideShow = pViewSh->getXSlideShowInstance();
if (!xSlideShow.is())
return true;
auto nBufferPointer = sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pBuffer));
sal_Bool bBitmapLayer = false;
bool bDone = xSlideShow->renderNextLOKSlideLayer(nBufferPointer, bBitmapLayer, rJsonMsg);
bIsBitmapLayer = bBitmapLayer;
return bDone;
}
SdrModel& SdXImpressDocument::getSdrModelFromUnoModel() const
{
OSL_ENSURE(GetDoc(), "No SdrModel in draw/Impress, should not happen");
return *GetDoc(); // TTTT should be reference
}
void SAL_CALL SdXImpressDocument::dispose()
{
if( mbDisposed )
return;
::SolarMutexGuard aGuard;
if( mpDoc )
{
EndListening( *mpDoc );
mpDoc = nullptr;
}
// Call the base class dispose() before setting the mbDisposed flag
// to true. The reason for this is that if close() has not yet been
// called this is done in SfxBaseModel::dispose(). At the end of
// that dispose() is called again. It is important to forward this
// second dispose() to the base class, too.
// As a consequence the following code has to be able to be run twice.
SfxBaseModel::dispose();
mbDisposed = true;
rtl::Reference< SdDocLinkTargets > xLinks( mxLinks );
if( xLinks.is() )
{
xLinks->dispose();
xLinks = nullptr;
}
rtl::Reference< SdDrawPagesAccess > xDrawPagesAccess( mxDrawPagesAccess );
if( xDrawPagesAccess.is() )
{
xDrawPagesAccess->dispose();
xDrawPagesAccess = nullptr;
}
rtl::Reference< SdMasterPagesAccess > xMasterPagesAccess( mxMasterPagesAccess );
if( xDrawPagesAccess.is() )
{
xMasterPagesAccess->dispose();
xMasterPagesAccess = nullptr;
}
rtl::Reference< SdLayerManager > xLayerManager( mxLayerManager );
if( xLayerManager.is() )
{
xLayerManager->dispose();
xLayerManager = nullptr;
}
mxDashTable = nullptr;
mxGradientTable = nullptr;
mxHatchTable = nullptr;
mxBitmapTable = nullptr;
mxTransGradientTable = nullptr;
mxMarkerTable = nullptr;
mxDrawingPool = nullptr;
}
SdDrawPagesAccess::SdDrawPagesAccess( SdXImpressDocument& rMyModel ) noexcept
: mpModel( &rMyModel)
{
}
SdDrawPagesAccess::~SdDrawPagesAccess() noexcept
{
}
// XIndexAccess
sal_Int32 SAL_CALL SdDrawPagesAccess::getCount()
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
return mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
}
uno::Any SAL_CALL SdDrawPagesAccess::getByIndex( sal_Int32 Index )
{
uno::Reference< drawing::XDrawPage > xDrawPage( getDrawPageByIndex(Index) );
return uno::Any(xDrawPage);
}
SdGenericDrawPage* SdDrawPagesAccess::getDrawPageByIndex( sal_Int32 Index )
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
if( (Index < 0) || (Index >= mpModel->mpDoc->GetSdPageCount( PageKind::Standard ) ) )
throw lang::IndexOutOfBoundsException();
SdPage* pPage = mpModel->mpDoc->GetSdPage( static_cast<sal_uInt16>(Index), PageKind::Standard );
if( pPage )
return dynamic_cast<SdGenericDrawPage*>( pPage->getUnoPage().get() );
return nullptr;
}
// XNameAccess
uno::Any SAL_CALL SdDrawPagesAccess::getByName( const OUString& aName )
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
if( !aName.isEmpty() )
{
const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
sal_uInt16 nPage;
for( nPage = 0; nPage < nCount; nPage++ )
{
SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard );
if(nullptr == pPage)
continue;
if( aName == SdDrawPage::getPageApiName( pPage ) )
{
uno::Any aAny;
uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
aAny <<= xDrawPage;
return aAny;
}
}
}
throw container::NoSuchElementException();
}
uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getElementNames()
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
uno::Sequence< OUString > aNames( nCount );
OUString* pNames = aNames.getArray();
sal_uInt16 nPage;
for( nPage = 0; nPage < nCount; nPage++ )
{
SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard );
*pNames++ = SdDrawPage::getPageApiName( pPage );
}
return aNames;
}
sal_Bool SAL_CALL SdDrawPagesAccess::hasByName( const OUString& aName )
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
sal_uInt16 nPage;
for( nPage = 0; nPage < nCount; nPage++ )
{
SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard );
if(nullptr == pPage)
continue;
if( aName == SdDrawPage::getPageApiName( pPage ) )
return true;
}
return false;
}
// XElementAccess
uno::Type SAL_CALL SdDrawPagesAccess::getElementType()
{
return cppu::UnoType<drawing::XDrawPage>::get();
}
sal_Bool SAL_CALL SdDrawPagesAccess::hasElements()
{
return getCount() > 0;
}
// XDrawPages
/**
* Creates a new page with model at the specified position.
* @returns corresponding SdDrawPage
*/
uno::Reference< drawing::XDrawPage > SAL_CALL SdDrawPagesAccess::insertNewByIndex( sal_Int32 nIndex )
{
::SolarMutexGuard aGuard;
comphelper::ProfileZone aZone("insertNewByIndex");
if( nullptr == mpModel )
throw lang::DisposedException();
if( mpModel->mpDoc )
{
SdPage* pPage = mpModel->InsertSdPage( static_cast<sal_uInt16>(nIndex), false );
if( pPage )
{
uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
return xDrawPage;
}
}
uno::Reference< drawing::XDrawPage > xDrawPage;
return xDrawPage;
}
/**
* Removes the specified SdDrawPage from the model and the internal list. It
* only works, if there is at least one *normal* page in the model after
* removing this page.
*/
void SAL_CALL SdDrawPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage )
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel || mpModel->mpDoc == nullptr )
throw lang::DisposedException();
SdDrawDocument& rDoc = *mpModel->mpDoc;
sal_uInt16 nPageCount = rDoc.GetSdPageCount( PageKind::Standard );
if( nPageCount > 1 )
{
// get pPage from xPage and determine the Id (nPos ) afterwards
SdDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SdDrawPage>( xPage );
if( pSvxPage )
{
SdPage* pPage = static_cast<SdPage*>(pSvxPage->GetSdrPage());
if(pPage && ( pPage->GetPageKind() == PageKind::Standard ) )
{
sal_uInt16 nPage = pPage->GetPageNum();
SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetPage( nPage+1 ) );
bool bUndo = rDoc.IsUndoEnabled();
if( bUndo )
{
// Add undo actions and delete the pages. The order of adding
// the undo actions is important.
rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) );
rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
}
rDoc.RemovePage( nPage ); // the page
rDoc.RemovePage( nPage ); // the notes page
if( bUndo )
{
rDoc.EndUndo();
}
}
}
}
mpModel->SetModified();
}
// XServiceInfo
OUString SAL_CALL SdDrawPagesAccess::getImplementationName( )
{
return u"SdDrawPagesAccess"_ustr;
}
sal_Bool SAL_CALL SdDrawPagesAccess::supportsService( const OUString& ServiceName )
{
return cppu::supportsService(this, ServiceName);
}
uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getSupportedServiceNames( )
{
return { u"com.sun.star.drawing.DrawPages"_ustr };
}
// XComponent
void SAL_CALL SdDrawPagesAccess::dispose( )
{
mpModel = nullptr;
}
void SAL_CALL SdDrawPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& )
{
OSL_FAIL( "not implemented!" );
}
void SAL_CALL SdDrawPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& )
{
OSL_FAIL( "not implemented!" );
}
SdMasterPagesAccess::SdMasterPagesAccess( SdXImpressDocument& rMyModel ) noexcept
: mpModel(&rMyModel)
{
}
SdMasterPagesAccess::~SdMasterPagesAccess() noexcept
{
}
// XComponent
void SAL_CALL SdMasterPagesAccess::dispose( )
{
mpModel = nullptr;
}
void SAL_CALL SdMasterPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& )
{
OSL_FAIL( "not implemented!" );
}
void SAL_CALL SdMasterPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& )
{
OSL_FAIL( "not implemented!" );
}
// XIndexAccess
sal_Int32 SAL_CALL SdMasterPagesAccess::getCount()
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel->mpDoc )
throw lang::DisposedException();
return mpModel->mpDoc->GetMasterSdPageCount(PageKind::Standard);
}
/**
* Provides a drawing::XDrawPage interface for accessing the Masterpage at the
* specified position in the model.
*/
uno::Any SAL_CALL SdMasterPagesAccess::getByIndex( sal_Int32 Index )
{
::SolarMutexGuard aGuard;
comphelper::ProfileZone aZone("SdMasterPagesAccess::getByIndex");
if( nullptr == mpModel )
throw lang::DisposedException();
uno::Any aAny;
if( (Index < 0) || (Index >= mpModel->mpDoc->GetMasterSdPageCount( PageKind::Standard ) ) )
throw lang::IndexOutOfBoundsException();
SdPage* pPage = mpModel->mpDoc->GetMasterSdPage( static_cast<sal_uInt16>(Index), PageKind::Standard );
if( pPage )
{
uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
aAny <<= xDrawPage;
}
return aAny;
}
// XElementAccess
uno::Type SAL_CALL SdMasterPagesAccess::getElementType()
{
return cppu::UnoType<drawing::XDrawPage>::get();
}
sal_Bool SAL_CALL SdMasterPagesAccess::hasElements()
{
return getCount() > 0;
}
// XDrawPages
uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNewByIndex( sal_Int32 nInsertPos )
{
return insertNewImpl(nInsertPos, std::nullopt);
}
// XDrawPages2
uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNamedNewByIndex( sal_Int32 nInsertPos, const OUString& sName )
{
return insertNewImpl(nInsertPos, sName);
}
uno::Reference< drawing::XDrawPage > SdMasterPagesAccess::insertNewImpl( sal_Int32 nInsertPos, std::optional<OUString> oPageName )
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
uno::Reference< drawing::XDrawPage > xDrawPage;
SdDrawDocument* pDoc = mpModel->mpDoc;
if( pDoc )
{
// calculate internal index and check for range errors
const sal_Int32 nMPageCount = pDoc->GetMasterPageCount();
nInsertPos = nInsertPos * 2 + 1;
if( nInsertPos < 0 || nInsertPos > nMPageCount )
nInsertPos = nMPageCount;
// now generate a unique name for the new masterpage
OUString aPrefix;
if (oPageName)
aPrefix = *oPageName;
else
{
const OUString aStdPrefix( SdResId(STR_LAYOUT_DEFAULT_NAME) );
aPrefix = aStdPrefix;
bool bUnique = true;
std::vector<OUString> aPageNames;
for (sal_Int32 nMaster = 1; nMaster < nMPageCount; ++nMaster)
{
const SdPage* pPage = static_cast<const SdPage*>(pDoc->GetMasterPage(static_cast<sal_uInt16>(nMaster)));
if (!pPage)
continue;
aPageNames.push_back(pPage->GetName());
if (aPageNames.back() == aPrefix)
bUnique = false;
}
sal_Int32 i = 0;
while (!bUnique)
{
aPrefix = aStdPrefix + " " + OUString::number(++i);
bUnique = std::find(aPageNames.begin(), aPageNames.end(), aPrefix) == aPageNames.end();
}
}
OUString aLayoutName = aPrefix + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE;
// create styles
static_cast<SdStyleSheetPool*>(pDoc->GetStyleSheetPool())->CreateLayoutStyleSheets( aPrefix );
// get the first page for initial size and border settings
SdPage* pPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Standard );
SdPage* pRefNotesPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Notes);
// create and insert new draw masterpage
rtl::Reference<SdPage> pMPage = mpModel->mpDoc->AllocSdPage(true);
pMPage->SetSize( pPage->GetSize() );
pMPage->SetBorder( pPage->GetLeftBorder(),
pPage->GetUpperBorder(),
pPage->GetRightBorder(),
pPage->GetLowerBorder() );
if (oPageName)
// no need to update the page URLs on a brand new page
pMPage->SetName(*oPageName, /*bUpdatePageRelativeURLs*/false);
pMPage->SetLayoutName( aLayoutName );
pDoc->InsertMasterPage(pMPage.get(), static_cast<sal_uInt16>(nInsertPos));
{
// ensure default MasterPage fill
pMPage->EnsureMasterPageDefaultBackground();
}
xDrawPage.set( pMPage->getUnoPage(), uno::UNO_QUERY );
// create and insert new notes masterpage
rtl::Reference<SdPage> pMNotesPage = mpModel->mpDoc->AllocSdPage(true);
pMNotesPage->SetSize( pRefNotesPage->GetSize() );
pMNotesPage->SetPageKind(PageKind::Notes);
pMNotesPage->SetBorder( pRefNotesPage->GetLeftBorder(),
pRefNotesPage->GetUpperBorder(),
pRefNotesPage->GetRightBorder(),
pRefNotesPage->GetLowerBorder() );
pMNotesPage->SetLayoutName( aLayoutName );
pDoc->InsertMasterPage(pMNotesPage.get(), static_cast<sal_uInt16>(nInsertPos) + 1);
pMNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
mpModel->SetModified();
}
return xDrawPage;
}
/**
* Removes the specified SdMasterPage from the model and the internal list. It
* only works, if there is no *normal* page using this page as MasterPage in
* the model.
*/
void SAL_CALL SdMasterPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage )
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel || mpModel->mpDoc == nullptr )
throw lang::DisposedException();
SdMasterPage* pSdPage = comphelper::getFromUnoTunnel<SdMasterPage>( xPage );
if(pSdPage == nullptr)
return;
SdPage* pPage = dynamic_cast< SdPage* > (pSdPage->GetSdrPage());
DBG_ASSERT( pPage && pPage->IsMasterPage(), "SdMasterPage is not masterpage?");
if( !pPage || !pPage->IsMasterPage() || (mpModel->mpDoc->GetMasterPageUserCount(pPage) > 0))
return; //Todo: this should be excepted
// only standard pages can be removed directly
if( pPage->GetPageKind() != PageKind::Standard )
return;
sal_uInt16 nPage = pPage->GetPageNum();
SdDrawDocument& rDoc = *mpModel->mpDoc;
SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetMasterPage( nPage+1 ) );
bool bUndo = rDoc.IsUndoEnabled();
if( bUndo )
{
// Add undo actions and delete the pages. The order of adding
// the undo actions is important.
rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) );
rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
}
// remove both pages
rDoc.RemoveMasterPage( nPage );
rDoc.RemoveMasterPage( nPage );
if( bUndo )
{
rDoc.EndUndo();
}
}
// XServiceInfo
OUString SAL_CALL SdMasterPagesAccess::getImplementationName( )
{
return u"SdMasterPagesAccess"_ustr;
}
sal_Bool SAL_CALL SdMasterPagesAccess::supportsService( const OUString& ServiceName )
{
return cppu::supportsService(this, ServiceName);
}
uno::Sequence< OUString > SAL_CALL SdMasterPagesAccess::getSupportedServiceNames( )
{
return { u"com.sun.star.drawing.MasterPages"_ustr };
}
SdDocLinkTargets::SdDocLinkTargets(SdXImpressDocument& rMyModel)
: mpModel(&rMyModel)
{
for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++)
aNames[i] = SdResId(aTypeResIds[i]);
}
SdDocLinkTargets::~SdDocLinkTargets() noexcept
{
}
// XComponent
void SAL_CALL SdDocLinkTargets::dispose( )
{
mpModel = nullptr;
}
void SAL_CALL SdDocLinkTargets::addEventListener( const uno::Reference< lang::XEventListener >& )
{
OSL_FAIL( "not implemented!" );
}
void SAL_CALL SdDocLinkTargets::removeEventListener( const uno::Reference< lang::XEventListener >& )
{
OSL_FAIL( "not implemented!" );
}
// XNameAccess
uno::Any SAL_CALL SdDocLinkTargets::getByName( const OUString& aName )
{
if (mpModel)
{
for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++)
if ( aNames[i] == aName )
return uno::Any(uno::Reference< beans::XPropertySet >(new SdDocLinkTargetType( mpModel, i )));
}
throw container::NoSuchElementException();
}
uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getElementNames()
{
uno::Sequence<OUString> aRet(SdLinkTargetType::Count);
OUString* pArray = aRet.getArray();
for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++)
pArray[i] = aNames[i];
return aRet;
}
sal_Bool SAL_CALL SdDocLinkTargets::hasByName( const OUString& aName )
{
for (const auto & i : aNames)
if ( i == aName )
return true;
return false;
}
// container::XElementAccess
uno::Type SAL_CALL SdDocLinkTargets::getElementType()
{
return cppu::UnoType<beans::XPropertySet>::get();
}
sal_Bool SAL_CALL SdDocLinkTargets::hasElements()
{
return true;
}
SdPage* SdDocLinkTarget::FindPage( std::u16string_view rName ) const
{
SdDrawDocument* pDoc = mpModel->GetDoc();
if( pDoc == nullptr )
return nullptr;
const sal_uInt16 nMaxPages = pDoc->GetPageCount();
const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount();
sal_uInt16 nPage;
SdPage* pPage;
const bool bDraw = pDoc->GetDocumentType() == DocumentType::Draw;
// standard pages
for( nPage = 0; nPage < nMaxPages; nPage++ )
{
pPage = static_cast<SdPage*>(pDoc->GetPage( nPage ));
if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) )
return pPage;
}
// master pages
for( nPage = 0; nPage < nMaxMasterPages; nPage++ )
{
pPage = static_cast<SdPage*>(pDoc->GetMasterPage( nPage ));
if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) )
return pPage;
}
return nullptr;
}
// XServiceInfo
OUString SAL_CALL SdDocLinkTargets::getImplementationName()
{
return u"SdDocLinkTargets"_ustr;
}
sal_Bool SAL_CALL SdDocLinkTargets::supportsService( const OUString& ServiceName )
{
return cppu::supportsService( this, ServiceName );
}
uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getSupportedServiceNames()
{
return { u"com.sun.star.document.LinkTargets"_ustr };
}
SdDocLinkTargetType::SdDocLinkTargetType(SdXImpressDocument* pModel, sal_uInt16 nT)
: mpModel(pModel)
, mnType(nT)
{
maName = SdResId(aTypeResIds[nT]);
}
// beans::XPropertySet
uno::Reference< beans::XPropertySetInfo > SAL_CALL SdDocLinkTargetType::getPropertySetInfo()
{
static uno::Reference< beans::XPropertySetInfo > aRef;//(new SfxItemPropertySetInfo( lcl_GetLinkTargetMap() ));
return aRef;
}
void SAL_CALL SdDocLinkTargetType::setPropertyValue(const OUString& /* aPropertyName */,
const uno::Any& /* aValue */)
{
// everything is read-only
}
uno::Any SAL_CALL SdDocLinkTargetType::getPropertyValue(const OUString& PropertyName)
{
uno::Any aRet;
if ( PropertyName == "LinkDisplayName" )
aRet <<= maName;
return aRet;
}
void SAL_CALL SdDocLinkTargetType::addPropertyChangeListener( const OUString&,
const uno::Reference<beans::XPropertyChangeListener>&)
{ OSL_FAIL("not implemented"); }
void SAL_CALL SdDocLinkTargetType::removePropertyChangeListener( const OUString&,
const uno::Reference<beans::XPropertyChangeListener>&)
{ OSL_FAIL("not implemented"); }
void SAL_CALL SdDocLinkTargetType::addVetoableChangeListener( const OUString&,
const uno::Reference<beans::XVetoableChangeListener>&)
{ OSL_FAIL("not implemented"); }
void SAL_CALL SdDocLinkTargetType::removeVetoableChangeListener( const OUString&,
const uno::Reference<beans::XVetoableChangeListener>&)
{ OSL_FAIL("not implemented"); }
// document::XLinkTargetSupplier
uno::Reference< container::XNameAccess > SAL_CALL SdDocLinkTargetType::getLinks()
{
return new SdDocLinkTarget( mpModel, mnType );
}
// XServiceInfo
OUString SAL_CALL SdDocLinkTargetType::getImplementationName()
{
return u"SdDocLinkTargetType"_ustr;
}
sal_Bool SAL_CALL SdDocLinkTargetType::supportsService( const OUString& ServiceName )
{
return cppu::supportsService( this, ServiceName );
}
uno::Sequence< OUString > SAL_CALL SdDocLinkTargetType::getSupportedServiceNames()
{
return { u"com.sun.star.document.LinkTargetSupplier"_ustr };
}
SdDocLinkTarget::SdDocLinkTarget( SdXImpressDocument* pModel, sal_uInt16 nT )
: mpModel(pModel)
, mnType(nT)
{
}
// container::XNameAccess
uno::Any SAL_CALL SdDocLinkTarget::getByName(const OUString& aName)
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
SdPage* pPage = FindPage( aName );
if( pPage == nullptr )
throw container::NoSuchElementException();
uno::Any aAny;
uno::Reference< beans::XPropertySet > xProps( pPage->getUnoPage(), uno::UNO_QUERY );
if( xProps.is() )
aAny <<= xProps;
return aAny;
}
uno::Sequence<OUString> SAL_CALL SdDocLinkTarget::getElementNames()
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
SdDrawDocument* pDoc = mpModel->GetDoc();
if( pDoc == nullptr )
{
return { };
}
if( pDoc->GetDocumentType() == DocumentType::Draw )
{
const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( PageKind::Standard );
const sal_uInt16 nMaxMasterPages = pDoc->GetMasterSdPageCount( PageKind::Standard );
uno::Sequence< OUString > aSeq( mnType == SdLinkTargetType::Page ? nMaxPages : nMaxMasterPages );
OUString* pStr = aSeq.getArray();
sal_uInt16 nPage;
if (mnType == SdLinkTargetType::Page)
{
// standard pages
for( nPage = 0; nPage < nMaxPages; nPage++ )
*pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName();
}
else
{
// master pages
for( nPage = 0; nPage < nMaxMasterPages; nPage++ )
*pStr++ = pDoc->GetMasterSdPage( nPage, PageKind::Standard )->GetName();
}
return aSeq;
}
else
{
PageKind eKind;
switch (mnType)
{
case SdLinkTargetType::Notes:
eKind = PageKind::Notes;
break;
case SdLinkTargetType::Handout:
eKind = PageKind::Handout;
break;
default:
eKind = PageKind::Standard;
break;
}
const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( eKind );
const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount();
uno::Sequence< OUString > aSeq( mnType == SdLinkTargetType::MasterPage ? nMaxMasterPages : nMaxPages );
OUString* pStr = aSeq.getArray();
sal_uInt16 nPage;
switch (mnType)
{
case SdLinkTargetType::Page:
{
for( nPage = 0; nPage < nMaxPages; nPage++ )
*pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName();
break;
}
case SdLinkTargetType::Notes:
{
for( nPage = 0; nPage < nMaxPages; nPage++ )
*pStr++ = pDoc->GetSdPage( nPage, PageKind::Notes )->GetName();
break;
}
case SdLinkTargetType::Handout:
{
for( nPage = 0; nPage < nMaxPages; nPage++ )
*pStr++ = pDoc->GetSdPage( nPage, PageKind::Handout )->GetName();
break;
}
case SdLinkTargetType::MasterPage:
{
for( nPage = 0; nPage < nMaxMasterPages; nPage++ )
*pStr++ = static_cast<SdPage*>(pDoc->GetMasterPage( nPage ))->GetName();
break;
}
}
return aSeq;
}
}
sal_Bool SAL_CALL SdDocLinkTarget::hasByName(const OUString& aName)
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
return FindPage( aName ) != nullptr;
}
// container::XElementAccess
uno::Type SAL_CALL SdDocLinkTarget::getElementType()
{
return cppu::UnoType<beans::XPropertySet>::get();
}
sal_Bool SAL_CALL SdDocLinkTarget::hasElements()
{
::SolarMutexGuard aGuard;
if( nullptr == mpModel )
throw lang::DisposedException();
return mpModel->GetDoc() != nullptr;
}
// XServiceInfo
OUString SAL_CALL SdDocLinkTarget::getImplementationName()
{
return u"SdDocLinkTarget"_ustr;
}
sal_Bool SAL_CALL SdDocLinkTarget::supportsService( const OUString& ServiceName )
{
return cppu::supportsService( this, ServiceName );
}
uno::Sequence< OUString > SAL_CALL SdDocLinkTarget::getSupportedServiceNames()
{
return { u"com.sun.star.document.LinkTargets"_ustr };
}
rtl::Reference< SdXImpressDocument > SdXImpressDocument::GetModel( SdDrawDocument const & rDocument )
{
rtl::Reference< SdXImpressDocument > xRet;
::sd::DrawDocShell* pDocShell(rDocument.GetDocSh());
if( pDocShell )
{
uno::Reference<frame::XModel> xModel(pDocShell->GetModel());
xRet.set( dynamic_cast< SdXImpressDocument* >( xModel.get() ) );
}
return xRet;
}
void NotifyDocumentEvent(SdDrawDocument const & rDocument, const OUString& rEventName)
{
rtl::Reference<SdXImpressDocument> xModel(SdXImpressDocument::GetModel(rDocument));
if (xModel.is())
{
uno::Reference<uno::XInterface> xSource(static_cast<uno::XWeak*>(xModel.get()));
NotifyDocumentEvent(rDocument, rEventName, xSource);
}
}
void NotifyDocumentEvent(SdDrawDocument const & rDocument, const OUString& rEventName, const uno::Reference<uno::XInterface>& xSource)
{
rtl::Reference<SdXImpressDocument> xModel(SdXImpressDocument::GetModel(rDocument));
if (xModel.is())
{
css::document::EventObject aEvent(xSource, rEventName);
xModel->notifyEvent(aEvent);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V547 Expression 'nTransitionType != 0' is always false.
↑ V614 Uninitialized variable 'nFillColor' used.
↑ V614 Uninitialized variable 'aFillStyle' used.
↑ V547 Expression 'bExportNotesPages' is always false.
↑ V547 Expression 'bExportNotesPages' is always false.
↑ V547 Expression 'bIsVisible' is always true.
↑ V547 Expression 'bBackgroundVisibility' is always true.
↑ V572 It is odd that the object which was created using 'new' operator is immediately cast to another type.
↑ V1019 Compound assignment expression 'aTemp >>= nTemp' is used inside condition.
↑ V1019 Compound assignment expression 'Arguments[0] >>= arg' is used inside condition.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'nType' variable was assigned the same value.
↑ V1048 The 'aNote.meType' variable was assigned the same value.
↑ V1048 The 'nTime' variable was assigned the same value.