1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <sal/config.h>
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
24 #include <com/sun/star/lang/NoSupportException.hpp>
25 #include <com/sun/star/drawing/XShape.hpp>
26 #include <vcl/svapp.hxx>
27 #include <svl/itempool.hxx>
28 #include <svtools/unoevent.hxx>
29 #include <comphelper/sequence.hxx>
30 #include <o3tl/string_view.hxx>
31 #include <cppuhelper/supportsservice.hxx>
33 #include <cppuhelper/implbase.hxx>
34 #include <svx/unofill.hxx>
35 #include <editeng/unonrule.hxx>
36 #include <svtools/unoimap.hxx>
37 #include <sfx2/event.hxx>
38 #include <svx/fmmodel.hxx>
39 #include <svx/fmpage.hxx>
40 #include <svx/unoapi.hxx>
42 #include <svx/svdmodel.hxx>
43 #include <svx/unoprov.hxx>
44 #include <svx/unopage.hxx>
45 #include <editeng/unofield.hxx>
46 #include <svx/unomod.hxx>
47 #include <svx/unomodel.hxx>
48 #include <svx/svdobj.hxx>
49 #include <svx/svdpage.hxx>
50 #include <svx/SvxXTextColumns.hxx>
51 #include <svx/unoshape.hxx>
52 #include <svx/xmlgrhlp.hxx>
54 #include <com/sun/star/text/textfield/Type.hpp>
58 using namespace ::com::sun::star
;
62 #define QUERYINT( xint ) \
63 if( rType == cppu::UnoType<xint>::get() ) \
64 aAny <<= uno::Reference< xint >(this)
68 class SvxUnoDrawPagesAccess
: public ::cppu::WeakImplHelper
< css::drawing::XDrawPages
, css::lang::XServiceInfo
>
71 SvxUnoDrawingModel
& mrModel
;
74 explicit SvxUnoDrawPagesAccess( SvxUnoDrawingModel
& rMyModel
) noexcept
;
77 virtual css::uno::Reference
< css::drawing::XDrawPage
> SAL_CALL
insertNewByIndex( sal_Int32 nIndex
) override
;
78 virtual void SAL_CALL
remove( const css::uno::Reference
< css::drawing::XDrawPage
>& xPage
) override
;
81 virtual sal_Int32 SAL_CALL
getCount() override
;
82 virtual css::uno::Any SAL_CALL
getByIndex( sal_Int32 Index
) override
;
85 virtual css::uno::Type SAL_CALL
getElementType() override
;
86 virtual sal_Bool SAL_CALL
hasElements() override
;
89 virtual OUString SAL_CALL
getImplementationName( ) override
;
90 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
91 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
95 static const SvEventDescription
* ImplGetSupportedMacroItems()
97 static const SvEventDescription aMacroDescriptionsImpl
[] =
99 { SvMacroItemId::OnMouseOver
, "OnMouseOver" },
100 { SvMacroItemId::OnMouseOut
, "OnMouseOut" },
101 { SvMacroItemId::NONE
, nullptr }
104 return aMacroDescriptionsImpl
;
109 /** fills the given EventObject from the given SdrHint.
111 true if the SdrHint could be translated to an EventObject<br>
114 bool SvxUnoDrawMSFactory::createEvent( const SdrModel
* pDoc
, const SdrHint
* pSdrHint
, css::document::EventObject
& aEvent
)
116 const SdrObject
* pObj
= nullptr;
117 const SdrPage
* pPage
= nullptr;
119 switch( pSdrHint
->GetKind() )
121 // case SdrHintKind::LayerChange: // layer definition changed
122 // case SdrHintKind::LayerOrderChange: // layer order changed (Insert/Remove/ChangePos)
123 // case HINT_LAYERSETCHG: // layer set changed
124 // case HINT_LAYERSETORDERCHG: // layer set order changed (Insert/Remove/ChangePos)
126 // case HINT_PAGECHG: // page changed
127 // aEvent.EventName = "PageModified";
128 // pPage = pSdrHint->GetPage();
130 case SdrHintKind::PageOrderChange
: // draw or master page order changed (Insert/Remove/ChangePos)
131 aEvent
.EventName
= "PageOrderModified";
132 pPage
= pSdrHint
->GetPage();
134 case SdrHintKind::ObjectChange
: // object changed
135 aEvent
.EventName
= "ShapeModified";
136 pObj
= pSdrHint
->GetObject();
138 case SdrHintKind::ObjectInserted
: // add new draw object
139 aEvent
.EventName
= "ShapeInserted";
140 pObj
= pSdrHint
->GetObject();
142 case SdrHintKind::ObjectRemoved
: // removed draw object from list
143 aEvent
.EventName
= "ShapeRemoved";
144 pObj
= pSdrHint
->GetObject();
146 // SdrHintKind::DefaultTabChange, // default tab width changed
147 // SdrHintKind::SwitchToPage, // #94278# UNDO/REDO at an object evtl. on another page
148 // HINT_OBJLISTCLEAR // Is called before an SdrObjList will be cleared
154 aEvent
.Source
= const_cast<SdrObject
*>(pObj
)->getUnoShape();
156 aEvent
.Source
= const_cast<SdrPage
*>(pPage
)->getUnoPage();
158 aEvent
.Source
= const_cast<SdrModel
*>(pDoc
)->getUnoModel();
165 css::uno::Reference
<css::uno::XInterface
> create(
166 OUString
const & rServiceSpecifier
, OUString
const & referer
)
168 if( rServiceSpecifier
.startsWith("com.sun.star.drawing.") )
170 std::optional
<SdrObjKind
> nType
= UHashMap::getId( rServiceSpecifier
);
173 SdrInventor nI
= IsInventorE3D(*nType
) ? SdrInventor::E3d
: SdrInventor::Default
;
175 return cppu::getXWeak(SvxDrawPage::CreateShapeByTypeAndInventor( *nType
, nI
, nullptr, nullptr, referer
).get());
178 else if (rServiceSpecifier
== "com.sun.star.document.ImportGraphicStorageHandler")
180 return cppu::getXWeak( SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode::Read
).get() );
182 else if (rServiceSpecifier
== "com.sun.star.text.TextColumns")
184 return SvxXTextColumns_createInstance();
187 uno::Reference
< uno::XInterface
> xRet( SvxUnoDrawMSFactory::createTextField( rServiceSpecifier
) );
189 throw lang::ServiceNotRegisteredException("unknown service: " + rServiceSpecifier
);
196 uno::Reference
< uno::XInterface
> SAL_CALL
SvxUnoDrawMSFactory::createInstance( const OUString
& rServiceSpecifier
)
198 return create(rServiceSpecifier
, "");
201 uno::Reference
< uno::XInterface
> SvxUnoDrawMSFactory::createTextField( std::u16string_view ServiceSpecifier
)
203 return SvxUnoTextCreateTextField( ServiceSpecifier
);
206 uno::Reference
< uno::XInterface
> SAL_CALL
SvxUnoDrawMSFactory::createInstanceWithArguments( const OUString
& ServiceSpecifier
, const uno::Sequence
< css::uno::Any
>& Arguments
)
209 if ((ServiceSpecifier
== "com.sun.star.drawing.GraphicObjectShape"
210 || ServiceSpecifier
== "com.sun.star.drawing.AppletShape"
211 || ServiceSpecifier
== "com.sun.star.drawing.FrameShape"
212 || ServiceSpecifier
== "com.sun.star.drawing.OLE2Shape"
213 || ServiceSpecifier
== "com.sun.star.drawing.MediaShape"
214 || ServiceSpecifier
== "com.sun.star.drawing.PluginShape")
215 && Arguments
.getLength() == 1 && (Arguments
[0] >>= arg
))
217 return create(ServiceSpecifier
, arg
);
219 throw lang::NoSupportException();
222 uno::Sequence
< OUString
> SAL_CALL
SvxUnoDrawMSFactory::getAvailableServiceNames()
224 return UHashMap::getServiceNames();
227 SdrModel
& SvxUnoDrawingModel::getSdrModelFromUnoModel() const
229 OSL_ENSURE(mpDoc
, "No SdrModel in UnoDrawingModel, should not happen");
233 SvxUnoDrawingModel::SvxUnoDrawingModel(SdrModel
* pDoc
) noexcept
234 : SfxBaseModel(nullptr),
239 SvxUnoDrawingModel::~SvxUnoDrawingModel() noexcept
243 uno::Any SAL_CALL
SvxUnoDrawingModel::queryInterface( const uno::Type
& rType
)
247 QUERYINT(lang::XServiceInfo
);
248 else QUERYINT(lang::XMultiServiceFactory
);
249 else QUERYINT(drawing::XDrawPagesSupplier
);
250 else QUERYINT(css::ucb::XAnyCompareFactory
);
252 return SfxBaseModel::queryInterface( rType
);
258 uno::Sequence
< uno::Type
> SAL_CALL
SvxUnoDrawingModel::getTypes( )
260 if( !maTypeSequence
.hasElements() )
262 maTypeSequence
= comphelper::concatSequences( SfxBaseModel::getTypes(),
264 cppu::UnoType
<lang::XServiceInfo
>::get(),
265 cppu::UnoType
<lang::XMultiServiceFactory
>::get(),
266 cppu::UnoType
<drawing::XDrawPagesSupplier
>::get(),
267 cppu::UnoType
<css::ucb::XAnyCompareFactory
>::get() });
269 return maTypeSequence
;
272 uno::Sequence
< sal_Int8
> SAL_CALL
SvxUnoDrawingModel::getImplementationId( )
274 return css::uno::Sequence
<sal_Int8
>();
277 void SAL_CALL
SvxUnoDrawingModel::lockControllers( )
280 mpDoc
->setLock(true);
283 void SAL_CALL
SvxUnoDrawingModel::unlockControllers( )
285 if( mpDoc
&& mpDoc
->isLocked() )
287 mpDoc
->setLock(false);
291 sal_Bool SAL_CALL
SvxUnoDrawingModel::hasControllersLocked( )
293 return mpDoc
&& mpDoc
->isLocked();
296 // XDrawPagesSupplier
297 uno::Reference
< drawing::XDrawPages
> SAL_CALL
SvxUnoDrawingModel::getDrawPages()
299 ::SolarMutexGuard aGuard
;
301 uno::Reference
< drawing::XDrawPages
> xDrawPages( mxDrawPagesAccess
);
303 if( !xDrawPages
.is() )
304 mxDrawPagesAccess
= xDrawPages
= new SvxUnoDrawPagesAccess(*this);
309 // XMultiServiceFactory ( SvxFmMSFactory )
310 uno::Reference
< uno::XInterface
> SAL_CALL
SvxUnoDrawingModel::createInstance( const OUString
& aServiceSpecifier
)
312 ::SolarMutexGuard aGuard
;
314 if( aServiceSpecifier
== "com.sun.star.drawing.DashTable" )
316 if( !mxDashTable
.is() )
317 mxDashTable
= SvxUnoDashTable_createInstance( mpDoc
);
320 if( aServiceSpecifier
== "com.sun.star.drawing.GradientTable" )
322 if( !mxGradientTable
.is() )
323 mxGradientTable
= SvxUnoGradientTable_createInstance( mpDoc
);
324 return mxGradientTable
;
326 if( aServiceSpecifier
== "com.sun.star.drawing.HatchTable" )
328 if( !mxHatchTable
.is() )
329 mxHatchTable
= SvxUnoHatchTable_createInstance( mpDoc
);
332 if( aServiceSpecifier
== "com.sun.star.drawing.BitmapTable" )
334 if( !mxBitmapTable
.is() )
335 mxBitmapTable
= SvxUnoBitmapTable_createInstance( mpDoc
);
336 return mxBitmapTable
;
338 if( aServiceSpecifier
== "com.sun.star.drawing.TransparencyGradientTable" )
340 if( !mxTransGradientTable
.is() )
341 mxTransGradientTable
= SvxUnoTransGradientTable_createInstance( mpDoc
);
342 return mxTransGradientTable
;
344 if( aServiceSpecifier
== "com.sun.star.drawing.MarkerTable" )
346 if( !mxMarkerTable
.is() )
347 mxMarkerTable
= SvxUnoMarkerTable_createInstance( mpDoc
);
348 return mxMarkerTable
;
350 if( aServiceSpecifier
== "com.sun.star.text.NumberingRules" )
352 return uno::Reference
< uno::XInterface
>( SvxCreateNumRule( mpDoc
), uno::UNO_QUERY
);
355 if ( aServiceSpecifier
== "com.sun.star.image.ImageMapRectangleObject" )
357 return SvUnoImageMapRectangleObject_createInstance( ImplGetSupportedMacroItems() );
360 if ( aServiceSpecifier
== "com.sun.star.image.ImageMapCircleObject" )
362 return SvUnoImageMapCircleObject_createInstance( ImplGetSupportedMacroItems() );
365 if ( aServiceSpecifier
== "com.sun.star.image.ImageMapPolygonObject" )
367 return SvUnoImageMapPolygonObject_createInstance( ImplGetSupportedMacroItems() );
370 if( aServiceSpecifier
== "com.sun.star.text.TextField.DateTime" )
372 return cppu::getXWeak(new SvxUnoTextField(text::textfield::Type::DATE
));
375 uno::Reference
< uno::XInterface
> xRet
;
377 static constexpr OUString
aPackagePrefix( u
"com.sun.star.presentation."_ustr
);
378 if( aServiceSpecifier
.startsWith( aPackagePrefix
) )
380 SvxShape
* pShape
= nullptr;
382 SdrObjKind nType
= SdrObjKind::Text
;
383 std::u16string_view aTypeName
= aServiceSpecifier
.subView( aPackagePrefix
.getLength() );
384 // create a shape wrapper
385 if( o3tl::starts_with(aTypeName
, u
"TitleTextShape") )
387 nType
= SdrObjKind::Text
;
389 else if( o3tl::starts_with(aTypeName
, u
"OutlinerShape" ) )
391 nType
= SdrObjKind::Text
;
393 else if( o3tl::starts_with(aTypeName
, u
"SubtitleShape" ) )
395 nType
= SdrObjKind::Text
;
397 else if( o3tl::starts_with(aTypeName
, u
"GraphicObjectShape" ) )
399 nType
= SdrObjKind::Graphic
;
401 else if( o3tl::starts_with(aTypeName
, u
"PageShape" ) )
403 nType
= SdrObjKind::Page
;
405 else if( o3tl::starts_with(aTypeName
, u
"OLE2Shape" ) )
407 nType
= SdrObjKind::OLE2
;
409 else if( o3tl::starts_with(aTypeName
, u
"ChartShape" ) )
411 nType
= SdrObjKind::OLE2
;
413 else if( o3tl::starts_with(aTypeName
, u
"OrgChartShape" ) )
415 nType
= SdrObjKind::OLE2
;
417 else if( o3tl::starts_with(aTypeName
, u
"NotesShape" ) )
419 nType
= SdrObjKind::Text
;
421 else if( o3tl::starts_with(aTypeName
, u
"HandoutShape" ) )
423 nType
= SdrObjKind::Page
;
425 else if( o3tl::starts_with(aTypeName
, u
"FooterShape" ) )
427 nType
= SdrObjKind::Text
;
429 else if( o3tl::starts_with(aTypeName
, u
"HeaderShape" ) )
431 nType
= SdrObjKind::Text
;
433 else if( o3tl::starts_with(aTypeName
, u
"SlideNumberShape" ) )
435 nType
= SdrObjKind::Text
;
437 else if( o3tl::starts_with(aTypeName
, u
"DateTimeShape" ) )
439 nType
= SdrObjKind::Text
;
441 else if( o3tl::starts_with(aTypeName
, u
"TableShape" ) )
443 nType
= SdrObjKind::Table
;
447 throw lang::ServiceNotRegisteredException();
450 // create the API wrapper
451 rtl::Reference
<SvxShape
> xNewShape
= CreateSvxShapeByTypeAndInventor( nType
, SdrInventor::Default
, "" );
452 pShape
= xNewShape
.get();
456 pShape
->SetShapeType(aServiceSpecifier
);
458 xRet
= cppu::getXWeak(pShape
);
462 xRet
= SvxFmMSFactory::createInstance( aServiceSpecifier
);
468 uno::Sequence
< OUString
> SAL_CALL
SvxUnoDrawingModel::getAvailableServiceNames()
470 const uno::Sequence
< OUString
> aSNS_ORG( SvxFmMSFactory::getAvailableServiceNames() );
472 uno::Sequence
< OUString
> aSNS
{
473 "com.sun.star.drawing.DashTable",
474 "com.sun.star.drawing.GradientTable",
475 "com.sun.star.drawing.HatchTable",
476 "com.sun.star.drawing.BitmapTable",
477 "com.sun.star.drawing.TransparencyGradientTable",
478 "com.sun.star.drawing.MarkerTable",
479 "com.sun.star.text.NumberingRules",
480 "com.sun.star.image.ImageMapRectangleObject",
481 "com.sun.star.image.ImageMapCircleObject",
482 "com.sun.star.image.ImageMapPolygonObject",
484 "com.sun.star.presentation.TitleTextShape",
485 "com.sun.star.presentation.OutlinerShape",
486 "com.sun.star.presentation.SubtitleShape",
487 "com.sun.star.presentation.GraphicObjectShape",
488 "com.sun.star.presentation.ChartShape",
489 "com.sun.star.presentation.PageShape",
490 "com.sun.star.presentation.OLE2Shape",
491 "com.sun.star.presentation.TableShape",
492 "com.sun.star.presentation.OrgChartShape",
493 "com.sun.star.presentation.NotesShape",
494 "com.sun.star.presentation.HandoutShape"
497 return comphelper::concatSequences( aSNS_ORG
, aSNS
);
500 // lang::XServiceInfo
501 OUString SAL_CALL
SvxUnoDrawingModel::getImplementationName()
503 return "SvxUnoDrawingModel";
506 sal_Bool SAL_CALL
SvxUnoDrawingModel::supportsService( const OUString
& ServiceName
)
508 return cppu::supportsService( this, ServiceName
);
511 uno::Sequence
< OUString
> SAL_CALL
SvxUnoDrawingModel::getSupportedServiceNames()
513 return { "com.sun.star.drawing.DrawingDocument" };
516 // XAnyCompareFactory
517 uno::Reference
< css::ucb::XAnyCompare
> SAL_CALL
SvxUnoDrawingModel::createAnyCompareByName( const OUString
& )
519 return SvxCreateNumRuleCompare();
522 SvxUnoDrawPagesAccess::SvxUnoDrawPagesAccess( SvxUnoDrawingModel
& rMyModel
) noexcept
528 sal_Int32 SAL_CALL
SvxUnoDrawPagesAccess::getCount()
530 ::SolarMutexGuard aGuard
;
532 sal_Int32 nCount
= 0;
535 nCount
= mrModel
.mpDoc
->GetPageCount();
540 uno::Any SAL_CALL
SvxUnoDrawPagesAccess::getByIndex( sal_Int32 Index
)
542 ::SolarMutexGuard aGuard
;
548 if( (Index
< 0) || (Index
>= mrModel
.mpDoc
->GetPageCount() ) )
549 throw lang::IndexOutOfBoundsException();
551 SdrPage
* pPage
= mrModel
.mpDoc
->GetPage( static_cast<sal_uInt16
>(Index
) );
554 uno::Reference
< uno::XInterface
> xPage( pPage
->mxUnoPage
);
558 xPage
= static_cast<drawing::XDrawPage
*>(new SvxDrawPage( pPage
));
559 pPage
->mxUnoPage
= xPage
;
569 uno::Type SAL_CALL
SvxUnoDrawPagesAccess::getElementType()
571 return cppu::UnoType
<drawing::XDrawPage
>::get();
574 sal_Bool SAL_CALL
SvxUnoDrawPagesAccess::hasElements()
576 return getCount() > 0;
581 // create a new page with model at given position
582 // and return corresponding SdDrawPage
583 uno::Reference
< drawing::XDrawPage
> SAL_CALL
SvxUnoDrawPagesAccess::insertNewByIndex( sal_Int32 nIndex
)
585 ::SolarMutexGuard aGuard
;
587 uno::Reference
< drawing::XDrawPage
> xDrawPage
;
591 rtl::Reference
<SdrPage
> pPage
;
593 if( auto pFormModel
= dynamic_cast<FmFormModel
*>( mrModel
.mpDoc
) )
594 pPage
= new FmFormPage(*pFormModel
);
596 pPage
= new SdrPage(*mrModel
.mpDoc
);
598 mrModel
.mpDoc
->InsertPage( pPage
.get(), static_cast<sal_uInt16
>(nIndex
) );
599 xDrawPage
.set( pPage
->getUnoPage(), uno::UNO_QUERY
);
605 void SAL_CALL
SvxUnoDrawPagesAccess::remove( const uno::Reference
< drawing::XDrawPage
>& xPage
)
607 ::SolarMutexGuard aGuard
;
609 sal_uInt16 nPageCount
= mrModel
.mpDoc
->GetPageCount();
610 if( nPageCount
<= 1 )
613 // get pPage from xPage and get Id (nPos)
614 SvxDrawPage
* pSvxPage
= comphelper::getFromUnoTunnel
<SvxDrawPage
>( xPage
);
617 SdrPage
* pPage
= pSvxPage
->GetSdrPage();
620 sal_uInt16 nPage
= pPage
->GetPageNum();
621 mrModel
.mpDoc
->DeletePage( nPage
);
628 OUString SAL_CALL
SvxUnoDrawPagesAccess::getImplementationName( )
630 return "SvxUnoDrawPagesAccess";
633 sal_Bool SAL_CALL
SvxUnoDrawPagesAccess::supportsService( const OUString
& ServiceName
)
635 return cppu::supportsService(this, ServiceName
);
638 uno::Sequence
< OUString
> SAL_CALL
SvxUnoDrawPagesAccess::getSupportedServiceNames( )
640 return { "com.sun.star.drawing.DrawPages" };
643 css::uno::Reference
< css::container::XIndexReplace
> SvxCreateNumRule(SdrModel
* pModel
)
645 const SvxNumRule
* pDefaultRule
= nullptr;
648 const SvxNumBulletItem
* pItem
= pModel
->GetItemPool().GetSecondaryPool()->GetPoolDefaultItem(EE_PARA_NUMBULLET
);
651 pDefaultRule
= &pItem
->GetNumRule();
657 return SvxCreateNumRule( *pDefaultRule
);
661 SvxNumRule
aTempRule( SvxNumRuleFlags::NONE
, 10, false );
662 return SvxCreateNumRule( aTempRule
);
667 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */