tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sd / source / ui / unoidl / unomodel.cxx
blobaf23f62fddfd7c928e56f6c06e28d01e58cadce6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
22 #include <com/sun/star/presentation/XPresentation2.hpp>
24 #include <com/sun/star/drawing/FillStyle.hpp>
25 #include <com/sun/star/drawing/LineStyle.hpp>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
29 #include <com/sun/star/lang/Locale.hpp>
30 #include <com/sun/star/awt/XDevice.hpp>
31 #include <com/sun/star/document/IndexedPropertyValues.hpp>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/util/XTheme.hpp>
34 #include <com/sun/star/animations/AnimationFill.hpp>
35 #include <com/sun/star/animations/AnimationRestart.hpp>
36 #include <com/sun/star/animations/AnimationEndSync.hpp>
37 #include <com/sun/star/animations/AnimationCalcMode.hpp>
38 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
39 #include <com/sun/star/animations/AnimationNodeType.hpp>
40 #include <com/sun/star/animations/AnimationTransformType.hpp>
41 #include <com/sun/star/animations/AnimationColorSpace.hpp>
42 #include <com/sun/star/animations/Event.hpp>
43 #include <com/sun/star/animations/EventTrigger.hpp>
44 #include <com/sun/star/animations/Timing.hpp>
45 #include <com/sun/star/animations/TransitionType.hpp>
46 #include <com/sun/star/animations/TransitionSubType.hpp>
47 #include <com/sun/star/animations/ValuePair.hpp>
48 #include <com/sun/star/animations/XAnimate.hpp>
49 #include <com/sun/star/animations/XAnimateMotion.hpp>
50 #include <com/sun/star/animations/XAnimateColor.hpp>
51 #include <com/sun/star/animations/XAnimateTransform.hpp>
52 #include <com/sun/star/animations/XIterateContainer.hpp>
53 #include <com/sun/star/animations/XTimeContainer.hpp>
54 #include <com/sun/star/animations/XTransitionFilter.hpp>
55 #include <com/sun/star/presentation/EffectNodeType.hpp>
56 #include <com/sun/star/presentation/EffectPresetClass.hpp>
57 #include <com/sun/star/presentation/ParagraphTarget.hpp>
58 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
59 #include <com/sun/star/presentation/TextAnimationType.hpp>
62 #include <com/sun/star/embed/Aspects.hpp>
64 #include <animations/animationnodehelper.hxx>
66 #include <officecfg/Office/Common.hxx>
67 #include <officecfg/Office/Impress.hxx>
68 #include <comphelper/dispatchcommand.hxx>
69 #include <comphelper/indexedpropertyvalues.hxx>
70 #include <comphelper/lok.hxx>
71 #include <comphelper/propertysequence.hxx>
72 #include <comphelper/propertyvalue.hxx>
73 #include <comphelper/sequence.hxx>
74 #include <comphelper/servicehelper.hxx>
75 #include <cppuhelper/supportsservice.hxx>
76 #include <comphelper/processfactory.hxx>
77 #include <comphelper/profilezone.hxx>
79 #include <sal/log.hxx>
80 #include <editeng/unofield.hxx>
81 #include <notifydocumentevent.hxx>
82 #include <tpaction.hxx>
83 #include <unomodel.hxx>
84 #include "unopool.hxx"
85 #include <sfx2/lokhelper.hxx>
86 #include <sfx2/dispatch.hxx>
87 #include <vcl/svapp.hxx>
88 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
90 #include <editeng/UnoForbiddenCharsTable.hxx>
91 #include <svx/svdoutl.hxx>
92 #include <o3tl/any.hxx>
93 #include <o3tl/safeint.hxx>
94 #include <o3tl/string_view.hxx>
95 #include <o3tl/test_info.hxx>
96 #include <o3tl/unit_conversion.hxx>
97 #include <svx/UnoNamespaceMap.hxx>
98 #include <svx/svdlayer.hxx>
99 #include <svx/svdsob.hxx>
100 #include <svx/svdundo.hxx>
101 #include <svx/svdomedia.hxx>
102 #include <svx/unoapi.hxx>
103 #include <svx/unofill.hxx>
104 #include <svx/sdrpagewindow.hxx>
105 #include <svx/sdrpaintwindow.hxx>
106 #include <editeng/fontitem.hxx>
107 #include <toolkit/awt/vclxdevice.hxx>
108 #include <svx/svdpool.hxx>
109 #include <svx/svdpagv.hxx>
110 #include <svtools/unoimap.hxx>
111 #include <svx/unoshape.hxx>
112 #include <editeng/unonrule.hxx>
113 #include <editeng/eeitem.hxx>
114 #include <unotools/datetime.hxx>
115 #include <sax/tools/converter.hxx>
116 #include <xmloff/autolayout.hxx>
117 #include <xmloff/xmltoken.hxx>
118 #include <rtl/math.hxx>
119 #include <tools/helpers.hxx>
120 #include <tools/json_writer.hxx>
122 // Support creation of GraphicStorageHandler and EmbeddedObjectResolver
123 #include <svx/xmleohlp.hxx>
124 #include <svx/xmlgrhlp.hxx>
125 #include <DrawDocShell.hxx>
126 #include <ViewShellBase.hxx>
127 #include "UnoDocumentSettings.hxx"
129 #include <Annotation.hxx>
130 #include <drawdoc.hxx>
131 #include <sdmod.hxx>
132 #include <sdresid.hxx>
133 #include <sdpage.hxx>
135 #include <strings.hrc>
136 #include <strings.hxx>
137 #include "unolayer.hxx"
138 #include <unopage.hxx>
139 #include "unocpres.hxx"
140 #include "unoobj.hxx"
141 #include <stlpool.hxx>
142 #include "unopback.hxx"
143 #include <unokywds.hxx>
145 #include <FrameView.hxx>
146 #include <ClientView.hxx>
147 #include <DrawViewShell.hxx>
148 #include <ViewShell.hxx>
149 #include <Window.hxx>
150 #include <optsitem.hxx>
151 #include <SlideshowLayerRenderer.hxx>
153 #include <vcl/pdfextoutdevdata.hxx>
154 #include <vcl/pdf/PDFNote.hxx>
156 #include <com/sun/star/presentation/AnimationSpeed.hpp>
157 #include <com/sun/star/presentation/ClickAction.hpp>
158 #include <svx/sdr/contact/viewobjectcontact.hxx>
159 #include <svx/sdr/contact/viewcontact.hxx>
160 #include <svx/sdr/contact/displayinfo.hxx>
162 #include <com/sun/star/office/XAnnotation.hpp>
163 #include <com/sun/star/office/XAnnotationAccess.hpp>
164 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
165 #include <com/sun/star/geometry/RealPoint2D.hpp>
166 #include <com/sun/star/util/DateTime.hpp>
168 #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
170 #include <sfx2/lokcomponenthelpers.hxx>
171 #include <sfx2/LokControlHandler.hxx>
172 #include <tools/gen.hxx>
173 #include <tools/debug.hxx>
174 #include <tools/urlobj.hxx>
175 #include <comphelper/diagnose_ex.hxx>
176 #include <tools/UnitConversion.hxx>
177 #include <svx/ColorSets.hxx>
178 #include <docmodel/theme/Theme.hxx>
180 #include <frozen/bits/defines.h>
181 #include <frozen/bits/elsa_std.h>
182 #include <frozen/unordered_map.h>
184 #include <app.hrc>
186 using namespace ::cppu;
187 using namespace ::com::sun::star;
188 using namespace ::sd;
190 const TranslateId aTypeResIds[SdLinkTargetType::Count] =
192 STR_SD_PAGE, // SdLinkTargetType::Page
193 STR_NOTES_MODE, // SdLinkTargetType::Notes
194 STR_HANDOUT, // SdLinkTargetType::Handout
195 STR_MASTERPAGE_NAME, // SdLinkTargetType::MasterPage
198 TranslateId SdTPAction::GetClickActionSdResId( presentation::ClickAction eCA )
200 switch( eCA )
202 case presentation::ClickAction_NONE: return STR_CLICK_ACTION_NONE;
203 case presentation::ClickAction_PREVPAGE: return STR_CLICK_ACTION_PREVPAGE;
204 case presentation::ClickAction_NEXTPAGE: return STR_CLICK_ACTION_NEXTPAGE;
205 case presentation::ClickAction_FIRSTPAGE: return STR_CLICK_ACTION_FIRSTPAGE;
206 case presentation::ClickAction_LASTPAGE: return STR_CLICK_ACTION_LASTPAGE;
207 case presentation::ClickAction_BOOKMARK: return STR_CLICK_ACTION_BOOKMARK;
208 case presentation::ClickAction_DOCUMENT: return STR_CLICK_ACTION_DOCUMENT;
209 case presentation::ClickAction_PROGRAM: return STR_CLICK_ACTION_PROGRAM;
210 case presentation::ClickAction_MACRO: return STR_CLICK_ACTION_MACRO;
211 case presentation::ClickAction_SOUND: return STR_CLICK_ACTION_SOUND;
212 case presentation::ClickAction_VERB: return STR_CLICK_ACTION_VERB;
213 case presentation::ClickAction_STOPPRESENTATION: return STR_CLICK_ACTION_STOPPRESENTATION;
214 default: OSL_FAIL( "No StringResource for ClickAction available!" );
216 return {};
219 class SdUnoForbiddenCharsTable : public SvxUnoForbiddenCharsTable,
220 public SfxListener
222 public:
223 explicit SdUnoForbiddenCharsTable(SdrModel* pModel);
224 virtual ~SdUnoForbiddenCharsTable() override;
226 // SfxListener
227 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override;
228 protected:
229 virtual void onChange() override;
231 private:
232 SdrModel* mpModel;
235 namespace {
237 class SlideBackgroundInfo
239 public:
240 SlideBackgroundInfo(const uno::Reference<drawing::XDrawPage>& xDrawPage,
241 const uno::Reference<drawing::XDrawPage>& xMasterPage);
242 bool slideHasOwnBackground() const { return mbIsCustom; }
243 bool hasBackground() const { return bHasBackground; }
244 bool isSolidColor() const { return mbIsSolidColor; }
245 ::Color getFillColor() const;
246 sal_Int32 getFillTransparency() const;
247 OString getFillColorAsRGBA() const;
248 private:
249 bool getFillStyleImpl(const uno::Reference<drawing::XDrawPage>& xDrawPage);
250 private:
251 uno::Reference<beans::XPropertySet> mxBackground;
252 bool mbIsCustom;
253 bool bHasBackground;
254 bool mbIsSolidColor;
255 drawing::FillStyle maFillStyle;
258 SlideBackgroundInfo::SlideBackgroundInfo(
259 const uno::Reference<drawing::XDrawPage>& xDrawPage,
260 const uno::Reference<drawing::XDrawPage>& xMasterPage)
261 : mbIsCustom(false)
262 , bHasBackground(false)
263 , mbIsSolidColor(false)
264 , maFillStyle(drawing::FillStyle_NONE)
266 mbIsCustom = getFillStyleImpl(xDrawPage);
267 bHasBackground = mbIsCustom;
268 if (!bHasBackground)
270 bHasBackground = getFillStyleImpl(xMasterPage);
272 if (bHasBackground)
274 if (maFillStyle == drawing::FillStyle_SOLID)
276 OUString sGradientName;
277 mxBackground->getPropertyValue("FillTransparenceGradientName") >>= sGradientName;
278 if (sGradientName.isEmpty())
280 mbIsSolidColor = true;
286 sal_Int32 SlideBackgroundInfo::getFillTransparency() const
288 if (!mxBackground.is())
289 return 0;
290 sal_Int32 nFillTransparency = 0;
291 mxBackground->getPropertyValue("FillTransparence") >>= nFillTransparency;
292 return nFillTransparency;
295 ::Color SlideBackgroundInfo::getFillColor() const
297 if (!mxBackground.is())
298 return {};
299 if (sal_Int32 nFillColor; mxBackground->getPropertyValue("FillColor") >>= nFillColor)
301 return ::Color(ColorTransparency, nFillColor & 0xffffff);
303 return {};
306 OString SlideBackgroundInfo::getFillColorAsRGBA() const
308 ::Color aColor = getFillColor();
309 OString sColor = aColor.AsRGBHEXString().toUtf8();
310 sal_uInt32 nAlpha = std::round((100 - getFillTransparency()) * 255 / 100.0);
311 std::stringstream ss;
312 ss << std::hex << std::uppercase << std::setfill ('0') << std::setw(2) << nAlpha;
313 sColor += ss.str().c_str();
314 return sColor;
317 bool SlideBackgroundInfo::getFillStyleImpl(const uno::Reference<drawing::XDrawPage>& xDrawPage)
319 if( xDrawPage.is() )
321 uno::Reference< beans::XPropertySet > xPropSet( xDrawPage, uno::UNO_QUERY );
322 if( xPropSet.is() )
324 uno::Reference< beans::XPropertySet > xBackground;
325 if (xPropSet->getPropertySetInfo()->hasPropertyByName("Background"))
326 xPropSet->getPropertyValue( "Background" ) >>= xBackground;
327 if( xBackground.is() )
329 drawing::FillStyle aFillStyle;
330 if( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle )
332 maFillStyle = aFillStyle;
333 if (aFillStyle != drawing::FillStyle_NONE)
335 mxBackground = std::move(xBackground);
336 return true;
342 return false;
345 using namespace ::css::animations;
346 using namespace ::css::beans;
347 using namespace ::css::container;
348 using namespace ::css::uno;
349 using namespace ::xmloff::token;
350 using namespace ::css::presentation;
352 template <typename T, std::size_t N>
353 constexpr auto mapEnumToString(std::pair<T, std::string_view> const (&items)[N])
355 return frozen::make_unordered_map<T, std::string_view, N>(items);
358 constexpr auto constTransitionTypeToString = mapEnumToString<sal_Int16>({
359 { animations::TransitionType::BARWIPE, "BarWipe" }, // Wipe
360 { animations::TransitionType::PINWHEELWIPE, "PineWheelWipe" }, // Wheel
361 { animations::TransitionType::SLIDEWIPE, "SlideWipe" }, // Cover, Uncover
362 { animations::TransitionType::RANDOMBARWIPE, "RandomBarWipe" }, // Bars
363 { animations::TransitionType::CHECKERBOARDWIPE, "CheckerBoardWipe" }, // Checkers
364 { animations::TransitionType::FOURBOXWIPE, "FourBoxWipe" }, // Shape
365 { animations::TransitionType::IRISWIPE, "IrisWipe" }, // Box
366 { animations::TransitionType::FANWIPE, "FanWipe" }, // Wedge
367 { animations::TransitionType::BLINDSWIPE, "BlindWipe"}, // Venetian
368 { animations::TransitionType::FADE, "Fade"},
369 { animations::TransitionType::DISSOLVE, "Dissolve"},
370 { animations::TransitionType::PUSHWIPE, "PushWipe"}, // Comb
371 { animations::TransitionType::ELLIPSEWIPE, "EllipseWipe"}, // Shape
372 { animations::TransitionType::BARNDOORWIPE, "BarnDoorWipe"}, // Split
373 { animations::TransitionType::WATERFALLWIPE, "WaterfallWipe"}, // Diagonal
374 { animations::TransitionType::MISCSHAPEWIPE, "MiscShapeWipe"},
375 { animations::TransitionType::ZOOM, "Zoom"}
378 constexpr auto constTransitionSubTypeToString = mapEnumToString<sal_Int16>({
379 { animations::TransitionSubType::LEFTTORIGHT, "LeftToRight" },
380 { animations::TransitionSubType::TOPTOBOTTOM, "TopToBottom" },
381 { animations::TransitionSubType::EIGHTBLADE, "8Blade" },
382 { animations::TransitionSubType::FOURBLADE, "4Blade" },
383 { animations::TransitionSubType::THREEBLADE, "3Blade" },
384 { animations::TransitionSubType::TWOBLADEVERTICAL, "2BladeVertical" },
385 { animations::TransitionSubType::ONEBLADE, "1Blade" },
386 { animations::TransitionSubType::FROMTOPLEFT, "FromTopLeft" },
387 { animations::TransitionSubType::FROMTOPRIGHT, "FromTopRight"},
388 { animations::TransitionSubType::FROMBOTTOMLEFT, "FromBottomLeft"},
389 { animations::TransitionSubType::FROMBOTTOMRIGHT, "FromBottomRight"},
390 { animations::TransitionSubType::VERTICAL, "Vertical"},
391 { animations::TransitionSubType::HORIZONTAL, "Horizontal"},
392 { animations::TransitionSubType::DOWN, "Down"},
393 { animations::TransitionSubType::ACROSS, "Across"},
394 { animations::TransitionSubType::CORNERSOUT, "CornersOut"},
395 { animations::TransitionSubType::DIAMOND, "Diamond"},
396 { animations::TransitionSubType::CIRCLE, "Circle"},
397 { animations::TransitionSubType::RECTANGLE, "Rectangle"},
398 { animations::TransitionSubType::CENTERTOP, "CenterTop"},
399 { animations::TransitionSubType::CROSSFADE, "CrossFade"},
400 { animations::TransitionSubType::FADEOVERCOLOR, "FadeOverColor"},
401 { animations::TransitionSubType::FROMLEFT, "FromLeft"},
402 { animations::TransitionSubType::FROMRIGHT, "FromRight"},
403 { animations::TransitionSubType::FROMTOP, "FromTop"},
404 { animations::TransitionSubType::HORIZONTALLEFT, "HorizontalLeft"},
405 { animations::TransitionSubType::HORIZONTALRIGHT, "HorizontalRight"},
406 { animations::TransitionSubType::COMBVERTICAL, "CombVertical"},
407 { animations::TransitionSubType::COMBHORIZONTAL, "CombHorizontal"},
408 { animations::TransitionSubType::TOPLEFT, "TopLeft"},
409 { animations::TransitionSubType::TOPRIGHT, "TopRight"},
410 { animations::TransitionSubType::BOTTOMRIGHT, "BottomRight"},
411 { animations::TransitionSubType::BOTTOMLEFT, "BottomLeft"},
412 { animations::TransitionSubType::TOPCENTER, "TopCenter"},
413 { animations::TransitionSubType::RIGHTCENTER, "RightCenter"},
414 { animations::TransitionSubType::BOTTOMCENTER, "BottomCenter"},
415 { animations::TransitionSubType::FANOUTHORIZONTAL, "FanOutHorizontal"},
416 { animations::TransitionSubType::CORNERSIN, "CornersIn"},
417 { animations::TransitionSubType::HEART, "Heart"},
418 { animations::TransitionSubType::ROTATEIN, "RotateIn"}
421 constexpr auto constAnimationNodeTypeToString = mapEnumToString<sal_Int16>({
422 { AnimationNodeType::ANIMATE, "Animate" },
423 { AnimationNodeType::ANIMATECOLOR, "AnimateColor" },
424 { AnimationNodeType::ANIMATEMOTION, "Animate" },
425 { AnimationNodeType::ANIMATEPHYSICS, "Animate" },
426 { AnimationNodeType::ANIMATETRANSFORM, "AnimateTransform" },
427 { AnimationNodeType::AUDIO, "Audio" },
428 { AnimationNodeType::COMMAND, "Command" },
429 { AnimationNodeType::CUSTOM, "Custom" },
430 { AnimationNodeType::ITERATE, "Iterate" },
431 { AnimationNodeType::PAR, "Par" },
432 { AnimationNodeType::SEQ, "Seq" },
433 { AnimationNodeType::SET, "Set" },
434 { AnimationNodeType::TRANSITIONFILTER, "TransitionFilter" },
437 constexpr auto constFillToString = mapEnumToString<sal_Int16>({
438 { AnimationFill::DEFAULT, "Default" },
439 { AnimationFill::REMOVE, "Remove" },
440 { AnimationFill::FREEZE, "Freeze" },
441 { AnimationFill::HOLD, "Hold" },
442 { AnimationFill::TRANSITION, "Transition" },
443 { AnimationFill::AUTO, "Auto" },
446 constexpr auto constRestartToString = mapEnumToString<sal_Int16>({
447 { AnimationRestart::DEFAULT, "Default" },
448 { AnimationRestart::ALWAYS, "Always" },
449 { AnimationRestart::WHEN_NOT_ACTIVE, "WhenNotActive" },
450 { AnimationRestart::NEVER, "Never" },
453 constexpr auto constEndSyncToString = mapEnumToString<sal_Int16>({
454 { AnimationEndSync::FIRST, "First" },
455 { AnimationEndSync::LAST, "Last" },
456 { AnimationEndSync::ALL, "All" },
457 { AnimationEndSync::MEDIA, "Media" },
460 constexpr auto constCalcModeToString = mapEnumToString<sal_Int16>({
461 { AnimationCalcMode::DISCRETE, "Discrete" },
462 { AnimationCalcMode::LINEAR, "Linear" },
463 { AnimationCalcMode::PACED, "Paced" },
464 { AnimationCalcMode::SPLINE, "Spline" },
467 constexpr auto constAdditiveModeToString = mapEnumToString<sal_Int16>({
468 { AnimationAdditiveMode::BASE, "Base" },
469 { AnimationAdditiveMode::SUM, "Sum" },
470 { AnimationAdditiveMode::REPLACE, "Replace" },
471 { AnimationAdditiveMode::MULTIPLY, "Multiply" },
472 { AnimationAdditiveMode::NONE, "None" },
475 constexpr auto constEffectPresetClassToString = mapEnumToString<sal_Int16>({
476 { EffectPresetClass::CUSTOM, "Custom" },
477 { EffectPresetClass::ENTRANCE, "Entrance" },
478 { EffectPresetClass::EXIT, "Exit" },
479 { EffectPresetClass::EMPHASIS, "Emphasis" },
480 { EffectPresetClass::MOTIONPATH, "MotionPath" },
481 { EffectPresetClass::OLEACTION, "OleAction" },
482 { EffectPresetClass::MEDIACALL, "MediaCall" },
485 constexpr auto constEffectNodeTypeToString = mapEnumToString<sal_Int16>({
486 { EffectNodeType::DEFAULT, "Default" },
487 { EffectNodeType::ON_CLICK, "OnClick" },
488 { EffectNodeType::WITH_PREVIOUS, "WithPrevious" },
489 { EffectNodeType::AFTER_PREVIOUS, "AfterPrevious" },
490 { EffectNodeType::MAIN_SEQUENCE, "MainSequence" },
491 { EffectNodeType::TIMING_ROOT, "TimingRoot" },
492 { EffectNodeType::INTERACTIVE_SEQUENCE, "InteractiveSequence" },
495 constexpr auto constEventTriggerToString = mapEnumToString<sal_Int16>({
496 { EventTrigger::BEGIN_EVENT, "BeginEvent" },
497 { EventTrigger::END_EVENT, "EndEvent" },
498 { EventTrigger::NONE, "None" },
499 { EventTrigger::ON_BEGIN, "OnBegin" },
500 { EventTrigger::ON_CLICK, "OnClick" },
501 { EventTrigger::ON_DBL_CLICK, "OnDblClick" },
502 { EventTrigger::ON_END, "OnEnd" },
503 { EventTrigger::ON_MOUSE_ENTER, "OnMouseEnter" },
504 { EventTrigger::ON_MOUSE_LEAVE, "OnMouseLeave" },
505 { EventTrigger::ON_NEXT, "OnNext" },
506 { EventTrigger::ON_PREV, "OnPrev" },
507 { EventTrigger::ON_STOP_AUDIO, "OnStopAudio" },
508 { EventTrigger::REPEAT, "Repeat" },
511 constexpr auto constTimingToString = mapEnumToString<Timing>({
512 { Timing_INDEFINITE, "indefinite" },
513 { Timing_MEDIA, "media" },
516 constexpr auto constTransformTypeToString = mapEnumToString<sal_Int16>({
517 { AnimationTransformType::TRANSLATE, "Translate" },
518 { AnimationTransformType::SCALE, "Scale" },
519 { AnimationTransformType::ROTATE, "Rotate" },
520 { AnimationTransformType::SKEWX, "SkewX" },
521 { AnimationTransformType::SKEWY, "SkewY" },
524 constexpr auto constSubItemToString = mapEnumToString<sal_Int16>({
525 { ShapeAnimationSubType::AS_WHOLE, "AsWhole" },
526 { ShapeAnimationSubType::ONLY_BACKGROUND, "OnlyBackground" },
527 { ShapeAnimationSubType::ONLY_TEXT, "OnlyText" },
530 constexpr auto constIterateTypeToString = mapEnumToString<sal_Int16>({
531 { TextAnimationType::BY_PARAGRAPH, "ByParagraph" },
532 { TextAnimationType::BY_WORD, "ByWord" },
533 { TextAnimationType::BY_LETTER, "ByLetter" },
536 constexpr auto constFillStyleToString = mapEnumToString<drawing::FillStyle>({
537 { drawing::FillStyle_NONE, "None" },
538 { drawing::FillStyle_SOLID, "Solid" },
539 { drawing::FillStyle_BITMAP, "Bitmap" },
540 { drawing::FillStyle_GRADIENT, "Gradient" },
541 { drawing::FillStyle_HATCH, "Hatch" },
544 constexpr auto constLineStyleToString = mapEnumToString<drawing::LineStyle>({
545 { drawing::LineStyle_NONE, "None" },
546 { drawing::LineStyle_SOLID, "Solid" },
547 { drawing::LineStyle_DASH, "Dash" },
551 constexpr auto constAttributeNameToXMLEnum
552 = frozen::make_unordered_map<std::string_view, XMLTokenEnum>({
553 { "X", XML_X },
554 { "Y", XML_Y },
555 { "Width", XML_WIDTH },
556 { "Height", XML_HEIGHT },
557 { "Rotate", XML_ROTATE },
558 { "SkewX", XML_SKEWX },
559 { "FillColor", XML_FILL_COLOR },
560 { "FillStyle", XML_FILL },
561 { "LineColor", XML_STROKE_COLOR },
562 { "LineStyle",XML_STROKE },
563 { "CharColor", XML_COLOR },
564 { "CharRotation", XML_TEXT_ROTATION_ANGLE },
565 { "CharWeight", XML_FONT_WEIGHT },
566 { "CharUnderline", XML_TEXT_UNDERLINE },
567 { "CharFontName", XML_FONT_FAMILY },
568 { "CharHeight", XML_FONT_SIZE },
569 { "CharPosture", XML_FONT_STYLE },
570 { "Visibility", XML_VISIBILITY },
571 { "Opacity", XML_OPACITY },
572 { "DimColor", XML_DIM },
575 class AnimationsExporter
577 public:
578 AnimationsExporter(::tools::JsonWriter& rWriter,
579 const Reference<drawing::XDrawPage>& xDrawPage);
580 void exportAnimations();
581 [[nodiscard]] bool hasEffects() const { return mbHasEffects; }
583 private:
584 void exportNode(const Reference<XAnimationNode>& xNode);
585 void exportNodeImpl(const Reference<XAnimationNode>& xNode);
586 void exportContainer(const Reference<XTimeContainer>& xContainer);
588 void exportAnimate(const Reference<XAnimate>& xAnimate);
590 void convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp, const Any& rValue) const;
591 void convertTiming(OStringBuffer& sTmp, const Any& rValue) const;
593 private:
594 ::tools::JsonWriter& mrWriter;
595 Reference<drawing::XDrawPage> mxDrawPage;
596 Reference<XPropertySet> mxPageProps;
597 Reference<XAnimationNode> mxRootNode;
598 bool mbHasEffects;
601 AnimationsExporter::AnimationsExporter(::tools::JsonWriter& rWriter,
602 const Reference<drawing::XDrawPage>& xDrawPage)
603 : mrWriter(rWriter)
604 , mxDrawPage(xDrawPage)
605 , mbHasEffects(false)
607 if (!mxDrawPage.is())
608 return;
612 mxPageProps = Reference<XPropertySet>(xDrawPage, UNO_QUERY);
613 if (!mxPageProps.is())
614 return;
616 Reference<XAnimationNodeSupplier> xAnimNodeSupplier(mxDrawPage, UNO_QUERY);
617 if (!xAnimNodeSupplier.is())
618 return;
620 Reference<XAnimationNode> xRootNode = xAnimNodeSupplier->getAnimationNode();
621 if (xRootNode.is())
623 // first check if there are no animations
624 Reference<XEnumerationAccess> xEnumerationAccess(xRootNode, UNO_QUERY_THROW);
625 Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(),
626 css::uno::UNO_SET_THROW);
627 if (xEnumeration->hasMoreElements())
629 // first child node may be an empty main sequence, check this
630 Reference<XAnimationNode> xMainNode(xEnumeration->nextElement(), UNO_QUERY_THROW);
631 Reference<XEnumerationAccess> xMainEnumerationAccess(xMainNode, UNO_QUERY_THROW);
632 Reference<XEnumeration> xMainEnumeration(
633 xMainEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW);
635 // only export if the main sequence is not empty or if there are additional
636 // trigger sequences
637 mbHasEffects
638 = xMainEnumeration->hasMoreElements() || xEnumeration->hasMoreElements();
641 if (mbHasEffects)
642 mxRootNode = std::move(xRootNode);
644 catch (const RuntimeException&)
646 TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
650 template <typename EnumT, size_t N>
651 constexpr bool convertEnum(OStringBuffer& rBuffer, EnumT nValue,
652 const frozen::unordered_map<EnumT, std::string_view, N>& rMap)
654 auto iterator = rMap.find(nValue);
655 if (iterator == rMap.end())
656 return false;
657 rBuffer.append(iterator->second);
658 return true;
661 void convertDouble(OStringBuffer& rBuffer, double fValue)
663 ::rtl::math::doubleToStringBuffer(rBuffer, fValue, rtl_math_StringFormat_Automatic,
664 rtl_math_DecimalPlaces_Max, '.', true);
667 void convertBool(OStringBuffer& rBuffer, bool bValue)
669 rBuffer.append( bValue );
672 void convertPath(OStringBuffer& sTmp, const Any& rPath)
674 OUString aStr;
675 rPath >>= aStr;
676 sTmp = aStr.toUtf8();
679 void convertColor(OStringBuffer& rBuffer, sal_Int32 nColor)
681 OUStringBuffer aUBuffer;
682 ::sax::Converter::convertColor(aUBuffer, nColor);
683 rBuffer.append(aUBuffer.makeStringAndClear().toUtf8());
686 void convertColor(OStringBuffer& rBuffer, const Any& rValue)
688 sal_Int32 nColor = 0;
689 if (rValue >>= nColor)
691 convertColor(rBuffer, nColor);
693 else
695 Sequence<double> aHSL;
696 if ((rValue >>= aHSL) && (aHSL.getLength() == 3))
698 rBuffer.append("hsl(" + OString::number(aHSL[0]) + ","
699 + OString::number(aHSL[1] * 100.0) + "%,"
700 + OString::number(aHSL[2] * 100.0) + "%)");
705 bool isValidNode(const Reference<XAnimationNode>& xNode)
707 if (xNode.is())
709 sal_Int16 nNodeType = xNode->getType();
710 auto iterator = constAnimationNodeTypeToString.find(nNodeType);
711 return iterator != constAnimationNodeTypeToString.end();
713 return false;
716 void AnimationsExporter::exportAnimations()
718 if (!mxDrawPage.is() || !mxPageProps.is() || !mxRootNode.is() || !hasEffects())
719 return;
721 if (isValidNode(mxRootNode))
723 auto aNode = mrWriter.startNode("root");
724 exportNodeImpl(mxRootNode);
727 void AnimationsExporter::exportNode(const Reference<XAnimationNode>& xNode)
729 if (!isValidNode(xNode))
730 return;
731 auto aStruct = mrWriter.startStruct();
732 exportNodeImpl(xNode);
735 void AnimationsExporter::exportNodeImpl(const Reference<XAnimationNode>& xNode)
739 std::string sId = GetInterfaceHash(xNode);
740 mrWriter.put("id", sId);
741 sal_Int16 nNodeType = xNode->getType();
742 auto iterator = constAnimationNodeTypeToString.find(nNodeType);
743 assert(iterator != constAnimationNodeTypeToString.end() && "must be previously checked with isValidNode");
744 mrWriter.put("nodeName", iterator->second);
746 // common properties
747 OStringBuffer sTmp;
748 Any aTemp;
749 double fTemp = 0;
750 sal_Int16 nTemp;
752 aTemp = xNode->getBegin();
753 if (aTemp.hasValue())
755 convertTiming(sTmp, aTemp);
756 mrWriter.put("begin", sTmp.makeStringAndClear());
758 aTemp = xNode->getDuration();
759 if (aTemp.hasValue())
761 if (aTemp >>= fTemp)
763 convertDouble(sTmp, fTemp);
764 sTmp.append('s');
765 mrWriter.put("dur", sTmp.makeStringAndClear());
767 else
769 Timing eTiming;
770 if (aTemp >>= eTiming)
772 mrWriter.put("dur", eTiming == Timing_INDEFINITE ? "indefinite" : "media");
776 aTemp = xNode->getEnd();
777 if (aTemp.hasValue())
779 convertTiming(sTmp, aTemp);
780 mrWriter.put("end", sTmp.makeStringAndClear());
782 nTemp = xNode->getFill();
783 if (nTemp != AnimationFill::DEFAULT)
785 convertEnum(sTmp, nTemp, constFillToString);
786 mrWriter.put("fill", sTmp.makeStringAndClear());
788 nTemp = xNode->getFillDefault();
789 if (nTemp != AnimationFill::INHERIT)
791 convertEnum(sTmp, nTemp, constFillToString);
792 mrWriter.put("fillDefault", sTmp.makeStringAndClear());
794 nTemp = xNode->getRestart();
795 if (nTemp != AnimationRestart::DEFAULT)
797 convertEnum(sTmp, nTemp, constRestartToString);
798 mrWriter.put("restart", sTmp.makeStringAndClear());
800 nTemp = xNode->getRestartDefault();
801 if (nTemp != AnimationRestart::INHERIT)
803 convertEnum(sTmp, nTemp, constRestartToString);
804 mrWriter.put("restartDefault", sTmp.makeStringAndClear());
806 fTemp = xNode->getAcceleration();
807 if (fTemp != 0.0)
809 convertDouble(sTmp, fTemp);
810 mrWriter.put("accelerate", sTmp.makeStringAndClear());
812 fTemp = xNode->getDecelerate();
813 if (fTemp != 0.0)
815 convertDouble(sTmp, fTemp);
816 mrWriter.put("decelerate", sTmp.makeStringAndClear());
818 bool bTemp = xNode->getAutoReverse();
819 if (bTemp)
821 convertBool(sTmp, bTemp);
822 mrWriter.put("autoreverse", sTmp.makeStringAndClear());
824 aTemp = xNode->getRepeatCount();
825 if (aTemp.hasValue())
827 Timing eTiming;
828 if ((aTemp >>= eTiming) && (eTiming == Timing_INDEFINITE))
830 mrWriter.put("repeatCount", "indefinite");
832 else if (aTemp >>= fTemp)
834 convertDouble(sTmp, fTemp);
835 mrWriter.put("repeatCount", sTmp.makeStringAndClear());
838 aTemp = xNode->getRepeatDuration();
839 if (aTemp.hasValue())
841 Timing eTiming;
842 if ((aTemp >>= eTiming) && (eTiming == Timing_INDEFINITE))
844 mrWriter.put("repeatDur", "indefinite");
846 else if (aTemp >>= fTemp)
848 convertDouble(sTmp, fTemp);
849 mrWriter.put("repeatDur", sTmp.makeStringAndClear());
852 aTemp = xNode->getEndSync();
853 if (aTemp.hasValue() && (aTemp >>= nTemp))
855 convertEnum(sTmp, nTemp, constEndSyncToString);
856 mrWriter.put("endSync", sTmp.makeStringAndClear());
859 sal_Int16 nContainerNodeType = EffectNodeType::DEFAULT;
860 const Sequence<NamedValue> aUserData(xNode->getUserData());
861 for (const auto& rValue : aUserData)
863 if (IsXMLToken(rValue.Name, XML_NODE_TYPE))
865 if ((rValue.Value >>= nContainerNodeType)
866 && (nContainerNodeType != EffectNodeType::DEFAULT))
868 convertEnum(sTmp, nContainerNodeType, constEffectNodeTypeToString);
869 mrWriter.put("nodeType", sTmp.makeStringAndClear());
872 else if (IsXMLToken(rValue.Name, XML_PRESET_ID))
874 OUString aPresetId;
875 if (rValue.Value >>= aPresetId)
877 mrWriter.put("presetId", aPresetId);
880 else if (IsXMLToken(rValue.Name, XML_PRESET_SUB_TYPE))
882 OUString aPresetSubType;
883 if (rValue.Value >>= aPresetSubType)
885 mrWriter.put("presetSubType", aPresetSubType);
888 else if (IsXMLToken(rValue.Name, XML_PRESET_CLASS))
890 sal_Int16 nEffectPresetClass = sal_uInt16(0);
891 if (rValue.Value >>= nEffectPresetClass)
893 convertEnum(sTmp, nEffectPresetClass, constEffectPresetClassToString);
894 mrWriter.put("presetClass", sTmp.makeStringAndClear());
897 else if (IsXMLToken(rValue.Name, XML_MASTER_ELEMENT))
899 Reference<XInterface> xMaster;
900 rValue.Value >>= xMaster;
901 if (xMaster.is())
903 const std::string aIdentifier(GetInterfaceHash(xMaster));
904 if (!aIdentifier.empty())
905 mrWriter.put("masterElement", aIdentifier);
908 else if (IsXMLToken(rValue.Name, XML_GROUP_ID))
910 sal_Int32 nGroupId = 0;
911 if (rValue.Value >>= nGroupId)
912 mrWriter.put("groupId", nGroupId);
914 else
916 OUString aTmp;
917 if (rValue.Value >>= aTmp)
918 mrWriter.put(rValue.Name, aTmp);
922 switch (nNodeType)
924 case AnimationNodeType::PAR:
925 case AnimationNodeType::SEQ:
926 case AnimationNodeType::ITERATE:
928 Reference<XTimeContainer> xContainer(xNode, UNO_QUERY_THROW);
929 exportContainer(xContainer);
931 break;
933 case AnimationNodeType::ANIMATE:
934 case AnimationNodeType::SET:
935 case AnimationNodeType::ANIMATEMOTION:
936 case AnimationNodeType::ANIMATEPHYSICS:
937 case AnimationNodeType::ANIMATECOLOR:
938 case AnimationNodeType::ANIMATETRANSFORM:
939 case AnimationNodeType::TRANSITIONFILTER:
941 Reference<XAnimate> xAnimate(xNode, UNO_QUERY_THROW);
942 exportAnimate(xAnimate);
944 break;
945 case AnimationNodeType::AUDIO:
947 SAL_WARN("sd", "AnimationsExporter::exportNode(): Audio Node not supported.");
949 break;
950 case AnimationNodeType::COMMAND:
952 SAL_WARN("sd", "AnimationsExporter::exportNode(): Command Node not supported.");
954 break;
955 default:
957 OSL_FAIL(
958 "sd unomodel: AnimationsExporter::exportNode(), invalid AnimationNodeType!");
962 catch (const RuntimeException&)
964 TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
968 void AnimationsExporter::convertTiming(OStringBuffer& sTmp, const Any& rValue) const
970 if (!rValue.hasValue())
971 return;
973 if (auto pSequence = o3tl::tryAccess<Sequence<Any>>(rValue))
975 const sal_Int32 nLength = pSequence->getLength();
976 sal_Int32 nElement;
977 const Any* pAny = pSequence->getConstArray();
979 OStringBuffer sTmp2;
981 for (nElement = 0; nElement < nLength; nElement++, pAny++)
983 if (!sTmp.isEmpty())
984 sTmp.append(';');
985 convertTiming(sTmp2, *pAny);
986 sTmp.append(sTmp2);
987 sTmp2.setLength(0);
990 else if (auto x = o3tl::tryAccess<double>(rValue))
992 sTmp.append(*x);
993 sTmp.append('s');
995 else if (auto pTiming = o3tl::tryAccess<Timing>(rValue))
997 const auto svTiming = (*pTiming == Timing_MEDIA)
998 ? constTimingToString.at(Timing_MEDIA)
999 : constTimingToString.at(Timing_INDEFINITE);
1000 sTmp.append(svTiming);
1002 else if (auto pEvent = o3tl::tryAccess<Event>(rValue))
1004 OStringBuffer sTmp2;
1006 if (pEvent->Trigger != EventTrigger::NONE)
1008 if (pEvent->Source.hasValue())
1010 anim::convertTarget(sTmp, pEvent->Source);
1011 sTmp.append('.');
1014 convertEnum(sTmp2, pEvent->Trigger, constEventTriggerToString);
1016 sTmp.append(sTmp2);
1017 sTmp2.setLength(0);
1020 if (pEvent->Offset.hasValue())
1022 convertTiming(sTmp2, pEvent->Offset);
1024 if (!sTmp.isEmpty())
1025 sTmp.append('+');
1027 sTmp.append(sTmp2);
1028 sTmp2.setLength(0);
1031 else
1033 OSL_FAIL("sd.unomodel: AnimationsExporter::convertTiming, invalid value type!");
1037 void AnimationsExporter::convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp,
1038 const Any& rValue) const
1040 if (!rValue.hasValue())
1041 return;
1043 if (auto pValuePair = o3tl::tryAccess<ValuePair>(rValue))
1045 OStringBuffer sTmp2;
1046 convertValue(eAttributeName, sTmp, pValuePair->First);
1047 sTmp.append(',');
1048 convertValue(eAttributeName, sTmp2, pValuePair->Second);
1049 sTmp.append(sTmp2);
1051 else if (auto pSequence = o3tl::tryAccess<Sequence<Any>>(rValue))
1053 const sal_Int32 nLength = pSequence->getLength();
1054 sal_Int32 nElement;
1055 const Any* pAny = pSequence->getConstArray();
1057 OStringBuffer sTmp2;
1059 for (nElement = 0; nElement < nLength; nElement++, pAny++)
1061 if (!sTmp.isEmpty())
1062 sTmp.append(';');
1063 convertValue(eAttributeName, sTmp2, *pAny);
1064 sTmp.append(sTmp2);
1065 sTmp2.setLength(0);
1068 else
1070 switch (eAttributeName)
1072 case XML_X:
1073 case XML_Y:
1074 case XML_WIDTH:
1075 case XML_HEIGHT:
1076 case XML_ANIMATETRANSFORM:
1077 case XML_ANIMATEMOTION:
1078 case XML_ANIMATEPHYSICS:
1080 if (auto sValue = o3tl::tryAccess<OUString>(rValue))
1082 sTmp.append(sValue->toUtf8());
1084 else if (auto aValue = o3tl::tryAccess<double>(rValue))
1086 sTmp.append(*aValue);
1088 else
1090 OSL_FAIL("sd::AnimationsExporter::convertValue(), invalid value type!");
1092 return;
1094 case XML_SKEWX:
1095 case XML_ROTATE:
1096 case XML_OPACITY:
1097 case XML_TRANSITIONFILTER:
1098 if (auto aValue = o3tl::tryAccess<double>(rValue))
1100 sTmp.append(*aValue);
1102 break;
1103 case XML_TEXT_ROTATION_ANGLE:
1104 if (auto aValue = o3tl::tryAccess<sal_Int16>(rValue))
1106 // on win and armv7 platforms compiler complains
1107 // that append(sal_Int16) is ambiguous
1108 sTmp.append(static_cast<sal_Int32>(*aValue));
1110 break;
1111 case XML_FILL_COLOR:
1112 case XML_STROKE_COLOR:
1113 case XML_DIM:
1114 case XML_COLOR:
1116 convertColor(sTmp, rValue);
1118 break;
1119 case XML_FILL:
1120 if (auto aValue = o3tl::tryAccess<drawing::FillStyle>(rValue))
1122 convertEnum(sTmp, *aValue, constFillStyleToString);
1124 break;
1125 case XML_STROKE:
1126 if (auto aValue = o3tl::tryAccess<drawing::LineStyle>(rValue))
1128 convertEnum(sTmp, *aValue, constLineStyleToString);
1130 break;
1131 case XML_FONTSIZE:
1132 if (auto aValue = o3tl::tryAccess<double>(rValue))
1134 double fValue = *aValue * 100;
1135 fValue += fValue > 0 ? 0.5 : -0.5;
1136 auto nValue = static_cast<sal_Int32>(fValue);
1137 sTmp.append(nValue); // percent
1139 break;
1140 case XML_FONT_WEIGHT:
1141 case XML_FONT_STYLE:
1142 case XML_TEXT_UNDERLINE:
1143 SAL_WARN("sd", "AnimationsExporter::convertValue(): value type "
1144 << GetXMLToken(eAttributeName) << " not supported");
1145 break;
1146 case XML_VISIBILITY:
1147 if (auto aValue = o3tl::tryAccess<bool>(rValue))
1149 OUString sValue = *aValue ? GetXMLToken(XML_VISIBLE) : GetXMLToken(XML_HIDDEN);
1150 sTmp.append(sValue.toUtf8());
1152 break;
1153 default:
1154 OSL_FAIL("unomodel: AnimationsExporter::convertValue(), invalid AttributeName!");
1159 void AnimationsExporter::exportContainer(const Reference<XTimeContainer>& xContainer)
1163 const sal_Int32 nNodeType = xContainer->getType();
1165 if (nNodeType == AnimationNodeType::ITERATE)
1167 OStringBuffer sTmp;
1168 Reference<XIterateContainer> xIter(xContainer, UNO_QUERY_THROW);
1170 Any aTemp(xIter->getTarget());
1171 if (aTemp.hasValue())
1173 anim::convertTarget(sTmp, aTemp);
1174 mrWriter.put("targetElement", sTmp.makeStringAndClear());
1176 sal_Int16 nTemp = xIter->getSubItem();
1177 if (nTemp)
1179 convertEnum(sTmp, nTemp, constSubItemToString);
1180 mrWriter.put("subItem", sTmp.makeStringAndClear());
1182 nTemp = xIter->getIterateType();
1183 if (nTemp)
1185 convertEnum(sTmp, nTemp, constIterateTypeToString);
1186 mrWriter.put("iterateType", sTmp.makeStringAndClear());
1188 double fTemp = xIter->getIterateInterval();
1189 if (fTemp != 0)
1191 OUStringBuffer buf;
1192 ::sax::Converter::convertDuration(buf, fTemp / (24 * 60 * 60));
1193 mrWriter.put("iterateInterval", sTmp.makeStringAndClear());
1197 auto anArray = mrWriter.startArray("children");
1199 Reference<XEnumerationAccess> xEnumerationAccess(xContainer, UNO_QUERY_THROW);
1200 Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(),
1201 css::uno::UNO_SET_THROW);
1202 while (xEnumeration->hasMoreElements())
1204 Reference<XAnimationNode> xChildNode(xEnumeration->nextElement(), UNO_QUERY_THROW);
1205 exportNode(xChildNode);
1208 catch (const RuntimeException&)
1210 TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
1214 void AnimationsExporter::exportAnimate(const Reference<XAnimate>& xAnimate)
1218 const sal_Int16 nNodeType = xAnimate->getType();
1220 OStringBuffer sTmp;
1221 sal_Int16 nTemp;
1222 bool bTemp;
1224 Any aTemp(xAnimate->getTarget());
1225 if (aTemp.hasValue())
1227 anim::convertTarget(sTmp, aTemp);
1228 mrWriter.put("targetElement", sTmp.makeStringAndClear());
1230 nTemp = xAnimate->getSubItem();
1231 if (nTemp)
1233 convertEnum(sTmp, nTemp, constSubItemToString);
1234 mrWriter.put("subItem", sTmp.makeStringAndClear());
1237 XMLTokenEnum eAttributeName = XML_TOKEN_INVALID;
1238 if (nNodeType == AnimationNodeType::TRANSITIONFILTER)
1240 eAttributeName = XML_TRANSITIONFILTER;
1242 else if (nNodeType == AnimationNodeType::ANIMATETRANSFORM)
1244 eAttributeName = XML_ANIMATETRANSFORM;
1246 else if (nNodeType == AnimationNodeType::ANIMATEMOTION)
1248 eAttributeName = XML_ANIMATEMOTION;
1250 else if (nNodeType == AnimationNodeType::ANIMATEPHYSICS)
1252 eAttributeName = XML_ANIMATEPHYSICS;
1254 else
1256 OString sTemp(xAnimate->getAttributeName().toUtf8());
1257 if (!sTemp.isEmpty())
1259 auto iterator = constAttributeNameToXMLEnum.find(sTemp);
1260 if (iterator != constAttributeNameToXMLEnum.end())
1262 eAttributeName = iterator->second;
1263 mrWriter.put("attributeName", sTemp);
1265 else
1267 mrWriter.put("attributeName", "invalid");
1272 Sequence<Any> aValues(xAnimate->getValues());
1273 if (aValues.hasElements())
1275 aTemp <<= aValues;
1276 convertValue(eAttributeName, sTmp, aTemp);
1277 mrWriter.put("values", sTmp.makeStringAndClear());
1279 else
1281 aTemp = xAnimate->getFrom();
1282 if (aTemp.hasValue())
1284 convertValue(eAttributeName, sTmp, aTemp);
1285 mrWriter.put("from", sTmp.makeStringAndClear());
1288 aTemp = xAnimate->getBy();
1289 if (aTemp.hasValue())
1291 convertValue(eAttributeName, sTmp, aTemp);
1292 mrWriter.put("by", sTmp.makeStringAndClear());
1295 aTemp = xAnimate->getTo();
1296 if (aTemp.hasValue())
1298 convertValue(eAttributeName, sTmp, aTemp);
1299 mrWriter.put("to", sTmp.makeStringAndClear());
1303 if (nNodeType != AnimationNodeType::SET)
1305 const Sequence<double> aKeyTimes(xAnimate->getKeyTimes());
1306 if (aKeyTimes.hasElements())
1308 for (const auto& rKeyTime : aKeyTimes)
1310 if (!sTmp.isEmpty())
1311 sTmp.append(';');
1313 sTmp.append(rKeyTime);
1315 mrWriter.put("keyTimes", sTmp.makeStringAndClear());
1318 OUString sTemp(xAnimate->getFormula());
1319 if (!sTemp.isEmpty())
1321 mrWriter.put("formula", sTemp);
1324 if ((nNodeType != AnimationNodeType::TRANSITIONFILTER)
1325 && (nNodeType != AnimationNodeType::AUDIO))
1327 // calcMode = "discrete | linear | paced | spline"
1328 nTemp = xAnimate->getCalcMode();
1329 if (((nNodeType == AnimationNodeType::ANIMATEMOTION)
1330 && (nTemp != AnimationCalcMode::PACED))
1331 || ((nNodeType != AnimationNodeType::ANIMATEMOTION)
1332 && (nTemp != AnimationCalcMode::LINEAR)))
1334 convertEnum(sTmp, nTemp, constCalcModeToString);
1335 mrWriter.put("calcMode", sTmp.makeStringAndClear());
1338 bTemp = xAnimate->getAccumulate();
1339 if (bTemp)
1341 mrWriter.put("accumulate", "sum");
1344 nTemp = xAnimate->getAdditive();
1345 if (nTemp != AnimationAdditiveMode::REPLACE)
1347 convertEnum(sTmp, nTemp, constAdditiveModeToString);
1348 mrWriter.put("additive", sTmp.makeStringAndClear());
1352 const Sequence<TimeFilterPair> aTimeFilter(xAnimate->getTimeFilter());
1353 if (aTimeFilter.hasElements())
1355 for (const auto& rPair : aTimeFilter)
1357 if (!sTmp.isEmpty())
1358 sTmp.append(';');
1360 sTmp.append(OString::number(rPair.Time) + ","
1361 + OString::number(rPair.Progress));
1363 mrWriter.put("keySplines", sTmp.makeStringAndClear());
1367 switch (nNodeType)
1369 case AnimationNodeType::ANIMATEMOTION:
1371 Reference<XAnimateMotion> xAnimateMotion(xAnimate, UNO_QUERY_THROW);
1373 aTemp = xAnimateMotion->getPath();
1374 if (aTemp.hasValue())
1376 convertPath(sTmp, aTemp);
1377 mrWriter.put("path", sTmp.makeStringAndClear());
1380 break;
1381 case AnimationNodeType::ANIMATEPHYSICS:
1383 SAL_WARN(
1384 "sd",
1385 "unomodel: AnimationsExporter::exportAnimate(): AnimatePhysics not supported");
1387 break;
1388 case AnimationNodeType::ANIMATECOLOR:
1390 Reference<XAnimateColor> xAnimateColor(xAnimate, UNO_QUERY_THROW);
1392 nTemp = xAnimateColor->getColorInterpolation();
1393 mrWriter.put("colorInterpolation",
1394 (nTemp == AnimationColorSpace::RGB) ? "rgb" : "hsl");
1396 bTemp = xAnimateColor->getDirection();
1397 mrWriter.put("colorInterpolationDirection",
1398 bTemp ? "clockwise" : "counterClockwise");
1400 break;
1401 case AnimationNodeType::ANIMATETRANSFORM:
1403 mrWriter.put("attributeName", "transform");
1405 Reference<XAnimateTransform> xTransform(xAnimate, UNO_QUERY_THROW);
1406 nTemp = xTransform->getTransformType();
1407 convertEnum(sTmp, nTemp, constTransformTypeToString);
1408 mrWriter.put("transformType", sTmp.makeStringAndClear());
1410 break;
1411 case AnimationNodeType::TRANSITIONFILTER:
1413 Reference<XTransitionFilter> xTransitionFilter(xAnimate, UNO_QUERY);
1415 sal_Int16 nTransition = xTransitionFilter->getTransition();
1416 convertEnum(sTmp, nTransition, constTransitionTypeToString);
1417 mrWriter.put("transitionType", sTmp.makeStringAndClear());
1419 sal_Int16 nSubtype = xTransitionFilter->getSubtype();
1420 if (nSubtype != TransitionSubType::DEFAULT)
1422 convertEnum(sTmp, nSubtype, constTransitionSubTypeToString);
1423 mrWriter.put("transitionSubType", sTmp.makeStringAndClear());
1426 bTemp = xTransitionFilter->getMode();
1427 if (!bTemp)
1428 mrWriter.put("transitionMode", "out");
1430 bTemp = xTransitionFilter->getDirection();
1431 if (!bTemp)
1432 mrWriter.put("transitionDirection", "reverse");
1434 if ((nTransition == TransitionType::FADE)
1435 && ((nSubtype == TransitionSubType::FADETOCOLOR)
1436 || (nSubtype == TransitionSubType::FADEFROMCOLOR)))
1438 sal_Int32 nColor = xTransitionFilter->getFadeColor();
1439 convertColor(sTmp, nColor);
1440 mrWriter.put("transitionFadeColor", sTmp.makeStringAndClear());
1443 break;
1444 default:
1446 SAL_WARN("sd",
1447 "unomodel: AnimationsExporter::exportAnimate(): not supported node type: "
1448 << nNodeType);
1452 catch (const Exception&)
1454 TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter");
1458 } // end anonymous namespace
1460 SdUnoForbiddenCharsTable::SdUnoForbiddenCharsTable( SdrModel* pModel )
1461 : SvxUnoForbiddenCharsTable( pModel->GetForbiddenCharsTable() ), mpModel( pModel )
1463 StartListening( *pModel );
1466 void SdUnoForbiddenCharsTable::onChange()
1468 if( mpModel )
1470 mpModel->ReformatAllTextObjects();
1474 SdUnoForbiddenCharsTable::~SdUnoForbiddenCharsTable()
1476 SolarMutexGuard g;
1478 if( mpModel )
1479 EndListening( *mpModel );
1482 void SdUnoForbiddenCharsTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept
1484 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
1485 return;
1486 const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint );
1487 if( SdrHintKind::ModelCleared == pSdrHint->GetKind() )
1489 mpModel = nullptr;
1493 const sal_uInt16 WID_MODEL_LANGUAGE = 1;
1494 const sal_uInt16 WID_MODEL_TABSTOP = 2;
1495 const sal_uInt16 WID_MODEL_VISAREA = 3;
1496 const sal_uInt16 WID_MODEL_MAPUNIT = 4;
1497 const sal_uInt16 WID_MODEL_FORBCHARS = 5;
1498 const sal_uInt16 WID_MODEL_CONTFOCUS = 6;
1499 const sal_uInt16 WID_MODEL_DSGNMODE = 7;
1500 const sal_uInt16 WID_MODEL_BASICLIBS = 8;
1501 const sal_uInt16 WID_MODEL_RUNTIMEUID = 9;
1502 const sal_uInt16 WID_MODEL_BUILDID = 10;
1503 const sal_uInt16 WID_MODEL_HASVALIDSIGNATURES = 11;
1504 const sal_uInt16 WID_MODEL_DIALOGLIBS = 12;
1505 const sal_uInt16 WID_MODEL_FONTS = 13;
1506 const sal_uInt16 WID_MODEL_INTEROPGRABBAG = 14;
1507 const sal_uInt16 WID_MODEL_THEME = 15;
1508 const sal_uInt16 WID_MODEL_ALLOWLINKUPDATE = 16;
1510 static const SvxItemPropertySet* ImplGetDrawModelPropertySet()
1512 // Attention: the first parameter HAS TO BE sorted!!!
1513 const static SfxItemPropertyMapEntry aDrawModelPropertyMap_Impl[] =
1515 { u"BuildId"_ustr, WID_MODEL_BUILDID, ::cppu::UnoType<OUString>::get(), 0, 0},
1516 { sUNO_Prop_CharLocale, WID_MODEL_LANGUAGE, ::cppu::UnoType<lang::Locale>::get(), 0, 0},
1517 { sUNO_Prop_TabStop, WID_MODEL_TABSTOP, ::cppu::UnoType<sal_Int32>::get(), 0, 0},
1518 { sUNO_Prop_VisibleArea, WID_MODEL_VISAREA, ::cppu::UnoType<awt::Rectangle>::get(), 0, 0},
1519 { sUNO_Prop_MapUnit, WID_MODEL_MAPUNIT, ::cppu::UnoType<sal_Int16>::get(), beans::PropertyAttribute::READONLY, 0},
1520 { sUNO_Prop_ForbiddenCharacters, WID_MODEL_FORBCHARS, cppu::UnoType<i18n::XForbiddenCharacters>::get(), beans::PropertyAttribute::READONLY, 0},
1521 { sUNO_Prop_AutomContFocus, WID_MODEL_CONTFOCUS, cppu::UnoType<bool>::get(), 0, 0},
1522 { sUNO_Prop_ApplyFrmDsgnMode, WID_MODEL_DSGNMODE, cppu::UnoType<bool>::get(), 0, 0},
1523 { u"BasicLibraries"_ustr, WID_MODEL_BASICLIBS, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
1524 { u"DialogLibraries"_ustr, WID_MODEL_DIALOGLIBS, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
1525 { sUNO_Prop_RuntimeUID, WID_MODEL_RUNTIMEUID, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
1526 { sUNO_Prop_HasValidSignatures, WID_MODEL_HASVALIDSIGNATURES, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY, 0},
1527 { sUNO_Prop_AllowLinkUpdate, WID_MODEL_ALLOWLINKUPDATE, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY, 0},
1528 { u"Fonts"_ustr, WID_MODEL_FONTS, cppu::UnoType<uno::Sequence<uno::Any>>::get(), beans::PropertyAttribute::READONLY, 0},
1529 { sUNO_Prop_InteropGrabBag, WID_MODEL_INTEROPGRABBAG, cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get(), 0, 0},
1530 { sUNO_Prop_Theme, WID_MODEL_THEME, cppu::UnoType<util::XTheme>::get(), 0, 0},
1532 static SvxItemPropertySet aDrawModelPropertySet_Impl( aDrawModelPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
1533 return &aDrawModelPropertySet_Impl;
1536 // this ctor is used from the DocShell
1537 SdXImpressDocument::SdXImpressDocument(::sd::DrawDocShell* pShell, bool bClipBoard)
1538 : SfxBaseModel( pShell ),
1539 mpDocShell( pShell ),
1540 mpDoc( pShell ? pShell->GetDoc() : nullptr ),
1541 mbDisposed(false),
1542 mbImpressDoc( pShell && pShell->GetDoc() && pShell->GetDoc()->GetDocumentType() == DocumentType::Impress ),
1543 mbClipBoard( bClipBoard ),
1544 mpPropSet( ImplGetDrawModelPropertySet() ),
1545 mbPaintTextEdit( true )
1547 if( mpDoc )
1549 StartListening( *mpDoc );
1551 else
1553 OSL_FAIL("DocShell is invalid");
1557 SdXImpressDocument::SdXImpressDocument(SdDrawDocument* pDoc, bool bClipBoard)
1558 : SfxBaseModel( nullptr ),
1559 mpDocShell( nullptr ),
1560 mpDoc( pDoc ),
1561 mbDisposed(false),
1562 mbImpressDoc( pDoc && pDoc->GetDocumentType() == DocumentType::Impress ),
1563 mbClipBoard( bClipBoard ),
1564 mpPropSet( ImplGetDrawModelPropertySet() ),
1565 mbPaintTextEdit( true )
1567 if( mpDoc )
1569 StartListening( *mpDoc );
1571 else
1573 OSL_FAIL("SdDrawDocument is invalid");
1577 /***********************************************************************
1579 ***********************************************************************/
1580 SdXImpressDocument::~SdXImpressDocument() noexcept
1584 // XInterface
1585 uno::Any SAL_CALL SdXImpressDocument::queryInterface( const uno::Type & rType )
1587 uno::Any aAny;
1589 if (rType == cppu::UnoType<lang::XServiceInfo>::get())
1590 aAny <<= uno::Reference<lang::XServiceInfo>(this);
1591 else if (rType == cppu::UnoType<beans::XPropertySet>::get())
1592 aAny <<= uno::Reference<beans::XPropertySet>(this);
1593 else if (rType == cppu::UnoType<lang::XMultiServiceFactory>::get())
1594 aAny <<= uno::Reference<lang::XMultiServiceFactory>(this);
1595 else if (rType == cppu::UnoType<drawing::XDrawPageDuplicator>::get())
1596 aAny <<= uno::Reference<drawing::XDrawPageDuplicator>(this);
1597 else if (rType == cppu::UnoType<drawing::XLayerSupplier>::get())
1598 aAny <<= uno::Reference<drawing::XLayerSupplier>(this);
1599 else if (rType == cppu::UnoType<drawing::XMasterPagesSupplier>::get())
1600 aAny <<= uno::Reference<drawing::XMasterPagesSupplier>(this);
1601 else if (rType == cppu::UnoType<drawing::XDrawPagesSupplier>::get())
1602 aAny <<= uno::Reference<drawing::XDrawPagesSupplier>(this);
1603 else if (rType == cppu::UnoType<presentation::XHandoutMasterSupplier>::get())
1604 aAny <<= uno::Reference<presentation::XHandoutMasterSupplier>(this);
1605 else if (rType == cppu::UnoType<document::XLinkTargetSupplier>::get())
1606 aAny <<= uno::Reference<document::XLinkTargetSupplier>(this);
1607 else if (rType == cppu::UnoType<style::XStyleFamiliesSupplier>::get())
1608 aAny <<= uno::Reference<style::XStyleFamiliesSupplier>(this);
1609 else if (rType == cppu::UnoType<css::ucb::XAnyCompareFactory>::get())
1610 aAny <<= uno::Reference<css::ucb::XAnyCompareFactory>(this);
1611 else if (rType == cppu::UnoType<view::XRenderable>::get())
1612 aAny <<= uno::Reference<view::XRenderable>(this);
1613 else if (mbImpressDoc && rType == cppu::UnoType<presentation::XPresentationSupplier>::get())
1614 aAny <<= uno::Reference< presentation::XPresentationSupplier >(this);
1615 else if (mbImpressDoc && rType == cppu::UnoType<presentation::XCustomPresentationSupplier>::get())
1616 aAny <<= uno::Reference< presentation::XCustomPresentationSupplier >(this);
1617 else
1618 return SfxBaseModel::queryInterface(rType);
1620 return aAny;
1623 void SAL_CALL SdXImpressDocument::acquire() noexcept
1625 SfxBaseModel::acquire();
1628 void SAL_CALL SdXImpressDocument::release() noexcept
1630 if (osl_atomic_decrement( &m_refCount ) != 0)
1631 return;
1633 // restore reference count:
1634 osl_atomic_increment( &m_refCount );
1635 if(!mbDisposed)
1639 dispose();
1641 catch (const uno::RuntimeException&)
1643 // don't break throw ()
1644 TOOLS_WARN_EXCEPTION( "sd", "" );
1647 SfxBaseModel::release();
1650 // XUnoTunnel
1651 const css::uno::Sequence< sal_Int8 > & SdXImpressDocument::getUnoTunnelId() noexcept
1653 static const comphelper::UnoIdInit theSdXImpressDocumentUnoTunnelId;
1654 return theSdXImpressDocumentUnoTunnelId.getSeq();
1657 sal_Int64 SAL_CALL SdXImpressDocument::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
1659 if (comphelper::isUnoTunnelId<SdrModel>(rIdentifier))
1660 return comphelper::getSomething_cast(mpDoc);
1662 return comphelper::getSomethingImpl(rIdentifier, this,
1663 comphelper::FallbackToGetSomethingOf<SfxBaseModel>{});
1666 // XTypeProvider
1667 uno::Sequence< uno::Type > SAL_CALL SdXImpressDocument::getTypes( )
1669 ::SolarMutexGuard aGuard;
1671 if( !maTypeSequence.hasElements() )
1673 uno::Sequence< uno::Type > aTypes( SfxBaseModel::getTypes() );
1674 aTypes = comphelper::concatSequences(aTypes,
1675 uno::Sequence {
1676 cppu::UnoType<beans::XPropertySet>::get(),
1677 cppu::UnoType<lang::XServiceInfo>::get(),
1678 cppu::UnoType<lang::XMultiServiceFactory>::get(),
1679 cppu::UnoType<drawing::XDrawPageDuplicator>::get(),
1680 cppu::UnoType<drawing::XLayerSupplier>::get(),
1681 cppu::UnoType<drawing::XMasterPagesSupplier>::get(),
1682 cppu::UnoType<drawing::XDrawPagesSupplier>::get(),
1683 cppu::UnoType<document::XLinkTargetSupplier>::get(),
1684 cppu::UnoType<style::XStyleFamiliesSupplier>::get(),
1685 cppu::UnoType<css::ucb::XAnyCompareFactory>::get(),
1686 cppu::UnoType<view::XRenderable>::get() });
1687 if( mbImpressDoc )
1689 aTypes = comphelper::concatSequences(aTypes,
1690 uno::Sequence {
1691 cppu::UnoType<presentation::XPresentationSupplier>::get(),
1692 cppu::UnoType<presentation::XCustomPresentationSupplier>::get(),
1693 cppu::UnoType<presentation::XHandoutMasterSupplier>::get() });
1695 maTypeSequence = std::move(aTypes);
1698 return maTypeSequence;
1701 uno::Sequence< sal_Int8 > SAL_CALL SdXImpressDocument::getImplementationId( )
1703 return css::uno::Sequence<sal_Int8>();
1706 /***********************************************************************
1708 ***********************************************************************/
1709 void SdXImpressDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1711 if( mpDoc )
1713 if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
1715 const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint );
1716 if( hasEventListeners() )
1718 document::EventObject aEvent;
1719 if( SvxUnoDrawMSFactory::createEvent( mpDoc, pSdrHint, aEvent ) )
1720 notifyEvent( aEvent );
1723 if( pSdrHint->GetKind() == SdrHintKind::ModelCleared )
1725 if( mpDoc )
1726 EndListening( *mpDoc );
1727 mpDoc = nullptr;
1728 mpDocShell = nullptr;
1731 else
1733 // did our SdDrawDocument just died?
1734 if(rHint.GetId() == SfxHintId::Dying)
1736 // yes, so we ask for a new one
1737 if( mpDocShell )
1739 SdDrawDocument *pNewDoc = mpDocShell->GetDoc();
1741 // is there a new one?
1742 if( pNewDoc != mpDoc )
1744 mpDoc = pNewDoc;
1745 if(mpDoc)
1746 StartListening( *mpDoc );
1752 SfxBaseModel::Notify( rBC, rHint );
1755 /******************************************************************************
1757 ******************************************************************************/
1758 SdPage* SdXImpressDocument::InsertSdPage( sal_uInt16 nPage, bool bDuplicate )
1760 sal_uInt16 nPageCount = mpDoc->GetSdPageCount( PageKind::Standard );
1761 SdrLayerAdmin& rLayerAdmin = mpDoc->GetLayerAdmin();
1762 SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
1763 SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
1765 rtl::Reference<SdPage> pStandardPage;
1767 if( 0 == nPageCount )
1769 // this is only used for clipboard where we only have one page
1770 pStandardPage = mpDoc->AllocSdPage(false);
1772 Size aDefSize(21000, 29700); // A4 portrait orientation
1773 pStandardPage->SetSize( aDefSize );
1774 mpDoc->InsertPage(pStandardPage.get(), 0);
1776 else
1778 // here we determine the page after which we should insert
1779 SdPage* pPreviousStandardPage = mpDoc->GetSdPage( std::min( static_cast<sal_uInt16>(nPageCount - 1), nPage ), PageKind::Standard );
1780 SdrLayerIDSet aVisibleLayers = pPreviousStandardPage->TRG_GetMasterPageVisibleLayers();
1781 bool bIsPageBack = aVisibleLayers.IsSet( aBckgrnd );
1782 bool bIsPageObj = aVisibleLayers.IsSet( aBckgrndObj );
1784 // AutoLayouts must be ready
1785 mpDoc->StopWorkStartupDelay();
1787 /* First we create a standard page and then a notes page. It is
1788 guaranteed, that after a standard page the corresponding notes page
1789 follows. */
1791 sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1792 SdPage* pPreviousNotesPage = static_cast<SdPage*>( mpDoc->GetPage( nStandardPageNum - 1 ) );
1793 sal_uInt16 nNotesPageNum = nStandardPageNum + 1;
1795 /**************************************************************
1796 * standard page
1797 **************************************************************/
1798 if( bDuplicate )
1799 pStandardPage = static_cast<SdPage*>( pPreviousStandardPage->CloneSdrPage(*mpDoc).get() );
1800 else
1801 pStandardPage = mpDoc->AllocSdPage(false);
1803 pStandardPage->SetSize( pPreviousStandardPage->GetSize() );
1804 pStandardPage->SetBorder( pPreviousStandardPage->GetLeftBorder(),
1805 pPreviousStandardPage->GetUpperBorder(),
1806 pPreviousStandardPage->GetRightBorder(),
1807 pPreviousStandardPage->GetLowerBorder() );
1808 pStandardPage->SetOrientation( pPreviousStandardPage->GetOrientation() );
1809 pStandardPage->SetName(OUString());
1811 // insert page after current page
1812 mpDoc->InsertPage(pStandardPage.get(), nStandardPageNum);
1814 if( !bDuplicate )
1816 // use MasterPage of the current page
1817 pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage());
1818 pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() );
1819 pStandardPage->SetAutoLayout(AUTOLAYOUT_NONE, true );
1822 aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
1823 aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
1824 aVisibleLayers.Set(aBckgrnd, bIsPageBack);
1825 aVisibleLayers.Set(aBckgrndObj, bIsPageObj);
1826 pStandardPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
1828 /**************************************************************
1829 * notes page
1830 **************************************************************/
1831 rtl::Reference<SdPage> pNotesPage;
1833 if( bDuplicate )
1834 pNotesPage = static_cast<SdPage*>( pPreviousNotesPage->CloneSdrPage(*mpDoc).get() );
1835 else
1836 pNotesPage = mpDoc->AllocSdPage(false);
1838 pNotesPage->SetSize( pPreviousNotesPage->GetSize() );
1839 pNotesPage->SetBorder( pPreviousNotesPage->GetLeftBorder(),
1840 pPreviousNotesPage->GetUpperBorder(),
1841 pPreviousNotesPage->GetRightBorder(),
1842 pPreviousNotesPage->GetLowerBorder() );
1843 pNotesPage->SetOrientation( pPreviousNotesPage->GetOrientation() );
1844 pNotesPage->SetName(OUString());
1845 pNotesPage->SetPageKind(PageKind::Notes);
1847 // insert page after current page
1848 mpDoc->InsertPage(pNotesPage.get(), nNotesPageNum);
1850 if( !bDuplicate )
1852 // use MasterPage of the current page
1853 pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage());
1854 pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() );
1855 pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true );
1859 SetModified();
1861 return pStandardPage.get();
1864 void SdXImpressDocument::SetModified() noexcept
1866 if( mpDoc )
1867 mpDoc->SetChanged();
1870 // XModel
1871 void SAL_CALL SdXImpressDocument::lockControllers( )
1873 ::SolarMutexGuard aGuard;
1875 if( nullptr == mpDoc )
1876 throw lang::DisposedException();
1878 mpDoc->setLock(true);
1881 void SAL_CALL SdXImpressDocument::unlockControllers( )
1883 ::SolarMutexGuard aGuard;
1885 if( nullptr == mpDoc )
1886 throw lang::DisposedException();
1888 if( mpDoc->isLocked() )
1890 mpDoc->setLock(false);
1894 sal_Bool SAL_CALL SdXImpressDocument::hasControllersLocked( )
1896 ::SolarMutexGuard aGuard;
1898 if( nullptr == mpDoc )
1899 throw lang::DisposedException();
1901 return mpDoc->isLocked();
1904 uno::Reference < container::XIndexAccess > SAL_CALL SdXImpressDocument::getViewData()
1906 ::SolarMutexGuard aGuard;
1908 if( nullptr == mpDoc )
1909 throw lang::DisposedException();
1911 uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() );
1913 if( !xRet.is() )
1915 const std::vector<std::unique_ptr<sd::FrameView>> &rList = mpDoc->GetFrameViewList();
1917 if( !rList.empty() )
1919 xRet = new comphelper::IndexedPropertyValuesContainer();
1921 uno::Reference < container::XIndexContainer > xCont( xRet, uno::UNO_QUERY );
1922 DBG_ASSERT( xCont.is(), "SdXImpressDocument::getViewData() failed for OLE object" );
1923 if( xCont.is() )
1925 for( sal_uInt32 i = 0, n = rList.size(); i < n; i++ )
1927 ::sd::FrameView* pFrameView = rList[ i ].get();
1929 uno::Sequence< beans::PropertyValue > aSeq;
1930 pFrameView->WriteUserDataSequence( aSeq );
1931 xCont->insertByIndex( i, uno::Any( aSeq ) );
1937 return xRet;
1940 void SAL_CALL SdXImpressDocument::setViewData( const uno::Reference < container::XIndexAccess >& xData )
1942 ::SolarMutexGuard aGuard;
1944 if( nullptr == mpDoc )
1945 throw lang::DisposedException();
1947 SfxBaseModel::setViewData( xData );
1948 if( !(mpDocShell && (mpDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED) && xData.is()) )
1949 return;
1951 const sal_Int32 nCount = xData->getCount();
1953 std::vector<std::unique_ptr<sd::FrameView>> &rViews = mpDoc->GetFrameViewList();
1955 rViews.clear();
1957 uno::Sequence< beans::PropertyValue > aSeq;
1958 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
1960 if( xData->getByIndex( nIndex ) >>= aSeq )
1962 std::unique_ptr<::sd::FrameView> pFrameView(new ::sd::FrameView( mpDoc ));
1963 pFrameView->ReadUserDataSequence( aSeq );
1964 rViews.push_back( std::move(pFrameView) );
1969 // XDrawPageDuplicator
1970 uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::duplicate( const uno::Reference< drawing::XDrawPage >& xPage )
1972 ::SolarMutexGuard aGuard;
1974 if( nullptr == mpDoc )
1975 throw lang::DisposedException();
1977 // get pPage from xPage and determine the Id (nPos ) afterwards
1978 SvxDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage );
1979 if( pSvxPage )
1981 SdPage* pPage = static_cast<SdPage*>( pSvxPage->GetSdrPage() );
1982 sal_uInt16 nPos = pPage->GetPageNum();
1983 nPos = ( nPos - 1 ) / 2;
1984 pPage = InsertSdPage( nPos, true );
1985 if( pPage )
1987 uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
1988 return xDrawPage;
1992 uno::Reference< drawing::XDrawPage > xDrawPage;
1993 return xDrawPage;
1996 // XDrawPagesSupplier
1997 uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getDrawPages()
1999 ::SolarMutexGuard aGuard;
2001 return getSdDrawPages();
2004 rtl::Reference< SdDrawPagesAccess > SdXImpressDocument::getSdDrawPages()
2006 if( nullptr == mpDoc )
2007 throw lang::DisposedException();
2009 rtl::Reference< SdDrawPagesAccess > xDrawPages( mxDrawPagesAccess );
2011 if( !xDrawPages.is() )
2013 initializeDocument();
2014 xDrawPages = new SdDrawPagesAccess(*this);
2015 mxDrawPagesAccess = xDrawPages.get();
2018 return xDrawPages;
2021 // XMasterPagesSupplier
2022 uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getMasterPages()
2024 ::SolarMutexGuard aGuard;
2026 if( nullptr == mpDoc )
2027 throw lang::DisposedException();
2029 rtl::Reference< SdMasterPagesAccess > xMasterPages( mxMasterPagesAccess );
2031 if( !xMasterPages.is() )
2033 if ( !hasControllersLocked() )
2034 initializeDocument();
2035 xMasterPages = new SdMasterPagesAccess(*this);
2036 mxMasterPagesAccess = xMasterPages.get();
2039 return xMasterPages;
2042 // XLayerManagerSupplier
2043 uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLayerManager( )
2045 ::SolarMutexGuard aGuard;
2047 if( nullptr == mpDoc )
2048 throw lang::DisposedException();
2050 rtl::Reference< SdLayerManager > xLayerManager( mxLayerManager );
2052 if( !xLayerManager.is() )
2054 xLayerManager = new SdLayerManager(*this);
2055 mxLayerManager = xLayerManager.get();
2058 return xLayerManager;
2061 // XCustomPresentationSupplier
2062 uno::Reference< container::XNameContainer > SAL_CALL SdXImpressDocument::getCustomPresentations()
2064 ::SolarMutexGuard aGuard;
2066 if( nullptr == mpDoc )
2067 throw lang::DisposedException();
2069 rtl::Reference< SdXCustomPresentationAccess > xCustomPres( mxCustomPresentationAccess );
2071 if( !xCustomPres.is() )
2073 xCustomPres = new SdXCustomPresentationAccess(*this);
2074 mxCustomPresentationAccess = xCustomPres.get();
2077 return xCustomPres;
2080 // XPresentationSupplier
2081 uno::Reference< presentation::XPresentation > SAL_CALL SdXImpressDocument::getPresentation()
2083 ::SolarMutexGuard aGuard;
2085 if( nullptr == mpDoc )
2086 throw lang::DisposedException();
2088 return mpDoc->getPresentation();
2091 // XHandoutMasterSupplier
2092 uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::getHandoutMasterPage()
2094 ::SolarMutexGuard aGuard;
2096 if( nullptr == mpDoc )
2097 throw lang::DisposedException();
2099 uno::Reference< drawing::XDrawPage > xPage;
2101 initializeDocument();
2102 SdPage* pPage = mpDoc->GetMasterSdPage(0, PageKind::Handout);
2103 if (pPage)
2104 xPage.set(pPage->getUnoPage(), uno::UNO_QUERY);
2105 return xPage;
2108 // XMultiServiceFactory ( SvxFmMSFactory )
2110 css::uno::Reference<css::uno::XInterface> SdXImpressDocument::create(
2111 OUString const & aServiceSpecifier, OUString const & referer)
2113 ::SolarMutexGuard aGuard;
2115 if( nullptr == mpDoc )
2116 throw lang::DisposedException();
2118 if( aServiceSpecifier == "com.sun.star.drawing.DashTable" )
2120 if( !mxDashTable.is() )
2121 mxDashTable = SvxUnoDashTable_createInstance( mpDoc );
2123 return mxDashTable;
2125 if( aServiceSpecifier == "com.sun.star.drawing.GradientTable" )
2127 if( !mxGradientTable.is() )
2128 mxGradientTable = SvxUnoGradientTable_createInstance( mpDoc );
2130 return mxGradientTable;
2132 if( aServiceSpecifier == "com.sun.star.drawing.HatchTable" )
2134 if( !mxHatchTable.is() )
2135 mxHatchTable = SvxUnoHatchTable_createInstance( mpDoc );
2137 return mxHatchTable;
2139 if( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" )
2141 if( !mxBitmapTable.is() )
2142 mxBitmapTable = SvxUnoBitmapTable_createInstance( mpDoc );
2144 return mxBitmapTable;
2146 if( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" )
2148 if( !mxTransGradientTable.is() )
2149 mxTransGradientTable = SvxUnoTransGradientTable_createInstance( mpDoc );
2151 return mxTransGradientTable;
2153 if( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" )
2155 if( !mxMarkerTable.is() )
2156 mxMarkerTable = SvxUnoMarkerTable_createInstance( mpDoc );
2158 return mxMarkerTable;
2160 if( aServiceSpecifier == "com.sun.star.text.NumberingRules" )
2162 return uno::Reference< uno::XInterface >( SvxCreateNumRule( mpDoc ), uno::UNO_QUERY );
2164 if( aServiceSpecifier == "com.sun.star.drawing.Background" )
2166 return uno::Reference< uno::XInterface >(
2167 static_cast<uno::XWeak*>(new SdUnoPageBackground( mpDoc )));
2170 if( aServiceSpecifier == "com.sun.star.drawing.Defaults" )
2172 if( !mxDrawingPool.is() )
2173 mxDrawingPool = SdUnoCreatePool( mpDoc );
2175 return mxDrawingPool;
2179 if ( aServiceSpecifier == sUNO_Service_ImageMapRectangleObject )
2181 return SvUnoImageMapRectangleObject_createInstance( ImplGetSupportedMacroItems() );
2184 if ( aServiceSpecifier == sUNO_Service_ImageMapCircleObject )
2186 return SvUnoImageMapCircleObject_createInstance( ImplGetSupportedMacroItems() );
2189 if ( aServiceSpecifier == sUNO_Service_ImageMapPolygonObject )
2191 return SvUnoImageMapPolygonObject_createInstance( ImplGetSupportedMacroItems() );
2194 if( aServiceSpecifier == "com.sun.star.document.Settings" ||
2195 ( !mbImpressDoc && ( aServiceSpecifier == "com.sun.star.drawing.DocumentSettings" ) ) ||
2196 ( mbImpressDoc && ( aServiceSpecifier == "com.sun.star.presentation.DocumentSettings" ) ) )
2198 return sd::DocumentSettings_createInstance( this );
2201 if( aServiceSpecifier == "com.sun.star.text.TextField.DateTime" ||
2202 aServiceSpecifier == "com.sun.star.text.textfield.DateTime" )
2204 return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::DATE ));
2207 if( aServiceSpecifier == "com.sun.star.presentation.TextField.Header" ||
2208 aServiceSpecifier == "com.sun.star.presentation.textfield.Header" )
2210 return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_HEADER ));
2213 if( aServiceSpecifier == "com.sun.star.presentation.TextField.Footer" ||
2214 aServiceSpecifier == "com.sun.star.presentation.textfield.Footer" )
2216 return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_FOOTER ));
2219 if( aServiceSpecifier == "com.sun.star.presentation.TextField.DateTime" ||
2220 aServiceSpecifier == "com.sun.star.presentation.textfield.DateTime" )
2222 return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_DATE_TIME ));
2225 if( aServiceSpecifier == "com.sun.star.text.TextField.PageName" ||
2226 aServiceSpecifier == "com.sun.star.text.textfield.PageName" )
2228 return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PAGE_NAME ));
2231 if (aServiceSpecifier == "com.sun.star.text.TextField.DocInfo.Custom" ||
2232 aServiceSpecifier == "com.sun.star.text.textfield.DocInfo.Custom")
2234 return static_cast<cppu::OWeakObject *>(new SvxUnoTextField(text::textfield::Type::DOCINFO_CUSTOM));
2237 if( aServiceSpecifier == "com.sun.star.xml.NamespaceMap" )
2239 static sal_uInt16 aWhichIds[] = { SDRATTR_XMLATTRIBUTES, EE_CHAR_XMLATTRIBS, EE_PARA_XMLATTRIBS, 0 };
2241 return svx::NamespaceMap_createInstance( aWhichIds, &mpDoc->GetItemPool() );
2244 // Support creation of GraphicStorageHandler and EmbeddedObjectResolver
2245 if (aServiceSpecifier == "com.sun.star.document.ExportGraphicStorageHandler")
2247 return static_cast<cppu::OWeakObject *>(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Write ));
2250 if (aServiceSpecifier == "com.sun.star.document.ImportGraphicStorageHandler")
2252 return static_cast<cppu::OWeakObject *>(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Read ));
2255 if( aServiceSpecifier == "com.sun.star.document.ExportEmbeddedObjectResolver" )
2257 comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist();
2258 if( nullptr == pPersist )
2259 throw lang::DisposedException();
2261 return static_cast<cppu::OWeakObject *>(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Write ));
2264 if( aServiceSpecifier == "com.sun.star.document.ImportEmbeddedObjectResolver" )
2266 comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist();
2267 if( nullptr == pPersist )
2268 throw lang::DisposedException();
2270 return static_cast<cppu::OWeakObject *>(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Read ));
2273 uno::Reference< uno::XInterface > xRet;
2275 if( aServiceSpecifier.startsWith( "com.sun.star.presentation.") )
2277 const std::u16string_view aType( aServiceSpecifier.subView(26) );
2278 rtl::Reference<SvxShape> pShape;
2280 SdrObjKind nType = SdrObjKind::Text;
2281 // create a shape wrapper
2282 if( o3tl::starts_with(aType, u"TitleTextShape" ) )
2284 nType = SdrObjKind::Text;
2286 else if( o3tl::starts_with(aType, u"OutlinerShape" ) )
2288 nType = SdrObjKind::Text;
2290 else if( o3tl::starts_with(aType, u"SubtitleShape" ) )
2292 nType = SdrObjKind::Text;
2294 else if( o3tl::starts_with(aType, u"GraphicObjectShape" ) )
2296 nType = SdrObjKind::Graphic;
2298 else if( o3tl::starts_with(aType, u"PageShape" ) )
2300 nType = SdrObjKind::Page;
2302 else if( o3tl::starts_with(aType, u"OLE2Shape" ) )
2304 nType = SdrObjKind::OLE2;
2306 else if( o3tl::starts_with(aType, u"ChartShape" ) )
2308 nType = SdrObjKind::OLE2;
2310 else if( o3tl::starts_with(aType, u"CalcShape" ) )
2312 nType = SdrObjKind::OLE2;
2314 else if( o3tl::starts_with(aType, u"TableShape" ) )
2316 nType = SdrObjKind::Table;
2318 else if( o3tl::starts_with(aType, u"OrgChartShape" ) )
2320 nType = SdrObjKind::OLE2;
2322 else if( o3tl::starts_with(aType, u"NotesShape" ) )
2324 nType = SdrObjKind::Text;
2326 else if( o3tl::starts_with(aType, u"HandoutShape" ) )
2328 nType = SdrObjKind::Page;
2330 else if( o3tl::starts_with(aType, u"FooterShape" ) )
2332 nType = SdrObjKind::Text;
2334 else if( o3tl::starts_with(aType, u"HeaderShape" ) )
2336 nType = SdrObjKind::Text;
2338 else if( o3tl::starts_with(aType, u"SlideNumberShape" ) )
2340 nType = SdrObjKind::Text;
2342 else if( o3tl::starts_with(aType, u"DateTimeShape" ) )
2344 nType = SdrObjKind::Text;
2346 else if( o3tl::starts_with(aType, u"MediaShape" ) )
2348 nType = SdrObjKind::Media;
2350 else
2352 throw lang::ServiceNotRegisteredException();
2355 // create the API wrapper
2356 pShape = CreateSvxShapeByTypeAndInventor( nType, SdrInventor::Default, referer );
2358 // set shape type
2359 if( pShape && !mbClipBoard )
2360 pShape->SetShapeType(aServiceSpecifier);
2362 xRet = static_cast<uno::XWeak*>(pShape.get());
2364 else if ( aServiceSpecifier == "com.sun.star.drawing.TableShape" )
2366 rtl::Reference<SvxShape> pShape = CreateSvxShapeByTypeAndInventor( SdrObjKind::Table, SdrInventor::Default, referer );
2367 if( pShape && !mbClipBoard )
2368 pShape->SetShapeType(aServiceSpecifier);
2370 xRet = static_cast<uno::XWeak*>(pShape.get());
2372 else
2374 xRet = SvxFmMSFactory::createInstance( aServiceSpecifier );
2377 uno::Reference< drawing::XShape > xShape( xRet, uno::UNO_QUERY );
2378 SvxShape* pShape = xShape.is() ? comphelper::getFromUnoTunnel<SvxShape>(xShape) : nullptr;
2379 if (pShape)
2381 xRet.clear();
2382 new SdXShape( pShape, this );
2383 xRet = xShape;
2384 xShape.clear();
2387 return xRet;
2390 uno::Reference< uno::XInterface > SAL_CALL SdXImpressDocument::createInstance( const OUString& aServiceSpecifier )
2392 return create(aServiceSpecifier, u""_ustr);
2395 css::uno::Reference<css::uno::XInterface>
2396 SdXImpressDocument::createInstanceWithArguments(
2397 OUString const & ServiceSpecifier,
2398 css::uno::Sequence<css::uno::Any> const & Arguments)
2400 OUString arg;
2401 if ((ServiceSpecifier == "com.sun.star.drawing.GraphicObjectShape"
2402 || ServiceSpecifier == "com.sun.star.drawing.AppletShape"
2403 || ServiceSpecifier == "com.sun.star.drawing.FrameShape"
2404 || ServiceSpecifier == "com.sun.star.drawing.OLE2Shape"
2405 || ServiceSpecifier == "com.sun.star.drawing.MediaShape"
2406 || ServiceSpecifier == "com.sun.star.drawing.PluginShape"
2407 || ServiceSpecifier == "com.sun.star.presentation.MediaShape")
2408 && Arguments.getLength() == 1 && (Arguments[0] >>= arg))
2410 return create(ServiceSpecifier, arg);
2412 return SvxFmMSFactory::createInstanceWithArguments(
2413 ServiceSpecifier, Arguments);
2416 uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getAvailableServiceNames()
2418 ::SolarMutexGuard aGuard;
2420 if( nullptr == mpDoc )
2421 throw lang::DisposedException();
2423 const uno::Sequence< OUString > aSNS_ORG( SvxFmMSFactory::getAvailableServiceNames() );
2425 uno::Sequence< OUString > aSNS_Common{ u"com.sun.star.drawing.DashTable"_ustr,
2426 u"com.sun.star.drawing.GradientTable"_ustr,
2427 u"com.sun.star.drawing.HatchTable"_ustr,
2428 u"com.sun.star.drawing.BitmapTable"_ustr,
2429 u"com.sun.star.drawing.TransparencyGradientTable"_ustr,
2430 u"com.sun.star.drawing.MarkerTable"_ustr,
2431 u"com.sun.star.text.NumberingRules"_ustr,
2432 u"com.sun.star.drawing.Background"_ustr,
2433 u"com.sun.star.document.Settings"_ustr,
2434 sUNO_Service_ImageMapRectangleObject,
2435 sUNO_Service_ImageMapCircleObject,
2436 sUNO_Service_ImageMapPolygonObject,
2437 u"com.sun.star.xml.NamespaceMap"_ustr,
2439 // Support creation of GraphicStorageHandler and EmbeddedObjectResolver
2440 u"com.sun.star.document.ExportGraphicStorageHandler"_ustr,
2441 u"com.sun.star.document.ImportGraphicStorageHandler"_ustr,
2442 u"com.sun.star.document.ExportEmbeddedObjectResolver"_ustr,
2443 u"com.sun.star.document.ImportEmbeddedObjectResolver"_ustr,
2444 u"com.sun.star.drawing.TableShape"_ustr };
2446 uno::Sequence< OUString > aSNS_Specific;
2448 if(mbImpressDoc)
2449 aSNS_Specific = { u"com.sun.star.presentation.TitleTextShape"_ustr,
2450 u"com.sun.star.presentation.OutlinerShape"_ustr,
2451 u"com.sun.star.presentation.SubtitleShape"_ustr,
2452 u"com.sun.star.presentation.GraphicObjectShape"_ustr,
2453 u"com.sun.star.presentation.ChartShape"_ustr,
2454 u"com.sun.star.presentation.PageShape"_ustr,
2455 u"com.sun.star.presentation.OLE2Shape"_ustr,
2456 u"com.sun.star.presentation.TableShape"_ustr,
2457 u"com.sun.star.presentation.OrgChartShape"_ustr,
2458 u"com.sun.star.presentation.NotesShape"_ustr,
2459 u"com.sun.star.presentation.HandoutShape"_ustr,
2460 u"com.sun.star.presentation.DocumentSettings"_ustr,
2461 u"com.sun.star.presentation.FooterShape"_ustr,
2462 u"com.sun.star.presentation.HeaderShape"_ustr,
2463 u"com.sun.star.presentation.SlideNumberShape"_ustr,
2464 u"com.sun.star.presentation.DateTimeShape"_ustr,
2465 u"com.sun.star.presentation.CalcShape"_ustr,
2466 u"com.sun.star.presentation.MediaShape"_ustr };
2467 else
2468 aSNS_Specific = { u"com.sun.star.drawing.DocumentSettings"_ustr };
2470 return comphelper::concatSequences( aSNS_ORG, aSNS_Common, aSNS_Specific );
2473 // lang::XServiceInfo
2474 OUString SAL_CALL SdXImpressDocument::getImplementationName()
2476 return u"SdXImpressDocument"_ustr;
2477 /* // Matching the .component information:
2478 return mbImpressDoc
2479 ? OUString("com.sun.star.comp.Draw.PresentationDocument")
2480 : OUString("com.sun.star.comp.Draw.DrawingDocument");
2484 sal_Bool SAL_CALL SdXImpressDocument::supportsService( const OUString& ServiceName )
2486 return cppu::supportsService(this, ServiceName);
2489 uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getSupportedServiceNames()
2491 ::SolarMutexGuard aGuard;
2493 return { u"com.sun.star.document.OfficeDocument"_ustr,
2494 u"com.sun.star.drawing.GenericDrawingDocument"_ustr,
2495 u"com.sun.star.drawing.DrawingDocumentFactory"_ustr,
2496 mbImpressDoc?u"com.sun.star.presentation.PresentationDocument"_ustr:u"com.sun.star.drawing.DrawingDocument"_ustr };
2499 // XPropertySet
2500 uno::Reference< beans::XPropertySetInfo > SAL_CALL SdXImpressDocument::getPropertySetInfo( )
2502 ::SolarMutexGuard aGuard;
2503 return mpPropSet->getPropertySetInfo();
2506 void SAL_CALL SdXImpressDocument::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
2508 ::SolarMutexGuard aGuard;
2510 if( nullptr == mpDoc )
2511 throw lang::DisposedException();
2513 const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName);
2515 switch( pEntry ? pEntry->nWID : -1 )
2517 case WID_MODEL_LANGUAGE:
2519 lang::Locale aLocale;
2520 if(!(aValue >>= aLocale))
2521 throw lang::IllegalArgumentException();
2523 mpDoc->SetLanguage( LanguageTag::convertToLanguageType(aLocale), EE_CHAR_LANGUAGE );
2524 break;
2526 case WID_MODEL_TABSTOP:
2528 sal_Int32 nValue = 0;
2529 if(!(aValue >>= nValue) || nValue < 0 )
2530 throw lang::IllegalArgumentException();
2532 mpDoc->SetDefaultTabulator(static_cast<sal_uInt16>(nValue));
2533 break;
2535 case WID_MODEL_VISAREA:
2537 SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh();
2538 if( !pEmbeddedObj )
2539 break;
2541 awt::Rectangle aVisArea;
2542 if( !(aValue >>= aVisArea) || (aVisArea.Width < 0) || (aVisArea.Height < 0) )
2543 throw lang::IllegalArgumentException();
2545 sal_Int32 nRight, nTop;
2546 if (o3tl::checked_add(aVisArea.X, aVisArea.Width, nRight) || o3tl::checked_add(aVisArea.Y, aVisArea.Height, nTop))
2547 throw lang::IllegalArgumentException();
2549 pEmbeddedObj->SetVisArea(::tools::Rectangle(aVisArea.X, aVisArea.Y, nRight, nTop));
2551 break;
2552 case WID_MODEL_CONTFOCUS:
2554 bool bFocus = false;
2555 if( !(aValue >>= bFocus ) )
2556 throw lang::IllegalArgumentException();
2557 mpDoc->SetAutoControlFocus( bFocus );
2559 break;
2560 case WID_MODEL_DSGNMODE:
2562 bool bMode = false;
2563 if( !(aValue >>= bMode ) )
2564 throw lang::IllegalArgumentException();
2565 mpDoc->SetOpenInDesignMode( bMode );
2567 break;
2568 case WID_MODEL_BUILDID:
2569 aValue >>= maBuildId;
2570 return;
2571 case WID_MODEL_MAPUNIT:
2572 case WID_MODEL_BASICLIBS:
2573 case WID_MODEL_RUNTIMEUID: // is read-only
2574 case WID_MODEL_DIALOGLIBS:
2575 case WID_MODEL_FONTS:
2576 throw beans::PropertyVetoException();
2577 case WID_MODEL_INTEROPGRABBAG:
2578 setGrabBagItem(aValue);
2579 break;
2580 case WID_MODEL_THEME:
2582 SdrModel& rModel = getSdrModelFromUnoModel();
2583 std::shared_ptr<model::Theme> pTheme = model::Theme::FromAny(aValue);
2584 rModel.setTheme(pTheme);
2586 break;
2587 default:
2588 throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
2591 SetModified();
2594 uno::Any SAL_CALL SdXImpressDocument::getPropertyValue( const OUString& PropertyName )
2596 ::SolarMutexGuard aGuard;
2598 uno::Any aAny;
2599 if( nullptr == mpDoc )
2600 throw lang::DisposedException();
2602 const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName);
2604 switch( pEntry ? pEntry->nWID : -1 )
2606 case WID_MODEL_LANGUAGE:
2608 LanguageType eLang = mpDoc->GetLanguage( EE_CHAR_LANGUAGE );
2609 aAny <<= LanguageTag::convertToLocale( eLang);
2610 break;
2612 case WID_MODEL_TABSTOP:
2613 aAny <<= static_cast<sal_Int32>(mpDoc->GetDefaultTabulator());
2614 break;
2615 case WID_MODEL_VISAREA:
2617 SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh();
2618 if( !pEmbeddedObj )
2619 break;
2621 const ::tools::Rectangle& aRect = pEmbeddedObj->GetVisArea();
2622 awt::Rectangle aVisArea( aRect.Left(), aRect.Top(), aRect.getOpenWidth(), aRect.getOpenHeight() );
2623 aAny <<= aVisArea;
2625 break;
2626 case WID_MODEL_MAPUNIT:
2628 SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh();
2629 if( !pEmbeddedObj )
2630 break;
2632 sal_Int16 nMeasureUnit = 0;
2633 SvxMapUnitToMeasureUnit( pEmbeddedObj->GetMapUnit(), nMeasureUnit );
2634 aAny <<= nMeasureUnit;
2636 break;
2637 case WID_MODEL_FORBCHARS:
2639 aAny <<= getForbiddenCharsTable();
2641 break;
2642 case WID_MODEL_CONTFOCUS:
2643 aAny <<= mpDoc->GetAutoControlFocus();
2644 break;
2645 case WID_MODEL_DSGNMODE:
2646 aAny <<= mpDoc->GetOpenInDesignMode();
2647 break;
2648 case WID_MODEL_BASICLIBS:
2649 aAny <<= mpDocShell->GetBasicContainer();
2650 break;
2651 case WID_MODEL_DIALOGLIBS:
2652 aAny <<= mpDocShell->GetDialogContainer();
2653 break;
2654 case WID_MODEL_RUNTIMEUID:
2655 aAny <<= getRuntimeUID();
2656 break;
2657 case WID_MODEL_BUILDID:
2658 return uno::Any( maBuildId );
2659 case WID_MODEL_HASVALIDSIGNATURES:
2660 aAny <<= hasValidSignatures();
2661 break;
2662 case WID_MODEL_ALLOWLINKUPDATE:
2664 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mpDocShell->getEmbeddedObjectContainer();
2665 aAny <<= rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
2666 break;
2668 case WID_MODEL_FONTS:
2670 uno::Sequence<uno::Any> aSeq;
2671 int nSeqIndex = 0;
2673 sal_uInt16 const aWhichIds[] { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK,
2674 EE_CHAR_FONTINFO_CTL };
2676 const SfxItemPool& rPool = mpDoc->GetPool();
2678 for(sal_uInt16 nWhichId : aWhichIds)
2680 ItemSurrogates aSurrogates;
2681 rPool.GetItemSurrogates(aSurrogates, nWhichId);
2682 const sal_uInt32 nItems(aSurrogates.size());
2684 aSeq.realloc( aSeq.getLength() + nItems*5 + 5 );
2685 auto pSeq = aSeq.getArray();
2687 for (const SfxPoolItem* pItem : aSurrogates)
2689 const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem);
2691 pSeq[nSeqIndex++] <<= pFont->GetFamilyName();
2692 pSeq[nSeqIndex++] <<= pFont->GetStyleName();
2693 pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetFamily());
2694 pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetPitch());
2695 pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetCharSet());
2698 const SvxFontItem& rFont = static_cast<const SvxFontItem&>(rPool.GetUserOrPoolDefaultItem( nWhichId ));
2700 pSeq[nSeqIndex++] <<= rFont.GetFamilyName();
2701 pSeq[nSeqIndex++] <<= rFont.GetStyleName();
2702 pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetFamily());
2703 pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetPitch());
2704 pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetCharSet());
2708 aSeq.realloc( nSeqIndex );
2709 aAny <<= aSeq;
2710 break;
2712 case WID_MODEL_INTEROPGRABBAG:
2713 getGrabBagItem(aAny);
2714 break;
2715 case WID_MODEL_THEME:
2717 SdrModel& rModel = getSdrModelFromUnoModel();
2718 auto const& pTheme = rModel.getTheme();
2719 if (pTheme)
2721 pTheme->ToAny(aAny);
2723 else
2725 beans::PropertyValues aValues;
2726 aAny <<= aValues;
2728 break;
2730 default:
2731 throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
2734 return aAny;
2737 void SAL_CALL SdXImpressDocument::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
2738 void SAL_CALL SdXImpressDocument::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
2739 void SAL_CALL SdXImpressDocument::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
2740 void SAL_CALL SdXImpressDocument::removeVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
2742 // XLinkTargetSupplier
2743 uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLinks()
2745 ::SolarMutexGuard aGuard;
2747 if( nullptr == mpDoc )
2748 throw lang::DisposedException();
2750 rtl::Reference< SdDocLinkTargets > xLinks( mxLinks );
2751 if( !xLinks.is() )
2753 xLinks = new SdDocLinkTargets( *this );
2754 mxLinks = xLinks.get();
2756 return xLinks;
2759 // XStyleFamiliesSupplier
2760 uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getStyleFamilies( )
2762 ::SolarMutexGuard aGuard;
2764 if( nullptr == mpDoc )
2765 throw lang::DisposedException();
2767 uno::Reference< container::XNameAccess > xStyles( static_cast< OWeakObject* >( mpDoc->GetStyleSheetPool() ), css::uno::UNO_QUERY );
2768 return xStyles;
2771 // XAnyCompareFactory
2772 uno::Reference< css::ucb::XAnyCompare > SAL_CALL SdXImpressDocument::createAnyCompareByName( const OUString& )
2774 return SvxCreateNumRuleCompare();
2777 // XRenderable
2778 sal_Int32 SAL_CALL SdXImpressDocument::getRendererCount( const uno::Any& rSelection,
2779 const uno::Sequence< beans::PropertyValue >& )
2781 ::SolarMutexGuard aGuard;
2782 sal_Int32 nRet = 0;
2784 if( nullptr == mpDoc )
2785 throw lang::DisposedException();
2787 if (mpDocShell)
2789 uno::Reference< frame::XModel > xModel;
2791 rSelection >>= xModel;
2793 if( xModel == mpDocShell->GetModel() )
2794 nRet = mpDoc->GetSdPageCount( PageKind::Standard );
2795 else
2797 uno::Reference< drawing::XShapes > xShapes;
2799 rSelection >>= xShapes;
2801 if( xShapes.is() && xShapes->getCount() )
2802 nRet = 1;
2805 return nRet;
2808 uno::Sequence< beans::PropertyValue > SAL_CALL SdXImpressDocument::getRenderer( sal_Int32 , const uno::Any& ,
2809 const uno::Sequence< beans::PropertyValue >& rxOptions )
2811 ::SolarMutexGuard aGuard;
2813 if( nullptr == mpDoc )
2814 throw lang::DisposedException();
2816 bool bExportNotesPages = false;
2817 for( const auto& rOption : rxOptions )
2819 if ( rOption.Name == "ExportNotesPages" )
2820 rOption.Value >>= bExportNotesPages;
2822 uno::Sequence< beans::PropertyValue > aRenderer;
2823 if (mpDocShell)
2825 awt::Size aPageSize;
2826 if ( bExportNotesPages )
2828 Size aNotesPageSize = mpDoc->GetSdPage( 0, PageKind::Notes )->GetSize();
2829 aPageSize = awt::Size( aNotesPageSize.Width(), aNotesPageSize.Height() );
2831 else
2833 const ::tools::Rectangle aVisArea( mpDocShell->GetVisArea( embed::Aspects::MSOLE_DOCPRINT ) );
2834 aPageSize = awt::Size( aVisArea.GetWidth(), aVisArea.GetHeight() );
2836 aRenderer = { comphelper::makePropertyValue(u"PageSize"_ustr, aPageSize) };
2838 return aRenderer;
2841 namespace {
2843 class ImplRenderPaintProc : public sdr::contact::ViewObjectContactRedirector
2845 const SdrLayerAdmin& rLayerAdmin;
2846 SdrPageView* pSdrPageView;
2848 public:
2849 bool IsVisible ( const SdrObject* pObj ) const;
2850 bool IsPrintable( const SdrObject* pObj ) const;
2852 ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView* pView);
2854 // all default implementations just call the same methods at the original. To do something
2855 // different, override the method and at least do what the method does.
2856 virtual void createRedirectedPrimitive2DSequence(
2857 const sdr::contact::ViewObjectContact& rOriginal,
2858 const sdr::contact::DisplayInfo& rDisplayInfo,
2859 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) override;
2864 ImplRenderPaintProc::ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView *const pView)
2865 : rLayerAdmin(rLA)
2866 , pSdrPageView(pView)
2870 static sal_Int32 ImplPDFGetBookmarkPage( const OUString& rBookmark, SdDrawDocument const & rDoc )
2872 sal_Int32 nPage = -1;
2874 OUString aBookmark( rBookmark );
2876 if( rBookmark.startsWith("#") )
2877 aBookmark = rBookmark.copy( 1 );
2879 // is the bookmark a page ?
2880 bool bIsMasterPage;
2881 sal_uInt16 nPgNum = rDoc.GetPageByName( aBookmark, bIsMasterPage );
2883 if ( nPgNum == SDRPAGE_NOTFOUND )
2885 // is the bookmark an object ?
2886 SdrObject* pObj = rDoc.GetObj( aBookmark );
2887 if (pObj)
2888 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
2890 if ( nPgNum != SDRPAGE_NOTFOUND )
2891 nPage = ( nPgNum - 1 ) / 2;
2892 return nPage;
2895 static void ImplPDFExportComments( const uno::Reference< drawing::XDrawPage >& xPage, vcl::PDFExtOutDevData& rPDFExtOutDevData )
2899 uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xPage, uno::UNO_QUERY_THROW );
2900 uno::Reference< office::XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() );
2902 while( xAnnotationEnumeration->hasMoreElements() )
2904 uno::Reference<office::XAnnotation> xAnnotation(xAnnotationEnumeration->nextElement());
2906 geometry::RealPoint2D aRealPoint2D(xAnnotation->getPosition());
2907 geometry::RealSize2D aRealSize2D(xAnnotation->getSize());
2909 Point aPoint(aRealPoint2D.X * 100.0, aRealPoint2D.Y * 100.0);
2910 Size aSize(aRealSize2D.Width * 100.0, aRealSize2D.Height * 100.0);
2912 Point aPopupPoint(aPoint.X(), aPoint.Y());
2913 Size aPopupSize(aSize.Width() * 10.0, aSize.Height() * 10.0);
2915 uno::Reference<text::XText> xText(xAnnotation->getTextRange());
2917 vcl::pdf::PDFNote aNote;
2918 aNote.maTitle = xAnnotation->getAuthor();
2919 aNote.maContents = xText->getString();
2920 aNote.maModificationDate = xAnnotation->getDateTime();
2921 auto* pAnnotation = dynamic_cast<sd::Annotation*>(xAnnotation.get());
2923 if (pAnnotation && pAnnotation->getCreationInfo().meType != sdr::annotation::AnnotationType::None)
2925 sdr::annotation::CreationInfo const& rCreation = pAnnotation->getCreationInfo();
2926 aNote.maPolygons = rCreation.maPolygons;
2927 aNote.maAnnotationColor = rCreation.maColor;
2928 aNote.maInteriorColor = rCreation.maFillColor;
2929 aNote.mfWidth = rCreation.mnWidth;
2930 switch (rCreation.meType)
2932 case sdr::annotation::AnnotationType::Square:
2933 aNote.meType = vcl::pdf::PDFAnnotationSubType::Square; break;
2934 case sdr::annotation::AnnotationType::Circle:
2935 aNote.meType = vcl::pdf::PDFAnnotationSubType::Circle; break;
2936 case sdr::annotation::AnnotationType::Polygon:
2937 aNote.meType = vcl::pdf::PDFAnnotationSubType::Polygon; break;
2938 case sdr::annotation::AnnotationType::Ink:
2939 aNote.meType = vcl::pdf::PDFAnnotationSubType::Ink; break;
2940 case sdr::annotation::AnnotationType::Highlight:
2941 aNote.meType = vcl::pdf::PDFAnnotationSubType::Highlight; break;
2942 case sdr::annotation::AnnotationType::Line:
2943 aNote.meType = vcl::pdf::PDFAnnotationSubType::Line; break;
2944 case sdr::annotation::AnnotationType::FreeText:
2945 aNote.meType = vcl::pdf::PDFAnnotationSubType::FreeText; break;
2946 default:
2947 aNote.meType = vcl::pdf::PDFAnnotationSubType::Text;
2948 break;
2952 rPDFExtOutDevData.CreateNote(::tools::Rectangle(aPoint, aSize), aNote,
2953 ::tools::Rectangle(aPopupPoint, aPopupSize));
2956 catch (const uno::Exception&)
2961 static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape >& xShape, SdDrawDocument& rDoc, vcl::PDFExtOutDevData& rPDFExtOutDevData )
2963 if ( xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
2965 uno::Reference< container::XIndexAccess > xIndexAccess( xShape, uno::UNO_QUERY );
2966 if ( xIndexAccess.is() )
2968 sal_Int32 i, nCount = xIndexAccess->getCount();
2969 for ( i = 0; i < nCount; i++ )
2971 uno::Reference< drawing::XShape > xSubShape( xIndexAccess->getByIndex( i ), uno::UNO_QUERY );
2972 if ( xSubShape.is() )
2973 ImplPDFExportShapeInteraction( xSubShape, rDoc, rPDFExtOutDevData );
2977 else
2979 uno::Reference< beans::XPropertySet > xShapePropSet( xShape, uno::UNO_QUERY );
2980 if( xShapePropSet.is() )
2982 Size aPageSize( rDoc.GetSdPage( 0, PageKind::Standard )->GetSize() );
2983 Point aPoint( 0, 0 );
2984 ::tools::Rectangle aPageRect( aPoint, aPageSize );
2986 awt::Point aShapePos( xShape->getPosition() );
2987 awt::Size aShapeSize( xShape->getSize() );
2988 ::tools::Rectangle aLinkRect( Point( aShapePos.X, aShapePos.Y ), Size( aShapeSize.Width, aShapeSize.Height ) );
2990 // Handle linked videos.
2991 if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape" || xShape->getShapeType() == "com.sun.star.presentation.MediaShape")
2993 OUString title;
2994 xShapePropSet->getPropertyValue(u"Title"_ustr) >>= title;
2995 OUString description;
2996 xShapePropSet->getPropertyValue(u"Description"_ustr) >>= description;
2997 OUString const altText(title.isEmpty()
2998 ? description
2999 : description.isEmpty()
3000 ? title
3001 : OUString::Concat(title) + OUString::Concat("\n") + OUString::Concat(description));
3003 OUString aMediaURL;
3004 xShapePropSet->getPropertyValue(u"MediaURL"_ustr) >>= aMediaURL;
3005 if (!aMediaURL.isEmpty())
3007 SdrObject const*const pSdrObj(SdrObject::getSdrObjectFromXShape(xShape));
3008 OUString const mimeType(xShapePropSet->getPropertyValue(u"MediaMimeType"_ustr).get<OUString>());
3009 sal_Int32 nScreenId = rPDFExtOutDevData.CreateScreen(aLinkRect, altText, mimeType, rPDFExtOutDevData.GetCurrentPageNumber(), pSdrObj);
3010 if (aMediaURL.startsWith("vnd.sun.star.Package:"))
3012 OUString aTempFileURL;
3013 xShapePropSet->getPropertyValue(u"PrivateTempFileURL"_ustr) >>= aTempFileURL;
3014 rPDFExtOutDevData.SetScreenStream(nScreenId, aTempFileURL);
3016 else
3017 rPDFExtOutDevData.SetScreenURL(nScreenId, aMediaURL);
3021 presentation::ClickAction eCa;
3022 uno::Any aAny( xShapePropSet->getPropertyValue( u"OnClick"_ustr ) );
3023 if ( aAny >>= eCa )
3025 OUString const actionName(SdResId(SdTPAction::GetClickActionSdResId(eCa)));
3026 switch ( eCa )
3028 case presentation::ClickAction_LASTPAGE :
3030 sal_Int32 nCount = rDoc.GetSdPageCount( PageKind::Standard );
3031 sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nCount - 1, vcl::PDFWriter::DestAreaType::FitRectangle );
3032 sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
3033 rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
3035 break;
3036 case presentation::ClickAction_FIRSTPAGE :
3038 sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, 0, vcl::PDFWriter::DestAreaType::FitRectangle );
3039 sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
3040 rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
3042 break;
3043 case presentation::ClickAction_PREVPAGE :
3045 sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber();
3046 if ( nDestPage )
3047 nDestPage--;
3048 sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle );
3049 sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
3050 rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
3052 break;
3053 case presentation::ClickAction_NEXTPAGE :
3055 sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber() + 1;
3056 sal_Int32 nLastPage = rDoc.GetSdPageCount( PageKind::Standard ) - 1;
3057 if ( nDestPage > nLastPage )
3058 nDestPage = nLastPage;
3059 sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle );
3060 sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
3061 rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
3063 break;
3065 case presentation::ClickAction_PROGRAM :
3066 case presentation::ClickAction_BOOKMARK :
3067 case presentation::ClickAction_DOCUMENT :
3069 OUString aBookmark;
3070 xShapePropSet->getPropertyValue( u"Bookmark"_ustr ) >>= aBookmark;
3071 if( !aBookmark.isEmpty() )
3073 switch( eCa )
3075 case presentation::ClickAction_DOCUMENT :
3076 case presentation::ClickAction_PROGRAM :
3078 sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
3079 rPDFExtOutDevData.SetLinkURL( nLinkId, aBookmark );
3081 break;
3082 case presentation::ClickAction_BOOKMARK :
3084 sal_Int32 nPage = ImplPDFGetBookmarkPage( aBookmark, rDoc );
3085 if ( nPage != -1 )
3087 sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle );
3088 sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName);
3089 rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId );
3092 break;
3093 default:
3094 break;
3098 break;
3100 case presentation::ClickAction_STOPPRESENTATION :
3101 case presentation::ClickAction_SOUND :
3102 case presentation::ClickAction_INVISIBLE :
3103 case presentation::ClickAction_VERB :
3104 case presentation::ClickAction_VANISH :
3105 case presentation::ClickAction_MACRO :
3106 default :
3107 break;
3114 void ImplRenderPaintProc::createRedirectedPrimitive2DSequence(
3115 const sdr::contact::ViewObjectContact& rOriginal,
3116 const sdr::contact::DisplayInfo& rDisplayInfo,
3117 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor)
3119 SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
3120 if(!pObject)
3122 // not an object, maybe a page
3123 sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor);
3124 return;
3126 SdrPage* pSdrPage(pObject->getSdrPageFromSdrObject());
3127 if(!pSdrPage)
3128 return;
3129 if(!pSdrPage->checkVisibility(rOriginal, rDisplayInfo, false))
3130 return;
3131 if(!IsVisible(pObject) || !IsPrintable(pObject))
3132 return;
3134 sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor);
3137 bool ImplRenderPaintProc::IsVisible( const SdrObject* pObj ) const
3139 bool bVisible = true;
3140 SdrLayerID nLayerId = pObj->GetLayer();
3141 if( pSdrPageView )
3143 const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId );
3144 if ( pSdrLayer )
3146 const OUString& aLayerName = pSdrLayer->GetName();
3147 bVisible = pSdrPageView->IsLayerVisible( aLayerName );
3150 return bVisible;
3152 bool ImplRenderPaintProc::IsPrintable( const SdrObject* pObj ) const
3154 bool bPrintable = true;
3155 SdrLayerID nLayerId = pObj->GetLayer();
3156 if( pSdrPageView )
3158 const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId );
3159 if ( pSdrLayer )
3161 const OUString& aLayerName = pSdrLayer->GetName();
3162 bPrintable = pSdrPageView->IsLayerPrintable( aLayerName );
3165 return bPrintable;
3169 namespace
3171 sal_Int16 CalcOutputPageNum(vcl::PDFExtOutDevData const * pPDFExtOutDevData, SdDrawDocument const *pDoc, sal_Int16 nPageNumber)
3173 //export all pages, simple one to one case
3174 if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides())
3175 return nPageNumber-1;
3176 //check all preceding pages, and only count non-hidden ones
3177 sal_Int16 nRet = 0;
3178 for (sal_Int16 i = 0; i < nPageNumber-1; ++i)
3180 if (!pDoc->GetSdPage(i, PageKind::Standard)->IsExcluded())
3181 ++nRet;
3183 return nRet;
3187 void SAL_CALL SdXImpressDocument::render( sal_Int32 nRenderer, const uno::Any& rSelection,
3188 const uno::Sequence< beans::PropertyValue >& rxOptions )
3190 ::SolarMutexGuard aGuard;
3192 if( nullptr == mpDoc )
3193 throw lang::DisposedException();
3195 if (!mpDocShell)
3196 return;
3198 uno::Reference< awt::XDevice > xRenderDevice;
3199 const sal_Int32 nPageNumber = nRenderer + 1;
3200 PageKind ePageKind = PageKind::Standard;
3201 bool bExportNotesPages = false;
3203 for( const auto& rOption : rxOptions )
3205 if ( rOption.Name == "RenderDevice" )
3206 rOption.Value >>= xRenderDevice;
3207 else if ( rOption.Name == "ExportNotesPages" )
3209 rOption.Value >>= bExportNotesPages;
3210 if ( bExportNotesPages )
3211 ePageKind = PageKind::Notes;
3215 if( !(xRenderDevice.is() && nPageNumber && ( nPageNumber <= mpDoc->GetSdPageCount( ePageKind ) )) )
3216 return;
3218 VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>( xRenderDevice.get() );
3219 VclPtr< OutputDevice> pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >();
3221 if( !pOut )
3222 return;
3224 vcl::PDFExtOutDevData* pPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData* >( pOut->GetExtOutDevData() );
3226 if ( mpDoc->GetSdPage(static_cast<sal_Int16>(nPageNumber)-1, PageKind::Standard)->IsExcluded() &&
3227 !(pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides()) )
3228 return;
3230 if (pPDFExtOutDevData)
3232 css::lang::Locale const docLocale(Application::GetSettings().GetLanguageTag().getLocale());
3233 pPDFExtOutDevData->SetDocumentLocale(docLocale);
3236 ::sd::ClientView aView( mpDocShell, pOut );
3237 ::tools::Rectangle aVisArea( Point(), mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1, ePageKind )->GetSize() );
3238 vcl::Region aRegion( aVisArea );
3240 ::sd::ViewShell* pOldViewSh = mpDocShell->GetViewShell();
3241 ::sd::View* pOldSdView = pOldViewSh ? pOldViewSh->GetView() : nullptr;
3243 if ( pOldSdView )
3244 pOldSdView->SdrEndTextEdit();
3246 aView.SetHlplVisible( false );
3247 aView.SetGridVisible( false );
3248 aView.SetBordVisible( false );
3249 aView.SetPageVisible( false );
3250 aView.SetGlueVisible( false );
3252 pOut->SetMapMode(MapMode(MapUnit::Map100thMM));
3253 pOut->IntersectClipRegion( aVisArea );
3255 uno::Reference< frame::XModel > xModel;
3256 rSelection >>= xModel;
3258 if( xModel == mpDocShell->GetModel() )
3260 aView.ShowSdrPage( mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1, ePageKind ));
3261 SdrPageView* pPV = aView.GetSdrPageView();
3263 if( pOldSdView )
3265 SdrPageView* pOldPV = pOldSdView->GetSdrPageView();
3266 if( pPV && pOldPV )
3268 pPV->SetVisibleLayers( pOldPV->GetVisibleLayers() );
3269 pPV->SetPrintableLayers( pOldPV->GetPrintableLayers() );
3273 ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(),
3274 pPV);
3276 // background color for outliner :o
3277 SdPage* pPage = pPV ? static_cast<SdPage*>(pPV->GetPage()) : nullptr;
3278 if( pPage )
3280 SdrOutliner& rOutl = mpDoc->GetDrawOutliner();
3281 bool bScreenDisplay(true);
3283 // #i75566# printing; suppress AutoColor BackgroundColor generation
3284 // for visibility reasons by giving GetPageBackgroundColor()
3285 // the needed hint
3286 // #i75566# PDF export; suppress AutoColor BackgroundColor generation (see printing)
3287 if (pOut && ((OUTDEV_PRINTER == pOut->GetOutDevType())
3288 || (OUTDEV_PDF == pOut->GetOutDevType())))
3289 bScreenDisplay = false;
3291 // #i75566# Name change GetBackgroundColor -> GetPageBackgroundColor and
3292 // hint value if screen display. Only then the AutoColor mechanisms shall be applied
3293 rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor( pPV, bScreenDisplay ) );
3296 // produce link annots for media shapes before painting them
3297 if ( pPDFExtOutDevData && pPage )
3301 uno::Any aAny;
3302 uno::Reference< drawing::XDrawPage > xPage( uno::Reference< drawing::XDrawPage >::query( pPage->getUnoPage() ) );
3303 if ( xPage.is() )
3305 if ( pPDFExtOutDevData->GetIsExportNotes() )
3306 ImplPDFExportComments( xPage, *pPDFExtOutDevData );
3307 uno::Reference< beans::XPropertySet > xPagePropSet( xPage, uno::UNO_QUERY );
3308 if( xPagePropSet.is() )
3310 // exporting object interactions to pdf
3312 // if necessary, the master page interactions will be exported first
3313 bool bIsBackgroundObjectsVisible = false; // #i39428# IsBackgroundObjectsVisible not available for Draw
3314 if ( mbImpressDoc && xPagePropSet->getPropertySetInfo()->hasPropertyByName( u"IsBackgroundObjectsVisible"_ustr ) )
3315 xPagePropSet->getPropertyValue( u"IsBackgroundObjectsVisible"_ustr ) >>= bIsBackgroundObjectsVisible;
3316 if ( bIsBackgroundObjectsVisible && !pPDFExtOutDevData->GetIsExportNotesPages() )
3318 uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( xPage, uno::UNO_QUERY );
3319 if ( xMasterPageTarget.is() )
3321 uno::Reference< drawing::XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage();
3322 if ( xMasterPage.is() )
3324 sal_Int32 i, nCount = xMasterPage->getCount();
3325 for ( i = 0; i < nCount; i++ )
3327 aAny = xMasterPage->getByIndex( i );
3328 uno::Reference< drawing::XShape > xShape;
3329 if ( aAny >>= xShape )
3330 ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData );
3336 // exporting slide page object interactions
3337 sal_Int32 i, nCount = xPage->getCount();
3338 for ( i = 0; i < nCount; i++ )
3340 aAny = xPage->getByIndex( i );
3341 uno::Reference< drawing::XShape > xShape;
3342 if ( aAny >>= xShape )
3343 ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData );
3346 // exporting transition effects to pdf
3347 if ( mbImpressDoc && !pPDFExtOutDevData->GetIsExportNotesPages() && pPDFExtOutDevData->GetIsExportTransitionEffects() )
3349 static constexpr OUString sEffect( u"Effect"_ustr );
3350 static constexpr OUString sSpeed ( u"Speed"_ustr );
3351 sal_Int32 nTime = 800;
3352 presentation::AnimationSpeed aAs;
3353 if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) )
3355 aAny = xPagePropSet->getPropertyValue( sSpeed );
3356 if ( aAny >>= aAs )
3358 switch( aAs )
3360 case presentation::AnimationSpeed_SLOW : nTime = 1500; break;
3361 case presentation::AnimationSpeed_FAST : nTime = 300; break;
3362 default:
3363 case presentation::AnimationSpeed_MEDIUM : nTime = 800;
3367 presentation::FadeEffect eFe;
3368 vcl::PDFWriter::PageTransition eType = vcl::PDFWriter::PageTransition::Regular;
3369 if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) )
3371 aAny = xPagePropSet->getPropertyValue( sEffect );
3372 if ( aAny >>= eFe )
3374 switch( eFe )
3376 case presentation::FadeEffect_HORIZONTAL_LINES :
3377 case presentation::FadeEffect_HORIZONTAL_CHECKERBOARD :
3378 case presentation::FadeEffect_HORIZONTAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsHorizontal; break;
3380 case presentation::FadeEffect_VERTICAL_LINES :
3381 case presentation::FadeEffect_VERTICAL_CHECKERBOARD :
3382 case presentation::FadeEffect_VERTICAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsVertical; break;
3384 case presentation::FadeEffect_UNCOVER_TO_RIGHT :
3385 case presentation::FadeEffect_UNCOVER_TO_UPPERRIGHT :
3386 case presentation::FadeEffect_ROLL_FROM_LEFT :
3387 case presentation::FadeEffect_FADE_FROM_UPPERLEFT :
3388 case presentation::FadeEffect_MOVE_FROM_UPPERLEFT :
3389 case presentation::FadeEffect_FADE_FROM_LEFT :
3390 case presentation::FadeEffect_MOVE_FROM_LEFT : eType = vcl::PDFWriter::PageTransition::WipeLeftToRight; break;
3392 case presentation::FadeEffect_UNCOVER_TO_BOTTOM :
3393 case presentation::FadeEffect_UNCOVER_TO_LOWERRIGHT :
3394 case presentation::FadeEffect_ROLL_FROM_TOP :
3395 case presentation::FadeEffect_FADE_FROM_UPPERRIGHT :
3396 case presentation::FadeEffect_MOVE_FROM_UPPERRIGHT :
3397 case presentation::FadeEffect_FADE_FROM_TOP :
3398 case presentation::FadeEffect_MOVE_FROM_TOP : eType = vcl::PDFWriter::PageTransition::WipeTopToBottom; break;
3400 case presentation::FadeEffect_UNCOVER_TO_LEFT :
3401 case presentation::FadeEffect_UNCOVER_TO_LOWERLEFT :
3402 case presentation::FadeEffect_ROLL_FROM_RIGHT :
3404 case presentation::FadeEffect_FADE_FROM_LOWERRIGHT :
3405 case presentation::FadeEffect_MOVE_FROM_LOWERRIGHT :
3406 case presentation::FadeEffect_FADE_FROM_RIGHT :
3407 case presentation::FadeEffect_MOVE_FROM_RIGHT : eType = vcl::PDFWriter::PageTransition::WipeRightToLeft; break;
3409 case presentation::FadeEffect_UNCOVER_TO_TOP :
3410 case presentation::FadeEffect_UNCOVER_TO_UPPERLEFT :
3411 case presentation::FadeEffect_ROLL_FROM_BOTTOM :
3412 case presentation::FadeEffect_FADE_FROM_LOWERLEFT :
3413 case presentation::FadeEffect_MOVE_FROM_LOWERLEFT :
3414 case presentation::FadeEffect_FADE_FROM_BOTTOM :
3415 case presentation::FadeEffect_MOVE_FROM_BOTTOM : eType = vcl::PDFWriter::PageTransition::WipeBottomToTop; break;
3417 case presentation::FadeEffect_OPEN_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalInward; break;
3418 case presentation::FadeEffect_CLOSE_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalOutward; break;
3420 case presentation::FadeEffect_OPEN_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalInward; break;
3421 case presentation::FadeEffect_CLOSE_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalOutward; break;
3423 case presentation::FadeEffect_FADE_TO_CENTER : eType = vcl::PDFWriter::PageTransition::BoxInward; break;
3424 case presentation::FadeEffect_FADE_FROM_CENTER : eType = vcl::PDFWriter::PageTransition::BoxOutward; break;
3426 case presentation::FadeEffect_NONE : eType = vcl::PDFWriter::PageTransition::Regular; break;
3428 case presentation::FadeEffect_RANDOM :
3429 case presentation::FadeEffect_DISSOLVE :
3430 default: eType = vcl::PDFWriter::PageTransition::Dissolve; break;
3435 if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) ||
3436 xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) )
3438 pPDFExtOutDevData->SetPageTransition( eType, nTime );
3444 catch (const uno::Exception&)
3449 aView.SdrPaintView::CompleteRedraw(pOut, aRegion, &aImplRenderPaintProc);
3451 if (pPDFExtOutDevData && pPage)
3455 Size aPageSize( mpDoc->GetSdPage( 0, PageKind::Standard )->GetSize() );
3456 Point aPoint( 0, 0 );
3457 ::tools::Rectangle aPageRect( aPoint, aPageSize );
3459 // resolving links found in this page by the method ImpEditEngine::Paint
3460 std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks();
3461 for ( const auto& rBookmark : rBookmarks )
3463 sal_Int32 nPage = ImplPDFGetBookmarkPage( rBookmark.aBookmark, *mpDoc );
3464 if ( nPage != -1 )
3466 if ( rBookmark.nLinkId != -1 )
3467 pPDFExtOutDevData->SetLinkDest( rBookmark.nLinkId, pPDFExtOutDevData->CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ) );
3468 else
3469 pPDFExtOutDevData->DescribeRegisteredDest( rBookmark.nDestId, aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle );
3471 else
3472 pPDFExtOutDevData->SetLinkURL( rBookmark.nLinkId, rBookmark.aBookmark );
3474 rBookmarks.clear();
3475 //---> #i56629, #i40318
3476 //get the page name, will be used as outline element in PDF bookmark pane
3477 OUString aPageName = mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1 , PageKind::Standard )->GetName();
3478 if( !aPageName.isEmpty() )
3480 // Destination PageNum
3481 const sal_Int32 nDestPageNum = CalcOutputPageNum(pPDFExtOutDevData, mpDoc, nPageNumber);
3483 // insert the bookmark to this page into the NamedDestinations
3484 if( pPDFExtOutDevData->GetIsExportNamedDestinations() )
3485 pPDFExtOutDevData->CreateNamedDest(aPageName, aPageRect, nDestPageNum);
3487 // add the name to the outline, (almost) same code as in sc/source/ui/unoobj/docuno.cxx
3488 // issue #i40318.
3490 if( pPDFExtOutDevData->GetIsExportBookmarks() )
3492 // Destination Export
3493 const sal_Int32 nDestId =
3494 pPDFExtOutDevData->CreateDest(aPageRect , nDestPageNum);
3496 // Create a new outline item:
3497 pPDFExtOutDevData->CreateOutlineItem( -1 , aPageName, nDestId );
3500 //<--- #i56629, #i40318
3502 catch (const uno::Exception&)
3508 else
3510 uno::Reference< drawing::XShapes > xShapes;
3511 rSelection >>= xShapes;
3513 if( xShapes.is() && xShapes->getCount() )
3515 SdrPageView* pPV = nullptr;
3517 ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(),
3518 pOldSdView ? pOldSdView->GetSdrPageView() : nullptr);
3520 for( sal_uInt32 i = 0, nCount = xShapes->getCount(); i < nCount; i++ )
3522 uno::Reference< drawing::XShape > xShape;
3523 xShapes->getByIndex( i ) >>= xShape;
3525 if( xShape.is() )
3527 SdrObject* pObj = SdrObject::getSdrObjectFromXShape( xShape );
3528 if( pObj && pObj->getSdrPageFromSdrObject()
3529 && aImplRenderPaintProc.IsVisible( pObj )
3530 && aImplRenderPaintProc.IsPrintable( pObj ) )
3532 if( !pPV )
3533 pPV = aView.ShowSdrPage( pObj->getSdrPageFromSdrObject() );
3535 if( pPV )
3536 aView.MarkObj( pObj, pPV );
3540 aView.DrawMarkedObj(*pOut);
3545 DrawViewShell* SdXImpressDocument::GetViewShell()
3547 DrawViewShell* pViewSh = dynamic_cast<DrawViewShell*>(mpDocShell->GetViewShell());
3548 if (!pViewSh)
3550 SAL_WARN("sd", "DrawViewShell not available!");
3551 return nullptr;
3553 return pViewSh;
3556 void SdXImpressDocument::paintTile( VirtualDevice& rDevice,
3557 int nOutputWidth, int nOutputHeight,
3558 int nTilePosX, int nTilePosY,
3559 ::tools::Long nTileWidth, ::tools::Long nTileHeight )
3561 DrawViewShell* pViewSh = GetViewShell();
3562 if (!pViewSh)
3563 return;
3565 // we need to skip tile invalidation for controls on rendering
3566 comphelper::LibreOfficeKit::setTiledPainting(true);
3568 // Setup drawing layer to work properly. Since we use a custom VirtualDevice
3569 // for the drawing, SdrPaintView::BeginCompleteRedraw() will call FindPaintWindow()
3570 // unsuccessfully and use a temporary window that doesn't keep state. So patch
3571 // the existing SdrPageWindow to use a temporary, and this way the state will be kept.
3572 // Well, at least that's how I understand it based on Writer's RenderContextGuard,
3573 // as the drawing layer classes lack documentation.
3574 SdrPageWindow* patchedPageWindow = nullptr;
3575 SdrPaintWindow* previousPaintWindow = nullptr;
3576 std::unique_ptr<SdrPaintWindow> temporaryPaintWindow;
3577 if(SdrView* pDrawView = pViewSh->GetDrawView())
3579 if(SdrPageView* pSdrPageView = pDrawView->GetSdrPageView())
3581 pSdrPageView->SetApplicationDocumentColor(pViewSh->GetViewOptions().mnDocBackgroundColor);
3582 patchedPageWindow = pSdrPageView->FindPageWindow(*getDocWindow()->GetOutDev());
3583 temporaryPaintWindow.reset(new SdrPaintWindow(*pDrawView, rDevice));
3584 if (patchedPageWindow)
3585 previousPaintWindow = patchedPageWindow->patchPaintWindow(*temporaryPaintWindow);
3589 // Scaling. Must convert from pixels to twips. We know
3590 // that VirtualDevices use a DPI of 96.
3591 // We specifically calculate these scales first as we're still
3592 // in TWIPs, and might as well minimize the number of conversions.
3593 const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
3594 Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale;
3595 Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale;
3597 // svx seems to be the only component that works natively in
3598 // 100th mm rather than TWIP. It makes most sense just to
3599 // convert here and in getDocumentSize, and leave the tiled
3600 // rendering API working in TWIPs.
3601 ::tools::Long nTileWidthHMM = convertTwipToMm100( nTileWidth );
3602 ::tools::Long nTileHeightHMM = convertTwipToMm100( nTileHeight );
3603 int nTilePosXHMM = convertTwipToMm100( nTilePosX );
3604 int nTilePosYHMM = convertTwipToMm100( nTilePosY );
3606 MapMode aMapMode = rDevice.GetMapMode();
3607 aMapMode.SetMapUnit( MapUnit::Map100thMM );
3608 aMapMode.SetOrigin( Point( -nTilePosXHMM,
3609 -nTilePosYHMM) );
3610 aMapMode.SetScaleX( scaleX );
3611 aMapMode.SetScaleY( scaleY );
3613 rDevice.SetMapMode( aMapMode );
3615 rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight) );
3617 Point aPoint(nTilePosXHMM, nTilePosYHMM);
3618 Size aSize(nTileWidthHMM, nTileHeightHMM);
3619 ::tools::Rectangle aRect(aPoint, aSize);
3621 SdrView* pView = pViewSh->GetDrawView();
3622 if (comphelper::LibreOfficeKit::isActive())
3623 pView->SetPaintTextEdit(mbPaintTextEdit);
3625 pViewSh->GetView()->CompleteRedraw(&rDevice, vcl::Region(aRect));
3627 if (comphelper::LibreOfficeKit::isActive())
3628 pView->SetPaintTextEdit(true);
3630 LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
3631 nTilePosX, nTilePosY, nTileWidth, nTileHeight);
3632 LokStarMathHelper::PaintAllInPlaceOnTile(rDevice, nOutputWidth, nOutputHeight, nTilePosX,
3633 nTilePosY, nTileWidth, nTileHeight);
3635 if(patchedPageWindow != nullptr)
3636 patchedPageWindow->unpatchPaintWindow(previousPaintWindow);
3638 // Draw Form controls
3639 SdrView* pDrawView = pViewSh->GetDrawView();
3640 SdrPageView* pPageView = pDrawView->GetSdrPageView();
3641 if (pPageView != nullptr)
3643 SdrPage* pPage = pPageView->GetPage();
3644 ::sd::Window* pActiveWin = pViewSh->GetActiveWindow();
3645 ::tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
3646 Size aOutputSize(nOutputWidth, nOutputHeight);
3647 LokControlHandler::paintControlTile(pPage, pDrawView, *pActiveWin, rDevice, aOutputSize, aTileRect);
3650 comphelper::LibreOfficeKit::setTiledPainting(false);
3653 OString SdXImpressDocument::getViewRenderState(SfxViewShell* pViewShell)
3655 OStringBuffer aState;
3656 DrawViewShell* pView = nullptr;
3658 if (ViewShellBase* pShellBase = dynamic_cast<ViewShellBase*>(pViewShell))
3659 pView = dynamic_cast<DrawViewShell*>(pShellBase->GetMainViewShell().get());
3660 else
3661 pView = GetViewShell();
3663 if (pView)
3665 const SdViewOptions& pVOpt = pView->GetViewOptions();
3666 if (mpDoc->GetOnlineSpell())
3667 aState.append('S');
3668 if (pVOpt.mnDocBackgroundColor == svtools::ColorConfig::GetDefaultColor(svtools::DOCCOLOR, 1))
3669 aState.append('D');
3670 aState.append(';');
3672 OString aThemeName = OUStringToOString(pVOpt.msColorSchemeName, RTL_TEXTENCODING_UTF8);
3673 aState.append(aThemeName);
3675 return aState.makeStringAndClear();
3678 void SdXImpressDocument::selectPart(int nPart, int nSelect)
3680 DrawViewShell* pViewSh = GetViewShell();
3681 if (!pViewSh)
3682 return;
3684 pViewSh->SelectPage(nPart, nSelect);
3687 void SdXImpressDocument::moveSelectedParts(int nPosition, bool bDuplicate)
3689 // Duplicating is currently unsupported.
3690 if (!bDuplicate)
3691 mpDoc->MovePages(nPosition);
3694 OUString SdXImpressDocument::getPartInfo(int nPart)
3696 DrawViewShell* pViewSh = GetViewShell();
3697 if (!pViewSh)
3698 return OUString();
3700 const SdPage* pSdPage = mpDoc->GetSdPage(nPart, pViewSh->GetPageKind());
3701 const bool bIsVisible = pSdPage && !pSdPage->IsExcluded();
3702 const bool bIsSelected = pViewSh->IsSelected(nPart);
3703 const sal_Int16 nMasterPageCount= pViewSh->GetDoc()->GetMasterSdPageCount(pViewSh->GetPageKind());
3705 OUString aPartInfo = "{ \"visible\": \"" +
3706 OUString::number(static_cast<unsigned int>(bIsVisible)) +
3707 "\", \"selected\": \"" +
3708 OUString::number(static_cast<unsigned int>(bIsSelected)) +
3709 "\", \"masterPageCount\": \"" +
3710 OUString::number(nMasterPageCount) +
3711 "\", \"mode\": \"" +
3712 OUString::number(getEditMode()) +
3713 "\" }";
3715 return aPartInfo;
3718 void SdXImpressDocument::setPart( int nPart, bool bAllowChangeFocus )
3720 DrawViewShell* pViewSh = GetViewShell();
3721 if (!pViewSh)
3722 return;
3724 pViewSh->SwitchPage( nPart, bAllowChangeFocus );
3727 int SdXImpressDocument::getParts()
3729 if (!mpDoc)
3730 return 0;
3732 if (isMasterViewMode())
3733 return mpDoc->GetMasterSdPageCount(PageKind::Standard);
3735 return mpDoc->GetSdPageCount(PageKind::Standard);
3738 int SdXImpressDocument::getPart()
3740 DrawViewShell* pViewSh = GetViewShell();
3741 if (!pViewSh)
3742 return 0;
3744 return pViewSh->GetViewShellBase().getPart();
3747 OUString SdXImpressDocument::getPartName(int nPart)
3749 SdPage* pPage;
3750 if (isMasterViewMode())
3751 pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard);
3752 else
3753 pPage = mpDoc->GetSdPage(nPart, PageKind::Standard);
3755 if (!pPage)
3757 SAL_WARN("sd", "DrawViewShell not available!");
3758 return OUString();
3761 return pPage->GetName();
3764 OUString SdXImpressDocument::getPartHash(int nPart)
3766 SdPage* pPage;
3767 if (isMasterViewMode())
3768 pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard);
3769 else
3770 pPage = mpDoc->GetSdPage(nPart, PageKind::Standard);
3772 if (!pPage)
3774 SAL_WARN("sd", "DrawViewShell not available!");
3775 return OUString();
3778 uno::Reference<drawing::XDrawPage> xDrawPage(pPage->getUnoPage(), uno::UNO_QUERY);
3779 return OUString::fromUtf8(GetInterfaceHash(xDrawPage));
3782 bool SdXImpressDocument::isMasterViewMode()
3784 DrawViewShell* pViewSh = GetViewShell();
3785 if (!pViewSh)
3786 return false;
3788 if (pViewSh->GetDispatcher())
3790 SfxPoolItemHolder aResult;
3791 pViewSh->GetDispatcher()->QueryState(SID_SLIDE_MASTER_MODE, aResult);
3792 const SfxBoolItem* isMasterViewMode(static_cast<const SfxBoolItem*>(aResult.getItem()));
3793 if (isMasterViewMode && isMasterViewMode->GetValue())
3794 return true;
3796 return false;
3799 VclPtr<vcl::Window> SdXImpressDocument::getDocWindow()
3801 SolarMutexGuard aGuard;
3802 DrawViewShell* pViewShell = GetViewShell();
3803 if (!pViewShell)
3804 return {};
3806 if (VclPtr<vcl::Window> pWindow = SfxLokHelper::getInPlaceDocWindow(pViewShell->GetViewShell()))
3807 return pWindow;
3809 return pViewShell->GetActiveWindow();
3812 void SdXImpressDocument::setPartMode( int nPartMode )
3814 DrawViewShell* pViewSh = GetViewShell();
3815 if (!pViewSh)
3816 return;
3818 PageKind aPageKind( PageKind::Standard );
3819 switch ( nPartMode )
3821 case LOK_PARTMODE_SLIDES:
3822 break;
3823 case LOK_PARTMODE_NOTES:
3824 aPageKind = PageKind::Notes;
3825 break;
3827 pViewSh->SetPageKind( aPageKind );
3828 //TODO do the same as setEditMode and then can probably remove the TODOs
3829 //from doc_setPartMode
3832 int SdXImpressDocument::getEditMode()
3834 DrawViewShell* pViewSh = GetViewShell();
3835 if (!pViewSh)
3836 return 0;
3838 return pViewSh->GetViewShellBase().getEditMode();
3841 void SdXImpressDocument::setEditMode(int nMode)
3843 SolarMutexGuard aGuard;
3845 DrawViewShell* pViewSh = GetViewShell();
3846 if (!pViewSh)
3847 return;
3849 pViewSh->GetViewShellBase().setEditMode(nMode);
3852 Size SdXImpressDocument::getDocumentSize()
3854 DrawViewShell* pViewSh = GetViewShell();
3855 if (!pViewSh)
3856 return Size();
3858 SdrView *pSdrView = pViewSh->GetView();
3859 if (!pSdrView)
3860 return Size();
3862 SdrPageView* pCurPageView = pSdrView->GetSdrPageView();
3863 if (!pCurPageView)
3864 return Size();
3866 Size aSize = pCurPageView->GetPageRect().GetSize();
3867 // Convert the size in 100th mm to TWIP
3868 // See paintTile above for further info.
3869 return o3tl::convert(aSize, o3tl::Length::mm100, o3tl::Length::twip);
3872 void SdXImpressDocument::getPostIts(::tools::JsonWriter& rJsonWriter)
3874 auto commentsNode = rJsonWriter.startNode("comments");
3875 if (!mpDoc)
3876 return;
3877 // Return annotations on master pages too ?
3878 const sal_uInt16 nMaxPages = mpDoc->GetPageCount();
3879 for (sal_uInt16 nPage = 0; nPage < nMaxPages; ++nPage)
3881 SdrPage* pPage = mpDoc->GetPage(nPage);
3883 for (auto const& xAnnotation : pPage->getAnnotations())
3885 sal_uInt32 nID = xAnnotation->GetId();
3886 OString nodeName = "comment" + OString::number(nID);
3887 auto commentNode = rJsonWriter.startNode(nodeName);
3888 rJsonWriter.put("id", nID);
3889 rJsonWriter.put("author", xAnnotation->getAuthor());
3890 rJsonWriter.put("dateTime", utl::toISO8601(xAnnotation->getDateTime()));
3891 uno::Reference<text::XText> xText(xAnnotation->getTextRange());
3892 rJsonWriter.put("text", xText->getString());
3893 rJsonWriter.put("parthash", pPage->GetUniqueID());
3894 geometry::RealPoint2D const aPoint = xAnnotation->getPosition();
3895 geometry::RealSize2D const aSize = xAnnotation->getSize();
3896 ::tools::Rectangle aRectangle(Point(aPoint.X * 100.0, aPoint.Y * 100.0), Size(aSize.Width * 100.0, aSize.Height * 100.0));
3897 aRectangle = o3tl::toTwips(aRectangle, o3tl::Length::mm100);
3898 OString sRectangle = aRectangle.toString();
3899 rJsonWriter.put("rectangle", sRectangle.getStr());
3904 void SdXImpressDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
3906 SolarMutexGuard aGuard;
3908 OUString sThemeName;
3909 OUString sBackgroundThemeName;
3911 if (DrawViewShell* pViewShell = GetViewShell())
3913 DrawView* pDrawView = pViewShell->GetDrawView();
3914 for (const beans::PropertyValue& rValue : rArguments)
3916 if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>())
3917 pDrawView->SetPageShadowVisible(rValue.Value.get<bool>());
3918 else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>())
3919 pDrawView->SetAuthor(rValue.Value.get<OUString>());
3920 else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
3921 mpDoc->SetOnlineSpell(rValue.Value.get<bool>());
3922 else if (rValue.Name == ".uno:ChangeTheme" && rValue.Value.has<OUString>())
3923 sThemeName = rValue.Value.get<OUString>();
3924 else if (rValue.Name == ".uno:InvertBackground" && rValue.Value.has<OUString>())
3925 sBackgroundThemeName = rValue.Value.get<OUString>();
3928 // Disable comments if requested
3929 SdOptions* pOptions = SdModule::get()->GetSdOptions(mpDoc->GetDocumentType());
3930 pOptions->SetShowComments(comphelper::LibreOfficeKit::isTiledAnnotations());
3932 pViewShell->SetRuler(false);
3933 pViewShell->SetScrollBarsVisible(false);
3935 if (sd::Window* pWindow = pViewShell->GetActiveWindow())
3937 // get the full page size in pixels
3938 pWindow->EnableMapMode();
3939 Size aSize(pWindow->LogicToPixel(pDrawView->GetSdrPageView()->GetPage()->GetSize()));
3940 // Disable map mode, so that it's possible to send mouse event
3941 // coordinates in logic units
3942 pWindow->EnableMapMode(false);
3944 // arrange UI elements again with new view size
3945 pViewShell->GetParentWindow()->SetSizePixel(aSize);
3946 pViewShell->Resize();
3949 // Forces all images to be swapped in synchronously, this
3950 // ensures that images are available when paintTile is called
3951 // (whereas with async loading images start being loaded after
3952 // we have painted the tile, resulting in an invalidate, followed
3953 // by the tile being rerendered - which is wasteful and ugly).
3954 pDrawView->SetSwapAsynchron(false);
3957 // when the "This document may contain formatting or content that cannot
3958 // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
3959 // causing 'Save' being disabled; so let's always save to the original
3960 // format
3961 auto xChanges = comphelper::ConfigurationChanges::create();
3962 officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
3964 if (!o3tl::IsRunningUnitTest() || !comphelper::LibreOfficeKit::isActive())
3965 officecfg::Office::Impress::MultiPaneGUI::SlideSorterBar::Visible::ImpressView::set(true,xChanges);
3966 xChanges->commit();
3968 // if we know what theme the user wants, then we can dispatch that now early
3969 if (!sThemeName.isEmpty())
3971 css::uno::Sequence<css::beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
3973 { "NewTheme", uno::Any(sThemeName) }
3974 }));
3975 comphelper::dispatchCommand(u".uno:ChangeTheme"_ustr, aPropertyValues);
3977 if (!sBackgroundThemeName.isEmpty())
3979 css::uno::Sequence<css::beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
3981 { "NewTheme", uno::Any(sBackgroundThemeName) }
3982 }));
3983 comphelper::dispatchCommand(".uno:InvertBackground", aPropertyValues);
3987 void SdXImpressDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode)
3989 SolarMutexGuard aGuard;
3990 SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
3993 void SdXImpressDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
3995 SolarMutexGuard aGuard;
3997 DrawViewShell* pViewShell = GetViewShell();
3998 if (!pViewShell)
3999 return;
4001 constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px);
4003 if (SfxLokHelper::testInPlaceComponentMouseEventHit(
4004 pViewShell->GetViewShell(), nType, nX, nY, nCount, nButtons, nModifier, fScale, fScale))
4005 return;
4007 // try to forward mouse event to control
4008 const Point aPointTwip(nX, nY);
4009 const Point aPointHMM = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100);
4010 SdrView* pDrawView = pViewShell->GetDrawView();
4011 SdrPageView* pPageView = pDrawView->GetSdrPageView();
4012 SdrPage* pPage = pPageView->GetPage();
4013 ::sd::Window* pActiveWin = pViewShell->GetActiveWindow();
4014 if (!pActiveWin)
4016 return;
4019 if (LokControlHandler::postMouseEvent(pPage, pDrawView, *pActiveWin, nType, aPointHMM, nCount, nButtons, nModifier))
4020 return;
4022 LokMouseEventData aMouseEventData(nType, aPointHMM, nCount, MouseEventModifiers::SIMPLECLICK,
4023 nButtons, nModifier);
4024 SfxLokHelper::postMouseEventAsync(pViewShell->GetActiveWindow(), aMouseEventData);
4027 void SdXImpressDocument::setTextSelection(int nType, int nX, int nY)
4029 SolarMutexGuard aGuard;
4031 DrawViewShell* pViewShell = GetViewShell();
4032 if (!pViewShell)
4033 return;
4035 LokChartHelper aChartHelper(pViewShell->GetViewShell());
4036 if (aChartHelper.setTextSelection(nType, nX, nY))
4037 return;
4039 Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
4040 switch (nType)
4042 case LOK_SETTEXTSELECTION_START:
4043 pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
4044 break;
4045 case LOK_SETTEXTSELECTION_END:
4046 pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
4047 break;
4048 case LOK_SETTEXTSELECTION_RESET:
4049 pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
4050 break;
4051 default:
4052 assert(false);
4053 break;
4057 uno::Reference<datatransfer::XTransferable> SdXImpressDocument::getSelection()
4059 SolarMutexGuard aGuard;
4061 DrawViewShell* pViewShell = GetViewShell();
4062 if (!pViewShell)
4063 return uno::Reference<datatransfer::XTransferable>();
4065 return pViewShell->GetSelectionTransferable();
4068 void SdXImpressDocument::setGraphicSelection(int nType, int nX, int nY)
4070 SolarMutexGuard aGuard;
4072 DrawViewShell* pViewShell = GetViewShell();
4073 if (!pViewShell)
4074 return;
4076 constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px);
4078 LokChartHelper aChartHelper(pViewShell->GetViewShell());
4079 if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale))
4080 return;
4082 Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
4083 switch (nType)
4085 case LOK_SETGRAPHICSELECTION_START:
4086 pViewShell->SetGraphicMm100Position(/*bStart=*/true, aPoint);
4087 break;
4088 case LOK_SETGRAPHICSELECTION_END:
4089 pViewShell->SetGraphicMm100Position(/*bStart=*/false, aPoint);
4090 break;
4091 default:
4092 assert(false);
4093 break;
4097 void SdXImpressDocument::resetSelection()
4099 SolarMutexGuard aGuard;
4101 DrawViewShell* pViewShell = GetViewShell();
4102 if (!pViewShell)
4103 return;
4105 SdrView* pSdrView = pViewShell->GetView();
4106 if (!pSdrView)
4107 return;
4109 if (pSdrView->IsTextEdit())
4111 // Reset the editeng selection.
4112 pSdrView->UnmarkAll();
4113 // Finish editing.
4114 pSdrView->SdrEndTextEdit();
4116 // Reset graphic selection.
4117 pSdrView->UnmarkAll();
4120 void SdXImpressDocument::setClientVisibleArea(const ::tools::Rectangle& rRectangle)
4122 SolarMutexGuard aGuard;
4124 DrawViewShell* pViewShell = GetViewShell();
4125 if (!pViewShell)
4126 return;
4128 pViewShell->GetViewShellBase().setLOKVisibleArea(rRectangle);
4131 void SdXImpressDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
4133 SolarMutexGuard aGuard;
4135 DrawViewShell* pViewShell = GetViewShell();
4136 if (!pViewShell)
4137 return;
4139 pViewShell->GetActiveWindow()->SetClipboard(xClipboard);
4142 bool SdXImpressDocument::isMimeTypeSupported()
4144 SolarMutexGuard aGuard;
4145 DrawViewShell* pViewShell = GetViewShell();
4146 if (!pViewShell)
4147 return false;
4149 TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(pViewShell->GetActiveWindow()));
4150 return EditEngine::HasValidData(aDataHelper.GetTransferable());
4153 PointerStyle SdXImpressDocument::getPointer()
4155 SolarMutexGuard aGuard;
4156 DrawViewShell* pViewShell = GetViewShell();
4157 if (!pViewShell)
4158 return PointerStyle::Arrow;
4160 Window* pWindow = pViewShell->GetActiveWindow();
4161 if (!pWindow)
4162 return PointerStyle::Arrow;
4164 return pWindow->GetPointer();
4167 uno::Reference< i18n::XForbiddenCharacters > SdXImpressDocument::getForbiddenCharsTable()
4169 rtl::Reference<SdUnoForbiddenCharsTable> xRef = mxForbiddenCharacters.get();
4170 if( !xRef )
4172 xRef = new SdUnoForbiddenCharsTable( mpDoc );
4173 mxForbiddenCharacters = xRef.get();
4175 return xRef;
4178 void SdXImpressDocument::initializeDocument()
4180 if( mbClipBoard )
4181 return;
4183 switch( mpDoc->GetPageCount() )
4185 case 1:
4187 // nasty hack to detect clipboard document
4188 mbClipBoard = true;
4189 break;
4191 case 0:
4193 mpDoc->CreateFirstPages();
4194 mpDoc->StopWorkStartupDelay();
4195 break;
4200 static
4201 void getShapeClickAction(const uno::Reference<drawing::XShape> &xShape, ::tools::JsonWriter& rJsonWriter)
4203 bool bIsShapeVisible = true;
4204 uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
4205 if (!xShapeProps)
4206 return;
4208 if (!xShapeProps->getPropertySetInfo()->hasPropertyByName( u"Visible"_ustr ))
4209 return;
4210 xShapeProps->getPropertyValue("Visible") >>= bIsShapeVisible;
4212 if (!bIsShapeVisible)
4213 return;
4215 if (!xShapeProps->getPropertySetInfo()->hasPropertyByName( u"OnClick"_ustr ))
4216 return;
4218 presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
4219 xShapeProps->getPropertyValue(u"OnClick"_ustr) >>= eClickAction;
4221 if (eClickAction != presentation::ClickAction_NONE)
4223 auto aShape = rJsonWriter.startStruct();
4225 sal_Int32 nVerb = 0;
4226 OUString sBookmark;
4228 if (xShapeProps->getPropertySetInfo()->hasPropertyByName( u"Bookmark"_ustr ))
4229 xShapeProps->getPropertyValue(u"Bookmark"_ustr) >>= sBookmark;
4232 auto* pObject = SdrObject::getSdrObjectFromXShape(xShape);
4233 auto const& rRectangle = pObject->GetLogicRect();
4234 auto aRectangle = o3tl::convert(rRectangle, o3tl::Length::mm100, o3tl::Length::twip);
4235 auto aRect = rJsonWriter.startNode("bounds");
4236 rJsonWriter.put("x", aRectangle.Left());
4237 rJsonWriter.put("y", aRectangle.Top());
4238 rJsonWriter.put("width", aRectangle.GetWidth());
4239 rJsonWriter.put("height", aRectangle.GetHeight());
4243 auto aInteraction = rJsonWriter.startNode("clickAction");
4244 switch (eClickAction)
4246 case presentation::ClickAction_BOOKMARK:
4247 rJsonWriter.put("action", "bookmark");
4248 rJsonWriter.put("bookmark", sBookmark);
4249 break;
4250 case presentation::ClickAction_DOCUMENT:
4251 rJsonWriter.put("action", "document");
4252 rJsonWriter.put("document", sBookmark);
4253 break;
4255 case presentation::ClickAction_PREVPAGE:
4256 rJsonWriter.put("action", "prevpage");
4257 break;
4258 case presentation::ClickAction_NEXTPAGE:
4259 rJsonWriter.put("action", "nextpage");
4260 break;
4262 case presentation::ClickAction_FIRSTPAGE:
4263 rJsonWriter.put("action", "firstpage");
4264 break;
4265 case presentation::ClickAction_LASTPAGE:
4266 rJsonWriter.put("action", "lastpage");
4267 break;
4269 case presentation::ClickAction_SOUND:
4270 rJsonWriter.put("action", "sound");
4271 rJsonWriter.put("sound", sBookmark);
4272 break;
4274 case presentation::ClickAction_VERB:
4275 rJsonWriter.put("action", "verb");
4276 xShapeProps->getPropertyValue(u"Verb"_ustr) >>= nVerb;
4277 rJsonWriter.put("verb", nVerb);
4278 break;
4280 case presentation::ClickAction_PROGRAM:
4281 rJsonWriter.put("action", "program");
4282 rJsonWriter.put("program", sBookmark);
4283 break;
4285 case presentation::ClickAction_MACRO:
4286 rJsonWriter.put("action", "macro");
4287 rJsonWriter.put("macro", sBookmark);
4288 break;
4290 case presentation::ClickAction_STOPPRESENTATION:
4291 rJsonWriter.put("action", "stoppresentation");
4292 break;
4294 default:
4295 break;
4301 OString SdXImpressDocument::getPresentationInfo() const
4303 ::tools::JsonWriter aJsonWriter;
4307 rtl::Reference<SdDrawPagesAccess> xDrawPages = const_cast<SdXImpressDocument*>(this)->getSdDrawPages();
4308 // size in twips
4309 Size aDocSize = const_cast<SdXImpressDocument*>(this)->getDocumentSize();
4310 aJsonWriter.put("docWidth", aDocSize.getWidth());
4311 aJsonWriter.put("docHeight", aDocSize.getHeight());
4313 sd::PresentationSettings const& rSettings = mpDoc->getPresentationSettings();
4315 const bool bIsEndless = rSettings.mbEndless;
4316 aJsonWriter.put("isEndless", bIsEndless);
4318 if (bIsEndless) {
4319 const sal_Int32 nPauseTimeout = rSettings.mnPauseTimeout;
4320 aJsonWriter.put("loopAndRepeatDuration", nPauseTimeout);
4323 auto aSlideList = aJsonWriter.startArray("slides");
4324 sal_Int32 nSlideCount = xDrawPages->getCount();
4325 for (sal_Int32 i = 0; i < nSlideCount; ++i)
4327 SdGenericDrawPage* pSlide(xDrawPages->getDrawPageByIndex(i));
4328 bool bIsVisible = true; // default visible
4329 pSlide->getPropertyValue("Visible") >>= bIsVisible;
4330 if (!bIsVisible)
4332 auto aSlideNode = aJsonWriter.startStruct();
4333 std::string sSlideHash = GetInterfaceHash(cppu::getXWeak(pSlide));
4334 aJsonWriter.put("hash", sSlideHash);
4335 aJsonWriter.put("index", i);
4336 aJsonWriter.put("hidden", true);
4338 else
4340 SdPage* pPage = SdPage::getImplementation(pSlide);
4342 auto aSlideNode = aJsonWriter.startStruct();
4343 std::string sSlideHash = GetInterfaceHash(cppu::getXWeak(pSlide));
4344 aJsonWriter.put("hash", sSlideHash);
4345 aJsonWriter.put("index", i);
4347 if (pPage)
4349 auto aName = SdDrawPage::getPageApiNameFromUiName(pPage->GetName());
4350 aJsonWriter.put("name", aName);
4353 bool bIsDrawPageEmpty = pSlide->getCount() == 0;
4354 aJsonWriter.put("empty", bIsDrawPageEmpty);
4356 // Notes
4357 SdPage* pNotesPage = pPage ? mpDoc->GetSdPage((pPage->GetPageNum() - 1) >> 1, PageKind::Notes) : nullptr;
4358 if (pNotesPage)
4360 SdrObject* pNotes = pNotesPage->GetPresObj(PresObjKind::Notes);
4361 if (pNotes)
4363 OUStringBuffer strNotes;
4364 OutlinerParaObject* pPara = pNotes->GetOutlinerParaObject();
4365 if (pPara)
4367 const EditTextObject& rText = pPara->GetTextObject();
4368 for (sal_Int32 nNote = 0; nNote < rText.GetParagraphCount(); nNote++)
4370 strNotes.append(rText.GetText(nNote));
4372 aJsonWriter.put("notes", strNotes.makeStringAndClear());
4377 SdMasterPage* pMasterPage = nullptr;
4378 SdDrawPage* pMasterPageTarget(dynamic_cast<SdDrawPage*>(pSlide));
4379 if (pMasterPageTarget)
4381 pMasterPage = pMasterPageTarget->getSdMasterPage();
4382 if (pMasterPage)
4384 std::string sMPHash = GetInterfaceHash(cppu::getXWeak(pMasterPage));
4385 aJsonWriter.put("masterPage", sMPHash);
4387 bool bBackgroundObjectsVisibility = true; // default visible
4388 pSlide->getPropertyValue("IsBackgroundObjectsVisible") >>= bBackgroundObjectsVisibility;
4389 aJsonWriter.put("masterPageObjectsVisibility", bBackgroundObjectsVisibility);
4393 bool bBackgroundVisibility = true; // default visible
4394 pSlide->getPropertyValue("IsBackgroundVisible") >>= bBackgroundVisibility;
4395 if (bBackgroundVisibility)
4397 SlideBackgroundInfo aSlideBackgroundInfo(pSlide, static_cast<SvxDrawPage*>(pMasterPage));
4398 if (aSlideBackgroundInfo.hasBackground())
4400 auto aBackgroundNode = aJsonWriter.startNode("background");
4401 aJsonWriter.put("isCustom", aSlideBackgroundInfo.slideHasOwnBackground());
4402 if (aSlideBackgroundInfo.isSolidColor())
4404 aJsonWriter.put("fillColor", aSlideBackgroundInfo.getFillColorAsRGBA());
4410 auto aVideoList = aJsonWriter.startArray("videos");
4411 SdrObjListIter aIterator(pPage, SdrIterMode::DeepWithGroups);
4412 while (aIterator.IsMore())
4414 auto* pObject = aIterator.Next();
4415 if (pObject->GetObjIdentifier() == SdrObjKind::Media)
4417 auto aVideosNode = aJsonWriter.startStruct();
4418 auto* pMediaObject = static_cast<SdrMediaObj*>(pObject);
4419 auto const& rRectangle = pMediaObject->GetLogicRect();
4420 auto aRectangle = o3tl::convert(rRectangle, o3tl::Length::mm100, o3tl::Length::twip);
4421 aJsonWriter.put("id", reinterpret_cast<sal_uInt64>(pMediaObject));
4422 aJsonWriter.put("url", pMediaObject->getTempURL());
4423 aJsonWriter.put("x", aRectangle.Left());
4424 aJsonWriter.put("y", aRectangle.Top());
4425 aJsonWriter.put("width", aRectangle.GetWidth());
4426 aJsonWriter.put("height", aRectangle.GetHeight());
4431 uno::Reference<drawing::XShapes> const xShapes(cppu::getXWeak(pSlide), uno::UNO_QUERY_THROW);
4432 if (xShapes.is())
4434 auto aInteractions = aJsonWriter.startArray("interactions");
4435 auto count = xShapes->getCount();
4436 for (auto j = 0; j < count; j++)
4438 auto xObject = xShapes->getByIndex(j);
4439 uno::Reference<drawing::XShape> xShape(xObject, uno::UNO_QUERY);
4440 if (!xShape.is())
4442 continue;
4445 getShapeClickAction(xShape, aJsonWriter);
4449 sal_Int32 nTransitionType = 0;
4450 pSlide->getPropertyValue("TransitionType") >>= nTransitionType;
4452 if (nTransitionType != 0)
4454 auto iterator = constTransitionTypeToString.find(nTransitionType);
4456 if (iterator != constTransitionTypeToString.end())
4458 aJsonWriter.put("transitionType", iterator->second);
4460 sal_Int32 nTransitionSubtype = 0;
4461 pSlide->getPropertyValue("TransitionSubtype") >>= nTransitionSubtype;
4463 auto iteratorSubType = constTransitionSubTypeToString.find(nTransitionSubtype);
4464 if (iteratorSubType != constTransitionSubTypeToString.end())
4466 aJsonWriter.put("transitionSubtype", iteratorSubType->second);
4468 else
4470 SAL_WARN("sd", "Transition sub-type unknown: " << nTransitionSubtype);
4473 bool nTransitionDirection = false;
4474 pSlide->getPropertyValue("TransitionDirection") >>= nTransitionDirection;
4475 aJsonWriter.put("transitionDirection", nTransitionDirection);
4477 // fade color
4478 if ((nTransitionType == TransitionType::FADE)
4479 && ((nTransitionSubtype == TransitionSubType::FADETOCOLOR)
4480 || (nTransitionSubtype == TransitionSubType::FADEFROMCOLOR)
4481 || (nTransitionSubtype == TransitionSubType::FADEOVERCOLOR)))
4483 sal_Int32 nFadeColor = 0;
4484 pSlide->getPropertyValue("TransitionFadeColor") >>= nFadeColor;
4485 OUStringBuffer sTmpBuf;
4486 ::sax::Converter::convertColor(sTmpBuf, nFadeColor);
4487 aJsonWriter.put("transitionFadeColor", sTmpBuf.makeStringAndClear());
4491 double nTransitionDuration(0.0);
4492 if( pSlide->getPropertySetInfo()->hasPropertyByName( "TransitionDuration" ) &&
4493 (pSlide->getPropertyValue( "TransitionDuration" ) >>= nTransitionDuration ) && nTransitionDuration != 0.0 )
4495 // convert transitionDuration time to ms
4496 aJsonWriter.put("transitionDuration", nTransitionDuration * 1000);
4500 sal_Int32 nChange(0);
4501 if( pSlide->getPropertySetInfo()->hasPropertyByName( "Change" ) &&
4502 (pSlide->getPropertyValue( "Change" ) >>= nChange ) && nChange == 1 )
4504 double fSlideDuration(0);
4505 if( pSlide->getPropertySetInfo()->hasPropertyByName( "HighResDuration" ) &&
4506 (pSlide->getPropertyValue( "HighResDuration" ) >>= fSlideDuration) )
4508 // convert slide duration time to ms
4509 aJsonWriter.put("nextSlideDuration", fSlideDuration * 1000);
4514 AnimationsExporter aAnimationExporter(aJsonWriter, pSlide);
4515 if (aAnimationExporter.hasEffects())
4517 auto aAnimationsNode = aJsonWriter.startNode("animations");
4518 aAnimationExporter.exportAnimations();
4523 catch (uno::Exception& )
4525 TOOLS_WARN_EXCEPTION("sd", "SdXImpressDocument::getSlideShowInfo ... maybe some property can't be retrieved");
4527 return aJsonWriter.finishAndGetAsOString();
4530 namespace
4532 bool isRequestedSlideValid(SdDrawDocument* mpDoc, sal_Int32 nSlideNumber, const std::string& slideHash)
4536 uno::Reference<drawing::XDrawPagesSupplier> xDrawPages(getXWeak(mpDoc->getUnoModel()), uno::UNO_QUERY_THROW);
4537 uno::Reference<container::XIndexAccess> xSlides(xDrawPages->getDrawPages(), uno::UNO_QUERY_THROW);
4538 uno::Reference<drawing::XDrawPage> xSlide(xSlides->getByIndex(nSlideNumber), uno::UNO_QUERY_THROW);
4539 if (xSlide.is())
4541 return slideHash == GetInterfaceHash(xSlide);
4544 catch (uno::Exception&)
4546 TOOLS_WARN_EXCEPTION( "sd", "SdXImpressDocument::createLOKSlideRenderer: failed" );
4548 return false;
4552 bool SdXImpressDocument::createSlideRenderer(
4553 const OString& rSlideHash,
4554 sal_Int32 nSlideNumber, sal_Int32& nViewWidth, sal_Int32& nViewHeight,
4555 bool /*bRenderBackground*/, bool /*bRenderMasterPage*/)
4557 std::string sSlideHash(rSlideHash);
4558 if (!isRequestedSlideValid(mpDoc, nSlideNumber, sSlideHash))
4559 return false;
4561 SdPage* pPage = mpDoc->GetSdPage(sal_uInt16(nSlideNumber), PageKind::Standard);
4562 if (!pPage)
4563 return false;
4565 mpSlideshowLayerRenderer.reset(new SlideshowLayerRenderer(*pPage));
4566 Size aDesiredSize(nViewWidth, nViewHeight);
4567 Size aCalculatedSize = mpSlideshowLayerRenderer->calculateAndSetSizePixel(aDesiredSize);
4568 nViewWidth = aCalculatedSize.Width();
4569 nViewHeight = aCalculatedSize.Height();
4570 return true;
4573 void SdXImpressDocument::postSlideshowCleanup()
4575 DrawViewShell* pViewSh = GetViewShell();
4576 if (!pViewSh)
4577 return;
4579 pViewSh->destroyXSlideShowInstance();
4582 bool SdXImpressDocument::renderNextSlideLayer(unsigned char* pBuffer, bool& bIsBitmapLayer, OUString& rJsonMsg)
4584 bool bDone = true;
4586 if (!mpSlideshowLayerRenderer)
4587 return bDone;
4589 OString sMsg;
4590 bool bOK = mpSlideshowLayerRenderer->render(pBuffer, sMsg);
4592 if (bOK)
4594 rJsonMsg = OUString::fromUtf8(sMsg);
4595 bIsBitmapLayer = true;
4596 bDone = false;
4599 return bDone;
4602 SdrModel& SdXImpressDocument::getSdrModelFromUnoModel() const
4604 OSL_ENSURE(GetDoc(), "No SdrModel in draw/Impress, should not happen");
4605 return *GetDoc(); // TTTT should be reference
4608 void SAL_CALL SdXImpressDocument::dispose()
4610 if( mbDisposed )
4611 return;
4613 ::SolarMutexGuard aGuard;
4615 if( mpDoc )
4617 EndListening( *mpDoc );
4618 mpDoc = nullptr;
4621 // Call the base class dispose() before setting the mbDisposed flag
4622 // to true. The reason for this is that if close() has not yet been
4623 // called this is done in SfxBaseModel::dispose(). At the end of
4624 // that dispose() is called again. It is important to forward this
4625 // second dispose() to the base class, too.
4626 // As a consequence the following code has to be able to be run twice.
4627 SfxBaseModel::dispose();
4628 mbDisposed = true;
4630 rtl::Reference< SdDocLinkTargets > xLinks( mxLinks );
4631 if( xLinks.is() )
4633 xLinks->dispose();
4634 xLinks = nullptr;
4637 rtl::Reference< SdDrawPagesAccess > xDrawPagesAccess( mxDrawPagesAccess );
4638 if( xDrawPagesAccess.is() )
4640 xDrawPagesAccess->dispose();
4641 xDrawPagesAccess = nullptr;
4644 rtl::Reference< SdMasterPagesAccess > xMasterPagesAccess( mxMasterPagesAccess );
4645 if( xDrawPagesAccess.is() )
4647 xMasterPagesAccess->dispose();
4648 xMasterPagesAccess = nullptr;
4651 rtl::Reference< SdLayerManager > xLayerManager( mxLayerManager );
4652 if( xLayerManager.is() )
4654 xLayerManager->dispose();
4655 xLayerManager = nullptr;
4658 mxDashTable = nullptr;
4659 mxGradientTable = nullptr;
4660 mxHatchTable = nullptr;
4661 mxBitmapTable = nullptr;
4662 mxTransGradientTable = nullptr;
4663 mxMarkerTable = nullptr;
4664 mxDrawingPool = nullptr;
4668 SdDrawPagesAccess::SdDrawPagesAccess( SdXImpressDocument& rMyModel ) noexcept
4669 : mpModel( &rMyModel)
4673 SdDrawPagesAccess::~SdDrawPagesAccess() noexcept
4677 // XIndexAccess
4678 sal_Int32 SAL_CALL SdDrawPagesAccess::getCount()
4680 ::SolarMutexGuard aGuard;
4682 if( nullptr == mpModel )
4683 throw lang::DisposedException();
4685 return mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
4688 uno::Any SAL_CALL SdDrawPagesAccess::getByIndex( sal_Int32 Index )
4690 uno::Reference< drawing::XDrawPage > xDrawPage( getDrawPageByIndex(Index) );
4691 return uno::Any(xDrawPage);
4694 SdGenericDrawPage* SdDrawPagesAccess::getDrawPageByIndex( sal_Int32 Index )
4696 ::SolarMutexGuard aGuard;
4698 if( nullptr == mpModel )
4699 throw lang::DisposedException();
4701 if( (Index < 0) || (Index >= mpModel->mpDoc->GetSdPageCount( PageKind::Standard ) ) )
4702 throw lang::IndexOutOfBoundsException();
4704 SdPage* pPage = mpModel->mpDoc->GetSdPage( static_cast<sal_uInt16>(Index), PageKind::Standard );
4705 if( pPage )
4706 return dynamic_cast<SdGenericDrawPage*>( pPage->getUnoPage().get() );
4708 return nullptr;
4711 // XNameAccess
4712 uno::Any SAL_CALL SdDrawPagesAccess::getByName( const OUString& aName )
4714 ::SolarMutexGuard aGuard;
4716 if( nullptr == mpModel )
4717 throw lang::DisposedException();
4719 if( !aName.isEmpty() )
4721 const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
4722 sal_uInt16 nPage;
4723 for( nPage = 0; nPage < nCount; nPage++ )
4725 SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard );
4726 if(nullptr == pPage)
4727 continue;
4729 if( aName == SdDrawPage::getPageApiName( pPage ) )
4731 uno::Any aAny;
4732 uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
4733 aAny <<= xDrawPage;
4734 return aAny;
4739 throw container::NoSuchElementException();
4742 uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getElementNames()
4744 ::SolarMutexGuard aGuard;
4746 if( nullptr == mpModel )
4747 throw lang::DisposedException();
4749 const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
4750 uno::Sequence< OUString > aNames( nCount );
4751 OUString* pNames = aNames.getArray();
4753 sal_uInt16 nPage;
4754 for( nPage = 0; nPage < nCount; nPage++ )
4756 SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard );
4757 *pNames++ = SdDrawPage::getPageApiName( pPage );
4760 return aNames;
4763 sal_Bool SAL_CALL SdDrawPagesAccess::hasByName( const OUString& aName )
4765 ::SolarMutexGuard aGuard;
4767 if( nullptr == mpModel )
4768 throw lang::DisposedException();
4770 const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard );
4771 sal_uInt16 nPage;
4772 for( nPage = 0; nPage < nCount; nPage++ )
4774 SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard );
4775 if(nullptr == pPage)
4776 continue;
4778 if( aName == SdDrawPage::getPageApiName( pPage ) )
4779 return true;
4782 return false;
4785 // XElementAccess
4786 uno::Type SAL_CALL SdDrawPagesAccess::getElementType()
4788 return cppu::UnoType<drawing::XDrawPage>::get();
4791 sal_Bool SAL_CALL SdDrawPagesAccess::hasElements()
4793 return getCount() > 0;
4796 // XDrawPages
4799 * Creates a new page with model at the specified position.
4800 * @returns corresponding SdDrawPage
4802 uno::Reference< drawing::XDrawPage > SAL_CALL SdDrawPagesAccess::insertNewByIndex( sal_Int32 nIndex )
4804 ::SolarMutexGuard aGuard;
4805 comphelper::ProfileZone aZone("insertNewByIndex");
4807 if( nullptr == mpModel )
4808 throw lang::DisposedException();
4810 if( mpModel->mpDoc )
4812 SdPage* pPage = mpModel->InsertSdPage( static_cast<sal_uInt16>(nIndex), false );
4813 if( pPage )
4815 uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
4816 return xDrawPage;
4819 uno::Reference< drawing::XDrawPage > xDrawPage;
4820 return xDrawPage;
4824 * Removes the specified SdDrawPage from the model and the internal list. It
4825 * only works, if there is at least one *normal* page in the model after
4826 * removing this page.
4828 void SAL_CALL SdDrawPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage )
4830 ::SolarMutexGuard aGuard;
4832 if( nullptr == mpModel || mpModel->mpDoc == nullptr )
4833 throw lang::DisposedException();
4835 SdDrawDocument& rDoc = *mpModel->mpDoc;
4837 sal_uInt16 nPageCount = rDoc.GetSdPageCount( PageKind::Standard );
4838 if( nPageCount > 1 )
4840 // get pPage from xPage and determine the Id (nPos ) afterwards
4841 SdDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SdDrawPage>( xPage );
4842 if( pSvxPage )
4844 SdPage* pPage = static_cast<SdPage*>(pSvxPage->GetSdrPage());
4845 if(pPage && ( pPage->GetPageKind() == PageKind::Standard ) )
4847 sal_uInt16 nPage = pPage->GetPageNum();
4849 SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetPage( nPage+1 ) );
4851 bool bUndo = rDoc.IsUndoEnabled();
4852 if( bUndo )
4854 // Add undo actions and delete the pages. The order of adding
4855 // the undo actions is important.
4856 rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) );
4857 rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
4858 rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
4861 rDoc.RemovePage( nPage ); // the page
4862 rDoc.RemovePage( nPage ); // the notes page
4864 if( bUndo )
4866 rDoc.EndUndo();
4872 mpModel->SetModified();
4875 // XServiceInfo
4877 OUString SAL_CALL SdDrawPagesAccess::getImplementationName( )
4879 return u"SdDrawPagesAccess"_ustr;
4882 sal_Bool SAL_CALL SdDrawPagesAccess::supportsService( const OUString& ServiceName )
4884 return cppu::supportsService(this, ServiceName);
4887 uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getSupportedServiceNames( )
4889 return { u"com.sun.star.drawing.DrawPages"_ustr };
4892 // XComponent
4893 void SAL_CALL SdDrawPagesAccess::dispose( )
4895 mpModel = nullptr;
4898 void SAL_CALL SdDrawPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& )
4900 OSL_FAIL( "not implemented!" );
4903 void SAL_CALL SdDrawPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& )
4905 OSL_FAIL( "not implemented!" );
4909 SdMasterPagesAccess::SdMasterPagesAccess( SdXImpressDocument& rMyModel ) noexcept
4910 : mpModel(&rMyModel)
4914 SdMasterPagesAccess::~SdMasterPagesAccess() noexcept
4918 // XComponent
4919 void SAL_CALL SdMasterPagesAccess::dispose( )
4921 mpModel = nullptr;
4924 void SAL_CALL SdMasterPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& )
4926 OSL_FAIL( "not implemented!" );
4929 void SAL_CALL SdMasterPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& )
4931 OSL_FAIL( "not implemented!" );
4934 // XIndexAccess
4935 sal_Int32 SAL_CALL SdMasterPagesAccess::getCount()
4937 ::SolarMutexGuard aGuard;
4939 if( nullptr == mpModel->mpDoc )
4940 throw lang::DisposedException();
4942 return mpModel->mpDoc->GetMasterSdPageCount(PageKind::Standard);
4946 * Provides a drawing::XDrawPage interface for accessing the Masterpage at the
4947 * specified position in the model.
4949 uno::Any SAL_CALL SdMasterPagesAccess::getByIndex( sal_Int32 Index )
4951 ::SolarMutexGuard aGuard;
4952 comphelper::ProfileZone aZone("SdMasterPagesAccess::getByIndex");
4954 if( nullptr == mpModel )
4955 throw lang::DisposedException();
4957 uno::Any aAny;
4959 if( (Index < 0) || (Index >= mpModel->mpDoc->GetMasterSdPageCount( PageKind::Standard ) ) )
4960 throw lang::IndexOutOfBoundsException();
4962 SdPage* pPage = mpModel->mpDoc->GetMasterSdPage( static_cast<sal_uInt16>(Index), PageKind::Standard );
4963 if( pPage )
4965 uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY );
4966 aAny <<= xDrawPage;
4969 return aAny;
4972 // XElementAccess
4973 uno::Type SAL_CALL SdMasterPagesAccess::getElementType()
4975 return cppu::UnoType<drawing::XDrawPage>::get();
4978 sal_Bool SAL_CALL SdMasterPagesAccess::hasElements()
4980 return getCount() > 0;
4983 // XDrawPages
4984 uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNewByIndex( sal_Int32 nInsertPos )
4986 return insertNewImpl(nInsertPos, std::nullopt);
4989 // XDrawPages2
4990 uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNamedNewByIndex( sal_Int32 nInsertPos, const OUString& sName )
4992 return insertNewImpl(nInsertPos, sName);
4995 uno::Reference< drawing::XDrawPage > SdMasterPagesAccess::insertNewImpl( sal_Int32 nInsertPos, std::optional<OUString> oPageName )
4997 ::SolarMutexGuard aGuard;
4999 if( nullptr == mpModel )
5000 throw lang::DisposedException();
5002 uno::Reference< drawing::XDrawPage > xDrawPage;
5004 SdDrawDocument* pDoc = mpModel->mpDoc;
5005 if( pDoc )
5007 // calculate internal index and check for range errors
5008 const sal_Int32 nMPageCount = pDoc->GetMasterPageCount();
5009 nInsertPos = nInsertPos * 2 + 1;
5010 if( nInsertPos < 0 || nInsertPos > nMPageCount )
5011 nInsertPos = nMPageCount;
5013 // now generate a unique name for the new masterpage
5014 OUString aPrefix;
5015 if (oPageName)
5016 aPrefix = *oPageName;
5017 else
5019 const OUString aStdPrefix( SdResId(STR_LAYOUT_DEFAULT_NAME) );
5020 aPrefix = aStdPrefix;
5022 bool bUnique = true;
5024 std::vector<OUString> aPageNames;
5025 for (sal_Int32 nMaster = 1; nMaster < nMPageCount; ++nMaster)
5027 const SdPage* pPage = static_cast<const SdPage*>(pDoc->GetMasterPage(static_cast<sal_uInt16>(nMaster)));
5028 if (!pPage)
5029 continue;
5030 aPageNames.push_back(pPage->GetName());
5031 if (aPageNames.back() == aPrefix)
5032 bUnique = false;
5035 sal_Int32 i = 0;
5036 while (!bUnique)
5038 aPrefix = aStdPrefix + " " + OUString::number(++i);
5039 bUnique = std::find(aPageNames.begin(), aPageNames.end(), aPrefix) == aPageNames.end();
5042 OUString aLayoutName = aPrefix + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE;
5044 // create styles
5045 static_cast<SdStyleSheetPool*>(pDoc->GetStyleSheetPool())->CreateLayoutStyleSheets( aPrefix );
5047 // get the first page for initial size and border settings
5048 SdPage* pPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Standard );
5049 SdPage* pRefNotesPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Notes);
5051 // create and insert new draw masterpage
5052 rtl::Reference<SdPage> pMPage = mpModel->mpDoc->AllocSdPage(true);
5053 pMPage->SetSize( pPage->GetSize() );
5054 pMPage->SetBorder( pPage->GetLeftBorder(),
5055 pPage->GetUpperBorder(),
5056 pPage->GetRightBorder(),
5057 pPage->GetLowerBorder() );
5058 if (oPageName)
5059 // no need to update the page URLs on a brand new page
5060 pMPage->SetName(*oPageName, /*bUpdatePageRelativeURLs*/false);
5061 pMPage->SetLayoutName( aLayoutName );
5062 pDoc->InsertMasterPage(pMPage.get(), static_cast<sal_uInt16>(nInsertPos));
5065 // ensure default MasterPage fill
5066 pMPage->EnsureMasterPageDefaultBackground();
5069 xDrawPage.set( pMPage->getUnoPage(), uno::UNO_QUERY );
5071 // create and insert new notes masterpage
5072 rtl::Reference<SdPage> pMNotesPage = mpModel->mpDoc->AllocSdPage(true);
5073 pMNotesPage->SetSize( pRefNotesPage->GetSize() );
5074 pMNotesPage->SetPageKind(PageKind::Notes);
5075 pMNotesPage->SetBorder( pRefNotesPage->GetLeftBorder(),
5076 pRefNotesPage->GetUpperBorder(),
5077 pRefNotesPage->GetRightBorder(),
5078 pRefNotesPage->GetLowerBorder() );
5079 pMNotesPage->SetLayoutName( aLayoutName );
5080 pDoc->InsertMasterPage(pMNotesPage.get(), static_cast<sal_uInt16>(nInsertPos) + 1);
5081 pMNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
5082 mpModel->SetModified();
5085 return xDrawPage;
5089 * Removes the specified SdMasterPage from the model and the internal list. It
5090 * only works, if there is no *normal* page using this page as MasterPage in
5091 * the model.
5093 void SAL_CALL SdMasterPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage )
5095 ::SolarMutexGuard aGuard;
5097 if( nullptr == mpModel || mpModel->mpDoc == nullptr )
5098 throw lang::DisposedException();
5100 SdMasterPage* pSdPage = comphelper::getFromUnoTunnel<SdMasterPage>( xPage );
5101 if(pSdPage == nullptr)
5102 return;
5104 SdPage* pPage = dynamic_cast< SdPage* > (pSdPage->GetSdrPage());
5106 DBG_ASSERT( pPage && pPage->IsMasterPage(), "SdMasterPage is not masterpage?");
5108 if( !pPage || !pPage->IsMasterPage() || (mpModel->mpDoc->GetMasterPageUserCount(pPage) > 0))
5109 return; //Todo: this should be excepted
5111 // only standard pages can be removed directly
5112 if( pPage->GetPageKind() != PageKind::Standard )
5113 return;
5115 sal_uInt16 nPage = pPage->GetPageNum();
5117 SdDrawDocument& rDoc = *mpModel->mpDoc;
5119 SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetMasterPage( nPage+1 ) );
5121 bool bUndo = rDoc.IsUndoEnabled();
5122 if( bUndo )
5124 // Add undo actions and delete the pages. The order of adding
5125 // the undo actions is important.
5126 rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) );
5127 rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
5128 rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
5131 // remove both pages
5132 rDoc.RemoveMasterPage( nPage );
5133 rDoc.RemoveMasterPage( nPage );
5135 if( bUndo )
5137 rDoc.EndUndo();
5141 // XServiceInfo
5143 OUString SAL_CALL SdMasterPagesAccess::getImplementationName( )
5145 return u"SdMasterPagesAccess"_ustr;
5148 sal_Bool SAL_CALL SdMasterPagesAccess::supportsService( const OUString& ServiceName )
5150 return cppu::supportsService(this, ServiceName);
5153 uno::Sequence< OUString > SAL_CALL SdMasterPagesAccess::getSupportedServiceNames( )
5155 return { u"com.sun.star.drawing.MasterPages"_ustr };
5158 SdDocLinkTargets::SdDocLinkTargets(SdXImpressDocument& rMyModel)
5159 : mpModel(&rMyModel)
5161 for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++)
5162 aNames[i] = SdResId(aTypeResIds[i]);
5165 SdDocLinkTargets::~SdDocLinkTargets() noexcept
5169 // XComponent
5170 void SAL_CALL SdDocLinkTargets::dispose( )
5172 mpModel = nullptr;
5175 void SAL_CALL SdDocLinkTargets::addEventListener( const uno::Reference< lang::XEventListener >& )
5177 OSL_FAIL( "not implemented!" );
5180 void SAL_CALL SdDocLinkTargets::removeEventListener( const uno::Reference< lang::XEventListener >& )
5182 OSL_FAIL( "not implemented!" );
5185 // XNameAccess
5186 uno::Any SAL_CALL SdDocLinkTargets::getByName( const OUString& aName )
5188 if (mpModel)
5190 for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++)
5191 if ( aNames[i] == aName )
5192 return uno::Any(uno::Reference< beans::XPropertySet >(new SdDocLinkTargetType( mpModel, i )));
5195 throw container::NoSuchElementException();
5198 uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getElementNames()
5200 uno::Sequence<OUString> aRet(SdLinkTargetType::Count);
5201 OUString* pArray = aRet.getArray();
5202 for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++)
5203 pArray[i] = aNames[i];
5204 return aRet;
5207 sal_Bool SAL_CALL SdDocLinkTargets::hasByName( const OUString& aName )
5209 for (const auto & i : aNames)
5210 if ( i == aName )
5211 return true;
5212 return false;
5215 // container::XElementAccess
5216 uno::Type SAL_CALL SdDocLinkTargets::getElementType()
5218 return cppu::UnoType<beans::XPropertySet>::get();
5221 sal_Bool SAL_CALL SdDocLinkTargets::hasElements()
5223 return true;
5226 SdPage* SdDocLinkTarget::FindPage( std::u16string_view rName ) const
5228 SdDrawDocument* pDoc = mpModel->GetDoc();
5229 if( pDoc == nullptr )
5230 return nullptr;
5232 const sal_uInt16 nMaxPages = pDoc->GetPageCount();
5233 const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount();
5235 sal_uInt16 nPage;
5236 SdPage* pPage;
5238 const bool bDraw = pDoc->GetDocumentType() == DocumentType::Draw;
5240 // standard pages
5241 for( nPage = 0; nPage < nMaxPages; nPage++ )
5243 pPage = static_cast<SdPage*>(pDoc->GetPage( nPage ));
5244 if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) )
5245 return pPage;
5248 // master pages
5249 for( nPage = 0; nPage < nMaxMasterPages; nPage++ )
5251 pPage = static_cast<SdPage*>(pDoc->GetMasterPage( nPage ));
5252 if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) )
5253 return pPage;
5256 return nullptr;
5259 // XServiceInfo
5260 OUString SAL_CALL SdDocLinkTargets::getImplementationName()
5262 return u"SdDocLinkTargets"_ustr;
5265 sal_Bool SAL_CALL SdDocLinkTargets::supportsService( const OUString& ServiceName )
5267 return cppu::supportsService( this, ServiceName );
5270 uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getSupportedServiceNames()
5272 return { u"com.sun.star.document.LinkTargets"_ustr };
5275 SdDocLinkTargetType::SdDocLinkTargetType(SdXImpressDocument* pModel, sal_uInt16 nT)
5276 : mpModel(pModel)
5277 , mnType(nT)
5279 maName = SdResId(aTypeResIds[nT]);
5282 // beans::XPropertySet
5284 uno::Reference< beans::XPropertySetInfo > SAL_CALL SdDocLinkTargetType::getPropertySetInfo()
5286 static uno::Reference< beans::XPropertySetInfo > aRef;//(new SfxItemPropertySetInfo( lcl_GetLinkTargetMap() ));
5287 return aRef;
5290 void SAL_CALL SdDocLinkTargetType::setPropertyValue(const OUString& /* aPropertyName */,
5291 const uno::Any& /* aValue */)
5293 // everything is read-only
5296 uno::Any SAL_CALL SdDocLinkTargetType::getPropertyValue(const OUString& PropertyName)
5298 uno::Any aRet;
5299 if ( PropertyName == "LinkDisplayName" )
5300 aRet <<= maName;
5302 return aRet;
5305 void SAL_CALL SdDocLinkTargetType::addPropertyChangeListener( const OUString&,
5306 const uno::Reference<beans::XPropertyChangeListener>&)
5307 { OSL_FAIL("not implemented"); }
5309 void SAL_CALL SdDocLinkTargetType::removePropertyChangeListener( const OUString&,
5310 const uno::Reference<beans::XPropertyChangeListener>&)
5311 { OSL_FAIL("not implemented"); }
5313 void SAL_CALL SdDocLinkTargetType::addVetoableChangeListener( const OUString&,
5314 const uno::Reference<beans::XVetoableChangeListener>&)
5315 { OSL_FAIL("not implemented"); }
5317 void SAL_CALL SdDocLinkTargetType::removeVetoableChangeListener( const OUString&,
5318 const uno::Reference<beans::XVetoableChangeListener>&)
5319 { OSL_FAIL("not implemented"); }
5321 // document::XLinkTargetSupplier
5323 uno::Reference< container::XNameAccess > SAL_CALL SdDocLinkTargetType::getLinks()
5325 return new SdDocLinkTarget( mpModel, mnType );
5328 // XServiceInfo
5329 OUString SAL_CALL SdDocLinkTargetType::getImplementationName()
5331 return u"SdDocLinkTargetType"_ustr;
5334 sal_Bool SAL_CALL SdDocLinkTargetType::supportsService( const OUString& ServiceName )
5336 return cppu::supportsService( this, ServiceName );
5339 uno::Sequence< OUString > SAL_CALL SdDocLinkTargetType::getSupportedServiceNames()
5341 return { u"com.sun.star.document.LinkTargetSupplier"_ustr };
5344 SdDocLinkTarget::SdDocLinkTarget( SdXImpressDocument* pModel, sal_uInt16 nT )
5345 : mpModel(pModel)
5346 , mnType(nT)
5350 // container::XNameAccess
5352 uno::Any SAL_CALL SdDocLinkTarget::getByName(const OUString& aName)
5354 ::SolarMutexGuard aGuard;
5356 if( nullptr == mpModel )
5357 throw lang::DisposedException();
5359 SdPage* pPage = FindPage( aName );
5361 if( pPage == nullptr )
5362 throw container::NoSuchElementException();
5364 uno::Any aAny;
5366 uno::Reference< beans::XPropertySet > xProps( pPage->getUnoPage(), uno::UNO_QUERY );
5367 if( xProps.is() )
5368 aAny <<= xProps;
5370 return aAny;
5373 uno::Sequence<OUString> SAL_CALL SdDocLinkTarget::getElementNames()
5375 ::SolarMutexGuard aGuard;
5377 if( nullptr == mpModel )
5378 throw lang::DisposedException();
5380 SdDrawDocument* pDoc = mpModel->GetDoc();
5381 if( pDoc == nullptr )
5383 return { };
5386 if( pDoc->GetDocumentType() == DocumentType::Draw )
5388 const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( PageKind::Standard );
5389 const sal_uInt16 nMaxMasterPages = pDoc->GetMasterSdPageCount( PageKind::Standard );
5391 uno::Sequence< OUString > aSeq( mnType == SdLinkTargetType::Page ? nMaxPages : nMaxMasterPages );
5392 OUString* pStr = aSeq.getArray();
5394 sal_uInt16 nPage;
5395 if (mnType == SdLinkTargetType::Page)
5397 // standard pages
5398 for( nPage = 0; nPage < nMaxPages; nPage++ )
5399 *pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName();
5401 else
5403 // master pages
5404 for( nPage = 0; nPage < nMaxMasterPages; nPage++ )
5405 *pStr++ = pDoc->GetMasterSdPage( nPage, PageKind::Standard )->GetName();
5407 return aSeq;
5409 else
5411 PageKind eKind;
5412 switch (mnType)
5414 case SdLinkTargetType::Notes:
5415 eKind = PageKind::Notes;
5416 break;
5417 case SdLinkTargetType::Handout:
5418 eKind = PageKind::Handout;
5419 break;
5420 default:
5421 eKind = PageKind::Standard;
5422 break;
5424 const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( eKind );
5425 const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount();
5427 uno::Sequence< OUString > aSeq( mnType == SdLinkTargetType::MasterPage ? nMaxMasterPages : nMaxPages );
5428 OUString* pStr = aSeq.getArray();
5430 sal_uInt16 nPage;
5431 switch (mnType)
5433 case SdLinkTargetType::Page:
5435 for( nPage = 0; nPage < nMaxPages; nPage++ )
5436 *pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName();
5437 break;
5439 case SdLinkTargetType::Notes:
5441 for( nPage = 0; nPage < nMaxPages; nPage++ )
5442 *pStr++ = pDoc->GetSdPage( nPage, PageKind::Notes )->GetName();
5443 break;
5445 case SdLinkTargetType::Handout:
5447 for( nPage = 0; nPage < nMaxPages; nPage++ )
5448 *pStr++ = pDoc->GetSdPage( nPage, PageKind::Handout )->GetName();
5449 break;
5451 case SdLinkTargetType::MasterPage:
5453 for( nPage = 0; nPage < nMaxMasterPages; nPage++ )
5454 *pStr++ = static_cast<SdPage*>(pDoc->GetMasterPage( nPage ))->GetName();
5455 break;
5458 return aSeq;
5462 sal_Bool SAL_CALL SdDocLinkTarget::hasByName(const OUString& aName)
5464 ::SolarMutexGuard aGuard;
5466 if( nullptr == mpModel )
5467 throw lang::DisposedException();
5469 return FindPage( aName ) != nullptr;
5472 // container::XElementAccess
5474 uno::Type SAL_CALL SdDocLinkTarget::getElementType()
5476 return cppu::UnoType<beans::XPropertySet>::get();
5479 sal_Bool SAL_CALL SdDocLinkTarget::hasElements()
5481 ::SolarMutexGuard aGuard;
5483 if( nullptr == mpModel )
5484 throw lang::DisposedException();
5486 return mpModel->GetDoc() != nullptr;
5489 // XServiceInfo
5490 OUString SAL_CALL SdDocLinkTarget::getImplementationName()
5492 return u"SdDocLinkTarget"_ustr;
5495 sal_Bool SAL_CALL SdDocLinkTarget::supportsService( const OUString& ServiceName )
5497 return cppu::supportsService( this, ServiceName );
5500 uno::Sequence< OUString > SAL_CALL SdDocLinkTarget::getSupportedServiceNames()
5502 return { u"com.sun.star.document.LinkTargets"_ustr };
5505 rtl::Reference< SdXImpressDocument > SdXImpressDocument::GetModel( SdDrawDocument const & rDocument )
5507 rtl::Reference< SdXImpressDocument > xRet;
5508 ::sd::DrawDocShell* pDocShell(rDocument.GetDocSh());
5509 if( pDocShell )
5511 uno::Reference<frame::XModel> xModel(pDocShell->GetModel());
5513 xRet.set( dynamic_cast< SdXImpressDocument* >( xModel.get() ) );
5516 return xRet;
5519 void NotifyDocumentEvent(SdDrawDocument const & rDocument, const OUString& rEventName)
5521 rtl::Reference<SdXImpressDocument> xModel(SdXImpressDocument::GetModel(rDocument));
5523 if (xModel.is())
5525 uno::Reference<uno::XInterface> xSource(static_cast<uno::XWeak*>(xModel.get()));
5526 NotifyDocumentEvent(rDocument, rEventName, xSource);
5530 void NotifyDocumentEvent(SdDrawDocument const & rDocument, const OUString& rEventName, const uno::Reference<uno::XInterface>& xSource)
5532 rtl::Reference<SdXImpressDocument> xModel(SdXImpressDocument::GetModel(rDocument));
5534 if (xModel.is())
5536 css::document::EventObject aEvent(xSource, rEventName);
5537 xModel->notifyEvent(aEvent);
5541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */