Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svtools/source/brwbox/brwbox3.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 <osl/diagnose.h>
21
#include <svtools/brwbox.hxx>
22
#include <vcl/accessibility/AccessibleBrowseBox.hxx>
23
#include <vcl/accessibility/AccessibleBrowseBoxHeaderCell.hxx>
24
#include <vcl/accessibility/AccessibleBrowseBoxObjType.hxx>
25
#include <vcl/accessibility/AccessibleBrowseBoxTableCell.hxx>
26
#include <sal/log.hxx>
27
#include <tools/debug.hxx>
28
#include <tools/multisel.hxx>
29
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
30
31
// Accessibility ==============================================================
32
33
using namespace ::com::sun::star::uno;
34
using ::com::sun::star::accessibility::XAccessible;
35
using namespace ::com::sun::star::accessibility;
36
37
Reference<XAccessible> BrowseBox::getAccessibleHeaderCell(BrowseBox::THeaderCellMap& _raHeaderCells,
38
                                                          sal_Int32 _nPos,
39
                                                          AccessibleBrowseBoxObjType _eType,
40
                                                          const Reference<XAccessible>& _rParent)
41
0
{
42
0
    Reference<XAccessible> xRet;
43
0
    BrowseBox::THeaderCellMap::iterator aFind = _raHeaderCells.find(_nPos);
44
0
    if (aFind == _raHeaderCells.end())
45
0
    {
46
0
        Reference<XAccessible> xAccessible
47
0
            = new AccessibleBrowseBoxHeaderCell(_nPos, _rParent, *this, _eType);
48
0
        aFind = _raHeaderCells.emplace(_nPos, xAccessible).first;
49
0
    }
50
0
    if (aFind != _raHeaderCells.end())
51
0
        xRet = aFind->second;
52
0
    return xRet;
53
0
}
54
55
Reference<XAccessible> BrowseBox::getAccessibleHeaderBar(AccessibleBrowseBoxObjType _eObjType)
56
0
{
57
0
    if (m_xAccessible && m_xAccessible->isAlive())
58
0
        return m_xAccessible->getHeaderBar(_eObjType);
59
0
    return nullptr;
60
0
}
61
62
Reference<XAccessible> BrowseBox::getAccessibleTable()
63
0
{
64
0
    if (m_xAccessible && m_xAccessible->isAlive())
65
0
        return m_xAccessible->getTable();
66
0
    return nullptr;
67
0
}
68
69
rtl::Reference<comphelper::OAccessible> BrowseBox::CreateAccessible()
70
0
{
71
0
    if (!m_xAccessible)
72
0
    {
73
0
        rtl::Reference<comphelper::OAccessible> pAccParent = GetAccessibleParent();
74
0
        if (pAccParent.is())
75
0
            m_xAccessible = new AccessibleBrowseBox(pAccParent, *this);
76
0
    }
77
78
0
    return m_xAccessible;
79
0
}
80
81
82
// Children -------------------------------------------------------------------
83
84
rtl::Reference<comphelper::OAccessible> BrowseBox::CreateAccessibleCell(sal_Int32 _nRow,
85
                                                                        sal_uInt16 _nColumnPos)
86
0
{
87
    // BBINDEX_TABLE must be the table
88
0
    OSL_ENSURE(m_xAccessible, "Invalid call: Accessible is null");
89
90
0
    return new AccessibleBrowseBoxTableCell(getAccessibleTable(), *this, _nRow, _nColumnPos);
91
0
}
92
93
94
Reference< XAccessible > BrowseBox::CreateAccessibleRowHeader( sal_Int32 _nRow )
95
0
{
96
0
    return getAccessibleHeaderCell(
97
0
        m_aRowHeaderCellMap, _nRow, AccessibleBrowseBoxObjType::RowHeaderCell,
98
0
        getAccessibleHeaderBar(AccessibleBrowseBoxObjType::RowHeaderBar));
99
0
}
100
101
102
Reference< XAccessible > BrowseBox::CreateAccessibleColumnHeader( sal_uInt16 _nColumnPos )
103
0
{
104
0
    return getAccessibleHeaderCell(
105
0
        m_aColHeaderCellMap, _nColumnPos, AccessibleBrowseBoxObjType::ColumnHeaderCell,
106
0
        getAccessibleHeaderBar(AccessibleBrowseBoxObjType::ColumnHeaderBar));
107
0
}
108
109
// Conversions ----------------------------------------------------------------
110
111
bool BrowseBox::ConvertPointToCellAddress(
112
        sal_Int32& rnRow, sal_uInt16& rnColumnPos, const Point& rPoint )
113
0
{
114
    //! TODO has to be checked
115
0
    rnRow = GetRowAtYPosPixel(rPoint.Y());
116
0
    rnColumnPos = GetColumnAtXPosPixel(rPoint.X());
117
0
    return rnRow != BROWSER_INVALIDID && rnColumnPos != BROWSER_INVALIDID;
118
0
}
119
120
121
bool BrowseBox::ConvertPointToRowHeader( sal_Int32& rnRow, const Point& rPoint )
122
0
{
123
0
    rnRow = GetRowAtYPosPixel(rPoint.Y());
124
    //  sal_uInt16 nColumnId = GetColumnAtXPosPixel(rPoint.X());
125
0
    return rnRow != BROWSER_INVALIDID;// && nColumnId == 0;
126
0
}
127
128
129
bool BrowseBox::ConvertPointToColumnHeader( sal_uInt16& _rnColumnPos, const Point& _rPoint )
130
0
{
131
0
    _rnColumnPos = GetColumnAtXPosPixel(_rPoint.X());
132
0
    return _rnColumnPos != BROWSER_INVALIDID;
133
0
}
134
135
136
bool BrowseBox::ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint )
137
0
{
138
    //! TODO has to be checked
139
0
    sal_Int32 nRow = 0;
140
0
    sal_uInt16 nColumn = 0;
141
0
    bool bRet = ConvertPointToCellAddress(nRow,nColumn,_rPoint);
142
0
    if ( bRet )
143
0
        _rnIndex = nRow * ColCount() + nColumn;
144
145
0
    return bRet;
146
0
}
147
148
149
// Object data and state ------------------------------------------------------
150
151
OUString BrowseBox::GetAccessibleObjectName( AccessibleBrowseBoxObjType eObjType,sal_Int32 _nPosition) const
152
0
{
153
0
    OUString aRetText;
154
0
    switch( eObjType )
155
0
    {
156
0
        case AccessibleBrowseBoxObjType::BrowseBox:
157
0
            aRetText = "BrowseBox";
158
0
            break;
159
0
        case AccessibleBrowseBoxObjType::Table:
160
0
            aRetText = "Table";
161
0
            break;
162
0
        case AccessibleBrowseBoxObjType::RowHeaderBar:
163
0
            aRetText = "RowHeaderBar";
164
0
            break;
165
0
        case AccessibleBrowseBoxObjType::ColumnHeaderBar:
166
0
            aRetText = "ColumnHeaderBar";
167
0
            break;
168
0
        case AccessibleBrowseBoxObjType::TableCell:
169
0
            if( ColCount() !=0 && GetRowCount()!=0)
170
0
            {
171
172
0
                sal_Int32 columnId = _nPosition % ColCount() +1;
173
0
                aRetText = GetColumnDescription( sal_Int16( columnId ) );
174
0
                sal_Int32 rowId = _nPosition / GetRowCount() + 1;
175
0
                aRetText += OUString::number(rowId);
176
0
            }
177
0
            else
178
0
                aRetText = "TableCell";
179
#if OSL_DEBUG_LEVEL > 0
180
            aRetText += " ["
181
                        + OUString::number(GetCurRow())
182
                        + ","
183
                        + OUString::number(sal_Int32(GetCurColumnId()))
184
                        + "]";
185
#endif
186
0
            break;
187
0
        case AccessibleBrowseBoxObjType::RowHeaderCell:
188
0
            {
189
0
                sal_Int32 rowId = _nPosition + 1;
190
0
                aRetText = OUString::number( rowId );
191
0
            }
192
#if OSL_DEBUG_LEVEL > 0
193
            aRetText += " ["
194
                        + OUString::number(GetCurRow())
195
                        + ","
196
                        + OUString::number(sal_Int32(GetCurColumnId()))
197
                        + "]";
198
#endif
199
0
            break;
200
0
        case AccessibleBrowseBoxObjType::ColumnHeaderCell:
201
0
            aRetText = GetColumnDescription( sal_Int16( _nPosition ) );
202
#if OSL_DEBUG_LEVEL > 0
203
            aRetText += " ["
204
                        + OUString::number(GetCurRow())
205
                        + ","
206
                        + OUString::number(sal_Int32(GetCurColumnId()))
207
                        + "]";
208
#endif
209
0
            break;
210
0
        default:
211
0
            OSL_FAIL("BrowseBox::GetAccessibleName: invalid enum!");
212
0
    }
213
0
    return aRetText;
214
0
}
215
216
217
OUString BrowseBox::GetAccessibleObjectDescription( AccessibleBrowseBoxObjType eObjType,sal_Int32 ) const
218
0
{
219
0
    OUString aRetText;
220
0
    switch( eObjType )
221
0
    {
222
0
        case AccessibleBrowseBoxObjType::BrowseBox:
223
0
            aRetText = "BrowseBox description";
224
0
            break;
225
0
        case AccessibleBrowseBoxObjType::Table:
226
            //  aRetText = "TABLE description";
227
0
            break;
228
0
        case AccessibleBrowseBoxObjType::RowHeaderBar:
229
            //  aRetText = "ROWHEADERBAR description";
230
0
            break;
231
0
        case AccessibleBrowseBoxObjType::ColumnHeaderBar:
232
            //  aRetText = "COLUMNHEADERBAR description";
233
0
            break;
234
0
        case AccessibleBrowseBoxObjType::TableCell:
235
            //  aRetText = "TABLECELL description";
236
0
            break;
237
0
        case AccessibleBrowseBoxObjType::RowHeaderCell:
238
            //  aRetText = "ROWHEADERCELL description";
239
0
            break;
240
0
        case AccessibleBrowseBoxObjType::ColumnHeaderCell:
241
            //  aRetText = "COLUMNHEADERCELL description";
242
0
            break;
243
0
        case AccessibleBrowseBoxObjType::CheckBoxCell:
244
0
            break;
245
0
    }
246
0
    return aRetText;
247
0
}
248
249
250
OUString BrowseBox::GetRowDescription( sal_Int32 ) const
251
0
{
252
0
    return OUString();
253
0
}
254
255
256
OUString BrowseBox::GetColumnDescription( sal_uInt16 _nColumn ) const
257
0
{
258
0
    return GetColumnTitle( GetColumnId( _nColumn ) );
259
0
}
260
261
262
void BrowseBox::FillAccessibleStateSet(
263
        sal_Int64& rStateSet,
264
        AccessibleBrowseBoxObjType eObjType ) const
265
0
{
266
0
    switch( eObjType )
267
0
    {
268
0
        case AccessibleBrowseBoxObjType::BrowseBox:
269
0
        case AccessibleBrowseBoxObjType::Table:
270
271
0
            rStateSet |= AccessibleStateType::FOCUSABLE;
272
0
            if ( HasFocus() )
273
0
                rStateSet |= AccessibleStateType::FOCUSED;
274
0
            if ( IsActive() )
275
0
                rStateSet |= AccessibleStateType::ACTIVE;
276
0
            if ( GetUpdateMode() )
277
0
                rStateSet |= AccessibleStateType::EDITABLE;
278
0
            if ( IsEnabled() )
279
0
            {
280
0
                rStateSet |= AccessibleStateType::ENABLED;
281
0
                rStateSet |= AccessibleStateType::SENSITIVE;
282
0
            }
283
0
            if ( IsReallyVisible() )
284
0
                rStateSet |= AccessibleStateType::VISIBLE;
285
0
            if ( eObjType == AccessibleBrowseBoxObjType::Table )
286
0
                rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
287
288
0
            break;
289
0
        case AccessibleBrowseBoxObjType::RowHeaderBar:
290
0
            rStateSet |= AccessibleStateType::FOCUSABLE;
291
0
            rStateSet |= AccessibleStateType::VISIBLE;
292
0
            if ( GetSelectRowCount() )
293
0
                rStateSet |= AccessibleStateType::FOCUSED;
294
0
            rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
295
0
            break;
296
0
        case AccessibleBrowseBoxObjType::ColumnHeaderBar:
297
0
            rStateSet |= AccessibleStateType::FOCUSABLE;
298
0
            rStateSet |= AccessibleStateType::VISIBLE;
299
0
            if ( GetSelectColumnCount() )
300
0
                rStateSet |= AccessibleStateType::FOCUSED;
301
0
            rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
302
0
            break;
303
0
        case AccessibleBrowseBoxObjType::TableCell:
304
0
            {
305
0
                sal_Int32 nRow = GetCurRow();
306
0
                sal_uInt16 nColumn = GetCurColumnId();
307
0
                if ( IsFieldVisible(nRow,nColumn) )
308
0
                    rStateSet |= AccessibleStateType::VISIBLE;
309
0
                if ( !IsFrozen( nColumn ) )
310
0
                    rStateSet |= AccessibleStateType::FOCUSABLE;
311
0
                rStateSet |= AccessibleStateType::TRANSIENT;
312
0
            }
313
0
            break;
314
0
        case AccessibleBrowseBoxObjType::RowHeaderCell:
315
0
        case AccessibleBrowseBoxObjType::ColumnHeaderCell:
316
0
        case AccessibleBrowseBoxObjType::CheckBoxCell:
317
0
            OSL_FAIL("Illegal call here!");
318
0
            break;
319
0
    }
320
0
}
321
322
void BrowseBox::FillAccessibleStateSetForCell( sal_Int64& _rStateSet,
323
                                               sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
324
0
{
325
    //! TODO check if the state is valid for table cells
326
0
    if ( IsCellVisible( _nRow, _nColumnPos ) )
327
0
        _rStateSet |= AccessibleStateType::VISIBLE;
328
0
    if ( GetCurrRow() == _nRow && GetCurrColumn() == _nColumnPos )
329
0
        _rStateSet |= AccessibleStateType::FOCUSED;
330
0
    else // only transient when column is not focused
331
0
        _rStateSet |= AccessibleStateType::TRANSIENT;
332
0
}
333
334
335
void BrowseBox::GrabTableFocus()
336
0
{
337
0
    GrabFocus();
338
0
}
339
340
OUString BrowseBox::GetCellText(sal_Int32, sal_uInt16 ) const
341
0
{
342
0
    SAL_WARN("svtools", "This method has to be implemented by the derived classes! BUG!!");
343
0
    return OUString();
344
0
}
345
346
347
void BrowseBox::commitHeaderBarEvent(sal_Int16 nEventId,
348
        const Any& rNewValue, const Any& rOldValue, bool _bColumnHeaderBar )
349
0
{
350
0
    if ( isAccessibleAlive() )
351
0
        m_xAccessible->commitHeaderBarEvent(nEventId, rNewValue, rOldValue, _bColumnHeaderBar);
352
0
}
353
354
void BrowseBox::commitTableEvent( sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
355
0
{
356
0
    if ( isAccessibleAlive() )
357
0
        m_xAccessible->commitTableEvent(_nEventId, _rNewValue, _rOldValue);
358
0
}
359
360
void BrowseBox::commitBrowseBoxEvent( sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
361
0
{
362
0
    if ( isAccessibleAlive() )
363
0
        m_xAccessible->commitEvent(_nEventId, _rNewValue, _rOldValue);
364
0
}
365
366
0
bool BrowseBox::isAccessibleAlive() const { return m_xAccessible && m_xAccessible->isAlive(); }
367
368
// IAccessibleTableProvider
369
370
sal_Int32 BrowseBox::GetCurrRow() const
371
0
{
372
0
    return GetCurRow();
373
0
}
374
375
sal_uInt16 BrowseBox::GetCurrColumn() const
376
0
{
377
0
    return GetColumnPos( GetCurColumnId() );
378
0
}
379
380
bool BrowseBox::HasRowHeader() const
381
0
{
382
0
    return ( GetColumnId( 0 ) == HandleColumnId ); // HandleColumn == RowHeader
383
0
}
384
385
bool BrowseBox::GoToCell( sal_Int32 _nRow, sal_uInt16 _nColumn )
386
0
{
387
0
    return GoToRowColumnId( _nRow, GetColumnId( _nColumn ) );
388
0
}
389
390
void BrowseBox::SelectColumn( sal_uInt16 _nColumn, bool _bSelect )
391
0
{
392
0
    SelectColumnPos( _nColumn, _bSelect );
393
0
}
394
395
bool BrowseBox::IsColumnSelected( sal_Int32 _nColumn ) const
396
0
{
397
0
    return ( pColSel && (0 <= _nColumn) && (_nColumn <= 0xFFF) ) &&
398
0
        pColSel->IsSelected( static_cast< sal_uInt16 >( _nColumn ) );
399
0
}
400
401
sal_Int32 BrowseBox::GetSelectedRowCount() const
402
0
{
403
0
    return GetSelectRowCount();
404
0
}
405
406
sal_Int32 BrowseBox::GetSelectedColumnCount() const
407
0
{
408
0
    const MultiSelection* pColumnSel = GetColumnSelection();
409
0
    return pColumnSel ? pColumnSel->GetSelectCount() : 0;
410
0
}
411
412
void BrowseBox::GetAllSelectedRows( css::uno::Sequence< sal_Int32 >& _rRows ) const
413
0
{
414
0
    sal_Int32 nCount = GetSelectRowCount();
415
0
    if( nCount )
416
0
    {
417
0
        _rRows.realloc( nCount );
418
0
        auto pRows = _rRows.getArray();
419
0
        pRows[ 0 ] = const_cast< BrowseBox* >( this )->FirstSelectedRow();
420
0
        for( sal_Int32 nIndex = 1; nIndex < nCount; ++nIndex )
421
0
            pRows[ nIndex ] = const_cast< BrowseBox* >( this )->NextSelectedRow();
422
0
        DBG_ASSERT( const_cast< BrowseBox* >( this )->NextSelectedRow() == BROWSER_ENDOFSELECTION,
423
0
                    "BrowseBox::GetAllSelectedRows - too many selected rows found" );
424
0
    }
425
0
}
426
427
void BrowseBox::GetAllSelectedColumns( css::uno::Sequence< sal_Int32 >& _rColumns ) const
428
0
{
429
0
    const MultiSelection* pColumnSel = GetColumnSelection();
430
0
    sal_Int32 nCount = GetSelectedColumnCount();
431
0
    if( !(pColumnSel && nCount) )
432
0
        return;
433
434
0
    _rColumns.realloc( nCount );
435
0
    auto pColumns = _rColumns.getArray();
436
437
0
    sal_Int32 nIndex = 0;
438
0
    const size_t nRangeCount = pColumnSel->GetRangeCount();
439
0
    for( size_t nRange = 0; nRange < nRangeCount; ++nRange )
440
0
    {
441
0
        const Range& rRange = pColumnSel->GetRange( nRange );
442
        // loop has to include aRange.Max()
443
0
        for( sal_Int32 nCol = rRange.Min(); nCol <= static_cast<sal_Int32>(rRange.Max()); ++nCol )
444
0
        {
445
0
            DBG_ASSERT( nIndex < nCount,
446
0
                "GetAllSelectedColumns - range overflow" );
447
0
            pColumns[ nIndex ] = nCol;
448
0
            ++nIndex;
449
0
        }
450
0
    }
451
0
}
452
453
bool BrowseBox::IsCellVisible( sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
454
0
{
455
0
    return IsFieldVisible( _nRow, GetColumnId( _nColumnPos ) );
456
0
}
457
458
OUString BrowseBox::GetAccessibleCellText(sal_Int32 _nRow, sal_uInt16 _nColPos) const
459
0
{
460
0
    return GetCellText( _nRow, GetColumnId( _nColPos ) );
461
0
}
462
463
464
bool BrowseBox::GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector )
465
0
{
466
0
    return GetOutDev()->GetGlyphBoundRects( rOrigin, rStr, nIndex, nLen, rVector );
467
0
}
468
469
tools::Rectangle BrowseBox::GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const
470
0
{
471
0
    return Control::GetWindowExtentsRelative( rRelativeWindow );
472
0
}
473
474
void BrowseBox::GrabFocus()
475
0
{
476
0
    Control::GrabFocus();
477
0
}
478
479
rtl::Reference<comphelper::OAccessible> BrowseBox::GetAccessible()
480
0
{
481
0
    return Control::GetAccessible();
482
0
}
483
484
vcl::Window* BrowseBox::GetAccessibleParentWindow() const
485
0
{
486
0
    return Control::GetAccessibleParentWindow();
487
0
}
488
489
vcl::Window* BrowseBox::GetWindowInstance()
490
0
{
491
0
    return this;
492
0
}
493
494
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */