xref: /trunk/main/sc/source/ui/unoobj/shapeuno.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_sc.hxx"
30 
31 #include <tools/debug.hxx>
32 #include <comphelper/uno3.hxx>
33 #include <comphelper/stl_types.hxx>
34 #include <svtools/unoevent.hxx>
35 #include <svtools/unoimap.hxx>
36 #include <svx/svdobj.hxx>
37 #include <svx/unoshape.hxx>
38 #include <editeng/unofield.hxx>
39 #include <svx/shapepropertynotifier.hxx>
40 #include <toolkit/helper/convert.hxx>
41 #include <cppuhelper/implbase2.hxx>
42 
43 #include <com/sun/star/drawing/XShape.hpp>
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 
46 #include "shapeuno.hxx"
47 #include "miscuno.hxx"
48 #include "cellsuno.hxx"
49 #include "textuno.hxx"
50 #include "fielduno.hxx"
51 #include "docsh.hxx"
52 #include "drwlayer.hxx"
53 #include "userdat.hxx"
54 #include "unonames.hxx"
55 #include "unoguard.hxx"
56 
57 using namespace ::com::sun::star;
58 
59 //------------------------------------------------------------------------
60 
61 DECLARE_STL_USTRINGACCESS_MAP( uno::Sequence< sal_Int8 > *,  ScShapeImplementationIdMap );
62 
63 static ScShapeImplementationIdMap aImplementationIdMap;
64 
65 const SfxItemPropertyMapEntry* lcl_GetShapeMap()
66 {
67     static SfxItemPropertyMapEntry aShapeMap_Impl[] =
68     {
69         {MAP_CHAR_LEN(SC_UNONAME_ANCHOR), 0, &getCppuType((uno::Reference<uno::XInterface>*)0), 0, 0 },
70         {MAP_CHAR_LEN(SC_UNONAME_HORIPOS), 0, &getCppuType((sal_Int32*)0), 0, 0 },
71         {MAP_CHAR_LEN(SC_UNONAME_IMAGEMAP), 0, &getCppuType((uno::Reference<container::XIndexContainer>*)0), 0, 0 },
72         {MAP_CHAR_LEN(SC_UNONAME_VERTPOS), 0, &getCppuType((sal_Int32*)0), 0, 0 },
73         {0,0,0,0,0,0}
74     };
75     return aShapeMap_Impl;
76 }
77 
78 // static
79 const SvEventDescription* ScShapeObj::GetSupportedMacroItems()
80 {
81     static const SvEventDescription aMacroDescriptionsImpl[] =
82     {
83         { 0, NULL }
84     };
85     return aMacroDescriptionsImpl;
86 }
87 
88 //------------------------------------------------------------------------
89 
90 namespace
91 {
92     void lcl_initializeNotifier( SdrObject& _rSdrObj, ::cppu::OWeakObject& _rShape )
93     {
94         ::svx::PPropertyValueProvider pProvider( new ::svx::PropertyValueProvider( _rShape, "Anchor" ) );
95         _rSdrObj.getShapePropertyChangeNotifier().registerProvider( ::svx::eSpreadsheetAnchor, pProvider );
96     }
97 }
98 
99 //------------------------------------------------------------------------
100 
101 ScShapeObj::ScShapeObj( uno::Reference<drawing::XShape>& xShape ) :
102       pShapePropertySet(NULL),
103       pShapePropertyState(NULL),
104       pImplementationId(NULL),
105       bIsTextShape(false),
106       bIsNoteCaption(false),
107       bInitializedNotifier(false)
108 {
109     comphelper::increment( m_refCount );
110 
111     {
112         mxShapeAgg = uno::Reference<uno::XAggregation>( xShape, uno::UNO_QUERY );
113         // extra block to force deletion of the temporary before setDelegator
114     }
115 
116     if (mxShapeAgg.is())
117     {
118         xShape = NULL;      // during setDelegator, mxShapeAgg must be the only ref
119 
120         mxShapeAgg->setDelegator( (cppu::OWeakObject*)this );
121 
122         xShape.set(uno::Reference<drawing::XShape>( mxShapeAgg, uno::UNO_QUERY ));
123 
124         bIsTextShape = ( SvxUnoTextBase::getImplementation( mxShapeAgg ) != NULL );
125     }
126 
127     {
128         SdrObject* pObj = GetSdrObject();
129         if ( pObj )
130         {
131             bIsNoteCaption = ScDrawLayer::IsNoteCaption( pObj );
132             lcl_initializeNotifier( *pObj, *this );
133             bInitializedNotifier = true;
134         }
135     }
136 
137     comphelper::decrement( m_refCount );
138 }
139 
140 ScShapeObj::~ScShapeObj()
141 {
142 //  if (mxShapeAgg.is())
143 //      mxShapeAgg->setDelegator(uno::Reference<uno::XInterface>());
144 }
145 
146 // XInterface
147 
148 uno::Any SAL_CALL ScShapeObj::queryInterface( const uno::Type& rType )
149                                                 throw(uno::RuntimeException)
150 {
151     uno::Any aRet = ScShapeObj_Base::queryInterface( rType );
152 
153     if ( !aRet.hasValue() && bIsTextShape )
154         aRet = ScShapeObj_TextBase::queryInterface( rType );
155 
156     if ( !aRet.hasValue() && bIsNoteCaption )
157         aRet = ScShapeObj_ChildBase::queryInterface( rType );
158 
159     if ( !aRet.hasValue() && mxShapeAgg.is() )
160         aRet = mxShapeAgg->queryAggregation( rType );
161 
162     return aRet;
163 }
164 
165 void SAL_CALL ScShapeObj::acquire() throw()
166 {
167         OWeakObject::acquire();
168 }
169 
170 void SAL_CALL ScShapeObj::release() throw()
171 {
172         OWeakObject::release();
173 }
174 
175 void ScShapeObj::GetShapePropertySet()
176 {
177     // #i61908# Store the result of queryAggregation in a member.
178     // The reference in mxShapeAgg is kept for this object's lifetime, so the pointer is always valid.
179 
180     if (!pShapePropertySet)
181     {
182         uno::Reference<beans::XPropertySet> xProp;
183         if ( mxShapeAgg.is() )
184             mxShapeAgg->queryAggregation( getCppuType((uno::Reference<beans::XPropertySet>*) 0) ) >>= xProp;
185         pShapePropertySet = xProp.get();
186     }
187 }
188 
189 void ScShapeObj::GetShapePropertyState()
190 {
191     // #i61908# Store the result of queryAggregation in a member.
192     // The reference in mxShapeAgg is kept for this object's lifetime, so the pointer is always valid.
193 
194     if (!pShapePropertyState)
195     {
196         uno::Reference<beans::XPropertyState> xState;
197         if ( mxShapeAgg.is() )
198             mxShapeAgg->queryAggregation( getCppuType((uno::Reference<beans::XPropertyState>*) 0) ) >>= xState;
199         pShapePropertyState = xState.get();
200     }
201 }
202 
203 uno::Reference<lang::XComponent> lcl_GetComponent( const uno::Reference<uno::XAggregation>& xAgg )
204 {
205     uno::Reference<lang::XComponent> xRet;
206     if ( xAgg.is() )
207         xAgg->queryAggregation( getCppuType((uno::Reference<lang::XComponent>*) 0) ) >>= xRet;
208     return xRet;
209 }
210 
211 uno::Reference<text::XText> lcl_GetText( const uno::Reference<uno::XAggregation>& xAgg )
212 {
213     uno::Reference<text::XText> xRet;
214     if ( xAgg.is() )
215         xAgg->queryAggregation( getCppuType((uno::Reference<text::XText>*) 0) ) >>= xRet;
216     return xRet;
217 }
218 
219 uno::Reference<text::XSimpleText> lcl_GetSimpleText( const uno::Reference<uno::XAggregation>& xAgg )
220 {
221     uno::Reference<text::XSimpleText> xRet;
222     if ( xAgg.is() )
223         xAgg->queryAggregation( getCppuType((uno::Reference<text::XSimpleText>*) 0) ) >>= xRet;
224     return xRet;
225 }
226 
227 uno::Reference<text::XTextRange> lcl_GetTextRange( const uno::Reference<uno::XAggregation>& xAgg )
228 {
229     uno::Reference<text::XTextRange> xRet;
230     if ( xAgg.is() )
231         xAgg->queryAggregation( getCppuType((uno::Reference<text::XTextRange>*) 0) ) >>= xRet;
232     return xRet;
233 }
234 
235 //  XPropertySet
236 
237 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScShapeObj::getPropertySetInfo()
238                                                         throw(uno::RuntimeException)
239 {
240     ScUnoGuard aGuard;
241 
242     // #i61527# cache property set info for this object
243     if ( !mxPropSetInfo.is() )
244     {
245         //  mix own and aggregated properties:
246         GetShapePropertySet();
247         if (pShapePropertySet)
248         {
249             uno::Reference<beans::XPropertySetInfo> xAggInfo(pShapePropertySet->getPropertySetInfo());
250             const uno::Sequence<beans::Property> aPropSeq(xAggInfo->getProperties());
251             mxPropSetInfo.set(new SfxExtItemPropertySetInfo( lcl_GetShapeMap(), aPropSeq ));
252         }
253     }
254     return mxPropSetInfo;
255 }
256 
257 sal_Bool lcl_GetPageNum( SdrPage* pPage, SdrModel& rModel, SCTAB& rNum )
258 {
259     sal_uInt16 nCount = rModel.GetPageCount();
260     for (sal_uInt16 i=0; i<nCount; i++)
261         if ( rModel.GetPage(i) == pPage )
262         {
263             rNum = static_cast<SCTAB>(i);
264             return sal_True;
265         }
266 
267     return sal_False;
268 }
269 
270 sal_Bool lcl_GetCaptionPoint( uno::Reference< drawing::XShape >& xShape, awt::Point& rCaptionPoint )
271 {
272     sal_Bool bReturn = sal_False;
273     rtl::OUString sType(xShape->getShapeType());
274     sal_Bool bCaptionShape(sType.equalsAscii("com.sun.star.drawing.CaptionShape"));
275     if (bCaptionShape)
276     {
277         uno::Reference < beans::XPropertySet > xShapeProp (xShape, uno::UNO_QUERY);
278         if (xShapeProp.is())
279         {
280             xShapeProp->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" )) ) >>= rCaptionPoint;
281             bReturn = sal_True;
282         }
283     }
284     return bReturn;
285 }
286 
287 ScRange lcl_GetAnchorCell( uno::Reference< drawing::XShape >& xShape, ScDocument* pDoc, SCTAB nTab,
288                           awt::Point& rUnoPoint, awt::Size& rUnoSize, awt::Point& rCaptionPoint )
289 {
290     ScRange aReturn;
291     rUnoPoint = xShape->getPosition();
292     rtl::OUString sType(xShape->getShapeType());
293     sal_Bool bCaptionShape(lcl_GetCaptionPoint(xShape, rCaptionPoint));
294     if (pDoc->IsNegativePage(nTab))
295     {
296         rUnoSize = xShape->getSize();
297         rUnoPoint.X += rUnoSize.Width; // the right top point is base
298         if (bCaptionShape)
299         {
300             if (rCaptionPoint.X > 0 && rCaptionPoint.X > rUnoSize.Width)
301                 rUnoPoint.X += rCaptionPoint.X - rUnoSize.Width;
302             if (rCaptionPoint.Y < 0)
303                 rUnoPoint.Y += rCaptionPoint.Y;
304         }
305         aReturn = pDoc->GetRange( nTab, Rectangle( VCLPoint(rUnoPoint), VCLPoint(rUnoPoint) ));
306     }
307     else
308     {
309         if (bCaptionShape)
310         {
311             if (rCaptionPoint.X < 0)
312                 rUnoPoint.X += rCaptionPoint.X;
313             if (rCaptionPoint.Y < 0)
314                 rUnoPoint.Y += rCaptionPoint.Y;
315         }
316         aReturn = pDoc->GetRange( nTab, Rectangle( VCLPoint(rUnoPoint), VCLPoint(rUnoPoint) ));
317     }
318 
319     return aReturn;
320 }
321 
322 awt::Point lcl_GetRelativePos( uno::Reference< drawing::XShape >& xShape, ScDocument* pDoc, SCTAB nTab, ScRange& rRange,
323                               awt::Size& rUnoSize, awt::Point& rCaptionPoint)
324 {
325     awt::Point aUnoPoint;
326     rRange = lcl_GetAnchorCell(xShape, pDoc, nTab, aUnoPoint, rUnoSize, rCaptionPoint);
327     if (pDoc->IsNegativePage(nTab))
328     {
329         Rectangle aRect(pDoc->GetMMRect( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() ));
330         Point aPoint(aRect.TopRight());
331         aUnoPoint.X -= aPoint.X();
332         aUnoPoint.Y -= aPoint.Y();
333     }
334     else
335     {
336         ScRange aRange = pDoc->GetRange( nTab, Rectangle( VCLPoint(aUnoPoint), VCLPoint(aUnoPoint) ));
337         Rectangle aRect(pDoc->GetMMRect( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() ));
338         Point aPoint(aRect.TopLeft());
339         aUnoPoint.X -= aPoint.X();
340         aUnoPoint.Y -= aPoint.Y();
341     }
342 
343     return aUnoPoint;
344 }
345 
346 void SAL_CALL ScShapeObj::setPropertyValue(
347                         const rtl::OUString& aPropertyName, const uno::Any& aValue )
348                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
349                         lang::IllegalArgumentException, lang::WrappedTargetException,
350                         uno::RuntimeException)
351 {
352     ScUnoGuard aGuard;
353     String aNameString(aPropertyName);
354 
355     if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) )
356     {
357         uno::Reference<sheet::XCellRangeAddressable> xRangeAdd(aValue, uno::UNO_QUERY);
358         if (xRangeAdd.is())
359         {
360             SdrObject *pObj = GetSdrObject();
361             if (pObj)
362             {
363                 ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
364                 SdrPage* pPage = pObj->GetPage();
365                 if ( pModel && pPage )
366                 {
367                     ScDocument* pDoc = pModel->GetDocument();
368                     if ( pDoc )
369                     {
370                         SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
371                         if ( pObjSh && pObjSh->ISA(ScDocShell) )
372                         {
373                             ScDocShell* pDocSh = (ScDocShell*)pObjSh;
374 
375                             SCTAB nTab = 0;
376                             if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
377                             {
378                                 table::CellRangeAddress aAddress = xRangeAdd->getRangeAddress();
379                                 if (nTab == aAddress.Sheet)
380                                 {
381                                     if (aAddress.StartRow != aAddress.EndRow) //should be a Spreadsheet
382                                     {
383                                         DBG_ASSERT(aAddress.StartRow == 0 && aAddress.EndRow == MAXROW &&
384                                             aAddress.StartColumn == 0 && aAddress.EndColumn == MAXCOL, "here should be a XSpreadsheet");
385                                         ScDrawLayer::SetAnchor(pObj, SCA_PAGE);
386                                     }
387                                     else
388                                     {
389                                         DBG_ASSERT(aAddress.StartRow == aAddress.EndRow &&
390                                             aAddress.StartColumn == aAddress.EndColumn, "here should be a XCell");
391                                         ScDrawLayer::SetAnchor(pObj, SCA_CELL);
392                                     }
393                                     Rectangle aRect(pDoc->GetMMRect( static_cast<SCCOL>(aAddress.StartColumn), static_cast<SCROW>(aAddress.StartRow),
394                                         static_cast<SCCOL>(aAddress.EndColumn), static_cast<SCROW>(aAddress.EndRow), aAddress.Sheet ));
395                                     uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
396                                     if (xShape.is())
397                                     {
398                                         Point aPoint;
399                                         Point aEndPoint;
400                                         if (pDoc->IsNegativePage(nTab))
401                                         {
402                                             aPoint = aRect.TopRight();
403                                             aEndPoint = aRect.BottomLeft();
404                                         }
405                                         else
406                                         {
407                                             aPoint = aRect.TopLeft();
408                                             aEndPoint = aRect.BottomRight();
409                                         }
410                                         awt::Size aUnoSize;
411                                         awt::Point aCaptionPoint;
412                                         ScRange aRange;
413                                         awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
414 
415                                         aUnoPoint.X += aPoint.X();
416                                         aUnoPoint.Y += aPoint.Y();
417 
418                                         if ( aUnoPoint.Y > aEndPoint.Y() )
419                                             aUnoPoint.Y = aEndPoint.Y() - 2;
420                                         if (pDoc->IsNegativePage(nTab))
421                                         {
422                                             if ( aUnoPoint.X < aEndPoint.X() )
423                                                 aUnoPoint.X = aEndPoint.X() + 2;
424                                             aUnoPoint.X -= aUnoSize.Width;
425                                             // remove difference to caption point
426                                             if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width)
427                                                 aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width;
428                                         }
429                                         else
430                                         {
431                                             if ( aUnoPoint.X > aEndPoint.X() )
432                                                 aUnoPoint.X = aEndPoint.X() - 2;
433                                             if (aCaptionPoint.X < 0)
434                                                 aUnoPoint.X -= aCaptionPoint.X;
435                                         }
436                                         if (aCaptionPoint.Y < 0)
437                                             aUnoPoint.Y -= aCaptionPoint.Y;
438 
439                                         xShape->setPosition(aUnoPoint);
440                                         pDocSh->SetModified();
441                                     }
442                                 }
443                             }
444                         }
445                     }
446                 }
447             }
448         }
449         else
450             throw lang::IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("only XCell or XSpreadsheet objects allowed")), static_cast<cppu::OWeakObject*>(this), 0);
451     }
452     else if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
453     {
454         SdrObject* pObj = GetSdrObject();
455         if ( pObj )
456         {
457             ImageMap aImageMap;
458             uno::Reference< uno::XInterface > xImageMapInt(aValue, uno::UNO_QUERY);
459 
460             if( !xImageMapInt.is() || !SvUnoImageMap_fillImageMap( xImageMapInt, aImageMap ) )
461                 throw lang::IllegalArgumentException();
462 
463             ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(pObj);
464             if( pIMapInfo )
465             {
466                 // replace existing image map
467                 pIMapInfo->SetImageMap( aImageMap );
468             }
469             else
470             {
471                 // insert new user data with image map
472                 pObj->InsertUserData(new ScIMapInfo(aImageMap) );
473             }
474         }
475     }
476     else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) )
477     {
478         sal_Int32 nPos = 0;
479         if (aValue >>= nPos)
480         {
481             SdrObject *pObj = GetSdrObject();
482             if (pObj)
483             {
484                 ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
485                 SdrPage* pPage = pObj->GetPage();
486                 if ( pModel && pPage )
487                 {
488                     SCTAB nTab = 0;
489                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
490                     {
491                         ScDocument* pDoc = pModel->GetDocument();
492                         if ( pDoc )
493                         {
494                             SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
495                             if ( pObjSh && pObjSh->ISA(ScDocShell) )
496                             {
497                                 ScDocShell* pDocSh = (ScDocShell*)pObjSh;
498                                 uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
499                                 if (xShape.is())
500                                 {
501                                     if (ScDrawLayer::GetAnchor(pObj) == SCA_PAGE)
502                                     {
503                                         awt::Point aPoint(xShape->getPosition());
504                                         awt::Size aSize(xShape->getSize());
505                                         awt::Point aCaptionPoint;
506                                         if (pDoc->IsNegativePage(nTab))
507                                         {
508                                             nPos *= -1;
509                                             nPos -= aSize.Width;
510                                         }
511                                         if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
512                                         {
513                                             if (pDoc->IsNegativePage(nTab))
514                                             {
515                                                 if (aCaptionPoint.X > 0 && aCaptionPoint.X > aSize.Width)
516                                                     nPos -= aCaptionPoint.X - aSize.Width;
517                                             }
518                                             else
519                                             {
520                                                 if (aCaptionPoint.X < 0)
521                                                     nPos -= aCaptionPoint.X;
522                                             }
523                                         }
524                                         aPoint.X = nPos;
525                                         xShape->setPosition(aPoint);
526                                         pDocSh->SetModified();
527                                     }
528                                     else if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
529                                     {
530                                         awt::Size aUnoSize;
531                                         awt::Point aCaptionPoint;
532                                         ScRange aRange;
533                                         awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
534                                         Rectangle aRect(pDoc->GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
535                                         if (pDoc->IsNegativePage(nTab))
536                                         {
537                                             aUnoPoint.X = -nPos;
538                                             Point aPoint(aRect.TopRight());
539                                             Point aEndPoint(aRect.BottomLeft());
540                                             aUnoPoint.X += aPoint.X();
541                                             if (aUnoPoint.X < aEndPoint.X())
542                                                 aUnoPoint.X = aEndPoint.X() + 2;
543                                             aUnoPoint.X -= aUnoSize.Width;
544                                             if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width)
545                                                 aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width;
546                                         }
547                                         else
548                                         {
549                                             aUnoPoint.X = nPos;
550                                             Point aPoint(aRect.TopLeft());
551                                             Point aEndPoint(aRect.BottomRight());
552                                             aUnoPoint.X += aPoint.X();
553                                             if (aUnoPoint.X > aEndPoint.X())
554                                                 aUnoPoint.X = aEndPoint.X() - 2;
555                                             if (aCaptionPoint.X < 0)
556                                                 aUnoPoint.X -= aCaptionPoint.X;
557                                         }
558                                         aUnoPoint.Y = xShape->getPosition().Y;
559                                         xShape->setPosition(aUnoPoint);
560                                         pDocSh->SetModified();
561                                     }
562                                     else
563                                     {
564                                         DBG_ERROR("unknown anchor type");
565                                     }
566                                 }
567                             }
568                         }
569                     }
570                 }
571             }
572         }
573     }
574     else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) )
575     {
576         sal_Int32 nPos = 0;
577         if (aValue >>= nPos)
578         {
579             SdrObject *pObj = GetSdrObject();
580             if (pObj)
581             {
582                 ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
583                 SdrPage* pPage = pObj->GetPage();
584                 if ( pModel && pPage )
585                 {
586                     SCTAB nTab = 0;
587                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
588                     {
589                         ScDocument* pDoc = pModel->GetDocument();
590                         if ( pDoc )
591                         {
592                             SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
593                             if ( pObjSh && pObjSh->ISA(ScDocShell) )
594                             {
595                                 ScDocShell* pDocSh = (ScDocShell*)pObjSh;
596                                 uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
597                                 if (xShape.is())
598                                 {
599                                     if (ScDrawLayer::GetAnchor(pObj) == SCA_PAGE)
600                                     {
601                                         awt::Point aPoint = xShape->getPosition();
602                                         awt::Point aCaptionPoint;
603                                         if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
604                                         {
605                                             if (aCaptionPoint.Y < 0)
606                                                 nPos -= aCaptionPoint.Y;
607                                         }
608                                         aPoint.Y = nPos;
609                                         xShape->setPosition(aPoint);
610                                         pDocSh->SetModified();
611                                     }
612                                     else if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
613                                     {
614                                         awt::Size aUnoSize;
615                                         awt::Point aCaptionPoint;
616                                         ScRange aRange;
617                                         awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
618                                         Rectangle aRect(pDoc->GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
619                                         Point aPoint(aRect.TopRight());
620                                         Point aEndPoint(aRect.BottomLeft());
621                                         aUnoPoint.Y = nPos;
622                                         aUnoPoint.Y += aPoint.Y();
623                                         if (aUnoPoint.Y > aEndPoint.Y())
624                                             aUnoPoint.Y = aEndPoint.Y() - 2;
625                                         if (aCaptionPoint.Y < 0)
626                                             aUnoPoint.Y -= aCaptionPoint.Y;
627                                         aUnoPoint.X = xShape->getPosition().X;
628                                         xShape->setPosition(aUnoPoint);
629                                         pDocSh->SetModified();
630                                     }
631                                     else
632                                     {
633                                         DBG_ERROR("unknown anchor type");
634                                     }
635                                 }
636                             }
637                         }
638                     }
639                 }
640             }
641         }
642     }
643     else
644     {
645         GetShapePropertySet();
646         if (pShapePropertySet)
647             pShapePropertySet->setPropertyValue( aPropertyName, aValue );
648     }
649 }
650 
651 uno::Any SAL_CALL ScShapeObj::getPropertyValue( const rtl::OUString& aPropertyName )
652                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
653                         uno::RuntimeException)
654 {
655     ScUnoGuard aGuard;
656     String aNameString = aPropertyName;
657 
658     uno::Any aAny;
659     if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) )
660     {
661         SdrObject *pObj = GetSdrObject();
662         if (pObj)
663         {
664             ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
665             SdrPage* pPage = pObj->GetPage();
666             if ( pModel && pPage )
667             {
668                 ScDocument* pDoc = pModel->GetDocument();
669                 if ( pDoc )
670                 {
671                     SCTAB nTab = 0;
672                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
673                     {
674                         SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
675                         if ( pObjSh && pObjSh->ISA(ScDocShell) )
676                         {
677                             ScDocShell* pDocSh = (ScDocShell*)pObjSh;
678                             uno::Reference< uno::XInterface > xAnchor;
679                             if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
680                             {
681                                 uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
682                                 if (xShape.is())
683                                 {
684                                     awt::Size aUnoSize;
685                                     awt::Point aCaptionPoint;
686                                     ScRange aRange;
687                                     awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
688 
689                                     xAnchor.set(static_cast<cppu::OWeakObject*>(new ScCellObj( pDocSh, aRange.aStart )));
690                                 }
691                             }
692                             else
693                             {
694                                 xAnchor.set(static_cast<cppu::OWeakObject*>(new ScTableSheetObj( pDocSh, nTab )));
695                             }
696                             aAny <<= xAnchor;
697                         }
698                     }
699                 }
700             }
701         }
702     }
703     else if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
704     {
705         uno::Reference< uno::XInterface > xImageMap;
706         SdrObject* pObj = GetSdrObject();
707         if ( pObj )
708         {
709             ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(GetSdrObject());
710             if( pIMapInfo )
711             {
712                 const ImageMap& rIMap = pIMapInfo->GetImageMap();
713                 xImageMap.set(SvUnoImageMap_createInstance( rIMap, GetSupportedMacroItems() ));
714             }
715             else
716                 xImageMap = SvUnoImageMap_createInstance( GetSupportedMacroItems() );
717         }
718         aAny <<= uno::Reference< container::XIndexContainer >::query( xImageMap );
719     }
720     else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) )
721     {
722         SdrObject *pObj = GetSdrObject();
723         if (pObj)
724         {
725             ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
726             SdrPage* pPage = pObj->GetPage();
727             if ( pModel && pPage )
728             {
729                 ScDocument* pDoc = pModel->GetDocument();
730                 if ( pDoc )
731                 {
732                     SCTAB nTab = 0;
733                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
734                     {
735                         uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
736                         if (xShape.is())
737                         {
738                             if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
739                             {
740                                 awt::Size aUnoSize;
741                                 awt::Point aCaptionPoint;
742                                 ScRange aRange;
743                                 awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
744                                 if (pDoc->IsNegativePage(nTab))
745                                     aUnoPoint.X *= -1;
746                                 aAny <<= aUnoPoint.X;
747                             }
748                             else
749                             {
750                                 awt::Point aCaptionPoint;
751                                 awt::Point aUnoPoint(xShape->getPosition());
752                                 awt::Size aUnoSize(xShape->getSize());
753                                 if (pDoc->IsNegativePage(nTab))
754                                 {
755                                     aUnoPoint.X *= -1;
756                                     aUnoPoint.X -= aUnoSize.Width;
757                                 }
758                                 if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
759                                 {
760                                     if (pDoc->IsNegativePage(nTab))
761                                     {
762                                         if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width)
763                                             aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width;
764                                     }
765                                     else
766                                     {
767                                         if (aCaptionPoint.X < 0)
768                                             aUnoPoint.X += aCaptionPoint.X;
769                                     }
770                                 }
771                                 aAny <<= aUnoPoint.X;
772                             }
773                         }
774                     }
775                 }
776             }
777         }
778     }
779     else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) )
780     {
781         SdrObject *pObj = GetSdrObject();
782         if (pObj)
783         {
784             ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
785             SdrPage* pPage = pObj->GetPage();
786             if ( pModel && pPage )
787             {
788                 ScDocument* pDoc = pModel->GetDocument();
789                 if ( pDoc )
790                 {
791                     SCTAB nTab = 0;
792                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
793                     {
794                         uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
795                         if (xShape.is())
796                         {
797                             uno::Reference< uno::XInterface > xAnchor;
798                             if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
799                             {
800                                 awt::Size aUnoSize;
801                                 awt::Point aCaptionPoint;
802                                 ScRange aRange;
803                                 awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
804 
805                                 aAny <<= aUnoPoint.Y;
806                             }
807                             else
808                             {
809                                 awt::Point aUnoPoint(xShape->getPosition());
810                                 awt::Point aCaptionPoint;
811                                 if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
812                                 {
813                                     if (aCaptionPoint.Y < 0)
814                                         aUnoPoint.Y += aCaptionPoint.Y;
815                                 }
816                                 aAny <<= aUnoPoint.Y;
817                             }
818                         }
819                     }
820                 }
821             }
822         }
823     }
824     else
825     {
826         GetShapePropertySet();
827         if (pShapePropertySet)
828             aAny = pShapePropertySet->getPropertyValue( aPropertyName );
829     }
830 
831     return aAny;
832 }
833 
834 void SAL_CALL ScShapeObj::addPropertyChangeListener( const rtl::OUString& aPropertyName,
835                             const uno::Reference<beans::XPropertyChangeListener>& aListener)
836                             throw(beans::UnknownPropertyException,
837                                     lang::WrappedTargetException, uno::RuntimeException)
838 {
839     ScUnoGuard aGuard;
840 
841     GetShapePropertySet();
842     if (pShapePropertySet)
843         pShapePropertySet->addPropertyChangeListener( aPropertyName, aListener );
844 
845     if ( !bInitializedNotifier )
846     {
847         // here's the latest chance to initialize the property notification at the SdrObject
848         // (in the ctor, where we also attempt to do this, we do not necessarily have
849         // and SdrObject, yet)
850         SdrObject* pObj = GetSdrObject();
851         OSL_ENSURE( pObj, "ScShapeObj::addPropertyChangeListener: no SdrObject -> no property change notification!" );
852         if ( pObj )
853             lcl_initializeNotifier( *pObj, *this );
854         bInitializedNotifier = true;
855     }
856 }
857 
858 void SAL_CALL ScShapeObj::removePropertyChangeListener( const rtl::OUString& aPropertyName,
859                             const uno::Reference<beans::XPropertyChangeListener>& aListener)
860                             throw(beans::UnknownPropertyException,
861                                     lang::WrappedTargetException, uno::RuntimeException)
862 {
863     ScUnoGuard aGuard;
864 
865     GetShapePropertySet();
866     if (pShapePropertySet)
867         pShapePropertySet->removePropertyChangeListener( aPropertyName, aListener );
868 }
869 
870 void SAL_CALL ScShapeObj::addVetoableChangeListener( const rtl::OUString& aPropertyName,
871                             const uno::Reference<beans::XVetoableChangeListener>& aListener)
872                             throw(beans::UnknownPropertyException,
873                                 lang::WrappedTargetException, uno::RuntimeException)
874 {
875     ScUnoGuard aGuard;
876 
877     GetShapePropertySet();
878     if (pShapePropertySet)
879         pShapePropertySet->addVetoableChangeListener( aPropertyName, aListener );
880 }
881 
882 void SAL_CALL ScShapeObj::removeVetoableChangeListener( const rtl::OUString& aPropertyName,
883                             const uno::Reference<beans::XVetoableChangeListener>& aListener)
884                             throw(beans::UnknownPropertyException,
885                                 lang::WrappedTargetException, uno::RuntimeException)
886 {
887     ScUnoGuard aGuard;
888 
889     GetShapePropertySet();
890     if (pShapePropertySet)
891         pShapePropertySet->removeVetoableChangeListener( aPropertyName, aListener );
892 }
893 
894 //  XPropertyState
895 
896 beans::PropertyState SAL_CALL ScShapeObj::getPropertyState( const rtl::OUString& aPropertyName )
897                                 throw(beans::UnknownPropertyException, uno::RuntimeException)
898 {
899     ScUnoGuard aGuard;
900     String aNameString(aPropertyName);
901 
902     beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE;
903     if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
904     {
905         // ImageMap is always "direct"
906     }
907     else if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) )
908     {
909         // Anchor is always "direct"
910     }
911     else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) )
912     {
913         // HoriPos is always "direct"
914     }
915     else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) )
916     {
917         // VertPos is always "direct"
918     }
919     else
920     {
921         GetShapePropertyState();
922         if (pShapePropertyState)
923             eRet = pShapePropertyState->getPropertyState( aPropertyName );
924     }
925 
926     return eRet;
927 }
928 
929 uno::Sequence<beans::PropertyState> SAL_CALL ScShapeObj::getPropertyStates(
930                                 const uno::Sequence<rtl::OUString>& aPropertyNames )
931                             throw(beans::UnknownPropertyException, uno::RuntimeException)
932 {
933     ScUnoGuard aGuard;
934 
935     //  simple loop to get own and aggregated states
936 
937     const rtl::OUString* pNames = aPropertyNames.getConstArray();
938     uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength());
939     beans::PropertyState* pStates = aRet.getArray();
940     for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++)
941         pStates[i] = getPropertyState(pNames[i]);
942     return aRet;
943 }
944 
945 void SAL_CALL ScShapeObj::setPropertyToDefault( const rtl::OUString& aPropertyName )
946                             throw(beans::UnknownPropertyException, uno::RuntimeException)
947 {
948     ScUnoGuard aGuard;
949     String aNameString(aPropertyName);
950 
951     if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
952     {
953         SdrObject* pObj = GetSdrObject();
954         if ( pObj )
955         {
956             ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(pObj);
957             if( pIMapInfo )
958             {
959                 ImageMap aEmpty;
960                 pIMapInfo->SetImageMap( aEmpty );   // replace with empty image map
961             }
962             else
963             {
964                 // nothing to do (no need to insert user data for an empty map)
965             }
966         }
967     }
968     else
969     {
970         GetShapePropertyState();
971         if (pShapePropertyState)
972             pShapePropertyState->setPropertyToDefault( aPropertyName );
973     }
974 }
975 
976 uno::Any SAL_CALL ScShapeObj::getPropertyDefault( const rtl::OUString& aPropertyName )
977                                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
978                                         uno::RuntimeException)
979 {
980     ScUnoGuard aGuard;
981     String aNameString = aPropertyName;
982 
983     uno::Any aAny;
984     if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
985     {
986         //  default: empty ImageMap
987         uno::Reference< uno::XInterface > xImageMap(SvUnoImageMap_createInstance( GetSupportedMacroItems() ));
988         aAny <<= uno::Reference< container::XIndexContainer >::query( xImageMap );
989     }
990     else
991     {
992         GetShapePropertyState();
993         if (pShapePropertyState)
994             aAny = pShapePropertyState->getPropertyDefault( aPropertyName );
995     }
996 
997     return aAny;
998 }
999 
1000 // XTextContent
1001 
1002 void SAL_CALL ScShapeObj::attach( const uno::Reference<text::XTextRange>& /* xTextRange */ )
1003                                 throw(lang::IllegalArgumentException, uno::RuntimeException)
1004 {
1005     ScUnoGuard aGuard;
1006 
1007     throw lang::IllegalArgumentException();     // anchor cannot be changed
1008 }
1009 
1010 uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getAnchor() throw(uno::RuntimeException)
1011 {
1012     ScUnoGuard aGuard;
1013 
1014     uno::Reference<text::XTextRange> xRet;
1015 
1016     SdrObject* pObj = GetSdrObject();
1017     if( pObj )
1018     {
1019         ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
1020         SdrPage* pPage = pObj->GetPage();
1021         if ( pModel )
1022         {
1023             ScDocument* pDoc = pModel->GetDocument();
1024             if ( pDoc )
1025             {
1026                 SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
1027                 if ( pObjSh && pObjSh->ISA(ScDocShell) )
1028                 {
1029                     ScDocShell* pDocSh = (ScDocShell*)pObjSh;
1030 
1031                     SCTAB nTab = 0;
1032                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
1033                     {
1034                         Point aPos(pObj->GetCurrentBoundRect().TopLeft());
1035                         ScRange aRange(pDoc->GetRange( nTab, Rectangle( aPos, aPos ) ));
1036 
1037                         //  anchor is always the cell
1038 
1039                         xRet.set(new ScCellObj( pDocSh, aRange.aStart ));
1040                     }
1041                 }
1042             }
1043         }
1044     }
1045 
1046     return xRet;
1047 }
1048 
1049 // XComponent
1050 
1051 void SAL_CALL ScShapeObj::dispose() throw(uno::RuntimeException)
1052 {
1053     ScUnoGuard aGuard;
1054 
1055     uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg));
1056     if ( xAggComp.is() )
1057         xAggComp->dispose();
1058 }
1059 
1060 void SAL_CALL ScShapeObj::addEventListener(
1061                         const uno::Reference<lang::XEventListener>& xListener )
1062                                                     throw(uno::RuntimeException)
1063 {
1064     ScUnoGuard aGuard;
1065 
1066     uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg));
1067     if ( xAggComp.is() )
1068         xAggComp->addEventListener(xListener);
1069 }
1070 
1071 void SAL_CALL ScShapeObj::removeEventListener(
1072                         const uno::Reference<lang::XEventListener>& xListener )
1073                                                     throw(uno::RuntimeException)
1074 {
1075     ScUnoGuard aGuard;
1076 
1077     uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg));
1078     if ( xAggComp.is() )
1079         xAggComp->removeEventListener(xListener);
1080 }
1081 
1082 // XText
1083 // (special handling for ScCellFieldObj)
1084 
1085 void lcl_CopyOneProperty( beans::XPropertySet& rDest, beans::XPropertySet& rSource, const sal_Char* pName )
1086 {
1087     rtl::OUString aNameStr(rtl::OUString::createFromAscii(pName));
1088     try
1089     {
1090         rDest.setPropertyValue( aNameStr, rSource.getPropertyValue( aNameStr ) );
1091     }
1092     catch (uno::Exception&)
1093     {
1094         DBG_ERROR("Exception in text field");
1095     }
1096 }
1097 
1098 void SAL_CALL ScShapeObj::insertTextContent( const uno::Reference<text::XTextRange>& xRange,
1099                                                 const uno::Reference<text::XTextContent>& xContent,
1100                                                 sal_Bool bAbsorb )
1101                                     throw(lang::IllegalArgumentException, uno::RuntimeException)
1102 {
1103     ScUnoGuard aGuard;
1104 
1105     uno::Reference<text::XTextContent> xEffContent;
1106 
1107     ScCellFieldObj* pCellField = ScCellFieldObj::getImplementation( xContent );
1108     if ( pCellField )
1109     {
1110         //  #105585# createInstance("TextField.URL") from the document creates a ScCellFieldObj.
1111         //  To insert it into drawing text, a SvxUnoTextField is needed instead.
1112         //  The ScCellFieldObj object is left in non-inserted state.
1113 
1114         SvxUnoTextField* pDrawField = new SvxUnoTextField( ID_URLFIELD );
1115         xEffContent.set(pDrawField);
1116         lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_URL );
1117         lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_REPR );
1118         lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_TARGET );
1119     }
1120     else
1121         xEffContent.set(xContent);
1122 
1123     uno::Reference<text::XText> xAggText(lcl_GetText(mxShapeAgg));
1124     if ( xAggText.is() )
1125         xAggText->insertTextContent( xRange, xEffContent, bAbsorb );
1126 }
1127 
1128 void SAL_CALL ScShapeObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent )
1129                                 throw(container::NoSuchElementException, uno::RuntimeException)
1130 {
1131     ScUnoGuard aGuard;
1132 
1133     //  ScCellFieldObj can't be used here.
1134 
1135     uno::Reference<text::XText> xAggText(lcl_GetText(mxShapeAgg));
1136     if ( xAggText.is() )
1137         xAggText->removeTextContent( xContent );
1138 }
1139 
1140 // XSimpleText (parent of XText)
1141 // Use own SvxUnoTextCursor subclass - everything is just passed to aggregated object
1142 
1143 uno::Reference<text::XTextCursor> SAL_CALL ScShapeObj::createTextCursor()
1144                                                     throw(uno::RuntimeException)
1145 {
1146     ScUnoGuard aGuard;
1147 
1148     if ( mxShapeAgg.is() )
1149     {
1150         //  ScDrawTextCursor must be used to ensure the ScShapeObj is returned by getText
1151 
1152         SvxUnoTextBase* pText = SvxUnoTextBase::getImplementation( mxShapeAgg );
1153         if (pText)
1154             return new ScDrawTextCursor( this, *pText );
1155     }
1156 
1157     return uno::Reference<text::XTextCursor>();
1158 }
1159 
1160 uno::Reference<text::XTextCursor> SAL_CALL ScShapeObj::createTextCursorByRange(
1161                                     const uno::Reference<text::XTextRange>& aTextPosition )
1162                                                     throw(uno::RuntimeException)
1163 {
1164     ScUnoGuard aGuard;
1165 
1166     if ( mxShapeAgg.is() && aTextPosition.is() )
1167     {
1168         //  ScDrawTextCursor must be used to ensure the ScShapeObj is returned by getText
1169 
1170         SvxUnoTextBase* pText = SvxUnoTextBase::getImplementation( mxShapeAgg );
1171         SvxUnoTextRangeBase* pRange = SvxUnoTextRangeBase::getImplementation( aTextPosition );
1172         if ( pText && pRange )
1173         {
1174             SvxUnoTextCursor* pCursor = new ScDrawTextCursor( this, *pText );
1175             uno::Reference<text::XTextCursor> xCursor( pCursor );
1176             pCursor->SetSelection( pRange->GetSelection() );
1177             return xCursor;
1178         }
1179     }
1180 
1181     return uno::Reference<text::XTextCursor>();
1182 }
1183 
1184 void SAL_CALL ScShapeObj::insertString( const uno::Reference<text::XTextRange>& xRange,
1185                                         const rtl::OUString& aString, sal_Bool bAbsorb )
1186                                     throw(uno::RuntimeException)
1187 {
1188     ScUnoGuard aGuard;
1189 
1190     uno::Reference<text::XSimpleText> xAggSimpleText(lcl_GetSimpleText(mxShapeAgg));
1191     if ( xAggSimpleText.is() )
1192         xAggSimpleText->insertString( xRange, aString, bAbsorb );
1193     else
1194         throw uno::RuntimeException();
1195 }
1196 
1197 void SAL_CALL ScShapeObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange,
1198                                                 sal_Int16 nControlCharacter, sal_Bool bAbsorb )
1199                                     throw(lang::IllegalArgumentException, uno::RuntimeException)
1200 {
1201     ScUnoGuard aGuard;
1202 
1203     uno::Reference<text::XSimpleText> xAggSimpleText(lcl_GetSimpleText(mxShapeAgg));
1204     if ( xAggSimpleText.is() )
1205         xAggSimpleText->insertControlCharacter( xRange, nControlCharacter, bAbsorb );
1206     else
1207         throw uno::RuntimeException();
1208 }
1209 
1210 // XTextRange
1211 // (parent of XSimpleText)
1212 
1213 uno::Reference<text::XText> SAL_CALL ScShapeObj::getText() throw(uno::RuntimeException)
1214 {
1215     ScUnoGuard aGuard;
1216     return this;
1217 }
1218 
1219 uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getStart() throw(uno::RuntimeException)
1220 {
1221     ScUnoGuard aGuard;
1222 
1223     uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
1224     if ( xAggTextRange.is() )
1225         return xAggTextRange->getStart();
1226     else
1227         throw uno::RuntimeException();
1228 
1229 //    return uno::Reference<text::XTextRange>();
1230 }
1231 
1232 uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getEnd() throw(uno::RuntimeException)
1233 {
1234     ScUnoGuard aGuard;
1235 
1236     uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
1237     if ( xAggTextRange.is() )
1238         return xAggTextRange->getEnd();
1239     else
1240         throw uno::RuntimeException();
1241 
1242 //    return uno::Reference<text::XTextRange>();
1243 }
1244 
1245 rtl::OUString SAL_CALL ScShapeObj::getString() throw(uno::RuntimeException)
1246 {
1247     ScUnoGuard aGuard;
1248 
1249     uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
1250     if ( xAggTextRange.is() )
1251         return xAggTextRange->getString();
1252     else
1253         throw uno::RuntimeException();
1254 
1255 //    return rtl::OUString();
1256 }
1257 
1258 void SAL_CALL ScShapeObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException)
1259 {
1260     ScUnoGuard aGuard;
1261 
1262     uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
1263     if ( xAggTextRange.is() )
1264         xAggTextRange->setString( aText );
1265     else
1266         throw uno::RuntimeException();
1267 }
1268 
1269 // XChild
1270 
1271 uno::Reference< uno::XInterface > SAL_CALL ScShapeObj::getParent() throw (uno::RuntimeException)
1272 {
1273     ScUnoGuard aGuard;
1274 
1275     // receive cell position from caption object (parent of a note caption is the note cell)
1276     SdrObject* pObj = GetSdrObject();
1277     if( pObj )
1278     {
1279         ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
1280         SdrPage* pPage = pObj->GetPage();
1281         if ( pModel )
1282         {
1283             ScDocument* pDoc = pModel->GetDocument();
1284             if ( pDoc )
1285             {
1286                 SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
1287                 if ( pObjSh && pObjSh->ISA(ScDocShell) )
1288                 {
1289                     ScDocShell* pDocSh = (ScDocShell*)pObjSh;
1290 
1291                     SCTAB nTab = 0;
1292                     if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
1293                     {
1294                         const ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObj, nTab );
1295                         if( pCaptData )
1296                             return static_cast< ::cppu::OWeakObject* >( new ScCellObj( pDocSh, pCaptData->maStart ) );
1297                     }
1298                 }
1299             }
1300         }
1301     }
1302 
1303     return 0;
1304 }
1305 
1306 void SAL_CALL ScShapeObj::setParent( const uno::Reference< uno::XInterface >& ) throw (lang::NoSupportException, uno::RuntimeException)
1307 {
1308     throw lang::NoSupportException();
1309 }
1310 
1311 // XTypeProvider
1312 
1313 uno::Sequence<uno::Type> SAL_CALL ScShapeObj::getTypes() throw(uno::RuntimeException)
1314 {
1315     uno::Sequence< uno::Type > aBaseTypes( ScShapeObj_Base::getTypes() );
1316 
1317     uno::Sequence< uno::Type > aTextTypes;
1318     if ( bIsTextShape )
1319         aTextTypes = ScShapeObj_TextBase::getTypes();
1320 
1321     uno::Reference<lang::XTypeProvider> xBaseProvider;
1322     if ( mxShapeAgg.is() )
1323         mxShapeAgg->queryAggregation( getCppuType((uno::Reference<lang::XTypeProvider>*) 0) ) >>= xBaseProvider;
1324     DBG_ASSERT( xBaseProvider.is(), "ScShapeObj: No XTypeProvider from aggregated shape!" );
1325 
1326     uno::Sequence< uno::Type > aAggTypes;
1327     if( xBaseProvider.is() )
1328         aAggTypes = xBaseProvider->getTypes();
1329 
1330     return ::comphelper::concatSequences( aBaseTypes, aTextTypes, aAggTypes );
1331 }
1332 
1333 uno::Sequence<sal_Int8> SAL_CALL ScShapeObj::getImplementationId()
1334                                                     throw(uno::RuntimeException)
1335 {
1336     ScUnoGuard aGuard;
1337     // do we need to compute the implementation id for this instance?
1338     if( !pImplementationId && mxShapeAgg.is())
1339     {
1340         uno::Reference< drawing::XShape > xAggShape;
1341         mxShapeAgg->queryAggregation( ::getCppuType((uno::Reference< drawing::XShape >*)0) ) >>= xAggShape;
1342 
1343         if( xAggShape.is() )
1344         {
1345             const rtl::OUString aShapeType( xAggShape->getShapeType() );
1346             // did we already compute an implementation id for the agregated shape type?
1347             ScShapeImplementationIdMap::iterator aIter( aImplementationIdMap.find(aShapeType ) );
1348             if( aIter == aImplementationIdMap.end() )
1349             {
1350                 // we need to create a new implementation id for this
1351                 // note: this memory is not free'd until application exists
1352                 //       but since we have a fixed set of shapetypes and the
1353                 //       memory will be reused this is ok.
1354                 pImplementationId = new uno::Sequence< sal_Int8 >( 16 );
1355                 rtl_createUuid( (sal_uInt8 *) pImplementationId->getArray(), 0, sal_True );
1356                 aImplementationIdMap[ aShapeType ] = pImplementationId;
1357             }
1358             else
1359             {
1360                 // use the already computed implementation id
1361                 pImplementationId = (*aIter).second;
1362             }
1363         }
1364     }
1365     if( NULL == pImplementationId )
1366     {
1367         DBG_ERROR( "Could not create an implementation id for a ScXShape!" );
1368         return uno::Sequence< sal_Int8 > ();
1369     }
1370     else
1371     {
1372         return *pImplementationId;
1373     }
1374 }
1375 
1376 SdrObject* ScShapeObj::GetSdrObject() const throw()
1377 {
1378     if(mxShapeAgg.is())
1379     {
1380         SvxShape* pShape = SvxShape::getImplementation( mxShapeAgg );
1381         if(pShape)
1382             return pShape->GetSdrObject();
1383     }
1384 
1385     return NULL;
1386 }
1387 
1388 #define SC_EVENTACC_ONCLICK     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnClick" ) )
1389 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1390 #define SC_EVENTACC_ONACTION    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAction" ) )
1391 #define SC_EVENTACC_URL         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) )
1392 #define SC_EVENTACC_ACTION      ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Action" ) )
1393 #endif
1394 #define SC_EVENTACC_SCRIPT      ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) )
1395 #define SC_EVENTACC_EVENTTYPE   ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EventType" ) )
1396 
1397 typedef ::cppu::WeakImplHelper1< container::XNameReplace > ShapeUnoEventAcess_BASE;
1398 class ShapeUnoEventAccessImpl : public ShapeUnoEventAcess_BASE
1399 {
1400 private:
1401     ScShapeObj* mpShape;
1402 
1403     ScMacroInfo* getInfo( sal_Bool bCreate = sal_False )
1404     {
1405         if( mpShape )
1406             if( SdrObject* pObj = mpShape->GetSdrObject() )
1407                 return ScDrawLayer::GetMacroInfo( pObj, bCreate );
1408         return 0;
1409     }
1410 
1411 public:
1412     ShapeUnoEventAccessImpl( ScShapeObj* pShape ): mpShape( pShape )
1413     {
1414     }
1415 
1416     // XNameReplace
1417     virtual void SAL_CALL replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
1418     {
1419         if ( !hasByName( aName ) )
1420             throw container::NoSuchElementException();
1421         uno::Sequence< beans::PropertyValue > aProperties;
1422         aElement >>= aProperties;
1423         const beans::PropertyValue* pProperties = aProperties.getConstArray();
1424         const sal_Int32 nCount = aProperties.getLength();
1425         sal_Int32 nIndex;
1426         bool isEventType = false;
1427         for( nIndex = 0; nIndex < nCount; nIndex++, pProperties++ )
1428         {
1429             if ( pProperties->Name.equals( SC_EVENTACC_EVENTTYPE ) )
1430             {
1431                 isEventType = true;
1432                 continue;
1433             }
1434 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1435             if ( isEventType && ((pProperties->Name == SC_EVENTACC_SCRIPT) || (pProperties->Name == SC_EVENTACC_URL)) )
1436 #else
1437             if ( isEventType && (pProperties->Name == SC_EVENTACC_SCRIPT) )
1438 #endif
1439             {
1440                 rtl::OUString sValue;
1441                 if ( pProperties->Value >>= sValue )
1442                 {
1443                     ScMacroInfo* pInfo = getInfo( sal_True );
1444                     DBG_ASSERT( pInfo, "shape macro info could not be created!" );
1445                     if ( !pInfo )
1446                         break;
1447                     if ( pProperties->Name == SC_EVENTACC_SCRIPT )
1448                         pInfo->SetMacro( sValue );
1449 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1450                     else
1451                         pInfo->SetHlink( sValue );
1452 #endif
1453                 }
1454             }
1455         }
1456     }
1457 
1458     // XNameAccess
1459     virtual uno::Any SAL_CALL getByName( const rtl::OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
1460     {
1461         uno::Sequence< beans::PropertyValue > aProperties;
1462         ScMacroInfo* pInfo = getInfo();
1463 
1464         if ( aName == SC_EVENTACC_ONCLICK )
1465         {
1466             if ( pInfo && (pInfo->GetMacro().getLength() > 0) )
1467             {
1468                 aProperties.realloc( 2 );
1469                 aProperties[ 0 ].Name = SC_EVENTACC_EVENTTYPE;
1470                 aProperties[ 0 ].Value <<= SC_EVENTACC_SCRIPT;
1471                 aProperties[ 1 ].Name = SC_EVENTACC_SCRIPT;
1472                 aProperties[ 1 ].Value <<= pInfo->GetMacro();
1473             }
1474         }
1475 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1476         else if( aName == SC_EVENTACC_ONACTION )
1477         {
1478             if ( pInfo && (pInfo->GetHlink().getLength() > 0) )
1479             {
1480                 aProperties.realloc( 2 );
1481                 aProperties[ 0 ].Name = SC_EVENTACC_EVENTTYPE;
1482                 aProperties[ 0 ].Value <<= SC_EVENTACC_ACTION;
1483                 aProperties[ 1 ].Name = SC_EVENTACC_URL;
1484                 aProperties[ 1 ].Value <<= pInfo->GetHlink();
1485             }
1486         }
1487 #endif
1488         else
1489         {
1490             throw container::NoSuchElementException();
1491         }
1492 
1493         return uno::Any( aProperties );
1494     }
1495 
1496     virtual uno::Sequence< rtl::OUString > SAL_CALL getElementNames() throw(uno::RuntimeException)
1497     {
1498 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1499         uno::Sequence< rtl::OUString > aSeq( 2 );
1500 #else
1501         uno::Sequence< rtl::OUString > aSeq( 1 );
1502 #endif
1503         aSeq[ 0 ] = SC_EVENTACC_ONCLICK;
1504 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1505         aSeq[ 1 ] = SC_EVENTACC_ONACTION;
1506 #endif
1507         return aSeq;
1508     }
1509 
1510     virtual sal_Bool SAL_CALL hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1511     {
1512 #ifdef ISSUE66550_HLINK_FOR_SHAPES
1513         return (aName == SC_EVENTACC_ONCLICK) || (aName == SC_EVENTACC_ONACTION);
1514 #else
1515         return aName == SC_EVENTACC_ONCLICK;
1516 #endif
1517     }
1518 
1519     // XElementAccess
1520     virtual uno::Type SAL_CALL getElementType() throw(uno::RuntimeException)
1521     {
1522         return *SEQTYPE(::getCppuType((const uno::Sequence< beans::PropertyValue >*)0));
1523     }
1524 
1525     virtual sal_Bool SAL_CALL hasElements() throw(uno::RuntimeException)
1526     {
1527         // elements are always present (but contained property sequences may be empty)
1528         return sal_True;
1529     }
1530 };
1531 
1532 ::uno::Reference< container::XNameReplace > SAL_CALL
1533 ScShapeObj::getEvents(  ) throw(uno::RuntimeException)
1534 {
1535     return new ShapeUnoEventAccessImpl( this );
1536 }
1537 
1538 ::rtl::OUString SAL_CALL ScShapeObj::getImplementationName(  ) throw (uno::RuntimeException)
1539 {
1540     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sc.ScShapeObj" ) );
1541 }
1542 
1543 ::sal_Bool SAL_CALL ScShapeObj::supportsService( const ::rtl::OUString& _ServiceName ) throw (uno::RuntimeException)
1544 {
1545     uno::Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
1546     for ( const ::rtl::OUString* pSupported = aSupported.getConstArray();
1547           pSupported != aSupported.getConstArray() + aSupported.getLength();
1548           ++pSupported
1549         )
1550         if ( _ServiceName == *pSupported )
1551             return sal_True;
1552     return sal_False;
1553 }
1554 
1555 uno::Sequence< ::rtl::OUString > SAL_CALL ScShapeObj::getSupportedServiceNames(  ) throw (uno::RuntimeException)
1556 {
1557     uno::Reference<lang::XServiceInfo> xSI;
1558     if ( mxShapeAgg.is() )
1559         mxShapeAgg->queryAggregation( lang::XServiceInfo::static_type() ) >>= xSI;
1560 
1561     uno::Sequence< ::rtl::OUString > aSupported;
1562     if ( xSI.is() )
1563         aSupported = xSI->getSupportedServiceNames();
1564 
1565     aSupported.realloc( aSupported.getLength() + 1 );
1566     aSupported[ aSupported.getLength() - 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) );
1567 
1568     if( bIsNoteCaption )
1569     {
1570         aSupported.realloc( aSupported.getLength() + 1 );
1571         aSupported[ aSupported.getLength() - 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.CellAnnotationShape" ) );
1572     }
1573 
1574     return aSupported;
1575 }
1576