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