Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/accessibility/vclxaccessiblelistitem.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 <accessibility/vclxaccessiblelistitem.hxx>
21
#include <accessibility/IComboListBoxHelper.hxx>
22
#include <com/sun/star/awt/Rectangle.hpp>
23
24
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
25
#include <com/sun/star/accessibility/AccessibleRole.hpp>
26
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
27
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
28
#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
29
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30
#include <cppuhelper/supportsservice.hxx>
31
#include <utility>
32
#include <vcl/svapp.hxx>
33
#include <vcl/toolkit/lstbox.hxx>
34
#include <vcl/unohelp.hxx>
35
#include <vcl/unohelp2.hxx>
36
#include <vcl/settings.hxx>
37
#include <unotools/accessiblerelationsethelper.hxx>
38
#include <i18nlangtag/languagetag.hxx>
39
40
namespace
41
{
42
    /// @throws css::lang::IndexOutOfBoundsException
43
    void checkIndex_Impl( sal_Int32 _nIndex, std::u16string_view _sText )
44
0
    {
45
0
        if ( _nIndex < 0 || _nIndex > static_cast<sal_Int32>(_sText.size()) )
46
0
            throw css::lang::IndexOutOfBoundsException();
47
0
    }
48
}
49
50
// class VCLXAccessibleListItem ------------------------------------------
51
52
using namespace ::com::sun::star::accessibility;
53
using namespace ::com::sun::star::uno;
54
using namespace ::com::sun::star::beans;
55
using namespace ::com::sun::star::lang;
56
using namespace ::com::sun::star;
57
58
59
// Ctor() and Dtor()
60
61
VCLXAccessibleListItem::VCLXAccessibleListItem(sal_Int32 _nIndexInParent,
62
                                               rtl::Reference<VCLXAccessibleList> _xParent)
63
0
    : m_nIndexInParent(_nIndexInParent)
64
0
    , m_bSelected(false)
65
0
    , m_bVisible(false)
66
0
    , m_xParent(std::move(_xParent))
67
0
{
68
0
    assert(m_xParent.is());
69
0
    IComboListBoxHelper* pListBoxHelper = m_xParent->getListBoxHelper();
70
0
    if (pListBoxHelper)
71
0
        m_sEntryText = pListBoxHelper->GetEntry(_nIndexInParent);
72
0
}
73
74
void VCLXAccessibleListItem::SetSelected( bool _bSelected )
75
0
{
76
0
    if ( m_bSelected != _bSelected )
77
0
    {
78
0
        Any aOldValue;
79
0
        Any aNewValue;
80
0
        if ( m_bSelected )
81
0
            aOldValue <<= AccessibleStateType::SELECTED;
82
0
        else
83
0
            aNewValue <<= AccessibleStateType::SELECTED;
84
0
        m_bSelected = _bSelected;
85
0
        NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
86
0
    }
87
0
}
88
89
void VCLXAccessibleListItem::SetVisible( bool _bVisible )
90
0
{
91
0
    if ( m_bVisible != _bVisible )
92
0
    {
93
0
        Any aOldValue, aNewValue;
94
0
        m_bVisible = _bVisible;
95
0
        (_bVisible ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE;
96
0
        NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
97
0
        (_bVisible ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING;
98
0
        NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
99
0
    }
100
0
}
101
102
void VCLXAccessibleListItem::NotifyAccessibleEvent( sal_Int16 _nEventId,
103
                                                    const css::uno::Any& _aOldValue,
104
                                                    const css::uno::Any& _aNewValue )
105
0
{
106
0
    comphelper::OAccessible::NotifyAccessibleEvent(_nEventId, _aOldValue, _aNewValue);
107
0
}
108
109
// OCommonAccessibleText
110
111
OUString VCLXAccessibleListItem::implGetText()
112
0
{
113
0
    return m_sEntryText;
114
0
}
115
116
Locale VCLXAccessibleListItem::implGetLocale()
117
0
{
118
0
    return Application::GetSettings().GetLanguageTag().getLocale();
119
0
}
120
121
void VCLXAccessibleListItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
122
0
{
123
0
    nStartIndex = 0;
124
0
    nEndIndex = 0;
125
0
}
126
127
awt::Rectangle VCLXAccessibleListItem::implGetBounds()
128
0
{
129
0
    tools::Rectangle aRect;
130
0
    IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
131
0
    if (pListBoxHelper)
132
0
    {
133
0
        aRect = pListBoxHelper->GetBoundingRectangle(m_nIndexInParent);
134
        // convert position relative to the combobox/listbox (parent's parent) to position relative
135
        // to direct parent by subtracting parent's relative position in the combobox/listbox
136
0
        aRect -= vcl::unohelper::ConvertToVCLPoint(m_xParent->getLocation());
137
0
    }
138
139
0
    return vcl::unohelper::ConvertToAWTRect(aRect);
140
0
}
141
142
// XComponent
143
144
void SAL_CALL VCLXAccessibleListItem::disposing()
145
0
{
146
0
    m_sEntryText.clear();
147
0
    m_xParent = nullptr;
148
149
0
    OAccessible::disposing();
150
0
}
151
152
// XAccessibleContext
153
154
sal_Int64 SAL_CALL VCLXAccessibleListItem::getAccessibleChildCount(  )
155
0
{
156
0
    return 0;
157
0
}
158
159
Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleChild( sal_Int64 )
160
0
{
161
0
    return Reference< XAccessible >();
162
0
}
163
164
Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleParent(  )
165
0
{
166
0
    SolarMutexGuard aSolarGuard;
167
168
0
    return m_xParent;
169
0
}
170
171
sal_Int64 SAL_CALL VCLXAccessibleListItem::getAccessibleIndexInParent(  )
172
0
{
173
0
    return m_nIndexInParent;
174
0
}
175
176
sal_Int16 SAL_CALL VCLXAccessibleListItem::getAccessibleRole(  )
177
0
{
178
0
    return AccessibleRole::LIST_ITEM;
179
    //  return AccessibleRole::LABEL;
180
0
}
181
182
OUString SAL_CALL VCLXAccessibleListItem::getAccessibleDescription(  )
183
0
{
184
    // no description for every item
185
0
    return OUString();
186
0
}
187
188
OUString SAL_CALL VCLXAccessibleListItem::getAccessibleName(  )
189
0
{
190
0
    SolarMutexGuard aSolarGuard;
191
192
    // entry text == accessible name
193
0
    return m_sEntryText;
194
0
}
195
196
Reference< XAccessibleRelationSet > SAL_CALL VCLXAccessibleListItem::getAccessibleRelationSet(  )
197
0
{
198
0
    return new utl::AccessibleRelationSetHelper;
199
0
}
200
201
sal_Int64 SAL_CALL VCLXAccessibleListItem::getAccessibleStateSet(  )
202
0
{
203
0
    SolarMutexGuard aSolarGuard;
204
205
0
    sal_Int64 nStateSet = 0;
206
207
0
    if (isAlive())
208
0
    {
209
0
        nStateSet |= AccessibleStateType::TRANSIENT;
210
211
0
        IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
212
0
        if (pListBoxHelper && pListBoxHelper->IsEnabled())
213
0
        {
214
0
            nStateSet |= AccessibleStateType::SELECTABLE;
215
0
            nStateSet |= AccessibleStateType::ENABLED;
216
0
            nStateSet |= AccessibleStateType::SENSITIVE;
217
0
        }
218
219
0
        if ( m_bSelected )
220
0
            nStateSet |= AccessibleStateType::SELECTED;
221
0
        if ( m_bVisible )
222
0
        {
223
0
            nStateSet |= AccessibleStateType::VISIBLE;
224
0
            nStateSet |= AccessibleStateType::SHOWING;
225
0
        }
226
0
    }
227
0
    else
228
0
        nStateSet |= AccessibleStateType::DEFUNC;
229
230
0
    return nStateSet;
231
0
}
232
233
Locale SAL_CALL VCLXAccessibleListItem::getLocale(  )
234
0
{
235
0
    SolarMutexGuard aSolarGuard;
236
237
0
    return implGetLocale();
238
0
}
239
240
// XAccessibleComponent
241
242
Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleAtPoint( const awt::Point& )
243
0
{
244
0
    return Reference< XAccessible >();
245
0
}
246
247
void SAL_CALL VCLXAccessibleListItem::grabFocus(  )
248
0
{
249
    // no focus for each item
250
0
}
251
252
// XAccessibleText
253
254
sal_Int32 SAL_CALL VCLXAccessibleListItem::getCaretPosition()
255
0
{
256
0
    return -1;
257
0
}
258
259
sal_Bool SAL_CALL VCLXAccessibleListItem::setCaretPosition( sal_Int32 nIndex )
260
0
{
261
0
    SolarMutexGuard aSolarGuard;
262
263
0
    if ( !implIsValidRange( nIndex, nIndex, m_sEntryText.getLength() ) )
264
0
        throw IndexOutOfBoundsException();
265
266
0
    return false;
267
0
}
268
269
sal_Unicode SAL_CALL VCLXAccessibleListItem::getCharacter( sal_Int32 nIndex )
270
0
{
271
0
    SolarMutexGuard aSolarGuard;
272
273
0
    return OCommonAccessibleText::implGetCharacter( m_sEntryText, nIndex );
274
0
}
275
276
Sequence< PropertyValue > SAL_CALL VCLXAccessibleListItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& )
277
0
{
278
0
    SolarMutexGuard aSolarGuard;
279
280
0
    if ( !implIsValidIndex( nIndex, m_sEntryText.getLength() ) )
281
0
        throw IndexOutOfBoundsException();
282
283
0
    return Sequence< PropertyValue >();
284
0
}
285
286
awt::Rectangle SAL_CALL VCLXAccessibleListItem::getCharacterBounds( sal_Int32 nIndex )
287
0
{
288
0
    SolarMutexGuard aSolarGuard;
289
290
0
    if ( !implIsValidIndex( nIndex, m_sEntryText.getLength() ) )
291
0
        throw IndexOutOfBoundsException();
292
293
0
    awt::Rectangle aBounds( 0, 0, 0, 0 );
294
0
    IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
295
0
    if (pListBoxHelper)
296
0
    {
297
0
        tools::Rectangle aCharRect = pListBoxHelper->GetEntryCharacterBounds( m_nIndexInParent, nIndex );
298
0
        tools::Rectangle aItemRect = pListBoxHelper->GetBoundingRectangle(m_nIndexInParent);
299
0
        aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
300
0
        aBounds = vcl::unohelper::ConvertToAWTRect(aCharRect);
301
0
    }
302
303
0
    return aBounds;
304
0
}
305
306
sal_Int32 SAL_CALL VCLXAccessibleListItem::getCharacterCount()
307
0
{
308
0
    SolarMutexGuard aSolarGuard;
309
310
0
    return m_sEntryText.getLength();
311
0
}
312
313
sal_Int32 SAL_CALL VCLXAccessibleListItem::getIndexAtPoint( const awt::Point& aPoint )
314
0
{
315
0
    SolarMutexGuard aSolarGuard;
316
317
0
    sal_Int32 nIndex = -1;
318
0
    IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
319
0
    if (pListBoxHelper)
320
0
    {
321
0
        sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
322
0
        tools::Rectangle aItemRect = pListBoxHelper->GetBoundingRectangle(m_nIndexInParent);
323
0
        Point aPnt(vcl::unohelper::ConvertToVCLPoint(aPoint));
324
0
        aPnt += aItemRect.TopLeft();
325
0
        sal_Int32 nI = pListBoxHelper->GetIndexForPoint( aPnt, nPos );
326
0
        if ( nI != -1 && m_nIndexInParent == nPos )
327
0
            nIndex = nI;
328
0
    }
329
0
    return nIndex;
330
0
}
331
332
OUString SAL_CALL VCLXAccessibleListItem::getSelectedText()
333
0
{
334
0
    return OUString();
335
0
}
336
337
sal_Int32 SAL_CALL VCLXAccessibleListItem::getSelectionStart()
338
0
{
339
0
    return 0;
340
0
}
341
342
sal_Int32 SAL_CALL VCLXAccessibleListItem::getSelectionEnd()
343
0
{
344
0
    return 0;
345
0
}
346
347
sal_Bool SAL_CALL VCLXAccessibleListItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
348
0
{
349
0
    SolarMutexGuard aSolarGuard;
350
351
0
    if ( !implIsValidRange( nStartIndex, nEndIndex, m_sEntryText.getLength() ) )
352
0
        throw IndexOutOfBoundsException();
353
354
0
    return false;
355
0
}
356
357
OUString SAL_CALL VCLXAccessibleListItem::getText()
358
0
{
359
0
    SolarMutexGuard aSolarGuard;
360
361
0
    return m_sEntryText;
362
0
}
363
364
OUString VCLXAccessibleListItem::getTextRangeImpl(sal_Int32 nStartIndex, sal_Int32 nEndIndex)
365
0
{
366
0
    return OCommonAccessibleText::implGetTextRange(m_sEntryText, nStartIndex, nEndIndex);
367
0
}
368
369
OUString SAL_CALL VCLXAccessibleListItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
370
0
{
371
0
    SolarMutexGuard aSolarGuard;
372
373
0
    return getTextRangeImpl(nStartIndex, nEndIndex);
374
0
}
375
376
css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
377
0
{
378
0
    SolarMutexGuard aSolarGuard;
379
380
0
    return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
381
0
}
382
383
css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
384
0
{
385
0
    SolarMutexGuard aSolarGuard;
386
387
0
    return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
388
0
}
389
390
css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
391
0
{
392
0
    SolarMutexGuard aSolarGuard;
393
394
0
    return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
395
0
}
396
397
sal_Bool SAL_CALL VCLXAccessibleListItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
398
0
{
399
0
    SolarMutexGuard aSolarGuard;
400
401
0
    checkIndex_Impl( nStartIndex, m_sEntryText );
402
0
    checkIndex_Impl( nEndIndex, m_sEntryText );
403
404
0
    bool bRet = false;
405
0
    IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
406
0
    if (pListBoxHelper)
407
0
    {
408
0
        Reference< datatransfer::clipboard::XClipboard > xClipboard = pListBoxHelper->GetClipboard();
409
0
        if ( xClipboard.is() )
410
0
        {
411
0
            OUString sText(getTextRangeImpl(nStartIndex, nEndIndex));
412
0
            rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
413
414
0
            SolarMutexReleaser aReleaser;
415
0
            xClipboard->setContents( pDataObj, nullptr );
416
0
            Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
417
0
            if( xFlushableClipboard.is() )
418
0
                xFlushableClipboard->flushClipboard();
419
420
0
            bRet = true;
421
0
        }
422
0
    }
423
424
0
    return bRet;
425
0
}
426
427
sal_Bool VCLXAccessibleListItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
428
0
{
429
0
    return false;
430
0
}
431
432
// AF (Oct. 29 2002): Return black as constant foreground color.  This is an
433
// initial implementation and has to be substituted by code that determines
434
// the color that is actually used.
435
sal_Int32 SAL_CALL VCLXAccessibleListItem::getForeground()
436
0
{
437
0
    return sal_Int32(COL_BLACK);
438
0
}
439
440
// AF (Oct. 29 2002): Return white as constant background color.  This is an
441
// initial implementation and has to be substituted by code that determines
442
// the color that is actually used.
443
sal_Int32 SAL_CALL VCLXAccessibleListItem::getBackground()
444
0
{
445
0
    return sal_Int32(COL_WHITE);
446
0
}
447
448
449
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */