xref: /trunk/main/svx/source/unodraw/gluepts.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <com/sun/star/container/XIdentifierContainer.hpp>
31 #include <com/sun/star/container/XIndexContainer.hpp>
32 #ifndef _COM_SUN_STAR_DRAWING_GLUEPOINT2_HDL_
33 #include <com/sun/star/drawing/GluePoint2.hpp>
34 #endif
35 
36 #include <cppuhelper/implbase2.hxx>
37 
38 #include <svx/svdmodel.hxx>
39 #include <svx/svdobj.hxx>
40 #include <svx/svdglue.hxx>
41 #include <svx/svdpage.hxx>
42 
43 using namespace ::com::sun::star;
44 using namespace ::rtl;
45 using namespace ::cppu;
46 
47 const sal_uInt16 NON_USER_DEFINED_GLUE_POINTS = 4;
48 
49 class SvxUnoGluePointAccess : public WeakImplHelper2< container::XIndexContainer, container::XIdentifierContainer >
50 {
51 private:
52     SdrObjectWeakRef    mpObject;
53 
54 public:
55     SvxUnoGluePointAccess( SdrObject* pObject ) throw();
56     virtual ~SvxUnoGluePointAccess() throw();
57 
58     // XIdentifierContainer
59     virtual sal_Int32 SAL_CALL insert( const uno::Any& aElement ) throw (lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException);
60     virtual void SAL_CALL removeByIdentifier( sal_Int32 Identifier ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException);
61 
62     // XIdentifierReplace
63     virtual void SAL_CALL replaceByIdentifer( sal_Int32 Identifier, const uno::Any& aElement ) throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException);
64 
65     // XIdentifierReplace
66     virtual uno::Any SAL_CALL getByIdentifier( sal_Int32 Identifier ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException);
67     virtual uno::Sequence< sal_Int32 > SAL_CALL getIdentifiers(  ) throw (uno::RuntimeException);
68 
69     /* deprecated */
70     // XIndexContainer
71     virtual void SAL_CALL insertByIndex( sal_Int32 Index, const uno::Any& Element ) throw(lang::IllegalArgumentException, lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException);
72     virtual void SAL_CALL removeByIndex( sal_Int32 Index ) throw(lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException);
73 
74     /* deprecated */
75     // XIndexReplace
76     virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const uno::Any& Element ) throw(lang::IllegalArgumentException, lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException);
77 
78     /* deprecated */
79     // XIndexAccess
80     virtual sal_Int32 SAL_CALL getCount(  ) throw(uno::RuntimeException);
81     virtual uno::Any SAL_CALL getByIndex( sal_Int32 Index ) throw(lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException);
82 
83     // XElementAccess
84     virtual uno::Type SAL_CALL getElementType(  ) throw( uno::RuntimeException);
85     virtual sal_Bool SAL_CALL hasElements(  ) throw( uno::RuntimeException);
86 };
87 
88 static void convert( const SdrGluePoint& rSdrGlue, drawing::GluePoint2& rUnoGlue ) throw()
89 {
90     rUnoGlue.Position.X = rSdrGlue.GetPos().X();
91     rUnoGlue.Position.Y = rSdrGlue.GetPos().Y();
92     rUnoGlue.IsRelative = rSdrGlue.IsPercent();
93 
94     switch( rSdrGlue.GetAlign() )
95     {
96     case SDRVERTALIGN_TOP|SDRHORZALIGN_LEFT:
97         rUnoGlue.PositionAlignment = drawing::Alignment_TOP_LEFT;
98         break;
99     case SDRHORZALIGN_CENTER|SDRVERTALIGN_TOP:
100         rUnoGlue.PositionAlignment = drawing::Alignment_TOP;
101         break;
102     case SDRVERTALIGN_TOP|SDRHORZALIGN_RIGHT:
103         rUnoGlue.PositionAlignment = drawing::Alignment_TOP_RIGHT;
104         break;
105     case SDRHORZALIGN_CENTER|SDRVERTALIGN_CENTER:
106         rUnoGlue.PositionAlignment = drawing::Alignment_CENTER;
107         break;
108     case SDRHORZALIGN_RIGHT|SDRVERTALIGN_CENTER:
109         rUnoGlue.PositionAlignment = drawing::Alignment_RIGHT;
110         break;
111     case SDRHORZALIGN_LEFT|SDRVERTALIGN_BOTTOM:
112         rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM_LEFT;
113         break;
114     case SDRHORZALIGN_CENTER|SDRVERTALIGN_BOTTOM:
115         rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM;
116         break;
117     case SDRHORZALIGN_RIGHT|SDRVERTALIGN_BOTTOM:
118         rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM_RIGHT;
119         break;
120 //  case SDRHORZALIGN_LEFT:
121     default:
122         rUnoGlue.PositionAlignment = drawing::Alignment_LEFT;
123         break;
124     }
125 
126     switch( rSdrGlue.GetEscDir() )
127     {
128     case SDRESC_LEFT:
129         rUnoGlue.Escape = drawing::EscapeDirection_LEFT;
130         break;
131     case SDRESC_RIGHT:
132         rUnoGlue.Escape = drawing::EscapeDirection_RIGHT;
133         break;
134     case SDRESC_TOP:
135         rUnoGlue.Escape = drawing::EscapeDirection_UP;
136         break;
137     case SDRESC_BOTTOM:
138         rUnoGlue.Escape = drawing::EscapeDirection_DOWN;
139         break;
140     case SDRESC_HORZ:
141         rUnoGlue.Escape = drawing::EscapeDirection_HORIZONTAL;
142         break;
143     case SDRESC_VERT:
144         rUnoGlue.Escape = drawing::EscapeDirection_VERTICAL;
145         break;
146 //          case SDRESC_SMART:
147     default:
148         rUnoGlue.Escape = drawing::EscapeDirection_SMART;
149         break;
150     }
151 }
152 
153 static void convert( const drawing::GluePoint2& rUnoGlue, SdrGluePoint& rSdrGlue ) throw()
154 {
155     rSdrGlue.SetPos( Point( rUnoGlue.Position.X, rUnoGlue.Position.Y ) );
156     rSdrGlue.SetPercent( rUnoGlue.IsRelative );
157 
158     switch( rUnoGlue.PositionAlignment )
159     {
160     case drawing::Alignment_TOP_LEFT:
161         rSdrGlue.SetAlign( SDRVERTALIGN_TOP|SDRHORZALIGN_LEFT );
162         break;
163     case drawing::Alignment_TOP:
164         rSdrGlue.SetAlign( SDRHORZALIGN_CENTER|SDRVERTALIGN_TOP );
165         break;
166     case drawing::Alignment_TOP_RIGHT:
167         rSdrGlue.SetAlign( SDRVERTALIGN_TOP|SDRHORZALIGN_RIGHT );
168         break;
169     case drawing::Alignment_CENTER:
170         rSdrGlue.SetAlign( SDRHORZALIGN_CENTER|SDRVERTALIGN_CENTER );
171         break;
172     case drawing::Alignment_RIGHT:
173         rSdrGlue.SetAlign( SDRHORZALIGN_RIGHT|SDRVERTALIGN_CENTER );
174         break;
175     case drawing::Alignment_BOTTOM_LEFT:
176         rSdrGlue.SetAlign( SDRHORZALIGN_LEFT|SDRVERTALIGN_BOTTOM );
177         break;
178     case drawing::Alignment_BOTTOM:
179         rSdrGlue.SetAlign( SDRHORZALIGN_CENTER|SDRVERTALIGN_BOTTOM );
180         break;
181     case drawing::Alignment_BOTTOM_RIGHT:
182         rSdrGlue.SetAlign( SDRHORZALIGN_RIGHT|SDRVERTALIGN_BOTTOM );
183         break;
184 //  case SDRHORZALIGN_LEFT:
185     default:
186         rSdrGlue.SetAlign( SDRHORZALIGN_LEFT );
187         break;
188     }
189     switch( rUnoGlue.Escape )
190     {
191     case drawing::EscapeDirection_LEFT:
192         rSdrGlue.SetEscDir(SDRESC_LEFT);
193         break;
194     case drawing::EscapeDirection_RIGHT:
195         rSdrGlue.SetEscDir(SDRESC_RIGHT);
196         break;
197     case drawing::EscapeDirection_UP:
198         rSdrGlue.SetEscDir(SDRESC_TOP);
199         break;
200     case drawing::EscapeDirection_DOWN:
201         rSdrGlue.SetEscDir(SDRESC_BOTTOM);
202         break;
203     case drawing::EscapeDirection_HORIZONTAL:
204         rSdrGlue.SetEscDir(SDRESC_HORZ);
205         break;
206     case drawing::EscapeDirection_VERTICAL:
207         rSdrGlue.SetEscDir(SDRESC_VERT);
208         break;
209 //  case drawing::EscapeDirection_SMART:
210     default:
211         rSdrGlue.SetEscDir(SDRESC_SMART);
212         break;
213     }
214 }
215 
216 SvxUnoGluePointAccess::SvxUnoGluePointAccess( SdrObject* pObject ) throw()
217 : mpObject( pObject )
218 {
219 }
220 
221 SvxUnoGluePointAccess::~SvxUnoGluePointAccess() throw()
222 {
223 }
224 
225 // XIdentifierContainer
226 sal_Int32 SAL_CALL SvxUnoGluePointAccess::insert( const uno::Any& aElement ) throw (lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
227 {
228     if( mpObject.is() )
229     {
230         SdrGluePointList* pList = mpObject->ForceGluePointList();
231         if( pList )
232         {
233             // second, insert the new glue point
234             drawing::GluePoint2 aUnoGlue;
235 
236             if( aElement >>= aUnoGlue )
237             {
238                 SdrGluePoint aSdrGlue;
239                 convert( aUnoGlue, aSdrGlue );
240                 sal_uInt16 nId = pList->Insert( aSdrGlue );
241 
242                 // only repaint, no objectchange
243                 mpObject->ActionChanged();
244                 // mpObject->BroadcastObjectChange();
245 
246                 return (sal_Int32)((*pList)[nId].GetId() + NON_USER_DEFINED_GLUE_POINTS) - 1;
247             }
248 
249             throw lang::IllegalArgumentException();
250         }
251     }
252 
253     return -1;
254 }
255 
256 void SAL_CALL SvxUnoGluePointAccess::removeByIdentifier( sal_Int32 Identifier ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
257 {
258     if( mpObject.is() && ( Identifier >= NON_USER_DEFINED_GLUE_POINTS ))
259     {
260         const sal_uInt16 nId = (sal_uInt16)(Identifier - NON_USER_DEFINED_GLUE_POINTS) + 1;
261 
262         SdrGluePointList* pList = const_cast<SdrGluePointList*>(mpObject->GetGluePointList());
263         const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
264         sal_uInt16 i;
265 
266         for( i = 0; i < nCount; i++ )
267         {
268             if( (*pList)[i].GetId() == nId )
269             {
270                 pList->Delete( i );
271 
272                 // only repaint, no objectchange
273                 mpObject->ActionChanged();
274                 // mpObject->BroadcastObjectChange();
275 
276                 return;
277             }
278         }
279     }
280 
281     throw container::NoSuchElementException();
282 }
283 
284 // XIdentifierReplace
285 void SAL_CALL SvxUnoGluePointAccess::replaceByIdentifer( sal_Int32 Identifier, const uno::Any& aElement ) throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
286 {
287     if( mpObject.is() && mpObject->IsNode() )
288     {
289         struct drawing::GluePoint2 aGluePoint;
290         if( (Identifier < NON_USER_DEFINED_GLUE_POINTS) || !(aElement >>= aGluePoint))
291             throw lang::IllegalArgumentException();
292 
293         const sal_uInt16 nId = (sal_uInt16)( Identifier - NON_USER_DEFINED_GLUE_POINTS ) + 1;
294 
295         SdrGluePointList* pList = const_cast< SdrGluePointList* >( mpObject->GetGluePointList() );
296         const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
297         sal_uInt16 i;
298         for( i = 0; i < nCount; i++ )
299         {
300             if( (*pList)[i].GetId() == nId )
301             {
302                 // change the glue point
303                 SdrGluePoint& rTempPoint = (*pList)[i];
304                 convert( aGluePoint, rTempPoint );
305 
306                 // only repaint, no objectchange
307                 mpObject->ActionChanged();
308                 // mpObject->BroadcastObjectChange();
309 
310                 return;
311             }
312         }
313 
314         throw container::NoSuchElementException();
315     }
316 }
317 
318 // XIdentifierAccess
319 uno::Any SAL_CALL SvxUnoGluePointAccess::getByIdentifier( sal_Int32 Identifier ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
320 {
321     if( mpObject.is() && mpObject->IsNode() )
322     {
323         struct drawing::GluePoint2 aGluePoint;
324 
325         if( Identifier < NON_USER_DEFINED_GLUE_POINTS ) // default glue point?
326         {
327             SdrGluePoint aTempPoint = mpObject->GetVertexGluePoint( (sal_uInt16)Identifier );
328             aGluePoint.IsUserDefined = sal_False;
329             convert( aTempPoint, aGluePoint );
330             return uno::makeAny( aGluePoint );
331         }
332         else
333         {
334             const sal_uInt16 nId = (sal_uInt16)( Identifier - NON_USER_DEFINED_GLUE_POINTS ) + 1;
335 
336             const SdrGluePointList* pList = mpObject->GetGluePointList();
337             const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
338             for( sal_uInt16 i = 0; i < nCount; i++ )
339             {
340                 const SdrGluePoint& rTempPoint = (*pList)[i];
341                 if( rTempPoint.GetId() == nId )
342                 {
343                     // #i38892#
344                     if(rTempPoint.IsUserDefined())
345                     {
346                         aGluePoint.IsUserDefined = sal_True;
347                     }
348 
349                     convert( rTempPoint, aGluePoint );
350                     return uno::makeAny( aGluePoint );
351                 }
352             }
353         }
354     }
355 
356     throw lang::IndexOutOfBoundsException();
357 }
358 
359 uno::Sequence< sal_Int32 > SAL_CALL SvxUnoGluePointAccess::getIdentifiers() throw (uno::RuntimeException)
360 {
361     if( mpObject.is() )
362     {
363         const SdrGluePointList* pList = mpObject->GetGluePointList();
364         const sal_uInt16 nCount = pList ? pList->GetCount() : 0;
365 
366         sal_uInt16 i;
367 
368         uno::Sequence< sal_Int32 > aIdSequence( nCount + NON_USER_DEFINED_GLUE_POINTS );
369         sal_Int32 *pIdentifier = aIdSequence.getArray();
370 
371         for( i = 0; i < NON_USER_DEFINED_GLUE_POINTS; i++ )
372             *pIdentifier++ = (sal_Int32)i;
373 
374         for( i = 0; i < nCount; i++ )
375             *pIdentifier++ = (sal_Int32) ( (*pList)[i].GetId() + NON_USER_DEFINED_GLUE_POINTS ) - 1;
376 
377         return aIdSequence;
378     }
379     else
380     {
381         uno::Sequence< sal_Int32 > aEmpty;
382         return aEmpty;
383     }
384 }
385 
386 /* deprecated */
387 
388 // XIndexContainer
389 void SAL_CALL SvxUnoGluePointAccess::insertByIndex( sal_Int32, const uno::Any& Element )
390     throw(lang::IllegalArgumentException, lang::IndexOutOfBoundsException,
391             lang::WrappedTargetException, uno::RuntimeException)
392 {
393     if( mpObject.is() )
394     {
395         SdrGluePointList* pList = mpObject->ForceGluePointList();
396         if( pList )
397         {
398             SdrGluePoint aSdrGlue;
399             drawing::GluePoint2 aUnoGlue;
400 
401             if( Element >>= aUnoGlue )
402             {
403                 convert( aUnoGlue, aSdrGlue );
404                 pList->Insert( aSdrGlue );
405 
406                 // only repaint, no objectchange
407                 mpObject->ActionChanged();
408                 // mpObject->BroadcastObjectChange();
409 
410                 return;
411             }
412 
413             throw lang::IllegalArgumentException();
414         }
415     }
416 
417     throw lang::IndexOutOfBoundsException();
418 }
419 
420 void SAL_CALL SvxUnoGluePointAccess::removeByIndex( sal_Int32 Index )
421     throw(lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException)
422 {
423     if( mpObject.is() )
424     {
425         SdrGluePointList* pList = mpObject->ForceGluePointList();
426         if( pList )
427         {
428             Index -= 4;
429             if( Index >= 0 && Index < pList->GetCount() )
430             {
431                 pList->Delete( (sal_uInt16)Index );
432 
433                 // only repaint, no objectchange
434                 mpObject->ActionChanged();
435                 // mpObject->BroadcastObjectChange();
436 
437                 return;
438             }
439         }
440     }
441 
442     throw lang::IndexOutOfBoundsException();
443 }
444 
445 // XIndexReplace
446 void SAL_CALL SvxUnoGluePointAccess::replaceByIndex( sal_Int32 Index, const uno::Any& Element )
447     throw(lang::IllegalArgumentException, lang::IndexOutOfBoundsException, lang::WrappedTargetException,
448     uno::RuntimeException)
449 {
450     drawing::GluePoint2 aUnoGlue;
451     if(!(Element >>= aUnoGlue))
452         throw lang::IllegalArgumentException();
453 
454     Index -= 4;
455     if( mpObject.is() && Index >= 0 )
456     {
457         SdrGluePointList* pList = const_cast< SdrGluePointList* >( mpObject->GetGluePointList() );
458         if( pList && Index < pList->GetCount() )
459         {
460             SdrGluePoint& rGlue = (*pList)[(sal_uInt16)Index];
461             convert( aUnoGlue, rGlue );
462 
463             // only repaint, no objectchange
464             mpObject->ActionChanged();
465             // mpObject->BroadcastObjectChange();
466         }
467     }
468 
469     throw lang::IndexOutOfBoundsException();
470 }
471 
472 // XIndexAccess
473 sal_Int32 SAL_CALL SvxUnoGluePointAccess::getCount()
474     throw(uno::RuntimeException)
475 {
476     sal_Int32 nCount = 0;
477     if( mpObject.is() )
478     {
479         // each node has a default of 4 glue points
480         // and any number of user defined glue points
481         if( mpObject->IsNode() )
482         {
483             nCount += 4;
484 
485             const SdrGluePointList* pList = mpObject->GetGluePointList();
486             if( pList )
487                 nCount += pList->GetCount();
488         }
489     }
490 
491     return nCount;
492 }
493 
494 uno::Any SAL_CALL SvxUnoGluePointAccess::getByIndex( sal_Int32 Index )
495     throw(lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException)
496 {
497     if( Index >= 0 && mpObject.is() && mpObject->IsNode() )
498     {
499         struct drawing::GluePoint2 aGluePoint;
500 
501         if( Index < 4 ) // default glue point?
502         {
503             SdrGluePoint aTempPoint = mpObject->GetVertexGluePoint( (sal_uInt16)Index );
504             aGluePoint.IsUserDefined = sal_False;
505             convert( aTempPoint, aGluePoint );
506             uno::Any aAny;
507             aAny <<= aGluePoint;
508             return aAny;
509         }
510         else
511         {
512             Index -= 4;
513             const SdrGluePointList* pList = mpObject->GetGluePointList();
514             if( pList && Index < pList->GetCount() )
515             {
516                 const SdrGluePoint& rTempPoint = (*pList)[(sal_uInt16)Index];
517                 aGluePoint.IsUserDefined = sal_True;
518                 convert( rTempPoint, aGluePoint );
519                 uno::Any aAny;
520                 aAny <<= aGluePoint;
521                 return aAny;
522             }
523         }
524     }
525 
526     throw lang::IndexOutOfBoundsException();
527 }
528 
529 // XElementAccess
530 uno::Type SAL_CALL SvxUnoGluePointAccess::getElementType()
531     throw( uno::RuntimeException)
532 {
533     return ::getCppuType((const struct drawing::GluePoint2*)0);
534 }
535 
536 sal_Bool SAL_CALL SvxUnoGluePointAccess::hasElements()
537     throw( uno::RuntimeException)
538 {
539     return mpObject.is() && mpObject->IsNode();
540 }
541 
542 /**
543  * Create a SvxUnoGluePointAccess
544  */
545 uno::Reference< uno::XInterface > SAL_CALL SvxUnoGluePointAccess_createInstance( SdrObject* pObject )
546 {
547     return *new SvxUnoGluePointAccess(pObject);
548 }
549