Coverage Report

Created: 2026-03-31 11:00

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