Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/accessibility/AccessibleBase.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 <AccessibleBase.hxx>
21
#include "AccessibleChartShape.hxx"
22
#include <ObjectHierarchy.hxx>
23
#include <ObjectIdentifier.hxx>
24
#include <ChartView.hxx>
25
#include <ChartController.hxx>
26
27
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
28
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
29
#include <com/sun/star/accessibility/AccessibleRole.hpp>
30
#include <com/sun/star/drawing/LineStyle.hpp>
31
#include <com/sun/star/drawing/FillStyle.hpp>
32
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
33
#include <sal/log.hxx>
34
#include <utility>
35
#include <vcl/svapp.hxx>
36
#include <i18nlangtag/languagetag.hxx>
37
#include <vcl/window.hxx>
38
#include <vcl/settings.hxx>
39
#include <o3tl/functional.hxx>
40
#include <o3tl/safeint.hxx>
41
#include <comphelper/diagnose_ex.hxx>
42
43
#include <algorithm>
44
#include <iterator>
45
46
#include "ChartElementFactory.hxx"
47
48
using namespace ::com::sun::star;
49
using namespace ::com::sun::star::accessibility;
50
51
using ::com::sun::star::uno::UNO_QUERY;
52
using ::com::sun::star::uno::Reference;
53
using ::osl::MutexGuard;
54
using ::osl::ClearableMutexGuard;
55
using ::com::sun::star::uno::Any;
56
57
namespace chart
58
{
59
60
/** @param bMayHaveChildren is false per default
61
 */
62
AccessibleBase::AccessibleBase(
63
    AccessibleElementInfo aAccInfo,
64
    bool bMayHaveChildren,
65
    bool bAlwaysTransparent /* default: false */ ) :
66
0
        m_bMayHaveChildren( bMayHaveChildren ),
67
0
        m_bChildrenInitialized( false ),
68
0
        m_nStateSet( 0 ),
69
0
        m_aAccInfo(std::move( aAccInfo )),
70
0
        m_bAlwaysTransparent( bAlwaysTransparent ),
71
0
        m_bStateSetInitialized( false )
72
0
{
73
    // initialize some states
74
0
    m_nStateSet |= AccessibleStateType::ENABLED;
75
0
    m_nStateSet |= AccessibleStateType::SHOWING;
76
0
    m_nStateSet |= AccessibleStateType::VISIBLE;
77
0
    m_nStateSet |= AccessibleStateType::SELECTABLE;
78
0
    m_nStateSet |= AccessibleStateType::FOCUSABLE;
79
0
}
80
81
AccessibleBase::~AccessibleBase()
82
0
{
83
0
    SAL_WARN_IF(isAlive(), "chart2.accessibility", "AccessibleBase destroyed while still alive");
84
0
}
85
86
bool AccessibleBase::NotifyEvent( EventType eEventType, const AccessibleUniqueId & rId )
87
0
{
88
0
    if( GetId() == rId )
89
0
    {
90
        // event is addressed to this object
91
92
0
        css::uno::Any aEmpty;
93
0
        css::uno::Any aSelected;
94
0
        aSelected <<= AccessibleStateType::SELECTED;
95
0
        switch( eEventType )
96
0
        {
97
0
            case EventType::GOT_SELECTION:
98
0
                {
99
0
                    AddState( AccessibleStateType::SELECTED );
100
0
                    NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aEmpty, aSelected);
101
102
0
                    AddState( AccessibleStateType::FOCUSED );
103
0
                    aSelected <<= AccessibleStateType::FOCUSED;
104
0
                    NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aEmpty, aSelected);
105
106
0
                    SAL_INFO("chart2.accessibility", "Selection acquired by: " << getAccessibleName());
107
0
                }
108
0
                break;
109
110
0
            case EventType::LOST_SELECTION:
111
0
                {
112
0
                    RemoveState( AccessibleStateType::SELECTED );
113
0
                    NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aSelected, aEmpty);
114
115
0
                    AddState( AccessibleStateType::FOCUSED );
116
0
                    aSelected <<= AccessibleStateType::FOCUSED;
117
0
                    NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aSelected, aEmpty);
118
0
                    SAL_INFO("chart2.accessibility", "Selection lost by: " << getAccessibleName());
119
0
                }
120
0
                break;
121
0
        }
122
0
        return true;
123
0
    }
124
0
    else if( m_bMayHaveChildren )
125
0
    {
126
0
        bool bStop = false;
127
128
0
        ClearableMutexGuard aGuard( m_aMutex );
129
        // make local copy for notification
130
0
        std::vector<rtl::Reference<AccessibleBase>> aLocalChildList(m_aChildList);
131
0
        aGuard.clear();
132
133
0
        for (auto const& localChild : aLocalChildList)
134
0
        {
135
0
            bStop = localChild->NotifyEvent(eEventType, rId);
136
0
            if (bStop)
137
0
                break;
138
0
        }
139
0
        return bStop;
140
0
    }
141
142
0
    return false;
143
0
}
144
145
void AccessibleBase::AddState( sal_Int64 aState )
146
0
{
147
0
    ensureAlive();
148
0
    m_nStateSet |= aState;
149
0
}
150
151
void AccessibleBase::RemoveState( sal_Int64 aState )
152
0
{
153
0
    ensureAlive();
154
0
    m_nStateSet &= ~aState;
155
0
}
156
157
bool AccessibleBase::UpdateChildren()
158
0
{
159
0
    bool bMustUpdateChildren = false;
160
0
    {
161
0
        MutexGuard aGuard( m_aMutex );
162
0
        if (!m_bMayHaveChildren || !isAlive())
163
0
            return false;
164
165
0
        bMustUpdateChildren = ( m_bMayHaveChildren &&
166
0
                                ! m_bChildrenInitialized );
167
0
    }
168
169
    // update unguarded
170
0
    if( bMustUpdateChildren )
171
0
        m_bChildrenInitialized = ImplUpdateChildren();
172
173
0
    return m_bChildrenInitialized;
174
0
}
175
176
bool AccessibleBase::ImplUpdateChildren()
177
0
{
178
0
    bool bResult = false;
179
180
0
    if( m_aAccInfo.m_spObjectHierarchy )
181
0
    {
182
0
        ObjectHierarchy::tChildContainer aModelChildren(
183
0
            m_aAccInfo.m_spObjectHierarchy->getChildren( GetId() ));
184
0
        std::vector< ChildOIDMap::key_type > aAccChildren;
185
0
        aAccChildren.reserve( aModelChildren.size());
186
0
        std::transform( m_aChildOIDMap.begin(), m_aChildOIDMap.end(),
187
0
                          std::back_inserter( aAccChildren ),
188
0
                          ::o3tl::select1st< ChildOIDMap::value_type >() );
189
190
0
        std::sort( aModelChildren.begin(), aModelChildren.end());
191
192
0
        std::vector< ObjectIdentifier > aChildrenToRemove, aChildrenToAdd;
193
0
        std::set_difference( aModelChildren.begin(), aModelChildren.end(),
194
0
                               aAccChildren.begin(), aAccChildren.end(),
195
0
                               std::back_inserter( aChildrenToAdd ));
196
0
        std::set_difference( aAccChildren.begin(), aAccChildren.end(),
197
0
                               aModelChildren.begin(), aModelChildren.end(),
198
0
                               std::back_inserter( aChildrenToRemove ));
199
200
0
        for (auto const& childToRemove : aChildrenToRemove)
201
0
        {
202
0
            RemoveChildByOId(childToRemove);
203
0
        }
204
205
0
        AccessibleElementInfo aAccInfo( GetInfo());
206
0
        aAccInfo.m_pParent = this;
207
208
0
        for (auto const& childToAdd : aChildrenToAdd)
209
0
        {
210
0
            aAccInfo.m_aOID = childToAdd;
211
0
            if ( childToAdd.isAutoGeneratedObject() )
212
0
            {
213
0
                AddChild( ChartElementFactory::CreateChartElement( aAccInfo ).get() );
214
0
            }
215
0
            else if ( childToAdd.isAdditionalShape() )
216
0
            {
217
0
                AddChild( new AccessibleChartShape( aAccInfo ) );
218
0
            }
219
0
        }
220
0
        bResult = true;
221
0
    }
222
223
0
    return bResult;
224
0
}
225
226
void AccessibleBase::AddChild( AccessibleBase * pChild  )
227
0
{
228
0
    OSL_ENSURE( pChild != nullptr, "Invalid Child" );
229
0
    if( !pChild )
230
0
        return;
231
232
0
    ClearableMutexGuard aGuard( m_aMutex );
233
234
0
    rtl::Reference<AccessibleBase> xChild(pChild);
235
0
    m_aChildList.push_back( xChild );
236
237
0
    m_aChildOIDMap[ pChild->GetId() ] = xChild;
238
239
    // inform listeners of new child
240
0
    if( m_bChildrenInitialized )
241
0
    {
242
0
        Any aEmpty, aNew;
243
0
        aNew <<= uno::Reference<XAccessible>(xChild);
244
245
0
        aGuard.clear();
246
0
        NotifyAccessibleEvent(AccessibleEventId::CHILD, aEmpty, aNew);
247
0
    }
248
0
}
249
250
void AccessibleBase::RemoveChildByOId( const ObjectIdentifier& rOId )
251
0
{
252
0
    ClearableMutexGuard aGuard( m_aMutex );
253
254
0
    ChildOIDMap::iterator aIt( m_aChildOIDMap.find( rOId ));
255
0
    if( aIt == m_aChildOIDMap.end())
256
0
        return;
257
258
0
    rtl::Reference<AccessibleBase> xChild(aIt->second);
259
260
    // remove from map
261
0
    m_aChildOIDMap.erase( aIt );
262
263
    // search child in vector
264
0
    auto aVecIter = std::find(m_aChildList.begin(), m_aChildList.end(), xChild);
265
266
0
    OSL_ENSURE( aVecIter != m_aChildList.end(),
267
0
                "Inconsistent ChildMap" );
268
269
    // remove child from vector
270
0
    m_aChildList.erase( aVecIter );
271
0
    bool bInitialized = m_bChildrenInitialized;
272
273
    // call listeners unguarded
274
0
    aGuard.clear();
275
276
    // inform listeners of removed child
277
0
    if( bInitialized )
278
0
    {
279
0
        Any aEmpty, aOld;
280
0
        aOld <<= uno::Reference<XAccessible>(xChild);
281
282
0
        NotifyAccessibleEvent(AccessibleEventId::CHILD, aOld, aEmpty);
283
0
    }
284
285
    // dispose the child
286
0
    if (xChild.is())
287
0
        xChild->dispose();
288
0
}
289
290
awt::Point AccessibleBase::GetUpperLeftOnScreen() const
291
0
{
292
0
    awt::Point aResult;
293
0
    if( m_aAccInfo.m_pParent )
294
0
    {
295
0
        ClearableMutexGuard aGuard( m_aMutex );
296
0
        AccessibleBase * pParent = m_aAccInfo.m_pParent;
297
0
        aGuard.clear();
298
299
0
        if( pParent )
300
0
        {
301
0
            aResult = pParent->GetUpperLeftOnScreen();
302
0
        }
303
0
        else
304
0
            OSL_FAIL( "Default position used is probably incorrect." );
305
0
    }
306
307
0
    return aResult;
308
0
}
309
310
void AccessibleBase::KillAllChildren()
311
0
{
312
0
    ClearableMutexGuard aGuard( m_aMutex );
313
314
    // make local copy for notification, and remove all children
315
0
    std::vector<rtl::Reference<AccessibleBase>> aLocalChildList;
316
0
    aLocalChildList.swap( m_aChildList );
317
0
    m_aChildOIDMap.clear();
318
319
0
    aGuard.clear();
320
321
    // call dispose for all children
322
    // and notify listeners
323
0
    Any aEmpty, aOld;
324
0
    for (auto const& localChild : aLocalChildList)
325
0
    {
326
0
        aOld <<= uno::Reference<XAccessible>(localChild);
327
0
        NotifyAccessibleEvent(AccessibleEventId::CHILD, aOld, aEmpty);
328
329
0
        if (localChild.is())
330
0
            localChild->dispose();
331
0
    }
332
0
    m_bChildrenInitialized = false;
333
0
}
334
335
void AccessibleBase::SetInfo( const AccessibleElementInfo & rNewInfo )
336
0
{
337
0
    m_aAccInfo = rNewInfo;
338
0
    if( m_bMayHaveChildren )
339
0
    {
340
0
        KillAllChildren();
341
0
    }
342
0
    NotifyAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, uno::Any(), uno::Any());
343
0
}
344
345
// ________ (XComponent::dispose) ________
346
void SAL_CALL AccessibleBase::disposing()
347
0
{
348
0
    {
349
0
        MutexGuard aGuard(m_aMutex);
350
0
        OSL_ENSURE(isAlive(), "dispose() called twice");
351
352
0
        OAccessible::disposing();
353
354
        // reset pointers
355
0
        m_aAccInfo.m_pWindow.reset();
356
0
        m_aAccInfo.m_pParent = nullptr;
357
358
0
        m_nStateSet = AccessibleStateType::DEFUNC;
359
360
0
    }
361
    // call listeners unguarded
362
363
0
    if( m_bMayHaveChildren )
364
0
    {
365
0
        KillAllChildren();
366
0
    }
367
0
    else
368
0
        OSL_ENSURE( m_aChildList.empty(), "Child list should be empty" );
369
0
}
370
371
// ________ AccessibleBase::XAccessibleContext ________
372
sal_Int64 SAL_CALL AccessibleBase::getAccessibleChildCount()
373
0
{
374
0
    ClearableMutexGuard aGuard( m_aMutex );
375
0
    if (!m_bMayHaveChildren || !isAlive())
376
0
        return 0;
377
378
0
    bool bMustUpdateChildren = ( m_bMayHaveChildren &&
379
0
                                 ! m_bChildrenInitialized );
380
381
0
    aGuard.clear();
382
383
    // update unguarded
384
0
    if( bMustUpdateChildren )
385
0
        UpdateChildren();
386
387
0
    return ImplGetAccessibleChildCount();
388
0
}
389
390
sal_Int64 AccessibleBase::ImplGetAccessibleChildCount() const
391
0
{
392
0
    return m_aChildList.size();
393
0
}
394
395
Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int64 i )
396
0
{
397
0
    ensureAlive();
398
0
    Reference< XAccessible > xResult;
399
400
0
    ClearableMutexGuard aGuard( m_aMutex );
401
0
    bool bMustUpdateChildren = ( m_bMayHaveChildren &&
402
0
                                 ! m_bChildrenInitialized );
403
404
0
    aGuard.clear();
405
406
0
    if( bMustUpdateChildren )
407
0
        UpdateChildren();
408
409
0
    xResult.set( ImplGetAccessibleChildById( i ));
410
411
0
    return xResult;
412
0
}
413
414
Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i ) const
415
0
{
416
0
    rtl::Reference<AccessibleBase> xResult;
417
418
0
    MutexGuard aGuard( m_aMutex);
419
0
    if( ! m_bMayHaveChildren ||
420
0
        i < 0 ||
421
0
        o3tl::make_unsigned( i ) >= m_aChildList.size() )
422
0
    {
423
0
        OUString aBuf = "Index " + OUString::number( i ) + " is invalid for range [ 0, " +
424
0
                        OUString::number( m_aChildList.size() - 1 ) +
425
0
                        " ]";
426
0
        lang::IndexOutOfBoundsException aEx( aBuf,
427
0
                                             const_cast< ::cppu::OWeakObject * >(
428
0
                                                 static_cast< const ::cppu::OWeakObject * >( this )));
429
0
        throw aEx;
430
0
    }
431
0
    else
432
0
        xResult = m_aChildList[i];
433
434
0
    return xResult;
435
0
}
436
437
Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent()
438
0
{
439
0
    ensureAlive();
440
0
    Reference< XAccessible > aResult;
441
0
    if( m_aAccInfo.m_pParent )
442
0
        aResult.set( m_aAccInfo.m_pParent );
443
444
0
    return aResult;
445
0
}
446
447
sal_Int64 SAL_CALL AccessibleBase::getAccessibleIndexInParent()
448
0
{
449
0
    ensureAlive();
450
451
0
    if( m_aAccInfo.m_spObjectHierarchy )
452
0
        return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() );
453
0
    return -1;
454
0
}
455
456
sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole()
457
0
{
458
0
    return AccessibleRole::SHAPE;
459
0
}
460
461
Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet()
462
0
{
463
0
    Reference< XAccessibleRelationSet > aResult;
464
0
    return aResult;
465
0
}
466
467
sal_Int64 SAL_CALL AccessibleBase::getAccessibleStateSet()
468
0
{
469
0
    if( ! m_bStateSetInitialized )
470
0
    {
471
0
        rtl::Reference< ::chart::ChartController > xSelSupp( GetInfo().m_xChartController );
472
0
        if ( xSelSupp.is() )
473
0
        {
474
0
            ObjectIdentifier aOID( xSelSupp->getSelection() );
475
0
            if ( aOID.isValid() && GetId() == aOID )
476
0
            {
477
0
                AddState( AccessibleStateType::SELECTED );
478
0
                AddState( AccessibleStateType::FOCUSED );
479
0
            }
480
0
        }
481
0
        m_bStateSetInitialized = true;
482
0
    }
483
484
0
    return m_nStateSet;
485
0
}
486
487
lang::Locale SAL_CALL AccessibleBase::getLocale()
488
0
{
489
0
    ensureAlive();
490
491
0
    return Application::GetSettings().GetLanguageTag().getLocale();
492
0
}
493
494
// ________ AccessibleBase::XAccessibleComponent ________
495
496
Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint )
497
0
{
498
0
    ensureAlive();
499
0
    rtl::Reference< AccessibleBase > aResult;
500
0
    awt::Rectangle aRect( implGetBounds());
501
502
    // children are positioned relative to this object, so translate bound rect
503
0
    aRect.X = 0;
504
0
    aRect.Y = 0;
505
506
    // children must be inside the own bound rect
507
0
    if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
508
0
        ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
509
0
    {
510
0
        ClearableMutexGuard aGuard( m_aMutex );
511
0
        std::vector<rtl::Reference<AccessibleBase>> aLocalChildList(m_aChildList);
512
0
        aGuard.clear();
513
514
0
        for (const rtl::Reference<AccessibleBase>& xLocalChild : aLocalChildList)
515
0
        {
516
0
            if (xLocalChild.is())
517
0
            {
518
0
                aRect = xLocalChild->implGetBounds();
519
0
                if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
520
0
                    ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
521
0
                {
522
0
                    aResult = xLocalChild;
523
0
                    break;
524
0
                }
525
0
            }
526
0
        }
527
0
    }
528
529
0
    return aResult;
530
0
}
531
532
css::awt::Rectangle AccessibleBase::implGetBounds()
533
0
{
534
0
    rtl::Reference<ChartView> pChartView = m_aAccInfo.m_xView.get();
535
0
    if( pChartView )
536
0
    {
537
0
        VclPtr<vcl::Window> pWindow = m_aAccInfo.m_pWindow;
538
0
        awt::Rectangle aLogicRect( pChartView->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() ));
539
0
        if( pWindow )
540
0
        {
541
0
            tools::Rectangle aRect( aLogicRect.X, aLogicRect.Y,
542
0
                             aLogicRect.X + aLogicRect.Width,
543
0
                             aLogicRect.Y + aLogicRect.Height );
544
0
            SolarMutexGuard aSolarGuard;
545
0
            aRect = pWindow->LogicToPixel( aRect );
546
547
            // aLogicRect is relative to the page, but we need a value relative
548
            // to the parent object
549
0
            awt::Point aParentLocOnScreen;
550
0
            uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY );
551
0
            if( xParent.is() )
552
0
                aParentLocOnScreen = xParent->getLocationOnScreen();
553
554
0
            awt::Point aULOnScreen = GetUpperLeftOnScreen();
555
0
            awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X,
556
0
                                aParentLocOnScreen.Y - aULOnScreen.Y );
557
558
0
            return awt::Rectangle( aRect.Left() - aOffset.X, aRect.Top() - aOffset.Y,
559
0
                                   aRect.getOpenWidth(), aRect.getOpenHeight());
560
0
        }
561
0
    }
562
563
0
    return awt::Rectangle();
564
0
}
565
566
void SAL_CALL AccessibleBase::grabFocus()
567
0
{
568
0
    ensureAlive();
569
570
0
    rtl::Reference< ::chart::ChartController > xSelSupp( GetInfo().m_xChartController );
571
0
    if ( xSelSupp.is() )
572
0
    {
573
0
        xSelSupp->select( GetId().getAny() );
574
0
    }
575
0
}
576
577
sal_Int32 SAL_CALL AccessibleBase::getForeground()
578
0
{
579
0
    return sal_Int32(getColor( ACC_BASE_FOREGROUND ));
580
0
}
581
582
sal_Int32 SAL_CALL AccessibleBase::getBackground()
583
0
{
584
0
    return sal_Int32(getColor( ACC_BASE_BACKGROUND ));
585
0
}
586
587
Color AccessibleBase::getColor( eColorType eColType )
588
0
{
589
0
    Color nResult = COL_TRANSPARENT;
590
0
    if( m_bAlwaysTransparent )
591
0
        return nResult;
592
593
0
    ObjectIdentifier aOID( m_aAccInfo.m_aOID );
594
0
    ObjectType eType( aOID.getObjectType() );
595
0
    Reference< beans::XPropertySet > xObjProp;
596
0
    OUString aObjectCID = aOID.getObjectCID();
597
0
    if( eType == OBJECTTYPE_LEGEND_ENTRY )
598
0
    {
599
        // for colors get the data series/point properties
600
0
        std::u16string_view aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID ));
601
0
        aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle );
602
0
    }
603
604
0
    xObjProp =
605
0
        ObjectIdentifier::getObjectPropertySet(
606
0
            aObjectCID, m_aAccInfo.m_xChartDocument );
607
0
    if( xObjProp.is())
608
0
    {
609
0
        try
610
0
        {
611
0
            OUString aPropName;
612
0
            OUString aStylePropName;
613
614
0
            switch( eType )
615
0
            {
616
0
                case OBJECTTYPE_LEGEND_ENTRY:
617
0
                case OBJECTTYPE_DATA_SERIES:
618
0
                case OBJECTTYPE_DATA_POINT:
619
0
                    if( eColType == ACC_BASE_FOREGROUND )
620
0
                    {
621
0
                        aPropName = "BorderColor";
622
0
                        aStylePropName = "BorderTransparency";
623
0
                    }
624
0
                    else
625
0
                    {
626
0
                        aPropName = "Color";
627
0
                        aStylePropName = "Transparency";
628
0
                    }
629
0
                    break;
630
0
                default:
631
0
                    if( eColType == ACC_BASE_FOREGROUND )
632
0
                    {
633
0
                        aPropName = "LineColor";
634
0
                        aStylePropName = "LineTransparence";
635
0
                    }
636
0
                    else
637
0
                    {
638
0
                        aPropName = "FillColor";
639
0
                        aStylePropName = "FillTransparence";
640
0
                    }
641
0
                    break;
642
0
            }
643
644
0
            bool bTransparent = m_bAlwaysTransparent;
645
0
            Reference< beans::XPropertySetInfo > xInfo = xObjProp->getPropertySetInfo();
646
0
            if( xInfo.is() &&
647
0
                xInfo->hasPropertyByName( aStylePropName ))
648
0
            {
649
0
                if( eColType == ACC_BASE_FOREGROUND )
650
0
                {
651
0
                    drawing::LineStyle aLStyle = drawing::LineStyle_SOLID;
652
0
                    if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle )
653
0
                        bTransparent = (aLStyle == drawing::LineStyle_NONE);
654
0
                }
655
0
                else
656
0
                {
657
0
                    drawing::FillStyle aFStyle = drawing::FillStyle_SOLID;
658
0
                    if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle )
659
0
                        bTransparent = (aFStyle == drawing::FillStyle_NONE);
660
0
                }
661
0
            }
662
663
0
            if( !bTransparent &&
664
0
                xInfo.is() &&
665
0
                xInfo->hasPropertyByName( aPropName ))
666
0
            {
667
0
                xObjProp->getPropertyValue( aPropName ) >>= nResult;
668
0
            }
669
0
        }
670
0
        catch( const uno::Exception & )
671
0
        {
672
0
            DBG_UNHANDLED_EXCEPTION("chart2");
673
0
        }
674
0
    }
675
676
0
    return nResult;
677
0
}
678
679
} // namespace chart
680
681
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */