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>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/container/XNameContainer.hpp>
26 #include <com/sun/star/drawing/PointSequence.hpp>
27 #include <com/sun/star/util/XCancellable.hpp>
29 #include <comphelper/sequence.hxx>
30 #include <cppuhelper/implbase.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <svl/itempool.hxx>
33 #include <svl/itemset.hxx>
34 #include <svl/lstner.hxx>
35 #include <svx/xlnedit.hxx>
36 #include <svx/xlnstit.hxx>
37 #include <svx/svdmodel.hxx>
38 #include <svx/xdef.hxx>
41 #include <vcl/svapp.hxx>
44 #include <svx/unofill.hxx>
46 #include <svx/unoapi.hxx>
48 using namespace ::com::sun::star
;
49 using namespace ::cppu
;
51 typedef std::vector
<std::unique_ptr
<SfxItemSet
>> ItemPoolVector
;
55 class SvxUnoMarkerTable
56 : public WeakImplHelper
<
58 container::XNameContainer
,
64 SfxItemPool
* mpModelPool
;
66 ItemPoolVector maItemSetVector
;
69 explicit SvxUnoMarkerTable( SdrModel
* pModel
) noexcept
;
70 virtual ~SvxUnoMarkerTable() noexcept override
;
75 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
) noexcept override
;
77 void ImplInsertByName( const OUString
& aName
, const uno::Any
& aElement
);
80 virtual OUString SAL_CALL
getImplementationName( ) override
;
81 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
82 virtual uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
85 virtual void SAL_CALL
cancel() override
;
88 virtual void SAL_CALL
insertByName( const OUString
& aName
, const uno::Any
& aElement
) override
;
89 virtual void SAL_CALL
removeByName( const OUString
& Name
) override
;
92 virtual void SAL_CALL
replaceByName( const OUString
& aName
, const uno::Any
& aElement
) override
;
95 virtual uno::Any SAL_CALL
getByName( const OUString
& aName
) override
;
96 virtual uno::Sequence
< OUString
> SAL_CALL
getElementNames( ) override
;
97 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
100 virtual uno::Type SAL_CALL
getElementType( ) override
;
101 virtual sal_Bool SAL_CALL
hasElements( ) override
;
106 SvxUnoMarkerTable::SvxUnoMarkerTable( SdrModel
* pModel
) noexcept
108 mpModelPool( pModel
? &pModel
->GetItemPool() : nullptr )
111 StartListening( *pModel
);
114 SvxUnoMarkerTable::~SvxUnoMarkerTable() noexcept
116 SolarMutexGuard aGuard
;
119 EndListening( *mpModel
);
123 void SvxUnoMarkerTable::dispose()
125 maItemSetVector
.clear();
129 void SvxUnoMarkerTable::Notify( SfxBroadcaster
&, const SfxHint
& rHint
) noexcept
131 if (rHint
.GetId() == SfxHintId::ThisIsAnSdrHint
)
133 const SdrHint
* pSdrHint
= static_cast<const SdrHint
*>(&rHint
);
134 if( SdrHintKind::ModelCleared
== pSdrHint
->GetKind() )
139 sal_Bool SAL_CALL
SvxUnoMarkerTable::supportsService( const OUString
& ServiceName
)
141 return cppu::supportsService(this, ServiceName
);
144 OUString SAL_CALL
SvxUnoMarkerTable::getImplementationName()
146 return "SvxUnoMarkerTable";
149 uno::Sequence
< OUString
> SAL_CALL
SvxUnoMarkerTable::getSupportedServiceNames( )
151 uno::Sequence
<OUString
> aSNS
{ "com.sun.star.drawing.MarkerTable" };
155 void SvxUnoMarkerTable::ImplInsertByName( const OUString
& aName
, const uno::Any
& aElement
)
157 maItemSetVector
.push_back(
158 std::make_unique
<SfxItemSetFixed
<XATTR_LINESTART
, XATTR_LINEEND
>>( *mpModelPool
));
159 auto pInSet
= maItemSetVector
.back().get();
161 XLineEndItem
aEndMarker(XATTR_LINEEND
);
162 aEndMarker
.SetName( aName
);
163 aEndMarker
.PutValue( aElement
, 0 );
165 pInSet
->Put( aEndMarker
);
167 XLineStartItem
aStartMarker(XATTR_LINESTART
);
168 aStartMarker
.SetName( aName
);
169 aStartMarker
.PutValue( aElement
, 0 );
171 pInSet
->Put( aStartMarker
);
175 void SAL_CALL
SvxUnoMarkerTable::insertByName( const OUString
& aApiName
, const uno::Any
& aElement
)
177 SolarMutexGuard aGuard
;
179 if( hasByName( aApiName
) )
180 throw container::ElementExistException();
182 OUString aName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aApiName
);
184 ImplInsertByName( aName
, aElement
);
187 void SAL_CALL
SvxUnoMarkerTable::cancel()
189 SolarMutexGuard aGuard
;
190 // drop all items that are owned by this service and not the document
191 // (i.e. they are unused)
195 void SAL_CALL
SvxUnoMarkerTable::removeByName( const OUString
& aApiName
)
197 SolarMutexGuard aGuard
;
199 OUString aName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aApiName
);
201 auto aIter
= std::find_if(maItemSetVector
.begin(), maItemSetVector
.end(),
202 [&aName
](const std::unique_ptr
<SfxItemSet
>& rpItem
) {
203 const NameOrIndex
*pItem
= &(rpItem
->Get( XATTR_LINEEND
) );
204 return pItem
->GetName() == aName
;
206 if (aIter
!= maItemSetVector
.end())
208 maItemSetVector
.erase( aIter
);
212 if( !hasByName( aName
) )
213 throw container::NoSuchElementException();
217 void SAL_CALL
SvxUnoMarkerTable::replaceByName( const OUString
& aApiName
, const uno::Any
& aElement
)
219 SolarMutexGuard aGuard
;
221 const OUString aName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aApiName
);
223 auto aIter
= std::find_if(maItemSetVector
.begin(), maItemSetVector
.end(),
224 [&aName
](const std::unique_ptr
<SfxItemSet
>& rpItem
) {
225 const NameOrIndex
*pItem
= &(rpItem
->Get( XATTR_LINEEND
) );
226 return pItem
->GetName() == aName
;
228 if (aIter
!= maItemSetVector
.end())
230 XLineEndItem
aEndMarker(XATTR_LINEEND
);
231 aEndMarker
.SetName( aName
);
232 if( !aEndMarker
.PutValue( aElement
, 0 ) )
233 throw lang::IllegalArgumentException();
235 (*aIter
)->Put( aEndMarker
);
237 XLineStartItem
aStartMarker(XATTR_LINESTART
);
238 aStartMarker
.SetName( aName
);
239 aStartMarker
.PutValue( aElement
, 0 );
241 (*aIter
)->Put( aStartMarker
);
245 // if it is not in our own sets, modify the pool!
249 for (const SfxPoolItem
* p
: mpModelPool
->GetItemSurrogates(XATTR_LINESTART
))
251 NameOrIndex
*pItem
= const_cast<NameOrIndex
*>(static_cast<const NameOrIndex
*>(p
));
252 if( pItem
&& pItem
->GetName() == aName
)
254 pItem
->PutValue( aElement
, 0 );
261 for (const SfxPoolItem
* p
: mpModelPool
->GetItemSurrogates(XATTR_LINEEND
))
263 NameOrIndex
*pItem
= const_cast<NameOrIndex
*>(static_cast<const NameOrIndex
*>(p
));
264 if( pItem
&& pItem
->GetName() == aName
)
266 pItem
->PutValue( aElement
, 0 );
273 throw container::NoSuchElementException();
275 ImplInsertByName( aName
, aElement
);
278 static bool getByNameFromPool( std::u16string_view rSearchName
, SfxItemPool
const * pPool
, sal_uInt16 nWhich
, uno::Any
& rAny
)
281 for (const SfxPoolItem
* p
: pPool
->GetItemSurrogates(nWhich
))
283 const NameOrIndex
*pItem
= static_cast<const NameOrIndex
*>(p
);
285 if( pItem
&& pItem
->GetName() == rSearchName
)
287 pItem
->QueryValue( rAny
);
296 uno::Any SAL_CALL
SvxUnoMarkerTable::getByName( const OUString
& aApiName
)
298 SolarMutexGuard aGuard
;
300 OUString aName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aApiName
);
304 if (mpModelPool
&& !aName
.isEmpty())
308 if (getByNameFromPool(aName
, mpModelPool
, XATTR_LINESTART
, aAny
))
311 if (getByNameFromPool(aName
, mpModelPool
, XATTR_LINEEND
, aAny
))
314 throw container::NoSuchElementException();
322 static void createNamesForPool( SfxItemPool
const * pPool
, sal_uInt16 nWhich
, std::set
< OUString
>& rNameSet
)
324 for (const SfxPoolItem
* p
: pPool
->GetItemSurrogates(nWhich
))
326 const NameOrIndex
* pItem
= static_cast<const NameOrIndex
*>(p
);
328 if( pItem
== nullptr || pItem
->GetName().isEmpty() )
331 OUString aName
= SvxUnogetApiNameForItem(XATTR_LINEEND
, pItem
->GetName());
332 rNameSet
.insert( aName
);
336 uno::Sequence
< OUString
> SAL_CALL
SvxUnoMarkerTable::getElementNames()
338 SolarMutexGuard aGuard
;
340 std::set
< OUString
> aNameSet
;
342 // search model pool for line starts
343 createNamesForPool( mpModelPool
, XATTR_LINESTART
, aNameSet
);
345 // search model pool for line ends
346 createNamesForPool( mpModelPool
, XATTR_LINEEND
, aNameSet
);
348 return comphelper::containerToSequence(aNameSet
);
351 sal_Bool SAL_CALL
SvxUnoMarkerTable::hasByName( const OUString
& aName
)
353 SolarMutexGuard aGuard
;
355 if( aName
.isEmpty() )
358 OUString aSearchName
;
360 const NameOrIndex
*pItem
;
362 aSearchName
= SvxUnogetInternalNameForItem(XATTR_LINESTART
, aName
);
364 for (const SfxPoolItem
* p
: mpModelPool
->GetItemSurrogates(XATTR_LINESTART
))
366 pItem
= static_cast<const NameOrIndex
*>(p
);
367 if( pItem
&& pItem
->GetName() == aSearchName
)
371 aSearchName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aName
);
373 for (const SfxPoolItem
* p
: mpModelPool
->GetItemSurrogates(XATTR_LINEEND
))
375 pItem
= static_cast<const NameOrIndex
*>(p
);
376 if( pItem
&& pItem
->GetName() == aSearchName
)
384 uno::Type SAL_CALL
SvxUnoMarkerTable::getElementType( )
386 return cppu::UnoType
<drawing::PointSequence
>::get();
389 sal_Bool SAL_CALL
SvxUnoMarkerTable::hasElements( )
391 SolarMutexGuard aGuard
;
393 const NameOrIndex
*pItem
;
396 for (const SfxPoolItem
* p
: mpModelPool
->GetItemSurrogates(XATTR_LINESTART
))
398 pItem
= static_cast<const NameOrIndex
*>(p
);
399 if( pItem
&& !pItem
->GetName().isEmpty() )
404 for (const SfxPoolItem
* p
: mpModelPool
->GetItemSurrogates(XATTR_LINEEND
))
406 pItem
= static_cast<const NameOrIndex
*>(p
);
407 if( pItem
&& !pItem
->GetName().isEmpty() )
415 * Create a hatchtable
417 uno::Reference
< uno::XInterface
> SvxUnoMarkerTable_createInstance( SdrModel
* pModel
)
419 return *new SvxUnoMarkerTable(pModel
);
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */