Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/treelist/svtabbx.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/accessibletablistbox.hxx>
21
22
#include <comphelper/types.hxx>
23
#include <vcl/toolkit/svtabbx.hxx>
24
#include <vcl/headbar.hxx>
25
#include <vcl/toolkit/svlbitm.hxx>
26
#include <vcl/toolkit/treelistbox.hxx>
27
#include <vcl/toolkit/treelistentry.hxx>
28
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
29
#include <com/sun/star/accessibility/XAccessible.hpp>
30
#include <rtl/ustrbuf.hxx>
31
#include <sal/log.hxx>
32
#include <o3tl/safeint.hxx>
33
#include <o3tl/string_view.hxx>
34
#include <osl/diagnose.h>
35
#include <strings.hrc>
36
#include <svdata.hxx>
37
#include <memory>
38
#include <tools/json_writer.hxx>
39
#include <comphelper/propertyvalue.hxx>
40
#include <vcl/accessibility/AccessibleBrowseBoxCheckBoxCell.hxx>
41
#include <vcl/accessibility/AccessibleBrowseBoxHeaderBar.hxx>
42
#include <vcl/accessibility/AccessibleBrowseBoxHeaderCell.hxx>
43
#include <vcl/accessibility/AccessibleBrowseBoxTableCell.hxx>
44
#include <vcl/filter/PngImageWriter.hxx>
45
#include <comphelper/base64.hxx>
46
47
using namespace ::com::sun::star::uno;
48
using namespace ::com::sun::star::accessibility;
49
50
namespace {
51
    OString lcl_extractPngString(const Bitmap& rImage)
52
0
    {
53
0
        SvMemoryStream aOStm(65535, 65535);
54
        // Use fastest compression "1"
55
0
        css::uno::Sequence<css::beans::PropertyValue> aFilterData{
56
0
            comphelper::makePropertyValue(u"Compression"_ustr, sal_Int32(1)),
57
0
        };
58
0
        vcl::PngImageWriter aPNGWriter(aOStm);
59
0
        aPNGWriter.setParameters(aFilterData);
60
0
        if (aPNGWriter.write(rImage))
61
0
        {
62
0
            css::uno::Sequence<sal_Int8> aSeq(static_cast<sal_Int8 const*>(aOStm.GetData()),
63
0
                                            aOStm.Tell());
64
0
            OStringBuffer aBuffer("data:image/png;base64,");
65
0
            ::comphelper::Base64::encode(aBuffer, aSeq);
66
0
            return aBuffer.makeStringAndClear();
67
0
        }
68
69
0
        return ""_ostr;
70
0
    }
71
}
72
73
static void lcl_DumpEntryAndSiblings(tools::JsonWriter& rJsonWriter,
74
                                     SvTreeListEntry* pEntry,
75
                                     SvTabListBox* pTabListBox,
76
                                     bool bCheckButtons)
77
0
{
78
0
    while (pEntry)
79
0
    {
80
0
        auto aNode = rJsonWriter.startStruct();
81
82
        // DEPRECATED
83
        // simple listbox value
84
0
        const SvLBoxItem* pIt = pEntry->GetFirstItem(SvLBoxItemType::String);
85
0
        if (pIt)
86
0
            rJsonWriter.put("text", static_cast<const SvLBoxString*>(pIt)->GetText());
87
88
        // column based data
89
0
        {
90
0
            auto aColumns = rJsonWriter.startArray("columns");
91
92
0
            for (size_t i = 0; i < pEntry->ItemCount(); i++)
93
0
            {
94
0
                SvLBoxItem& rItem = pEntry->GetItem(i);
95
0
                if (rItem.GetType() == SvLBoxItemType::String)
96
0
                {
97
0
                    const SvLBoxString* pStringItem = dynamic_cast<const SvLBoxString*>(&rItem);
98
0
                    if (pStringItem)
99
0
                    {
100
0
                        auto aColumn = rJsonWriter.startStruct();
101
0
                        rJsonWriter.put("text", pStringItem->GetText());
102
103
0
                        SvLBoxTab* pTab = pTabListBox->GetTab( pEntry, &rItem );
104
0
                        if ( pTab )
105
0
                            rJsonWriter.put("editable", pTab->IsEditable());
106
107
0
                        if (pStringItem->IsCustomRender())
108
0
                            rJsonWriter.put("customEntryRenderer", true);
109
0
                    }
110
0
                }
111
0
                else if (rItem.GetType() == SvLBoxItemType::ContextBmp)
112
0
                {
113
0
                    const SvLBoxContextBmp* pBmpItem = dynamic_cast<const SvLBoxContextBmp*>(&rItem);
114
0
                    if (pBmpItem)
115
0
                    {
116
0
                        const OUString aCollapsed = pBmpItem->GetBitmap1().GetStock();
117
0
                        const OUString aExpanded = pBmpItem->GetBitmap2().GetStock();
118
119
                        // send identifier only, we will use svg icon
120
0
                        if (!o3tl::trim(aCollapsed).empty() || !o3tl::trim(aExpanded).empty())
121
0
                        {
122
0
                            auto aColumn = rJsonWriter.startStruct();
123
0
                            if (!o3tl::trim(aCollapsed).empty())
124
0
                                rJsonWriter.put("collapsed", aCollapsed);
125
0
                            if (!o3tl::trim(aExpanded).empty())
126
0
                                rJsonWriter.put("expanded", aExpanded);
127
0
                        }
128
                        // custom bitmap - send png
129
0
                        else
130
0
                        {
131
0
                            Bitmap aCollapsedImage(pBmpItem->GetBitmap1().GetBitmap());
132
0
                            Bitmap aExpandedImage(pBmpItem->GetBitmap2().GetBitmap());
133
0
                            bool bHasCollapsed = !aCollapsedImage.IsEmpty() && !aCollapsedImage.GetSizePixel().IsEmpty();
134
0
                            bool bHasExpanded = !aExpandedImage.IsEmpty() && !aExpandedImage.GetSizePixel().IsEmpty();
135
0
                            if (bHasCollapsed || bHasExpanded)
136
0
                            {
137
0
                                auto aColumn = rJsonWriter.startStruct();
138
0
                                if (bHasCollapsed)
139
0
                                    rJsonWriter.put("collapsedimage", lcl_extractPngString(aCollapsedImage));
140
0
                                if (bHasExpanded)
141
0
                                    rJsonWriter.put("collapsedimage", lcl_extractPngString(aExpandedImage));
142
0
                            }
143
0
                        }
144
0
                    }
145
0
                }
146
0
            }
147
0
        }
148
149
        // SalInstanceTreeView does not use the flag CHILDREN_ON_DEMAND
150
        // and it creates a dummy child
151
0
        const SvTreeListEntries& rChildren = pEntry->GetChildEntries();
152
0
        if (rChildren.size() == 1)
153
0
        {
154
0
            auto& rChild = rChildren[0];
155
0
            if (const SvLBoxItem* pChild = rChild->GetFirstItem(SvLBoxItemType::String))
156
0
            {
157
0
                if (static_cast<const SvLBoxString*>(pChild)->GetText() == "<dummy>")
158
0
                    rJsonWriter.put("ondemand", true);
159
0
            }
160
0
        }
161
0
        if (rChildren.size() > 0 && !pTabListBox->IsExpanded(pEntry))
162
0
        {
163
0
            rJsonWriter.put("collapsed", true);
164
0
        }
165
166
0
        if (bCheckButtons)
167
0
        {
168
0
            SvButtonState eCheckState = pTabListBox->GetCheckButtonState(pEntry);
169
0
            if (eCheckState == SvButtonState::Unchecked)
170
0
                rJsonWriter.put("state", false);
171
0
            else if (eCheckState == SvButtonState::Checked)
172
0
                rJsonWriter.put("state", true);
173
0
            rJsonWriter.put("enabled", pTabListBox->GetCheckButtonEnabled(pEntry));
174
0
        }
175
176
0
        if (pTabListBox->IsSelected(pEntry))
177
0
            rJsonWriter.put("selected", true);
178
179
0
        rJsonWriter.put("row", pTabListBox->GetModel()->GetAbsPos(pEntry));
180
181
0
        SvTreeListEntry* pChild = pTabListBox->FirstChild(pEntry);
182
0
        if (pChild)
183
0
        {
184
0
            auto childrenNode = rJsonWriter.startArray("children");
185
0
            lcl_DumpEntryAndSiblings(rJsonWriter, pChild, pTabListBox, bCheckButtons);
186
0
        }
187
188
0
        pEntry = pEntry->NextSibling();
189
0
    }
190
0
}
191
192
void SvTabListBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
193
0
{
194
0
    SvTreeListBox::DumpAsPropertyTree(rJsonWriter);
195
196
0
    rJsonWriter.put("singleclickactivate", GetActivateOnSingleClick());
197
198
0
    switch (m_eRole)
199
0
    {
200
0
        case SvTabListBoxRole::Unknown:
201
0
            assert(false && "this shouldn't be possible on load from .ui");
202
0
            break;
203
0
        case SvTabListBoxRole::Tree:
204
0
            rJsonWriter.put("role", "tree");
205
0
            break;
206
0
        case SvTabListBoxRole::TreeGrid:
207
0
            rJsonWriter.put("role", "treegrid");
208
0
            break;
209
0
        case SvTabListBoxRole::ListBox:
210
0
            rJsonWriter.put("role", "listbox");
211
0
            break;
212
0
        case SvTabListBoxRole::Grid:
213
0
            rJsonWriter.put("role", "grid");
214
0
            break;
215
0
    }
216
217
0
    bool bCheckButtons = static_cast<int>(m_nTreeFlags & SvTreeFlags::CHKBTN);
218
219
0
    bool isRadioButton = false;
220
0
    if (m_pCheckButtonData)
221
0
    {
222
0
        isRadioButton = m_pCheckButtonData->IsRadio();
223
0
    }
224
225
0
    OUString checkboxtype;
226
0
    if (bCheckButtons)
227
0
    {
228
0
        checkboxtype = "checkbox";
229
0
        if(isRadioButton)
230
0
        {
231
0
            checkboxtype = "radio";
232
0
        }
233
0
    }
234
235
0
    rJsonWriter.put("checkboxtype", checkboxtype);
236
0
    if (GetCustomEntryRenderer())
237
0
        rJsonWriter.put("customEntryRenderer", true);
238
0
    auto entriesNode = rJsonWriter.startArray("entries");
239
0
    lcl_DumpEntryAndSiblings(rJsonWriter, First(), this, bCheckButtons);
240
0
}
241
242
// SvTreeListBox callback
243
244
void SvTabListBox::SetTabs()
245
0
{
246
0
    SvTreeListBox::SetTabs();
247
0
    if( mvTabList.empty() )
248
0
        return;
249
250
    // The tree listbox has now inserted its tabs into the list. Now we
251
    // fluff up the list with additional tabs and adjust the rightmost tab
252
    // of the tree listbox.
253
254
    // the 1st column (index 1 or 2 depending on button flags) is always set
255
    // editable by SvTreeListBox::SetTabs(),
256
    // which prevents setting a different column to editable as the first
257
    // one with the flag is picked in SvTreeListBox::ImplEditEntry()
258
0
    assert(m_aTabs.back()->nFlags & SvLBoxTabFlags::EDITABLE);
259
0
    if (!(mvTabList[0].nFlags & SvLBoxTabFlags::EDITABLE))
260
0
    {
261
0
        m_aTabs.back()->nFlags &= ~SvLBoxTabFlags::EDITABLE;
262
0
    }
263
264
    // append all other tabs to the list
265
0
    for( sal_uInt16 nCurTab = 1; nCurTab < sal_uInt16(mvTabList.size()); nCurTab++ )
266
0
    {
267
0
        SvLBoxTab& rTab = mvTabList[nCurTab];
268
0
        AddTab( rTab.GetPos(), rTab.nFlags );
269
0
    }
270
0
}
271
272
void SvTabListBox::InitEntry(SvTreeListEntry* pEntry, const OUString& rStr,
273
    const Image& rColl, const Image& rExp)
274
0
{
275
0
    SvTreeListBox::InitEntry(pEntry, rStr, rColl, rExp);
276
277
0
    sal_Int32 nIndex = 0;
278
    // TODO: verify if nTabCount is always >0 here!
279
0
    const sal_uInt16 nCount = mvTabList.size() - 1;
280
0
    for( sal_uInt16 nToken = 0; nToken < nCount; nToken++ )
281
0
    {
282
0
        const std::u16string_view aToken = GetToken(aCurEntry, nIndex);
283
0
        pEntry->AddItem(std::make_unique<SvLBoxString>(OUString(aToken)));
284
0
    }
285
0
}
286
287
SvTabListBox::SvTabListBox( vcl::Window* pParent, WinBits nBits )
288
0
    : SvTreeListBox( pParent, nBits )
289
0
    , m_eRole(SvTabListBoxRole::Unknown)
290
0
{
291
0
    SetHighlightRange();    // select full width
292
0
}
Unexecuted instantiation: SvTabListBox::SvTabListBox(vcl::Window*, long)
Unexecuted instantiation: SvTabListBox::SvTabListBox(vcl::Window*, long)
293
294
SvTabListBox::~SvTabListBox()
295
0
{
296
0
    disposeOnce();
297
0
}
298
299
void SvTabListBox::dispose()
300
0
{
301
0
    mvTabList.clear();
302
0
    SvTreeListBox::dispose();
303
0
}
304
305
void SvTabListBox::SetTabWidth(sal_uInt16 nTab, tools::Long tabWidth)
306
0
{
307
    // Ensure that mvTabList[nTab + 1] exists because it is required to calculate diff
308
0
    if (nTab + 2 > tools::Long(mvTabList.size()))
309
0
        mvTabList.resize(nTab + 2);
310
311
0
    tools::Long diff = tabWidth -
312
0
            (mvTabList[nTab + 1].GetPos() - mvTabList[nTab].GetPos()); // Width change
313
314
    // Shift all tab positions after nTab by diff
315
0
    for( sal_uInt16 nIdx = nTab + 1; nIdx < sal_uInt16(mvTabList.size()); nIdx++)
316
0
        mvTabList[nIdx].SetPos(mvTabList[nIdx].GetPos() + diff);
317
0
    SvTreeListBox::m_nTreeFlags |= SvTreeFlags::RECALCTABS;
318
0
    if( IsUpdateMode() )
319
0
        Invalidate();
320
0
}
321
322
void SvTabListBox::SetTabs(const std::vector<tools::Long>& rTabPositions)
323
0
{
324
0
    assert(!rTabPositions.empty());
325
0
    mvTabList.resize(rTabPositions.size());
326
327
0
    for( sal_uInt16 nIdx = 0; nIdx < sal_uInt16(mvTabList.size()); nIdx++)
328
0
        mvTabList[nIdx].SetPos(rTabPositions.at(nIdx));
329
330
0
    SvTreeListBox::m_nTreeFlags |= SvTreeFlags::RECALCTABS;
331
0
    if( IsUpdateMode() )
332
0
        Invalidate();
333
0
}
334
335
SvTreeListEntry* SvTabListBox::InsertEntry( const OUString& rText, SvTreeListEntry* pParent,
336
                                        bool /*bChildrenOnDemand*/,
337
                                        sal_uInt32 nPos, OUString* pUserData )
338
0
{
339
0
    return InsertEntryToColumn( rText, pParent, nPos, 0xffff, pUserData );
340
0
}
341
342
SvTreeListEntry* SvTabListBox::InsertEntryToColumn(const OUString& rStr,SvTreeListEntry* pParent,sal_uInt32 nPos,sal_uInt16 nCol,
343
    OUString* pUser )
344
0
{
345
0
    OUString aStr;
346
0
    if( nCol != 0xffff )
347
0
    {
348
0
        while( nCol )
349
0
        {
350
0
            aStr += "\t";
351
0
            nCol--;
352
0
        }
353
0
    }
354
0
    aStr += rStr;
355
0
    OUString aFirstStr( aStr );
356
0
    sal_Int32 nEnd = aFirstStr.indexOf( '\t' );
357
0
    if( nEnd != -1 )
358
0
    {
359
0
        aFirstStr = aFirstStr.copy(0, nEnd);
360
0
        aCurEntry = aStr.copy(++nEnd);
361
0
    }
362
0
    else
363
0
        aCurEntry.clear();
364
0
    return SvTreeListBox::InsertEntry( aFirstStr, pParent, false, nPos, pUser );
365
0
}
366
367
OUString SvTabListBox::GetEntryText( SvTreeListEntry* pEntry ) const
368
0
{
369
0
    return GetEntryText( pEntry, 0xffff );
370
0
}
371
372
OUString SvTabListBox::GetEntryText( const SvTreeListEntry* pEntry, sal_uInt16 nCol )
373
0
{
374
0
    DBG_ASSERT(pEntry,"GetEntryText:Invalid Entry");
375
0
    OUStringBuffer aResult;
376
0
    if( pEntry )
377
0
    {
378
0
        sal_uInt16 nCount = pEntry->ItemCount();
379
0
        sal_uInt16 nCur = 0;
380
0
        while( nCur < nCount )
381
0
        {
382
0
            const SvLBoxItem& rStr = pEntry->GetItem( nCur );
383
0
            if (rStr.GetType() == SvLBoxItemType::String)
384
0
            {
385
0
                if( nCol == 0xffff )
386
0
                {
387
0
                    if (!aResult.isEmpty())
388
0
                        aResult.append("\t");
389
0
                    aResult.append(static_cast<const SvLBoxString&>(rStr).GetText());
390
0
                }
391
0
                else
392
0
                {
393
0
                    if( nCol == 0 )
394
0
                        return static_cast<const SvLBoxString&>(rStr).GetText();
395
0
                    nCol--;
396
0
                }
397
0
            }
398
0
            nCur++;
399
0
        }
400
0
    }
401
0
    return aResult.makeStringAndClear();
402
0
}
403
404
OUString SvTabListBox::GetEntryText( sal_uInt32 nPos, sal_uInt16 nCol ) const
405
0
{
406
0
    SvTreeListEntry* pEntry = GetEntryOnPos( nPos );
407
0
    return GetEntryText( pEntry, nCol );
408
0
}
409
410
OUString SvTabListBox::GetCellText( sal_uInt32 nPos, sal_uInt16 nCol ) const
411
0
{
412
0
    SvTreeListEntry* pEntry = GetEntryOnPos( nPos );
413
0
    DBG_ASSERT( pEntry, "SvTabListBox::GetCellText(): Invalid Entry" );
414
0
    OUString aResult;
415
0
    if (pEntry && pEntry->ItemCount() > o3tl::make_unsigned(nCol+1))
416
0
    {
417
0
        const SvLBoxItem& rStr = pEntry->GetItem( nCol + 1 );
418
0
        if (rStr.GetType() == SvLBoxItemType::String)
419
0
            aResult = static_cast<const SvLBoxString&>(rStr).GetText();
420
0
    }
421
0
    return aResult;
422
0
}
423
424
// static
425
std::u16string_view SvTabListBox::GetToken( std::u16string_view sStr, sal_Int32& nIndex )
426
0
{
427
0
    return o3tl::getToken(sStr, 0, '\t', nIndex);
428
0
}
429
430
OUString SvTabListBox::GetTabEntryText( sal_uInt32 nPos, sal_uInt16 nCol ) const
431
0
{
432
0
    SvTreeListEntry* pEntry = GetEntryOnPos( nPos );
433
0
    DBG_ASSERT( pEntry, "GetTabEntryText(): Invalid entry " );
434
0
    OUStringBuffer aResult;
435
0
    if ( pEntry )
436
0
    {
437
0
        sal_uInt16 nCount = pEntry->ItemCount();
438
0
        sal_uInt16 nCur = 0;
439
0
        while( nCur < nCount )
440
0
        {
441
0
            const SvLBoxItem& rBoxItem = pEntry->GetItem( nCur );
442
0
            if (rBoxItem.GetType() == SvLBoxItemType::String)
443
0
            {
444
0
                if ( nCol == 0xffff )
445
0
                {
446
0
                    if (!aResult.isEmpty())
447
0
                        aResult.append("\t");
448
0
                    aResult.append(static_cast<const SvLBoxString&>(rBoxItem).GetText());
449
0
                }
450
0
                else
451
0
                {
452
0
                    if ( nCol == 0 )
453
0
                    {
454
0
                        OUString sRet = static_cast<const SvLBoxString&>(rBoxItem).GetText();
455
0
                        if ( sRet.isEmpty() )
456
0
                            sRet = VclResId( STR_SVT_ACC_EMPTY_FIELD );
457
0
                        return sRet;
458
0
                    }
459
0
                    --nCol;
460
0
                }
461
0
            }
462
0
            ++nCur;
463
0
        }
464
0
    }
465
0
    return aResult.makeStringAndClear();
466
0
}
467
468
SvTreeListEntry* SvTabListBox::GetEntryOnPos( sal_uInt32 _nEntryPos ) const
469
0
{
470
0
    SvTreeListEntry* pEntry = nullptr;
471
0
    sal_uInt32 i, nPos = 0, nCount = GetLevelChildCount( nullptr );
472
0
    for ( i = 0; i < nCount; ++i )
473
0
    {
474
0
        SvTreeListEntry* pParent = GetEntry(i);
475
0
        if ( nPos == _nEntryPos )
476
0
        {
477
0
            pEntry = pParent;
478
0
            break;
479
0
        }
480
0
        else
481
0
        {
482
0
            nPos++;
483
0
            pEntry = GetChildOnPos( pParent, _nEntryPos, nPos );
484
0
            if ( pEntry )
485
0
                break;
486
0
        }
487
0
    }
488
489
0
    return pEntry;
490
0
}
491
492
SvTreeListEntry* SvTabListBox::GetChildOnPos( SvTreeListEntry* _pParent, sal_uInt32 _nEntryPos, sal_uInt32& _rPos ) const
493
0
{
494
0
    sal_uInt32 i, nCount = GetLevelChildCount( _pParent );
495
0
    for ( i = 0; i < nCount; ++i )
496
0
    {
497
0
        SvTreeListEntry* pParent = GetEntry( _pParent, i );
498
0
        if ( _rPos == _nEntryPos )
499
0
            return pParent;
500
0
        else
501
0
        {
502
0
            _rPos++;
503
0
            SvTreeListEntry* pEntry = GetChildOnPos( pParent, _nEntryPos, _rPos );
504
0
            if ( pEntry )
505
0
                return pEntry;
506
0
        }
507
0
    }
508
509
0
    return nullptr;
510
0
}
511
512
void SvTabListBox::SetTabAlignCenter(sal_uInt16 nTab)
513
0
{
514
0
    DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
515
0
    if( nTab >= mvTabList.size() )
516
0
        return;
517
0
    SvLBoxTab& rTab = mvTabList[ nTab ];
518
0
    SvLBoxTabFlags nFlags = rTab.nFlags;
519
0
    nFlags &= ~SvLBoxTabFlags::ADJUST_FLAGS;
520
    // see SvLBoxTab::CalcOffset for force, which only matters for centering
521
0
    nFlags |= SvLBoxTabFlags::ADJUST_CENTER | SvLBoxTabFlags::FORCE;
522
0
    rTab.nFlags = nFlags;
523
0
    SvTreeListBox::m_nTreeFlags |= SvTreeFlags::RECALCTABS;
524
0
    if( IsUpdateMode() )
525
0
        Invalidate();
526
0
}
527
528
void SvTabListBox::SetTabEditable(sal_uInt16 nTab, bool bEditable)
529
0
{
530
0
    DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
531
0
    if( nTab >= mvTabList.size() )
532
0
        return;
533
0
    SvLBoxTab& rTab = mvTabList[ nTab ];
534
0
    if (bEditable)
535
0
        rTab.nFlags |= SvLBoxTabFlags::EDITABLE;
536
0
    else
537
0
        rTab.nFlags &= ~SvLBoxTabFlags::EDITABLE;
538
0
}
539
540
void SvTabListBox::SetTabVisible(sal_uInt16 nTab, bool bVisible)
541
0
{
542
0
    DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
543
0
    if( nTab >= mvTabList.size() )
544
0
        return;
545
546
0
    if( SvTreeListBox::m_nTreeFlags & SvTreeFlags::RECALCTABS )
547
0
        SetTabs();
548
549
    // Find index in aTabs
550
0
    nTab += m_aTabs.size() - mvTabList.size();
551
0
    SvLBoxTab* pTab = m_aTabs[ nTab ].get();
552
553
0
    if (!bVisible)
554
0
        pTab->nFlags |= SvLBoxTabFlags::HIDDEN;
555
0
    else
556
0
        pTab->nFlags &= ~SvLBoxTabFlags::HIDDEN;
557
0
}
558
559
bool SvTabListBox::GetTabVisible(sal_uInt16 nTab)
560
0
{
561
0
    DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
562
0
    if( nTab >= mvTabList.size() )
563
0
        return false;
564
565
0
    if( SvTreeListBox::m_nTreeFlags & SvTreeFlags::RECALCTABS )
566
0
        SetTabs();
567
568
0
    nTab += m_aTabs.size() - mvTabList.size();
569
0
    SvLBoxTab* pTab = m_aTabs[ nTab ].get();
570
0
    return !pTab->IsHidden();
571
0
}
572
573
tools::Long SvTabListBox::GetLogicTab( sal_uInt16 nTab )
574
0
{
575
0
    if (SvTreeListBox::m_nTreeFlags & SvTreeFlags::RECALCTABS)
576
0
        SetTabs();
577
578
0
    DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
579
0
    return m_aTabs[nTab]->GetPos();
580
0
}
581
582
SvHeaderTabListBox::SvHeaderTabListBox(vcl::Window* pParent, WinBits nWinStyle, HeaderBar* pHeaderBar)
583
0
    : SvTabListBox(pParent, nWinStyle)
584
0
    , m_bFirstPaint(true)
585
0
{
586
587
0
    assert(pHeaderBar);
588
0
    m_xHeaderBar = pHeaderBar;
589
0
    SetScrolledHdl(LINK(this, SvHeaderTabListBox, ScrollHdl_Impl));
590
0
    m_xHeaderBar->SetCreateAccessibleHdl(LINK(this, SvHeaderTabListBox, CreateAccessibleHdl_Impl));
591
0
}
Unexecuted instantiation: SvHeaderTabListBox::SvHeaderTabListBox(vcl::Window*, long, HeaderBar*)
Unexecuted instantiation: SvHeaderTabListBox::SvHeaderTabListBox(vcl::Window*, long, HeaderBar*)
592
593
SvHeaderTabListBox::~SvHeaderTabListBox()
594
0
{
595
0
    disposeOnce();
596
0
}
597
598
void SvHeaderTabListBox::dispose()
599
0
{
600
0
    for (rtl::Reference<AccessibleBrowseBoxHeaderCell>& rxChild : m_aAccessibleChildren)
601
0
        comphelper::disposeComponent(rxChild);
602
0
    m_aAccessibleChildren.clear();
603
0
    m_xAccessible.clear();
604
605
0
    m_xHeaderBar.reset();
606
0
    SvTabListBox::dispose();
607
0
}
608
609
void SvHeaderTabListBox::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
610
0
{
611
0
    if (m_bFirstPaint)
612
0
    {
613
0
        m_bFirstPaint = false;
614
0
    }
615
0
    SvTabListBox::Paint(rRenderContext, rRect);
616
0
}
617
618
HeaderBar* SvHeaderTabListBox::GetHeaderBar()
619
0
{
620
0
    return m_xHeaderBar;
621
0
}
622
623
bool SvHeaderTabListBox::IsItemChecked( SvTreeListEntry* pEntry, sal_uInt16 nCol )
624
0
{
625
0
    SvButtonState eState = SvButtonState::Unchecked;
626
0
    SvLBoxButton& rItem = static_cast<SvLBoxButton&>( pEntry->GetItem( nCol + 1 ) );
627
628
0
    if (rItem.GetType() == SvLBoxItemType::Button)
629
0
    {
630
0
        SvItemStateFlags nButtonFlags = rItem.GetButtonFlags();
631
0
        eState = SvLBoxButtonData::ConvertToButtonState( nButtonFlags );
632
0
    }
633
634
0
    return ( eState == SvButtonState::Checked );
635
0
}
636
637
SvTreeListEntry* SvHeaderTabListBox::InsertEntryToColumn(
638
    const OUString& rStr, SvTreeListEntry* pParent, sal_uInt32 nPos, sal_uInt16 nCol, OUString* pUserData )
639
0
{
640
0
    SvTreeListEntry* pEntry = SvTabListBox::InsertEntryToColumn( rStr, pParent, nPos, nCol, pUserData );
641
0
    RecalculateAccessibleChildren();
642
0
    return pEntry;
643
0
}
644
645
void SvHeaderTabListBox::Insert(SvTreeListEntry* pEnt, SvTreeListEntry* pPar, sal_uInt32 nPos)
646
0
{
647
0
    SvTabListBox::Insert(pEnt, pPar, nPos);
648
0
    RecalculateAccessibleChildren();
649
0
}
650
651
void SvHeaderTabListBox::Insert(SvTreeListEntry* pEntry, sal_uInt32 nRootPos)
652
0
{
653
0
    SvTabListBox::Insert(pEntry, nRootPos);
654
0
    RecalculateAccessibleChildren();
655
0
}
656
657
void SvHeaderTabListBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
658
0
{
659
0
    SvTabListBox::DumpAsPropertyTree(rJsonWriter);
660
661
0
    auto aHeaders = rJsonWriter.startArray("headers");
662
663
0
    HeaderBar* pHeaderBar = GetHeaderBar();
664
0
    for(sal_uInt16 i = 0; i < pHeaderBar->GetItemCount(); i++)
665
0
    {
666
0
        auto aNode = rJsonWriter.startStruct();
667
0
        sal_uInt16 nItemId = pHeaderBar->GetItemId(i);
668
0
        HeaderBarItemBits eItemBits = pHeaderBar->GetItemBits(nItemId);
669
0
        rJsonWriter.put("text", pHeaderBar->GetItemText(nItemId));
670
0
        rJsonWriter.put("sortable", !!(eItemBits & HeaderBarItemBits::CLICKABLE));
671
0
        if (eItemBits & HeaderBarItemBits::UPARROW)
672
0
            rJsonWriter.put("arrow", "up");
673
0
        else if (eItemBits & HeaderBarItemBits::DOWNARROW)
674
0
            rJsonWriter.put("arrow", "down");
675
0
    }
676
0
}
677
678
IMPL_LINK_NOARG(SvHeaderTabListBox, ScrollHdl_Impl, SvTreeListBox*, void)
679
0
{
680
0
    m_xHeaderBar->SetOffset(-GetXOffset());
681
0
}
682
683
IMPL_LINK_NOARG(SvHeaderTabListBox, CreateAccessibleHdl_Impl, HeaderBar*, void)
684
0
{
685
0
    css::uno::Reference< XAccessible > xAccParent = m_xHeaderBar->GetAccessibleParent();
686
0
    if ( xAccParent.is() )
687
0
    {
688
0
        rtl::Reference<comphelper::OAccessible> pAccessible = new AccessibleBrowseBoxHeaderBar(
689
0
            xAccParent, *this, AccessibleBrowseBoxObjType::ColumnHeaderBar);
690
0
        m_xHeaderBar->SetAccessible(pAccessible);
691
0
    }
692
0
}
693
694
void SvHeaderTabListBox::RecalculateAccessibleChildren()
695
0
{
696
0
    if ( !m_aAccessibleChildren.empty() )
697
0
    {
698
0
        sal_uInt32 nCount = ( GetRowCount() + 1 ) * GetColumnCount();
699
0
        if ( m_aAccessibleChildren.size() < nCount )
700
0
            m_aAccessibleChildren.resize( nCount );
701
0
        else
702
0
        {
703
0
            DBG_ASSERT( m_aAccessibleChildren.size() == nCount, "wrong children count" );
704
0
        }
705
0
    }
706
0
}
707
708
bool SvHeaderTabListBox::IsCellCheckBox( sal_Int32 _nRow, sal_uInt16 _nColumn, TriState& _rState ) const
709
0
{
710
0
    bool bRet = false;
711
0
    SvTreeListEntry* pEntry = GetEntryOnPos( _nRow );
712
0
    if ( pEntry )
713
0
    {
714
0
        sal_uInt16 nItemCount = pEntry->ItemCount();
715
0
        if ( nItemCount > ( _nColumn + 1 ) )
716
0
        {
717
0
            SvLBoxItem& rItem = pEntry->GetItem( _nColumn + 1 );
718
0
            if (rItem.GetType() == SvLBoxItemType::Button)
719
0
            {
720
0
                bRet = true;
721
0
                _rState = ( ( static_cast<SvLBoxButton&>(rItem).GetButtonFlags() & SvItemStateFlags::UNCHECKED ) == SvItemStateFlags::NONE )
722
0
                            ? TRISTATE_TRUE : TRISTATE_FALSE;
723
0
            }
724
0
        }
725
0
        else
726
0
        {
727
0
            SAL_WARN( "svtools.contnr", "SvHeaderTabListBox::IsCellCheckBox(): column out of range" );
728
0
        }
729
0
    }
730
0
    return bRet;
731
0
}
732
sal_Int32 SvHeaderTabListBox::GetRowCount() const
733
0
{
734
0
    return GetEntryCount();
735
0
}
736
737
sal_uInt16 SvHeaderTabListBox::GetColumnCount() const
738
0
{
739
0
    return m_xHeaderBar->GetItemCount();
740
0
}
741
742
sal_Int32 SvHeaderTabListBox::GetCurrRow() const
743
0
{
744
0
    sal_Int32 nRet = -1;
745
0
    SvTreeListEntry* pEntry = GetCurEntry();
746
0
    if ( pEntry )
747
0
    {
748
0
        sal_uInt32 nCount = GetEntryCount();
749
0
        for ( sal_uInt32 i = 0; i < nCount; ++i )
750
0
        {
751
0
            if ( pEntry == GetEntryOnPos(i) )
752
0
            {
753
0
                nRet = i;
754
0
                break;
755
0
            }
756
0
        }
757
0
    }
758
759
0
    return nRet;
760
0
}
761
762
sal_uInt16 SvHeaderTabListBox::GetCurrColumn() const
763
0
{
764
0
    return 0;
765
0
}
766
767
OUString SvHeaderTabListBox::GetRowDescription( sal_Int32 _nRow ) const
768
0
{
769
0
    return GetEntryText( _nRow );
770
0
}
771
772
OUString SvHeaderTabListBox::GetColumnDescription( sal_uInt16 _nColumn ) const
773
0
{
774
0
    return m_xHeaderBar->GetItemText(m_xHeaderBar->GetItemId(_nColumn ));
775
0
}
776
777
bool SvHeaderTabListBox::HasRowHeader() const
778
0
{
779
0
    return false;
780
0
}
781
782
bool SvHeaderTabListBox::GoToCell( sal_Int32 /*_nRow*/, sal_uInt16 /*_nColumn*/ )
783
0
{
784
0
    return false;
785
0
}
786
787
void SvHeaderTabListBox::SetNoSelection()
788
0
{
789
0
    SvTreeListBox::SelectAll(false);
790
0
}
791
792
void SvHeaderTabListBox::SelectAll()
793
0
{
794
0
    SvTreeListBox::SelectAll(true);
795
0
}
796
797
void SvHeaderTabListBox::SelectRow( sal_Int32 _nRow, bool _bSelect, bool )
798
0
{
799
0
    Select( GetEntryOnPos( _nRow ), _bSelect );
800
0
}
801
802
void SvHeaderTabListBox::SelectColumn( sal_uInt16, bool )
803
0
{
804
0
}
805
806
sal_Int32 SvHeaderTabListBox::GetSelectedRowCount() const
807
0
{
808
0
    return GetSelectionCount();
809
0
}
810
811
sal_Int32 SvHeaderTabListBox::GetSelectedColumnCount() const
812
0
{
813
0
    return 0;
814
0
}
815
816
bool SvHeaderTabListBox::IsRowSelected( sal_Int32 _nRow ) const
817
0
{
818
0
    SvTreeListEntry* pEntry = GetEntryOnPos( _nRow );
819
0
    return ( pEntry && IsSelected( pEntry ) );
820
0
}
821
822
bool SvHeaderTabListBox::IsColumnSelected( sal_Int32 ) const
823
0
{
824
0
    return false;
825
0
}
826
827
void SvHeaderTabListBox::GetAllSelectedRows(css::uno::Sequence<sal_Int32 >& rRowIndices) const
828
0
{
829
0
    const sal_Int32 nCount = GetSelectedRowCount();
830
0
    rRowIndices.realloc(nCount);
831
0
    auto pRows = rRowIndices.getArray();
832
0
    SvTreeListEntry* pEntry = FirstSelected();
833
0
    sal_Int32 nIndex = 0;
834
0
    while (nIndex < nCount && pEntry)
835
0
    {
836
0
        pRows[nIndex] = GetEntryPos(pEntry);
837
0
        pEntry = NextSelected( pEntry );
838
0
        ++nIndex;
839
0
    }
840
0
    assert(nIndex == nCount && "Mismatch between GetSelectedRowCount() and count of selected rows when iterating.");
841
0
}
842
843
void SvHeaderTabListBox::GetAllSelectedColumns( css::uno::Sequence< sal_Int32 >& ) const
844
0
{
845
0
}
846
847
bool SvHeaderTabListBox::IsCellVisible( sal_Int32, sal_uInt16 ) const
848
0
{
849
0
    return true;
850
0
}
851
852
OUString SvHeaderTabListBox::GetAccessibleCellText( sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
853
0
{
854
0
    return GetTabEntryText(_nRow, _nColumnPos);
855
0
}
856
857
tools::Rectangle SvHeaderTabListBox::calcHeaderRect(bool _bIsColumnBar)
858
0
{
859
0
    tools::Rectangle aRect;
860
0
    if ( _bIsColumnBar )
861
0
    {
862
0
        vcl::Window* pParent = m_xHeaderBar->GetAccessibleParentWindow();
863
0
        assert(pParent);
864
0
        aRect = m_xHeaderBar->GetWindowExtentsRelative(*pParent);
865
0
    }
866
0
    return aRect;
867
0
}
868
869
tools::Rectangle SvHeaderTabListBox::calcTableRect()
870
0
{
871
0
    tools::Rectangle aScreenRect(GetWindowExtentsAbsolute());
872
0
    return tools::Rectangle(Point(0, 0), aScreenRect.GetSize());
873
0
}
874
875
tools::Rectangle SvHeaderTabListBox::calcFieldRectPixel(sal_Int32 _nRow, sal_uInt16 _nColumn, bool _bIsHeader)
876
0
{
877
0
    DBG_ASSERT( !_bIsHeader || 0 == _nRow, "invalid parameters" );
878
0
    tools::Rectangle aRect;
879
0
    SvTreeListEntry* pEntry = GetEntryOnPos(_nRow );
880
0
    if ( pEntry )
881
0
    {
882
0
        aRect = _bIsHeader ? calcHeaderRect(true) : GetBoundingRect(pEntry);
883
0
        Point aTopLeft = aRect.TopLeft();
884
0
        DBG_ASSERT(m_xHeaderBar->GetItemCount() > _nColumn, "invalid column");
885
0
        tools::Rectangle aItemRect = m_xHeaderBar->GetItemRect(m_xHeaderBar->GetItemId(_nColumn));
886
0
        aTopLeft.setX( aItemRect.Left() );
887
0
        Size aSize = aItemRect.GetSize();
888
0
        aRect = tools::Rectangle( aTopLeft, aSize );
889
0
    }
890
891
0
    return aRect;
892
0
}
893
894
rtl::Reference<comphelper::OAccessible>
895
SvHeaderTabListBox::CreateAccessibleCell(sal_Int32 _nRow, sal_uInt16 _nColumnPos)
896
0
{
897
0
    OSL_ENSURE(m_xAccessible.is(), "Invalid call: Accessible is null");
898
899
0
    rtl::Reference< AccessibleBrowseBoxCell > xChild;
900
901
0
    TriState eState = TRISTATE_INDET;
902
0
    bool bIsCheckBox = IsCellCheckBox( _nRow, _nColumnPos, eState );
903
0
    if ( bIsCheckBox )
904
0
        xChild = new AccessibleCheckBoxCell(m_xAccessible->getTable(), *this, _nRow, _nColumnPos,
905
0
                                            eState, false);
906
0
    else
907
0
        xChild = new AccessibleBrowseBoxTableCell(m_xAccessible->getTable(), *this, _nRow,
908
0
                                                  _nColumnPos);
909
910
0
    return xChild;
911
0
}
912
913
Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleRowHeader( sal_Int32 )
914
0
{
915
0
    Reference< XAccessible > xHeader;
916
0
    return xHeader;
917
0
}
918
919
Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleColumnHeader( sal_uInt16 _nColumn )
920
0
{
921
    // first call? -> initial list
922
0
    if ( m_aAccessibleChildren.empty() )
923
0
    {
924
0
        const sal_uInt16 nColumnCount = GetColumnCount();
925
0
        m_aAccessibleChildren.resize( nColumnCount );
926
0
    }
927
928
    // get header
929
0
    rtl::Reference< AccessibleBrowseBoxHeaderCell > xChild = m_aAccessibleChildren[ _nColumn ];
930
    // already exists?
931
0
    if (!xChild.is() && m_xAccessible.is())
932
0
    {
933
        // no -> create new header cell
934
0
        xChild = new AccessibleBrowseBoxHeaderCell(_nColumn, m_xAccessible->getHeaderBar(), *this,
935
0
                                                   AccessibleBrowseBoxObjType::ColumnHeaderCell);
936
937
        // insert into list
938
0
        m_aAccessibleChildren[ _nColumn ] = xChild;
939
0
    }
940
0
    return xChild;
941
0
}
942
943
sal_Int32 SvHeaderTabListBox::GetAccessibleControlCount() const
944
0
{
945
0
    return -1;
946
0
}
947
948
rtl::Reference<comphelper::OAccessible> SvHeaderTabListBox::CreateAccessibleControl(sal_Int32)
949
0
{
950
0
    return {};
951
0
}
952
953
bool SvHeaderTabListBox::ConvertPointToControlIndex( sal_Int32&, const Point& )
954
0
{
955
0
    return false;
956
0
}
957
958
bool SvHeaderTabListBox::ConvertPointToCellAddress( sal_Int32&, sal_uInt16&, const Point& )
959
0
{
960
0
    return false;
961
0
}
962
963
bool SvHeaderTabListBox::ConvertPointToRowHeader( sal_Int32&, const Point& )
964
0
{
965
0
    return false;
966
0
}
967
968
bool SvHeaderTabListBox::ConvertPointToColumnHeader( sal_uInt16&, const Point& )
969
0
{
970
0
    return false;
971
0
}
972
973
OUString SvHeaderTabListBox::GetAccessibleObjectName( AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
974
0
{
975
0
    OUString aRetText;
976
0
    switch( _eType )
977
0
    {
978
0
        case AccessibleBrowseBoxObjType::BrowseBox:
979
0
        case AccessibleBrowseBoxObjType::Table:
980
0
        case AccessibleBrowseBoxObjType::ColumnHeaderBar:
981
            // should be empty now (see #i63983)
982
0
            aRetText.clear();
983
0
            break;
984
985
0
        case AccessibleBrowseBoxObjType::TableCell:
986
0
        {
987
            // here we need a valid pos, we can not handle -1
988
0
            if ( _nPos >= 0 )
989
0
            {
990
0
                sal_uInt16 nColumnCount = GetColumnCount();
991
0
                if (nColumnCount > 0)
992
0
                {
993
0
                    sal_Int32 nRow = _nPos / nColumnCount;
994
0
                    sal_uInt16 nColumn  = static_cast< sal_uInt16 >( _nPos % nColumnCount );
995
0
                    aRetText = GetCellText( nRow, nColumn );
996
0
                }
997
0
            }
998
0
            break;
999
0
        }
1000
0
        case AccessibleBrowseBoxObjType::CheckBoxCell:
1001
0
        {
1002
0
            break; // checkbox cells have no name
1003
0
        }
1004
0
        case AccessibleBrowseBoxObjType::ColumnHeaderCell:
1005
0
        {
1006
0
            aRetText = m_xHeaderBar->GetItemText(m_xHeaderBar->GetItemId(static_cast<sal_uInt16>(_nPos)));
1007
0
            break;
1008
0
        }
1009
1010
0
        case AccessibleBrowseBoxObjType::RowHeaderBar:
1011
0
        case AccessibleBrowseBoxObjType::RowHeaderCell:
1012
0
            aRetText = "error";
1013
0
            break;
1014
1015
0
        default:
1016
0
            OSL_FAIL("BrowseBox::GetAccessibleName: invalid enum!");
1017
0
    }
1018
0
    return aRetText;
1019
0
}
1020
1021
OUString SvHeaderTabListBox::GetAccessibleObjectDescription( AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
1022
0
{
1023
0
    OUString aRetText;
1024
1025
0
    if( _eType == AccessibleBrowseBoxObjType::TableCell && _nPos != -1 )
1026
0
    {
1027
0
        sal_uInt16 nColumnCount = GetColumnCount();
1028
0
        if (nColumnCount > 0)
1029
0
        {
1030
0
            sal_Int32 nRow = _nPos / nColumnCount;
1031
0
            sal_uInt16 nColumn  = static_cast< sal_uInt16 >( _nPos % nColumnCount );
1032
1033
0
            OUString aText( VclResId(STR_SVT_ACC_DESC_TABLISTBOX) );
1034
0
            aText = aText.replaceFirst( "%1", OUString::number( nRow ) );
1035
0
            OUString sColHeader = m_xHeaderBar->GetItemText(m_xHeaderBar->GetItemId(nColumn));
1036
0
            if ( sColHeader.isEmpty() )
1037
0
                sColHeader = OUString::number( nColumn );
1038
0
            aText = aText.replaceFirst( "%2", sColHeader );
1039
0
            aRetText = aText;
1040
0
        }
1041
0
    }
1042
1043
0
    return aRetText;
1044
0
}
1045
1046
void SvHeaderTabListBox::FillAccessibleStateSet( sal_Int64& _rStateSet, AccessibleBrowseBoxObjType _eType ) const
1047
0
{
1048
0
    switch( _eType )
1049
0
    {
1050
0
        case AccessibleBrowseBoxObjType::BrowseBox:
1051
0
        case AccessibleBrowseBoxObjType::Table:
1052
0
        {
1053
0
            _rStateSet |= AccessibleStateType::FOCUSABLE;
1054
0
            if ( HasFocus() )
1055
0
                _rStateSet |= AccessibleStateType::FOCUSED;
1056
0
            if ( IsActive() )
1057
0
                _rStateSet |= AccessibleStateType::ACTIVE;
1058
0
            if ( IsEnabled() )
1059
0
            {
1060
0
                _rStateSet |= AccessibleStateType::ENABLED;
1061
0
                _rStateSet |= AccessibleStateType::SENSITIVE;
1062
0
            }
1063
0
            if ( IsReallyVisible() )
1064
0
                _rStateSet |= AccessibleStateType::VISIBLE;
1065
0
            if ( _eType == AccessibleBrowseBoxObjType::Table )
1066
0
            {
1067
1068
0
                _rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
1069
0
                _rStateSet |= AccessibleStateType::MULTI_SELECTABLE;
1070
0
            }
1071
0
            break;
1072
0
        }
1073
1074
0
        case AccessibleBrowseBoxObjType::ColumnHeaderBar:
1075
0
        {
1076
0
            sal_Int32 nCurRow = GetCurrRow();
1077
0
            sal_uInt16 nCurColumn = GetCurrColumn();
1078
0
            if ( IsCellVisible( nCurRow, nCurColumn ) )
1079
0
                _rStateSet |= AccessibleStateType::VISIBLE;
1080
0
            if ( IsEnabled() )
1081
0
                _rStateSet |= AccessibleStateType::ENABLED;
1082
0
            _rStateSet |= AccessibleStateType::TRANSIENT;
1083
0
            break;
1084
0
        }
1085
1086
0
        case AccessibleBrowseBoxObjType::RowHeaderCell:
1087
0
        case AccessibleBrowseBoxObjType::ColumnHeaderCell:
1088
0
        {
1089
0
            _rStateSet |= AccessibleStateType::VISIBLE;
1090
0
            _rStateSet |= AccessibleStateType::FOCUSABLE;
1091
0
            _rStateSet |= AccessibleStateType::TRANSIENT;
1092
0
            if ( IsEnabled() )
1093
0
                _rStateSet |= AccessibleStateType::ENABLED;
1094
0
            break;
1095
0
        }
1096
0
        default:
1097
0
            break;
1098
0
    }
1099
0
}
1100
1101
void SvHeaderTabListBox::FillAccessibleStateSetForCell( sal_Int64& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumn ) const
1102
0
{
1103
0
    _rStateSet |= AccessibleStateType::FOCUSABLE;
1104
0
    _rStateSet |= AccessibleStateType::SELECTABLE;
1105
0
    _rStateSet |= AccessibleStateType::TRANSIENT;
1106
1107
0
    if ( IsCellVisible( _nRow, _nColumn ) )
1108
0
    {
1109
0
        _rStateSet |= AccessibleStateType::VISIBLE;
1110
0
        _rStateSet |= AccessibleStateType::ENABLED;
1111
0
    }
1112
1113
0
    if ( IsRowSelected( _nRow ) )
1114
0
    {
1115
0
        _rStateSet |= AccessibleStateType::ACTIVE;
1116
0
        if (HasChildPathFocus())
1117
0
            _rStateSet |= AccessibleStateType::FOCUSED;
1118
0
        _rStateSet |= AccessibleStateType::SELECTED;
1119
0
    }
1120
0
    if ( IsEnabled() )
1121
0
        _rStateSet |= AccessibleStateType::ENABLED;
1122
0
}
1123
1124
void SvHeaderTabListBox::GrabTableFocus()
1125
0
{
1126
0
    GrabFocus();
1127
0
}
1128
1129
bool SvHeaderTabListBox::GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector )
1130
0
{
1131
0
    return GetOutDev()->GetGlyphBoundRects( rOrigin, rStr, nIndex, nLen, rVector );
1132
0
}
1133
1134
tools::Rectangle SvHeaderTabListBox::GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const
1135
0
{
1136
0
    return Control::GetWindowExtentsRelative( rRelativeWindow );
1137
0
}
1138
1139
void SvHeaderTabListBox::GrabFocus()
1140
0
{
1141
0
    Control::GrabFocus();
1142
0
}
1143
1144
rtl::Reference<comphelper::OAccessible> SvHeaderTabListBox::GetAccessible()
1145
0
{
1146
0
    return Control::GetAccessible();
1147
0
}
1148
1149
vcl::Window* SvHeaderTabListBox::GetAccessibleParentWindow() const
1150
0
{
1151
0
    return Control::GetAccessibleParentWindow();
1152
0
}
1153
1154
vcl::Window* SvHeaderTabListBox::GetWindowInstance()
1155
0
{
1156
0
    return this;
1157
0
}
1158
1159
rtl::Reference<comphelper::OAccessible> SvHeaderTabListBox::CreateAccessible()
1160
0
{
1161
0
    if (m_xAccessible.is())
1162
0
        return m_xAccessible;
1163
1164
0
    rtl::Reference<comphelper::OAccessible> pAccParent = GetAccessibleParent();
1165
0
    if (pAccParent.is())
1166
0
    {
1167
0
        m_xAccessible = new AccessibleTabListBox(pAccParent, *this);
1168
0
        return m_xAccessible;
1169
0
    }
1170
0
    return nullptr;
1171
0
}
1172
1173
tools::Rectangle SvHeaderTabListBox::GetFieldCharacterBounds(sal_Int32,sal_Int32,sal_Int32)
1174
0
{
1175
0
    return tools::Rectangle();
1176
0
}
1177
1178
sal_Int32 SvHeaderTabListBox::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
1179
0
{
1180
0
    OUString sText = GetAccessibleCellText( _nRow, static_cast< sal_uInt16 >( _nColumnPos ) );
1181
0
    std::vector< tools::Rectangle > aRects;
1182
0
    if ( GetGlyphBoundRects(Point(0,0), sText, 0, sText.getLength(), aRects) )
1183
0
    {
1184
0
        sal_Int32 nPos = 0;
1185
0
        for (auto const& rectangle : aRects)
1186
0
        {
1187
0
            if( rectangle.Contains(_rPoint) )
1188
0
                return nPos;
1189
0
            ++nPos;
1190
0
        }
1191
0
    }
1192
1193
0
    return -1;
1194
0
}
1195
1196
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */