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 u
"SvxUnoMarkerTable"_ustr
;
149 uno::Sequence
< OUString
> SAL_CALL
SvxUnoMarkerTable::getSupportedServiceNames( )
151 uno::Sequence
<OUString
> aSNS
{ u
"com.sun.star.drawing.MarkerTable"_ustr
};
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!
250 mpModelPool
->iterateItemSurrogates(XATTR_LINESTART
, [&](SfxItemPool::SurrogateData
& rData
)
252 const NameOrIndex
* pItem(static_cast<const NameOrIndex
*>(&rData
.getItem()));
253 if( pItem
&& pItem
->GetName() == aName
)
255 NameOrIndex
* pNew(pItem
->Clone(mpModelPool
));
256 pNew
->PutValue(aElement
, 0);
257 rData
.setItem(std::unique_ptr
<SfxPoolItem
>(pNew
));
259 return false; // interrupt callbacks
261 return true; // continue callbacks
267 mpModelPool
->iterateItemSurrogates(XATTR_LINEEND
, [&](SfxItemPool::SurrogateData
& rData
)
269 const NameOrIndex
* pItem(static_cast<const NameOrIndex
*>(&rData
.getItem()));
270 if( pItem
&& pItem
->GetName() == aName
)
272 NameOrIndex
* pNew(pItem
->Clone(mpModelPool
));
273 pNew
->PutValue(aElement
, 0);
274 rData
.setItem(std::unique_ptr
<SfxPoolItem
>(pNew
));
276 return false; // interrupt callbacks
278 return true; // continue callbacks
283 throw container::NoSuchElementException();
285 ImplInsertByName( aName
, aElement
);
288 static bool getByNameFromPool( std::u16string_view rSearchName
, SfxItemPool
const * pPool
, SfxItemType eItemType
, uno::Any
& rAny
)
292 ItemSurrogates aSurrogates
;
293 pPool
->GetItemSurrogatesForItem(aSurrogates
, eItemType
);
294 for (const SfxPoolItem
* p
: aSurrogates
)
296 const NameOrIndex
*pItem
= static_cast<const NameOrIndex
*>(p
);
298 if( pItem
->GetName() == rSearchName
)
300 pItem
->QueryValue( rAny
);
310 uno::Any SAL_CALL
SvxUnoMarkerTable::getByName( const OUString
& aApiName
)
312 SolarMutexGuard aGuard
;
314 OUString aName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aApiName
);
318 if (mpModelPool
&& !aName
.isEmpty())
322 if (getByNameFromPool(aName
, mpModelPool
, SfxItemType::XLineStartItemType
, aAny
)) // XATTR_LINESTART
325 if (getByNameFromPool(aName
, mpModelPool
, SfxItemType::XLineEndItemType
, aAny
)) // XATTR_LINEEND
328 throw container::NoSuchElementException();
336 static void createNamesForPool( SfxItemPool
const * pPool
, SfxItemType eItemType
, std::set
< OUString
>& rNameSet
)
338 ItemSurrogates aSurrogates
;
339 pPool
->GetItemSurrogatesForItem(aSurrogates
, eItemType
);
340 for (const SfxPoolItem
* p
: aSurrogates
)
342 const NameOrIndex
* pItem
= static_cast<const NameOrIndex
*>(p
);
344 if( pItem
->GetName().isEmpty() )
347 OUString aName
= SvxUnogetApiNameForItem(XATTR_LINEEND
, pItem
->GetName());
348 rNameSet
.insert( aName
);
352 uno::Sequence
< OUString
> SAL_CALL
SvxUnoMarkerTable::getElementNames()
354 SolarMutexGuard aGuard
;
356 std::set
< OUString
> aNameSet
;
358 // search model pool for line starts
359 createNamesForPool( mpModelPool
, SfxItemType::XLineStartItemType
, aNameSet
); // XATTR_LINESTART
361 // search model pool for line ends
362 createNamesForPool( mpModelPool
, SfxItemType::XLineEndItemType
, aNameSet
); // XATTR_LINEEND
364 return comphelper::containerToSequence(aNameSet
);
367 sal_Bool SAL_CALL
SvxUnoMarkerTable::hasByName( const OUString
& aName
)
369 SolarMutexGuard aGuard
;
371 if( aName
.isEmpty() )
374 OUString aSearchName
;
376 const NameOrIndex
*pItem
;
378 aSearchName
= SvxUnogetInternalNameForItem(XATTR_LINESTART
, aName
);
381 ItemSurrogates aSurrogates
;
382 mpModelPool
->GetItemSurrogatesForItem(aSurrogates
, SfxItemType::XLineStartItemType
); // XATTR_LINESTART
383 for (const SfxPoolItem
* p
: aSurrogates
)
385 pItem
= static_cast<const NameOrIndex
*>(p
);
386 if( pItem
&& pItem
->GetName() == aSearchName
)
391 aSearchName
= SvxUnogetInternalNameForItem(XATTR_LINEEND
, aName
);
394 ItemSurrogates aSurrogates
;
395 mpModelPool
->GetItemSurrogatesForItem(aSurrogates
, SfxItemType::XLineEndItemType
); // XATTR_LINEEND
396 for (const SfxPoolItem
* p
: aSurrogates
)
398 pItem
= static_cast<const NameOrIndex
*>(p
);
399 if( pItem
&& pItem
->GetName() == aSearchName
)
408 uno::Type SAL_CALL
SvxUnoMarkerTable::getElementType( )
410 return cppu::UnoType
<drawing::PointSequence
>::get();
413 sal_Bool SAL_CALL
SvxUnoMarkerTable::hasElements( )
415 SolarMutexGuard aGuard
;
417 const NameOrIndex
*pItem
;
421 ItemSurrogates aSurrogates
;
422 mpModelPool
->GetItemSurrogatesForItem(aSurrogates
, SfxItemType::XLineStartItemType
); // XATTR_LINESTART
423 for (const SfxPoolItem
* p
: aSurrogates
)
425 pItem
= static_cast<const NameOrIndex
*>(p
);
426 if( pItem
&& !pItem
->GetName().isEmpty() )
433 ItemSurrogates aSurrogates
;
434 mpModelPool
->GetItemSurrogatesForItem(aSurrogates
, SfxItemType::XLineEndItemType
); // XATTR_LINEEND
435 for (const SfxPoolItem
* p
: aSurrogates
)
437 pItem
= static_cast<const NameOrIndex
*>(p
);
438 if( pItem
&& !pItem
->GetName().isEmpty() )
447 * Create a hatchtable
449 uno::Reference
< uno::XInterface
> SvxUnoMarkerTable_createInstance( SdrModel
* pModel
)
451 return *new SvxUnoMarkerTable(pModel
);
455 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */