Coverage Report

Created: 2026-09-28 10:59

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
399
0
    ClearableMutexGuard aGuard( m_aMutex );
400
0
    bool bMustUpdateChildren = ( m_bMayHaveChildren &&
401
0
                                 ! m_bChildrenInitialized );
402
403
0
    aGuard.clear();
404
405
0
    if( bMustUpdateChildren )
406
0
        UpdateChildren();
407
408
0
    return ImplGetAccessibleChildById(i);
409
0
}
410
411
Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i ) const
412
0
{
413
0
    MutexGuard aGuard( m_aMutex);
414
0
    if( ! m_bMayHaveChildren ||
415
0
        i < 0 ||
416
0
        o3tl::make_unsigned( i ) >= m_aChildList.size() )
417
0
    {
418
0
        OUString aBuf = "Index " + OUString::number( i ) + " is invalid for range [ 0, " +
419
0
                        OUString::number( m_aChildList.size() - 1 ) +
420
0
                        " ]";
421
0
        lang::IndexOutOfBoundsException aEx( aBuf,
422
0
                                             const_cast< ::cppu::OWeakObject * >(
423
0
                                                 static_cast< const ::cppu::OWeakObject * >( this )));
424
0
        throw aEx;
425
0
    }
426
427
0
    return m_aChildList[i];
428
0
}
429
430
Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent()
431
0
{
432
0
    ensureAlive();
433
0
    Reference< XAccessible > aResult;
434
0
    if( m_aAccInfo.m_pParent )
435
0
        aResult.set( m_aAccInfo.m_pParent );
436
437
0
    return aResult;
438
0
}
439
440
sal_Int64 SAL_CALL AccessibleBase::getAccessibleIndexInParent()
441
0
{
442
0
    ensureAlive();
443
444
0
    if( m_aAccInfo.m_spObjectHierarchy )
445
0
        return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() );
446
0
    return -1;
447
0
}
448
449
sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole()
450
0
{
451
0
    return AccessibleRole::SHAPE;
452
0
}
453
454
Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet()
455
0
{
456
0
    Reference< XAccessibleRelationSet > aResult;
457
0
    return aResult;
458
0
}
459
460
sal_Int64 SAL_CALL AccessibleBase::getAccessibleStateSet()
461
0
{
462
0
    if( ! m_bStateSetInitialized )
463
0
    {
464
0
        rtl::Reference< ::chart::ChartController > xSelSupp( GetInfo().m_xChartController );
465
0
        if ( xSelSupp.is() )
466
0
        {
467
0
            ObjectIdentifier aOID( xSelSupp->getSelection() );
468
0
            if ( aOID.isValid() && GetId() == aOID )
469
0
            {
470
0
                AddState( AccessibleStateType::SELECTED );
471
0
                AddState( AccessibleStateType::FOCUSED );
472
0
            }
473
0
        }
474
0
        m_bStateSetInitialized = true;
475
0
    }
476
477
0
    return m_nStateSet;
478
0
}
479
480
lang::Locale SAL_CALL AccessibleBase::getLocale()
481
0
{
482
0
    ensureAlive();
483
484
0
    return Application::GetSettings().GetLanguageTag().getLocale();
485
0
}
486
487
// ________ AccessibleBase::XAccessibleComponent ________
488
489
Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint )
490
0
{
491
0
    ensureAlive();
492
0
    rtl::Reference< AccessibleBase > aResult;
493
0
    awt::Rectangle aRect( implGetBounds());
494
495
    // children are positioned relative to this object, so translate bound rect
496
0
    aRect.X = 0;
497
0
    aRect.Y = 0;
498
499
    // children must be inside the own bound rect
500
0
    if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
501
0
        ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
502
0
    {
503
0
        ClearableMutexGuard aGuard( m_aMutex );
504
0
        std::vector<rtl::Reference<AccessibleBase>> aLocalChildList(m_aChildList);
505
0
        aGuard.clear();
506
507
0
        for (const rtl::Reference<AccessibleBase>& xLocalChild : aLocalChildList)
508
0
        {
509
0
            if (xLocalChild.is())
510
0
            {
511
0
                aRect = xLocalChild->implGetBounds();
512
0
                if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
513
0
                    ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
514
0
                {
515
0
                    aResult = xLocalChild;
516
0
                    break;
517
0
                }
518
0
            }
519
0
        }
520
0
    }
521
522
0
    return aResult;
523
0
}
524
525
css::awt::Rectangle AccessibleBase::implGetBounds()
526
0
{
527
0
    rtl::Reference<ChartView> pChartView = m_aAccInfo.m_xView.get();
528
0
    if( pChartView )
529
0
    {
530
0
        VclPtr<vcl::Window> pWindow = m_aAccInfo.m_pWindow;
531
0
        awt::Rectangle aLogicRect( pChartView->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() ));
532
0
        if( pWindow )
533
0
        {
534
0
            tools::Rectangle aRect( aLogicRect.X, aLogicRect.Y,
535
0
                             aLogicRect.X + aLogicRect.Width,
536
0
                             aLogicRect.Y + aLogicRect.Height );
537
0
            SolarMutexGuard aSolarGuard;
538
0
            aRect = pWindow->LogicToPixel( aRect );
539
540
            // aLogicRect is relative to the page, but we need a value relative
541
            // to the parent object
542
0
            awt::Point aParentLocOnScreen;
543
0
            uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY );
544
0
            if( xParent.is() )
545
0
                aParentLocOnScreen = xParent->getLocationOnScreen();
546
547
0
            awt::Point aULOnScreen = GetUpperLeftOnScreen();
548
0
            awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X,
549
0
                                aParentLocOnScreen.Y - aULOnScreen.Y );
550
551
0
            return awt::Rectangle( aRect.Left() - aOffset.X, aRect.Top() - aOffset.Y,
552
0
                                   aRect.getOpenWidth(), aRect.getOpenHeight());
553
0
        }
554
0
    }
555
556
0
    return awt::Rectangle();
557
0
}
558
559
void SAL_CALL AccessibleBase::grabFocus()
560
0
{
561
0
    ensureAlive();
562
563
0
    rtl::Reference< ::chart::ChartController > xSelSupp( GetInfo().m_xChartController );
564
0
    if ( xSelSupp.is() )
565
0
    {
566
0
        xSelSupp->select( GetId().getAny() );
567
0
    }
568
0
}
569
570
sal_Int32 SAL_CALL AccessibleBase::getForeground()
571
0
{
572
0
    return sal_Int32(getColor( ACC_BASE_FOREGROUND ));
573
0
}
574
575
sal_Int32 SAL_CALL AccessibleBase::getBackground()
576
0
{
577
0
    return sal_Int32(getColor( ACC_BASE_BACKGROUND ));
578
0
}
579
580
Color AccessibleBase::getColor( eColorType eColType )
581
0
{
582
0
    Color nResult = COL_TRANSPARENT;
583
0
    if( m_bAlwaysTransparent )
584
0
        return nResult;
585
586
0
    ObjectIdentifier aOID( m_aAccInfo.m_aOID );
587
0
    ObjectType eType( aOID.getObjectType() );
588
0
    Reference< beans::XPropertySet > xObjProp;
589
0
    OUString aObjectCID = aOID.getObjectCID();
590
0
    if( eType == OBJECTTYPE_LEGEND_ENTRY )
591
0
    {
592
        // for colors get the data series/point properties
593
0
        std::u16string_view aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID ));
594
0
        aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle );
595
0
    }
596
597
0
    xObjProp =
598
0
        ObjectIdentifier::getObjectPropertySet(
599
0
            aObjectCID, m_aAccInfo.m_xChartDocument );
600
0
    if( xObjProp.is())
601
0
    {
602
0
        try
603
0
        {
604
0
            OUString aPropName;
605
0
            OUString aStylePropName;
606
607
0
            switch( eType )
608
0
            {
609
0
                case OBJECTTYPE_LEGEND_ENTRY:
610
0
                case OBJECTTYPE_DATA_SERIES:
611
0
                case OBJECTTYPE_DATA_POINT:
612
0
                    if( eColType == ACC_BASE_FOREGROUND )
613
0
                    {
614
0
                        aPropName = "BorderColor";
615
0
                        aStylePropName = "BorderTransparency";
616
0
                    }
617
0
                    else
618
0
                    {
619
0
                        aPropName = "Color";
620
0
                        aStylePropName = "Transparency";
621
0
                    }
622
0
                    break;
623
0
                default:
624
0
                    if( eColType == ACC_BASE_FOREGROUND )
625
0
                    {
626
0
                        aPropName = "LineColor";
627
0
                        aStylePropName = "LineTransparence";
628
0
                    }
629
0
                    else
630
0
                    {
631
0
                        aPropName = "FillColor";
632
0
                        aStylePropName = "FillTransparence";
633
0
                    }
634
0
                    break;
635
0
            }
636
637
0
            bool bTransparent = m_bAlwaysTransparent;
638
0
            Reference< beans::XPropertySetInfo > xInfo = xObjProp->getPropertySetInfo();
639
0
            if( xInfo.is() &&
640
0
                xInfo->hasPropertyByName( aStylePropName ))
641
0
            {
642
0
                if( eColType == ACC_BASE_FOREGROUND )
643
0
                {
644
0
                    drawing::LineStyle aLStyle = drawing::LineStyle_SOLID;
645
0
                    if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle )
646
0
                        bTransparent = (aLStyle == drawing::LineStyle_NONE);
647
0
                }
648
0
                else
649
0
                {
650
0
                    drawing::FillStyle aFStyle = drawing::FillStyle_SOLID;
651
0
                    if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle )
652
0
                        bTransparent = (aFStyle == drawing::FillStyle_NONE);
653
0
                }
654
0
            }
655
656
0
            if( !bTransparent &&
657
0
                xInfo.is() &&
658
0
                xInfo->hasPropertyByName( aPropName ))
659
0
            {
660
0
                xObjProp->getPropertyValue( aPropName ) >>= nResult;
661
0
            }
662
0
        }
663
0
        catch( const uno::Exception & )
664
0
        {
665
0
            DBG_UNHANDLED_EXCEPTION("chart2");
666
0
        }
667
0
    }
668
669
0
    return nResult;
670
0
}
671
672
} // namespace chart
673
674
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */