Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/Accessibility/AccessiblePreviewHeaderCell.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 <sal/config.h>
21
22
#include <tools/gen.hxx>
23
#include <AccessibleText.hxx>
24
#include <editsrc.hxx>
25
#include <svx/AccessibleTextHelper.hxx>
26
#include <AccessiblePreviewHeaderCell.hxx>
27
#include <prevwsh.hxx>
28
#include <prevloc.hxx>
29
#include <strings.hxx>
30
31
#include <com/sun/star/accessibility/AccessibleRole.hpp>
32
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
33
#include <comphelper/sequence.hxx>
34
35
#include <vcl/window.hxx>
36
#include <vcl/svapp.hxx>
37
#include <vcl/unohelp.hxx>
38
#include <svl/hint.hxx>
39
#include <toolkit/helper/vclunohelper.hxx>
40
41
#ifdef indices
42
#undef indices
43
#endif
44
45
#ifdef extents
46
#undef extents
47
#endif
48
49
using namespace ::com::sun::star;
50
using namespace ::com::sun::star::accessibility;
51
52
ScAccessiblePreviewHeaderCell::ScAccessiblePreviewHeaderCell(
53
    const css::uno::Reference<css::accessibility::XAccessible>& rxParent,
54
    ScPreviewShell* pViewShell, const ScAddress& rCellPos, bool bIsColHdr, bool bIsRowHdr,
55
    sal_Int32 nIndex)
56
0
    : ImplInheritanceHelper(rxParent, AccessibleRole::TABLE_CELL)
57
0
    , mpViewShell(pViewShell)
58
0
    , mnIndex(nIndex)
59
0
    , maCellPos(rCellPos)
60
0
    , mbColumnHeader(bIsColHdr)
61
0
    , mbRowHeader(bIsRowHdr)
62
0
{
63
0
    if (mpViewShell)
64
0
        mpViewShell->AddAccessibilityObject(*this);
65
0
}
66
67
ScAccessiblePreviewHeaderCell::~ScAccessiblePreviewHeaderCell()
68
0
{
69
0
    if (mpViewShell)
70
0
        mpViewShell->RemoveAccessibilityObject(*this);
71
0
}
72
73
void SAL_CALL ScAccessiblePreviewHeaderCell::disposing()
74
0
{
75
0
    SolarMutexGuard aGuard;
76
0
    if (mpViewShell)
77
0
    {
78
0
        mpViewShell->RemoveAccessibilityObject(*this);
79
0
        mpViewShell = nullptr;
80
0
    }
81
82
0
    mpTableInfo.reset();
83
84
0
    ScAccessibleContextBase::disposing();
85
0
}
86
87
//=====  SfxListener  =====================================================
88
89
void ScAccessiblePreviewHeaderCell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
90
0
{
91
0
    const SfxHintId nId = rHint.GetId();
92
0
    if (nId == SfxHintId::ScAccVisAreaChanged)
93
0
    {
94
0
        if (mxTextHelper)
95
0
            mxTextHelper->UpdateChildren();
96
0
    }
97
0
    else if ( nId == SfxHintId::DataChanged )
98
0
    {
99
        //  column / row layout may change with any document change,
100
        //  so it must be invalidated
101
0
        mpTableInfo.reset();
102
0
    }
103
104
0
    ScAccessibleContextBase::Notify(rBC, rHint);
105
0
}
106
107
//=====  XAccessibleValue  ================================================
108
109
uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getCurrentValue()
110
0
{
111
0
    SolarMutexGuard aGuard;
112
0
    ensureAlive();
113
114
0
    double fValue(0.0);
115
0
    if (mbColumnHeader)
116
0
        fValue = maCellPos.Col();
117
0
    else
118
0
        fValue = maCellPos.Row();
119
120
0
    return uno::Any(fValue);
121
0
}
122
123
sal_Bool SAL_CALL ScAccessiblePreviewHeaderCell::setCurrentValue( const uno::Any& /* aNumber */ )
124
0
{
125
    //  it is not possible to set a value
126
0
    return false;
127
0
}
128
129
uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMaximumValue()
130
0
{
131
0
    SolarMutexGuard aGuard;
132
0
    ensureAlive();
133
134
0
    double fValue(0.0);
135
0
    ScDocument& rDoc = mpViewShell->GetDocument();
136
0
    if (mbColumnHeader)
137
0
        fValue = rDoc.MaxCol();
138
0
    else
139
0
        fValue = rDoc.MaxRow();
140
0
    return uno::Any(fValue);
141
0
}
142
143
uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMinimumValue()
144
0
{
145
0
    return uno::Any(0.0);
146
0
}
147
148
uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMinimumIncrement()
149
0
{
150
    // value can't be changed, s. 'setCurrentValue'
151
0
    return uno::Any();
152
0
}
153
154
//=====  XAccessibleComponent  ============================================
155
156
uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleAtPoint( const awt::Point& rPoint )
157
0
{
158
0
    rtl::Reference<comphelper::OAccessible> pRet;
159
0
    if (containsPoint(rPoint))
160
0
    {
161
0
        SolarMutexGuard aGuard;
162
0
        ensureAlive();
163
164
0
        if(!mxTextHelper)
165
0
            CreateTextHelper();
166
167
0
        pRet = mxTextHelper->GetAt(rPoint);
168
0
    }
169
170
0
    return pRet;
171
0
}
172
173
void SAL_CALL ScAccessiblePreviewHeaderCell::grabFocus()
174
0
{
175
0
    SolarMutexGuard aGuard;
176
0
    ensureAlive();
177
0
    if (getAccessibleParent().is())
178
0
    {
179
0
        uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
180
0
        if (xAccessibleComponent.is())
181
0
            xAccessibleComponent->grabFocus();
182
0
    }
183
0
}
184
185
//=====  XAccessibleContext  ==============================================
186
187
sal_Int64 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChildCount()
188
0
{
189
0
    SolarMutexGuard aGuard;
190
0
    ensureAlive();
191
0
    if (!mxTextHelper)
192
0
        CreateTextHelper();
193
0
    return mxTextHelper->GetChildCount();
194
0
}
195
196
uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChild(sal_Int64 nIndex)
197
0
{
198
0
    SolarMutexGuard aGuard;
199
0
    ensureAlive();
200
0
    if (!mxTextHelper)
201
0
        CreateTextHelper();
202
0
    return mxTextHelper->GetChild(nIndex);
203
0
}
204
205
sal_Int64 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleIndexInParent()
206
0
{
207
0
    return mnIndex;
208
0
}
209
210
sal_Int64 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleStateSet()
211
0
{
212
0
    SolarMutexGuard aGuard;
213
214
0
    sal_Int64 nParentStates = 0;
215
0
    if (getAccessibleParent().is())
216
0
    {
217
0
        uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
218
0
        nParentStates = xParentContext->getAccessibleStateSet();
219
0
    }
220
0
    sal_Int64 nStateSet = 0;
221
0
    if (IsDefunc(nParentStates))
222
0
        nStateSet |= AccessibleStateType::DEFUNC;
223
0
    else
224
0
    {
225
0
        nStateSet |= AccessibleStateType::ENABLED;
226
0
        nStateSet |= AccessibleStateType::MULTI_LINE;
227
0
        if (isShowing())
228
0
            nStateSet |= AccessibleStateType::SHOWING;
229
0
        nStateSet |= AccessibleStateType::TRANSIENT;
230
0
        if (isVisible())
231
0
            nStateSet |= AccessibleStateType::VISIBLE;
232
0
    }
233
0
    return nStateSet;
234
0
}
235
236
AbsoluteScreenPixelRectangle ScAccessiblePreviewHeaderCell::GetBoundingBoxOnScreen()
237
0
{
238
0
    tools::Rectangle aCellRect;
239
240
0
    FillTableInfo();
241
242
0
    if (mpTableInfo)
243
0
    {
244
0
        const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()];
245
0
        const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()];
246
247
0
        aCellRect = tools::Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
248
0
    }
249
250
0
    if (mpViewShell)
251
0
    {
252
0
        vcl::Window* pWindow = mpViewShell->GetWindow();
253
0
        if (pWindow)
254
0
        {
255
0
            AbsoluteScreenPixelRectangle aRect = pWindow->GetWindowExtentsAbsolute();
256
0
            aCellRect.Move(aRect.Left(), aRect.Top());
257
0
        }
258
0
    }
259
0
    return AbsoluteScreenPixelRectangle(aCellRect);
260
0
}
261
262
tools::Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBox()
263
0
{
264
0
    FillTableInfo();
265
266
0
    if (mpTableInfo)
267
0
    {
268
0
        const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()];
269
0
        const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()];
270
271
0
        tools::Rectangle aCellRect( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
272
0
        uno::Reference<XAccessible> xAccParent = getAccessibleParent();
273
0
        if (xAccParent.is())
274
0
        {
275
0
            uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext();
276
0
            uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY);
277
0
            if (xAccParentComp.is())
278
0
            {
279
0
                tools::Rectangle aParentRect(
280
0
                    vcl::unohelper::ConvertToVCLRect(xAccParentComp->getBounds()));
281
0
                aCellRect.Move(-aParentRect.Left(), -aParentRect.Top());
282
0
            }
283
0
        }
284
0
        return aCellRect;
285
0
    }
286
0
    return tools::Rectangle();
287
0
}
288
289
OUString ScAccessiblePreviewHeaderCell::createAccessibleDescription()
290
0
{
291
0
    return STR_ACC_HEADERCELL_DESCR;
292
0
}
293
294
OUString ScAccessiblePreviewHeaderCell::createAccessibleName()
295
0
{
296
0
    OUString sName = STR_ACC_HEADERCELL_NAME;
297
298
0
    if ( mbColumnHeader )
299
0
    {
300
0
        if ( mbRowHeader )
301
0
        {
302
            //! name for corner cell?
303
304
//          sName = "Column/Row Header";
305
0
        }
306
0
        else
307
0
        {
308
            // name of column header
309
0
            sName += ScColToAlpha( maCellPos.Col() );
310
0
        }
311
0
    }
312
0
    else
313
0
    {
314
        // name of row header
315
0
        sName += OUString::number(  maCellPos.Row() + 1 );
316
0
    }
317
318
0
    return sName;
319
0
}
320
321
bool ScAccessiblePreviewHeaderCell::IsDefunc( sal_Int64 nParentStates )
322
0
{
323
0
    return ScAccessibleContextBase::IsDefunc() || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
324
0
        (nParentStates & AccessibleStateType::DEFUNC);
325
0
}
326
327
void ScAccessiblePreviewHeaderCell::CreateTextHelper()
328
0
{
329
0
    if (!mxTextHelper)
330
0
    {
331
0
        mxTextHelper.reset( new ::accessibility::AccessibleTextHelper(
332
0
            std::make_unique<ScAccessibilityEditSource>(
333
0
                std::make_unique<ScAccessiblePreviewHeaderCellTextData>(
334
0
                    mpViewShell, getAccessibleName(), maCellPos,
335
0
                    mbColumnHeader, mbRowHeader))) );
336
0
        mxTextHelper->SetEventSource(this);
337
0
    }
338
0
}
339
340
void ScAccessiblePreviewHeaderCell::FillTableInfo() const
341
0
{
342
0
    if ( mpViewShell && !mpTableInfo )
343
0
    {
344
0
        Size aOutputSize;
345
0
        vcl::Window* pWindow = mpViewShell->GetWindow();
346
0
        if ( pWindow )
347
0
            aOutputSize = pWindow->GetOutputSizePixel();
348
0
        tools::Rectangle aVisRect( Point(), aOutputSize );
349
350
0
        mpTableInfo.reset( new ScPreviewTableInfo );
351
0
        mpViewShell->GetLocationData().GetTableInfo( aVisRect, *mpTableInfo );
352
0
    }
353
0
}
354
355
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */