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 <com/sun/star/container/NoSuchElementException.hpp>
21 #include <com/sun/star/container/XIdentifierContainer.hpp>
22 #include <com/sun/star/container/XIndexContainer.hpp>
23 #include <com/sun/star/drawing/GluePoint2.hpp>
24 #include <com/sun/star/lang/IllegalArgumentException.hpp>
25 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27 #include <cppuhelper/implbase.hxx>
28 #include <tools/weakbase.hxx>
29 #include <unotools/weakref.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/svdglue.hxx>
34 #include "gluepts.hxx"
36 using namespace ::com::sun::star
;
37 using namespace ::cppu
;
39 const sal_uInt16 NON_USER_DEFINED_GLUE_POINTS
= 4;
43 class SvxUnoGluePointAccess
: public WeakImplHelper
< container::XIndexContainer
, container::XIdentifierContainer
>
46 unotools::WeakReference
<SdrObject
> mpObject
;
49 explicit SvxUnoGluePointAccess( SdrObject
* pObject
) noexcept
;
51 // XIdentifierContainer
52 virtual sal_Int32 SAL_CALL
insert( const uno::Any
& aElement
) override
;
53 virtual void SAL_CALL
removeByIdentifier( sal_Int32 Identifier
) override
;
56 virtual void SAL_CALL
replaceByIdentifer( sal_Int32 Identifier
, const uno::Any
& aElement
) override
;
59 virtual uno::Any SAL_CALL
getByIdentifier( sal_Int32 Identifier
) override
;
60 virtual uno::Sequence
< sal_Int32
> SAL_CALL
getIdentifiers( ) override
;
64 virtual void SAL_CALL
insertByIndex( sal_Int32 Index
, const uno::Any
& Element
) override
;
65 virtual void SAL_CALL
removeByIndex( sal_Int32 Index
) override
;
69 virtual void SAL_CALL
replaceByIndex( sal_Int32 Index
, const uno::Any
& Element
) override
;
73 virtual sal_Int32 SAL_CALL
getCount( ) override
;
74 virtual uno::Any SAL_CALL
getByIndex( sal_Int32 Index
) override
;
77 virtual uno::Type SAL_CALL
getElementType( ) override
;
78 virtual sal_Bool SAL_CALL
hasElements( ) override
;
83 static void convert( const SdrGluePoint
& rSdrGlue
, drawing::GluePoint2
& rUnoGlue
) noexcept
85 rUnoGlue
.Position
.X
= rSdrGlue
.GetPos().X();
86 rUnoGlue
.Position
.Y
= rSdrGlue
.GetPos().Y();
87 rUnoGlue
.IsRelative
= rSdrGlue
.IsPercent();
89 SdrAlign eAlign
= rSdrGlue
.GetAlign();
90 if (eAlign
== (SdrAlign::VERT_TOP
|SdrAlign::HORZ_LEFT
))
91 rUnoGlue
.PositionAlignment
= drawing::Alignment_TOP_LEFT
;
92 else if (eAlign
== (SdrAlign::HORZ_CENTER
|SdrAlign::VERT_TOP
))
93 rUnoGlue
.PositionAlignment
= drawing::Alignment_TOP
;
94 else if (eAlign
== (SdrAlign::VERT_TOP
|SdrAlign::HORZ_RIGHT
))
95 rUnoGlue
.PositionAlignment
= drawing::Alignment_TOP_RIGHT
;
96 else if (eAlign
== (SdrAlign::HORZ_CENTER
|SdrAlign::VERT_CENTER
))
97 rUnoGlue
.PositionAlignment
= drawing::Alignment_CENTER
;
98 else if (eAlign
== (SdrAlign::HORZ_RIGHT
|SdrAlign::VERT_CENTER
))
99 rUnoGlue
.PositionAlignment
= drawing::Alignment_RIGHT
;
100 else if (eAlign
== (SdrAlign::HORZ_LEFT
|SdrAlign::VERT_BOTTOM
))
101 rUnoGlue
.PositionAlignment
= drawing::Alignment_BOTTOM_LEFT
;
102 else if (eAlign
== (SdrAlign::HORZ_CENTER
|SdrAlign::VERT_BOTTOM
))
103 rUnoGlue
.PositionAlignment
= drawing::Alignment_BOTTOM
;
104 else if (eAlign
== (SdrAlign::HORZ_RIGHT
|SdrAlign::VERT_BOTTOM
))
105 rUnoGlue
.PositionAlignment
= drawing::Alignment_BOTTOM_RIGHT
;
107 rUnoGlue
.PositionAlignment
= drawing::Alignment_LEFT
;
110 switch( rSdrGlue
.GetEscDir() )
112 case SdrEscapeDirection::LEFT
:
113 rUnoGlue
.Escape
= drawing::EscapeDirection_LEFT
;
115 case SdrEscapeDirection::RIGHT
:
116 rUnoGlue
.Escape
= drawing::EscapeDirection_RIGHT
;
118 case SdrEscapeDirection::TOP
:
119 rUnoGlue
.Escape
= drawing::EscapeDirection_UP
;
121 case SdrEscapeDirection::BOTTOM
:
122 rUnoGlue
.Escape
= drawing::EscapeDirection_DOWN
;
124 case SdrEscapeDirection::HORZ
:
125 rUnoGlue
.Escape
= drawing::EscapeDirection_HORIZONTAL
;
127 case SdrEscapeDirection::VERT
:
128 rUnoGlue
.Escape
= drawing::EscapeDirection_VERTICAL
;
130 // case SdrEscapeDirection::SMART:
132 rUnoGlue
.Escape
= drawing::EscapeDirection_SMART
;
137 static void convert( const drawing::GluePoint2
& rUnoGlue
, SdrGluePoint
& rSdrGlue
) noexcept
139 rSdrGlue
.SetPos( Point( rUnoGlue
.Position
.X
, rUnoGlue
.Position
.Y
) );
140 rSdrGlue
.SetPercent( rUnoGlue
.IsRelative
);
142 switch( rUnoGlue
.PositionAlignment
)
144 case drawing::Alignment_TOP_LEFT
:
145 rSdrGlue
.SetAlign( SdrAlign::VERT_TOP
|SdrAlign::HORZ_LEFT
);
147 case drawing::Alignment_TOP
:
148 rSdrGlue
.SetAlign( SdrAlign::HORZ_CENTER
|SdrAlign::VERT_TOP
);
150 case drawing::Alignment_TOP_RIGHT
:
151 rSdrGlue
.SetAlign( SdrAlign::VERT_TOP
|SdrAlign::HORZ_RIGHT
);
153 case drawing::Alignment_CENTER
:
154 rSdrGlue
.SetAlign( SdrAlign::HORZ_CENTER
|SdrAlign::VERT_CENTER
);
156 case drawing::Alignment_RIGHT
:
157 rSdrGlue
.SetAlign( SdrAlign::HORZ_RIGHT
|SdrAlign::VERT_CENTER
);
159 case drawing::Alignment_BOTTOM_LEFT
:
160 rSdrGlue
.SetAlign( SdrAlign::HORZ_LEFT
|SdrAlign::VERT_BOTTOM
);
162 case drawing::Alignment_BOTTOM
:
163 rSdrGlue
.SetAlign( SdrAlign::HORZ_CENTER
|SdrAlign::VERT_BOTTOM
);
165 case drawing::Alignment_BOTTOM_RIGHT
:
166 rSdrGlue
.SetAlign( SdrAlign::HORZ_RIGHT
|SdrAlign::VERT_BOTTOM
);
168 // case SdrAlign::HORZ_LEFT:
170 rSdrGlue
.SetAlign( SdrAlign::HORZ_LEFT
);
173 switch( rUnoGlue
.Escape
)
175 case drawing::EscapeDirection_LEFT
:
176 rSdrGlue
.SetEscDir(SdrEscapeDirection::LEFT
);
178 case drawing::EscapeDirection_RIGHT
:
179 rSdrGlue
.SetEscDir(SdrEscapeDirection::RIGHT
);
181 case drawing::EscapeDirection_UP
:
182 rSdrGlue
.SetEscDir(SdrEscapeDirection::TOP
);
184 case drawing::EscapeDirection_DOWN
:
185 rSdrGlue
.SetEscDir(SdrEscapeDirection::BOTTOM
);
187 case drawing::EscapeDirection_HORIZONTAL
:
188 rSdrGlue
.SetEscDir(SdrEscapeDirection::HORZ
);
190 case drawing::EscapeDirection_VERTICAL
:
191 rSdrGlue
.SetEscDir(SdrEscapeDirection::VERT
);
193 // case drawing::EscapeDirection_SMART:
195 rSdrGlue
.SetEscDir(SdrEscapeDirection::SMART
);
200 SvxUnoGluePointAccess::SvxUnoGluePointAccess( SdrObject
* pObject
) noexcept
201 : mpObject( pObject
)
205 // XIdentifierContainer
206 sal_Int32 SAL_CALL
SvxUnoGluePointAccess::insert( const uno::Any
& aElement
)
208 if( auto pObject
= mpObject
.get() )
210 SdrGluePointList
* pList
= pObject
->ForceGluePointList();
213 // second, insert the new gluepoint
214 drawing::GluePoint2 aUnoGlue
;
216 if( aElement
>>= aUnoGlue
)
218 SdrGluePoint aSdrGlue
;
219 convert( aUnoGlue
, aSdrGlue
);
220 sal_uInt16 nId
= pList
->Insert( aSdrGlue
);
222 // only repaint, no objectchange
223 pObject
->ActionChanged();
224 // mpObject->BroadcastObjectChange();
226 return static_cast<sal_Int32
>((*pList
)[nId
].GetId() + NON_USER_DEFINED_GLUE_POINTS
) - 1;
229 throw lang::IllegalArgumentException();
236 void SAL_CALL
SvxUnoGluePointAccess::removeByIdentifier( sal_Int32 Identifier
)
238 auto pObject
= mpObject
.get();
239 if( pObject
&& ( Identifier
>= NON_USER_DEFINED_GLUE_POINTS
))
241 const sal_uInt16 nId
= static_cast<sal_uInt16
>(Identifier
- NON_USER_DEFINED_GLUE_POINTS
) + 1;
243 SdrGluePointList
* pList
= const_cast<SdrGluePointList
*>(pObject
->GetGluePointList());
244 const sal_uInt16 nCount
= pList
? pList
->GetCount() : 0;
247 for( i
= 0; i
< nCount
; i
++ )
249 if( (*pList
)[i
].GetId() == nId
)
253 // only repaint, no objectchange
254 pObject
->ActionChanged();
255 // pObject->BroadcastObjectChange();
262 throw container::NoSuchElementException();
265 // XIdentifierReplace
266 void SAL_CALL
SvxUnoGluePointAccess::replaceByIdentifer( sal_Int32 Identifier
, const uno::Any
& aElement
)
268 auto pObject
= mpObject
.get();
272 struct drawing::GluePoint2 aGluePoint
;
273 if( (Identifier
< NON_USER_DEFINED_GLUE_POINTS
) || !(aElement
>>= aGluePoint
))
274 throw lang::IllegalArgumentException();
276 const sal_uInt16 nId
= static_cast<sal_uInt16
>( Identifier
- NON_USER_DEFINED_GLUE_POINTS
) + 1;
278 SdrGluePointList
* pList
= const_cast< SdrGluePointList
* >( pObject
->GetGluePointList() );
279 const sal_uInt16 nCount
= pList
? pList
->GetCount() : 0;
281 for( i
= 0; i
< nCount
; i
++ )
283 if( (*pList
)[i
].GetId() == nId
)
285 // change the gluepoint
286 SdrGluePoint
& rTempPoint
= (*pList
)[i
];
287 convert( aGluePoint
, rTempPoint
);
289 // only repaint, no objectchange
290 pObject
->ActionChanged();
291 // pObject->BroadcastObjectChange();
297 throw container::NoSuchElementException();
301 uno::Any SAL_CALL
SvxUnoGluePointAccess::getByIdentifier( sal_Int32 Identifier
)
303 auto pObject
= mpObject
.get();
306 struct drawing::GluePoint2 aGluePoint
;
308 if( Identifier
< NON_USER_DEFINED_GLUE_POINTS
) // default gluepoint?
310 SdrGluePoint aTempPoint
= pObject
->GetVertexGluePoint( static_cast<sal_uInt16
>(Identifier
) );
311 aGluePoint
.IsUserDefined
= false;
312 convert( aTempPoint
, aGluePoint
);
313 return uno::Any( aGluePoint
);
317 const sal_uInt16 nId
= static_cast<sal_uInt16
>( Identifier
- NON_USER_DEFINED_GLUE_POINTS
) + 1;
319 const SdrGluePointList
* pList
= pObject
->GetGluePointList();
320 const sal_uInt16 nCount
= pList
? pList
->GetCount() : 0;
321 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
323 const SdrGluePoint
& rTempPoint
= (*pList
)[i
];
324 if( rTempPoint
.GetId() == nId
)
327 if(rTempPoint
.IsUserDefined())
329 aGluePoint
.IsUserDefined
= true;
332 convert( rTempPoint
, aGluePoint
);
333 return uno::Any( aGluePoint
);
339 throw container::NoSuchElementException();
342 uno::Sequence
< sal_Int32
> SAL_CALL
SvxUnoGluePointAccess::getIdentifiers()
344 auto pObject
= mpObject
.get();
347 const SdrGluePointList
* pList
= pObject
->GetGluePointList();
348 const sal_uInt16 nCount
= pList
? pList
->GetCount() : 0;
352 uno::Sequence
< sal_Int32
> aIdSequence( nCount
+ NON_USER_DEFINED_GLUE_POINTS
);
353 sal_Int32
*pIdentifier
= aIdSequence
.getArray();
355 for( i
= 0; i
< NON_USER_DEFINED_GLUE_POINTS
; i
++ )
356 *pIdentifier
++ = static_cast<sal_Int32
>(i
);
358 for( i
= 0; i
< nCount
; i
++ )
359 *pIdentifier
++ = static_cast<sal_Int32
>( (*pList
)[i
].GetId() + NON_USER_DEFINED_GLUE_POINTS
) - 1;
365 uno::Sequence
< sal_Int32
> aEmpty
;
373 void SAL_CALL
SvxUnoGluePointAccess::insertByIndex( sal_Int32
, const uno::Any
& Element
)
375 auto pObject
= mpObject
.get();
378 SdrGluePointList
* pList
= pObject
->ForceGluePointList();
381 drawing::GluePoint2 aUnoGlue
;
383 if( Element
>>= aUnoGlue
)
385 SdrGluePoint aSdrGlue
;
386 convert( aUnoGlue
, aSdrGlue
);
387 pList
->Insert( aSdrGlue
);
389 // only repaint, no objectchange
390 pObject
->ActionChanged();
391 // pObject->BroadcastObjectChange();
396 throw lang::IllegalArgumentException();
400 throw lang::IndexOutOfBoundsException();
403 void SAL_CALL
SvxUnoGluePointAccess::removeByIndex( sal_Int32 Index
)
405 auto pObject
= mpObject
.get();
408 SdrGluePointList
* pList
= pObject
->ForceGluePointList();
412 if( Index
>= 0 && Index
< pList
->GetCount() )
414 pList
->Delete( static_cast<sal_uInt16
>(Index
) );
416 // only repaint, no objectchange
417 pObject
->ActionChanged();
418 // pObject->BroadcastObjectChange();
425 throw lang::IndexOutOfBoundsException();
429 void SAL_CALL
SvxUnoGluePointAccess::replaceByIndex( sal_Int32 Index
, const uno::Any
& Element
)
431 drawing::GluePoint2 aUnoGlue
;
432 if(!(Element
>>= aUnoGlue
))
433 throw lang::IllegalArgumentException();
435 auto pObject
= mpObject
.get();
437 if( pObject
&& Index
>= 0 )
439 SdrGluePointList
* pList
= const_cast< SdrGluePointList
* >( pObject
->GetGluePointList() );
440 if( pList
&& Index
< pList
->GetCount() )
442 SdrGluePoint
& rGlue
= (*pList
)[static_cast<sal_uInt16
>(Index
)];
443 convert( aUnoGlue
, rGlue
);
445 // only repaint, no objectchange
446 pObject
->ActionChanged();
447 // pObject->BroadcastObjectChange();
451 throw lang::IndexOutOfBoundsException();
455 sal_Int32 SAL_CALL
SvxUnoGluePointAccess::getCount()
457 auto pObject
= mpObject
.get();
458 sal_Int32 nCount
= 0;
461 // each node has a default of 4 gluepoints
462 // and any number of user defined gluepoints
465 const SdrGluePointList
* pList
= pObject
->GetGluePointList();
467 nCount
+= pList
->GetCount();
473 uno::Any SAL_CALL
SvxUnoGluePointAccess::getByIndex( sal_Int32 Index
)
475 auto pObject
= mpObject
.get();
476 if( Index
>= 0 && pObject
)
478 struct drawing::GluePoint2 aGluePoint
;
480 if( Index
< 4 ) // default gluepoint?
482 SdrGluePoint aTempPoint
= pObject
->GetVertexGluePoint( static_cast<sal_uInt16
>(Index
) );
483 aGluePoint
.IsUserDefined
= false;
484 convert( aTempPoint
, aGluePoint
);
485 return uno::Any(aGluePoint
);
490 const SdrGluePointList
* pList
= pObject
->GetGluePointList();
491 if( pList
&& Index
< pList
->GetCount() )
493 const SdrGluePoint
& rTempPoint
= (*pList
)[static_cast<sal_uInt16
>(Index
)];
494 aGluePoint
.IsUserDefined
= true;
495 convert( rTempPoint
, aGluePoint
);
496 return uno::Any(aGluePoint
);
501 throw lang::IndexOutOfBoundsException();
505 uno::Type SAL_CALL
SvxUnoGluePointAccess::getElementType()
507 return cppu::UnoType
<drawing::GluePoint2
>::get();
510 sal_Bool SAL_CALL
SvxUnoGluePointAccess::hasElements()
512 return bool(mpObject
.get());
516 * Create a SvxUnoGluePointAccess
518 uno::Reference
< uno::XInterface
> SvxUnoGluePointAccess_createInstance( SdrObject
* pObject
)
520 return *new SvxUnoGluePointAccess(pObject
);
523 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */