Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/accessibility/vclxaccessibletabpage.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/vclxaccessibletabpage.hxx>
21
22
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
23
#include <com/sun/star/accessibility/AccessibleRole.hpp>
24
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
25
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
26
#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
27
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28
#include <comphelper/accessiblecontexthelper.hxx>
29
#include <cppuhelper/supportsservice.hxx>
30
#include <unotools/accessiblerelationsethelper.hxx>
31
#include <vcl/accessibility/characterattributeshelper.hxx>
32
#include <vcl/mnemonic.hxx>
33
#include <vcl/svapp.hxx>
34
#include <vcl/unohelp.hxx>
35
#include <vcl/unohelp2.hxx>
36
#include <vcl/tabctrl.hxx>
37
#include <vcl/tabpage.hxx>
38
#include <vcl/settings.hxx>
39
#include <i18nlangtag/languagetag.hxx>
40
41
using namespace ::com::sun::star::accessibility;
42
using namespace ::com::sun::star::uno;
43
using namespace ::com::sun::star::lang;
44
using namespace ::com::sun::star::beans;
45
using namespace ::com::sun::star;
46
using namespace ::comphelper;
47
48
49
50
51
VCLXAccessibleTabPage::VCLXAccessibleTabPage( TabControl* pTabControl, sal_uInt16 nPageId )
52
0
    :m_pTabControl( pTabControl )
53
0
    ,m_nPageId( nPageId )
54
0
{
55
0
    m_bFocused  = IsFocused();
56
0
    m_bSelected = IsSelected();
57
0
    m_sPageText = GetPageText();
58
0
}
59
60
61
VCLXAccessibleTabPage::~VCLXAccessibleTabPage()
62
0
{
63
0
}
64
65
66
bool VCLXAccessibleTabPage::IsFocused() const
67
0
{
68
0
    bool bFocused = false;
69
70
0
    if ( m_pTabControl && m_pTabControl->HasFocus() && m_pTabControl->GetCurPageId() == m_nPageId )
71
0
        bFocused = true;
72
73
0
    return bFocused;
74
0
}
75
76
77
bool VCLXAccessibleTabPage::IsSelected() const
78
0
{
79
0
    bool bSelected = false;
80
81
0
    if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_nPageId )
82
0
        bSelected = true;
83
84
0
    return bSelected;
85
0
}
86
87
88
void VCLXAccessibleTabPage::SetFocused( bool bFocused )
89
0
{
90
0
    if ( m_bFocused != bFocused )
91
0
    {
92
0
        Any aOldValue, aNewValue;
93
0
        if ( m_bFocused )
94
0
            aOldValue <<= AccessibleStateType::FOCUSED;
95
0
        else
96
0
            aNewValue <<= AccessibleStateType::FOCUSED;
97
0
        m_bFocused = bFocused;
98
0
        NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
99
0
    }
100
0
}
101
102
103
void VCLXAccessibleTabPage::SetSelected( bool bSelected )
104
0
{
105
0
    if ( m_bSelected != bSelected )
106
0
    {
107
0
        Any aOldValue, aNewValue;
108
0
        if ( m_bSelected )
109
0
            aOldValue <<= AccessibleStateType::SELECTED;
110
0
        else
111
0
            aNewValue <<= AccessibleStateType::SELECTED;
112
0
        m_bSelected = bSelected;
113
0
        NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
114
0
    }
115
0
}
116
117
118
void VCLXAccessibleTabPage::SetPageText( const OUString& sPageText )
119
0
{
120
0
    Any aOldValue, aNewValue;
121
0
    if ( OCommonAccessibleText::implInitTextChangedEvent( m_sPageText, sPageText, aOldValue, aNewValue ) )
122
0
    {
123
0
        Any aOldName, aNewName;
124
0
        aOldName <<= m_sPageText;
125
0
        aNewName <<= sPageText;
126
0
        m_sPageText = sPageText;
127
0
        NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldName, aNewName );
128
0
        NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
129
0
    }
130
0
}
131
132
133
OUString VCLXAccessibleTabPage::GetPageText()
134
0
{
135
0
    OUString sText;
136
0
    if ( m_pTabControl )
137
0
        sText = removeMnemonicFromString( m_pTabControl->GetPageText( m_nPageId ) );
138
139
0
    return sText;
140
0
}
141
142
143
void VCLXAccessibleTabPage::Update( bool bNew )
144
0
{
145
0
    if ( !m_pTabControl )
146
0
        return;
147
148
0
    TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
149
0
    if ( !pTabPage )
150
0
        return;
151
152
0
    Reference< XAccessible > xChild( pTabPage->GetAccessible( bNew ) );
153
0
    if ( xChild.is() )
154
0
    {
155
0
        Any aOldValue, aNewValue;
156
0
        if ( bNew )
157
0
            aNewValue <<= xChild;
158
0
        else
159
0
            aOldValue <<= xChild;
160
0
        NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
161
0
    }
162
0
}
163
164
165
void VCLXAccessibleTabPage::FillAccessibleStateSet( sal_Int64& rStateSet )
166
0
{
167
0
    rStateSet |= AccessibleStateType::ENABLED;
168
0
    rStateSet |= AccessibleStateType::SENSITIVE;
169
170
0
    rStateSet |= AccessibleStateType::FOCUSABLE;
171
172
0
    if ( IsFocused() )
173
0
        rStateSet |= AccessibleStateType::FOCUSED;
174
175
0
    rStateSet |= AccessibleStateType::VISIBLE;
176
177
0
    rStateSet |= AccessibleStateType::SHOWING;
178
179
0
    rStateSet |= AccessibleStateType::SELECTABLE;
180
181
0
    if ( IsSelected() )
182
0
        rStateSet |= AccessibleStateType::SELECTED;
183
0
}
184
185
// OAccessible
186
187
awt::Rectangle VCLXAccessibleTabPage::implGetBounds()
188
0
{
189
0
    awt::Rectangle aBounds( 0, 0, 0, 0 );
190
191
0
    if ( m_pTabControl )
192
0
        aBounds = vcl::unohelper::ConvertToAWTRect(m_pTabControl->GetTabBounds(m_nPageId));
193
194
0
    return aBounds;
195
0
}
196
197
198
// OCommonAccessibleText
199
200
201
OUString VCLXAccessibleTabPage::implGetText()
202
0
{
203
0
    return GetPageText();
204
0
}
205
206
207
lang::Locale VCLXAccessibleTabPage::implGetLocale()
208
0
{
209
0
    return Application::GetSettings().GetLanguageTag().getLocale();
210
0
}
211
212
213
void VCLXAccessibleTabPage::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
214
0
{
215
0
    nStartIndex = 0;
216
0
    nEndIndex = 0;
217
0
}
218
219
220
// XComponent
221
222
223
void VCLXAccessibleTabPage::disposing()
224
0
{
225
0
    comphelper::OAccessibleTextHelper::disposing();
226
227
0
    m_pTabControl = nullptr;
228
0
    m_sPageText.clear();
229
0
}
230
231
232
// XServiceInfo
233
234
235
OUString VCLXAccessibleTabPage::getImplementationName()
236
0
{
237
0
    return u"com.sun.star.comp.toolkit.AccessibleTabPage"_ustr;
238
0
}
239
240
241
sal_Bool VCLXAccessibleTabPage::supportsService( const OUString& rServiceName )
242
0
{
243
0
    return cppu::supportsService(this, rServiceName);
244
0
}
245
246
247
Sequence< OUString > VCLXAccessibleTabPage::getSupportedServiceNames()
248
0
{
249
0
    return { u"com.sun.star.awt.AccessibleTabPage"_ustr };
250
0
}
251
252
// XAccessibleContext
253
254
255
sal_Int64 VCLXAccessibleTabPage::getAccessibleChildCount()
256
0
{
257
0
    OExternalLockGuard aGuard( this );
258
0
    return implGetAccessibleChildCount();
259
0
}
260
261
sal_Int64 VCLXAccessibleTabPage::implGetAccessibleChildCount()
262
0
{
263
0
    sal_Int64 nCount = 0;
264
0
    if ( m_pTabControl )
265
0
    {
266
0
        TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
267
0
        if ( pTabPage && pTabPage->IsVisible() )
268
0
            nCount = 1;
269
0
    }
270
271
0
    return nCount;
272
0
}
273
274
275
Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleChild( sal_Int64 i )
276
0
{
277
0
    OExternalLockGuard aGuard( this );
278
279
0
    if ( i < 0 || i >= implGetAccessibleChildCount() )
280
0
        throw IndexOutOfBoundsException();
281
282
0
    rtl::Reference<comphelper::OAccessible> pChild;
283
0
    if ( m_pTabControl )
284
0
    {
285
0
        TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
286
0
        if ( pTabPage && pTabPage->IsVisible() )
287
0
            pChild = pTabPage->GetAccessible();
288
0
    }
289
290
0
    return pChild;
291
0
}
292
293
294
Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleParent(  )
295
0
{
296
0
    OExternalLockGuard aGuard( this );
297
298
0
    Reference< XAccessible > xParent;
299
0
    if ( m_pTabControl )
300
0
        xParent = m_pTabControl->GetAccessible();
301
302
0
    return xParent;
303
0
}
304
305
306
sal_Int64 VCLXAccessibleTabPage::getAccessibleIndexInParent(  )
307
0
{
308
0
    OExternalLockGuard aGuard( this );
309
310
0
    sal_Int64 nIndexInParent = -1;
311
0
    if ( m_pTabControl )
312
0
        nIndexInParent = m_pTabControl->GetPagePos( m_nPageId );
313
314
0
    return nIndexInParent;
315
0
}
316
317
sal_Int16 VCLXAccessibleTabPage::getAccessibleRole()
318
0
{
319
0
    OExternalLockGuard aGuard( this );
320
321
0
    return AccessibleRole::PAGE_TAB;
322
0
}
323
324
OUString VCLXAccessibleTabPage::getAccessibleDescription()
325
0
{
326
0
    OExternalLockGuard aGuard( this );
327
328
0
    OUString sDescription;
329
0
    if ( m_pTabControl )
330
0
        sDescription = m_pTabControl->GetAccessibleDescription( m_nPageId );
331
332
0
    return sDescription;
333
0
}
334
335
OUString VCLXAccessibleTabPage::getAccessibleName()
336
0
{
337
0
    OExternalLockGuard aGuard( this );
338
339
0
    OUString sName;
340
0
    if ( m_pTabControl )
341
0
        sName = m_pTabControl->GetAccessibleName( m_nPageId );
342
343
0
    return sName;
344
0
}
345
346
Reference< XAccessibleRelationSet > VCLXAccessibleTabPage::getAccessibleRelationSet(  )
347
0
{
348
0
    OExternalLockGuard aGuard( this );
349
350
0
    return new utl::AccessibleRelationSetHelper;
351
0
}
352
353
354
sal_Int64 VCLXAccessibleTabPage::getAccessibleStateSet(  )
355
0
{
356
0
    OExternalLockGuard aGuard( this );
357
358
0
    sal_Int64 nStateSet = 0;
359
360
0
    if (isAlive())
361
0
        FillAccessibleStateSet( nStateSet );
362
0
    else
363
0
        nStateSet |= AccessibleStateType::DEFUNC;
364
365
0
    return nStateSet;
366
0
}
367
368
369
Locale VCLXAccessibleTabPage::getLocale(  )
370
0
{
371
0
    OExternalLockGuard aGuard( this );
372
373
0
    return Application::GetSettings().GetLanguageTag().getLocale();
374
0
}
375
376
377
// XAccessibleComponent
378
379
380
Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleAtPoint( const awt::Point& rPoint )
381
0
{
382
0
    OExternalLockGuard aGuard( this );
383
384
0
    for ( sal_Int64 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
385
0
    {
386
0
        Reference< XAccessible > xAcc = getAccessibleChild( i );
387
0
        if ( xAcc.is() )
388
0
        {
389
0
            Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
390
0
            if ( xComp.is() )
391
0
            {
392
0
                tools::Rectangle aRect = vcl::unohelper::ConvertToVCLRect(xComp->getBounds());
393
0
                Point aPos = vcl::unohelper::ConvertToVCLPoint(rPoint);
394
0
                if ( aRect.Contains( aPos ) )
395
0
                {
396
0
                    return xAcc;
397
0
                }
398
0
            }
399
0
        }
400
0
    }
401
402
0
    return nullptr;
403
0
}
404
405
406
void VCLXAccessibleTabPage::grabFocus(  )
407
0
{
408
0
    OExternalLockGuard aGuard( this );
409
410
0
    if ( m_pTabControl )
411
0
    {
412
0
        m_pTabControl->SelectTabPage( m_nPageId );
413
0
        m_pTabControl->GrabFocus();
414
0
    }
415
0
}
416
417
418
sal_Int32 VCLXAccessibleTabPage::getForeground( )
419
0
{
420
0
    OExternalLockGuard aGuard( this );
421
422
0
    sal_Int32 nColor = 0;
423
0
    Reference< XAccessible > xParent = getAccessibleParent();
424
0
    if ( xParent.is() )
425
0
    {
426
0
        Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
427
0
        if ( xParentComp.is() )
428
0
            nColor = xParentComp->getForeground();
429
0
    }
430
431
0
    return nColor;
432
0
}
433
434
435
sal_Int32 VCLXAccessibleTabPage::getBackground(  )
436
0
{
437
0
    OExternalLockGuard aGuard( this );
438
439
0
    sal_Int32 nColor = 0;
440
0
    Reference< XAccessible > xParent = getAccessibleParent();
441
0
    if ( xParent.is() )
442
0
    {
443
0
        Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
444
0
        if ( xParentComp.is() )
445
0
            nColor = xParentComp->getBackground();
446
0
    }
447
448
0
    return nColor;
449
0
}
450
451
// XAccessibleText
452
453
OUString VCLXAccessibleTabPage::getText()
454
0
{
455
0
    OExternalLockGuard aGuard( this );
456
457
0
    return GetPageText();
458
0
}
459
460
OUString VCLXAccessibleTabPage::getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex)
461
0
{
462
0
    OExternalLockGuard aGuard( this );
463
464
0
    return OCommonAccessibleText::implGetTextRange(GetPageText(), nStartIndex, nEndIndex);
465
0
}
466
467
sal_Unicode VCLXAccessibleTabPage::getCharacter( sal_Int32 nIndex )
468
0
{
469
0
     OExternalLockGuard aGuard( this );
470
471
0
     return OCommonAccessibleText::implGetCharacter( GetPageText(), nIndex );
472
0
}
473
474
sal_Int32 VCLXAccessibleTabPage::getCharacterCount()
475
0
{
476
0
    return GetPageText().getLength();
477
0
}
478
479
sal_Int32 VCLXAccessibleTabPage::getCaretPosition()
480
0
{
481
0
    OExternalLockGuard aGuard( this );
482
483
0
    return -1;
484
0
}
485
486
487
sal_Bool VCLXAccessibleTabPage::setCaretPosition( sal_Int32 nIndex )
488
0
{
489
0
    OExternalLockGuard aGuard( this );
490
491
0
    if ( !implIsValidRange( nIndex, nIndex, GetPageText().getLength() ) )
492
0
        throw IndexOutOfBoundsException();
493
494
0
    return false;
495
0
}
496
497
498
Sequence< PropertyValue > VCLXAccessibleTabPage::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
499
0
{
500
0
    OExternalLockGuard aGuard( this );
501
502
0
    Sequence< PropertyValue > aValues;
503
0
    OUString sText( GetPageText() );
504
505
0
    if ( !implIsValidIndex( nIndex, sText.getLength() ) )
506
0
        throw IndexOutOfBoundsException();
507
508
0
    if ( m_pTabControl )
509
0
    {
510
0
        vcl::Font aFont = m_pTabControl->GetFont();
511
0
        sal_Int32 nBackColor = getBackground();
512
0
        sal_Int32 nColor = getForeground();
513
0
        aValues = CharacterAttributesHelper( aFont, nBackColor, nColor )
514
0
            .GetCharacterAttributes( aRequestedAttributes );
515
0
    }
516
517
0
    return aValues;
518
0
}
519
520
521
awt::Rectangle VCLXAccessibleTabPage::getCharacterBounds( sal_Int32 nIndex )
522
0
{
523
0
    OExternalLockGuard aGuard( this );
524
525
0
    if ( !implIsValidIndex( nIndex, GetPageText().getLength() ) )
526
0
        throw IndexOutOfBoundsException();
527
528
0
    awt::Rectangle aBounds( 0, 0, 0, 0 );
529
0
    if ( m_pTabControl )
530
0
    {
531
0
        tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
532
0
        tools::Rectangle aCharRect; // m_pTabControl->GetCharacterBounds( m_nPageId, nIndex );
533
0
        aCharRect.Move( -aPageRect.Left(), -aPageRect.Top() );
534
0
        aBounds = vcl::unohelper::ConvertToAWTRect(aCharRect);
535
0
    }
536
537
0
    return aBounds;
538
0
}
539
540
541
sal_Int32 VCLXAccessibleTabPage::getIndexAtPoint( const awt::Point& /*aPoint*/ )
542
0
{
543
0
    OExternalLockGuard aGuard( this );
544
545
0
    sal_Int32 nIndex = -1;
546
//    if ( m_pTabControl )
547
//    {
548
//        sal_uInt16 nPageId = 0;
549
//        tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
550
//        Point aPnt( vcl::unohelper::ConvertToVCLPoint( aPoint ) );
551
//        aPnt += aPageRect.TopLeft();
552
//        sal_Int32 nI = m_pTabControl->GetIndexForPoint( aPnt, nPageId );
553
//        if ( nI != -1 && m_nPageId == nPageId )
554
//            nIndex = nI;
555
//    }
556
557
0
    return nIndex;
558
0
}
559
560
561
sal_Bool VCLXAccessibleTabPage::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
562
0
{
563
0
    OExternalLockGuard aGuard( this );
564
565
0
    if ( !implIsValidRange( nStartIndex, nEndIndex, GetPageText().getLength() ) )
566
0
        throw IndexOutOfBoundsException();
567
568
0
    return false;
569
0
}
570
571
572
sal_Bool VCLXAccessibleTabPage::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
573
0
{
574
0
    OExternalLockGuard aGuard( this );
575
576
0
    bool bReturn = false;
577
578
0
    if ( m_pTabControl )
579
0
    {
580
0
        Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pTabControl->GetClipboard();
581
0
        if ( xClipboard.is() )
582
0
        {
583
0
            OUString sText( implGetTextRange( GetPageText(), nStartIndex, nEndIndex ) );
584
585
0
            rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
586
587
0
            SolarMutexReleaser aReleaser;
588
0
            xClipboard->setContents( pDataObj, nullptr );
589
590
0
            Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
591
0
            if( xFlushableClipboard.is() )
592
0
                xFlushableClipboard->flushClipboard();
593
594
0
            bReturn = true;
595
0
        }
596
0
    }
597
598
0
    return bReturn;
599
0
}
600
601
sal_Bool VCLXAccessibleTabPage::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
602
0
{
603
0
    return false;
604
0
}
605
606
607
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */