Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/Accessibility/AccessiblePreviewCell.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 <scitems.hxx>
23
#include <tools/gen.hxx>
24
#include <AccessibleText.hxx>
25
#include <editsrc.hxx>
26
#include <AccessiblePreviewCell.hxx>
27
#include <prevwsh.hxx>
28
#include <prevloc.hxx>
29
#include <document.hxx>
30
#include <svx/AccessibleTextHelper.hxx>
31
#include <editeng/brushitem.hxx>
32
#include <vcl/window.hxx>
33
#include <vcl/svapp.hxx>
34
#include <vcl/unohelp.hxx>
35
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
36
#include <comphelper/sequence.hxx>
37
38
using namespace ::com::sun::star;
39
using namespace ::com::sun::star::accessibility;
40
41
ScAccessiblePreviewCell::ScAccessiblePreviewCell(
42
    const rtl::Reference<ScAccessiblePreviewTable>& rParent, ScPreviewShell* pViewShell,
43
    const ScAddress& rCellAddress, sal_Int32 nIndex)
44
0
    : ScAccessibleCellBase(rParent, (pViewShell ? &pViewShell->GetDocument() : nullptr),
45
0
                           rCellAddress, nIndex)
46
0
    , mpViewShell(pViewShell)
47
0
{
48
0
    if (mpViewShell)
49
0
        mpViewShell->AddAccessibilityObject(*this);
50
0
}
51
52
ScAccessiblePreviewCell::~ScAccessiblePreviewCell()
53
0
{
54
0
    if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
55
0
    {
56
        // increment refcount to prevent double call of dtor
57
0
        osl_atomic_increment( &m_refCount );
58
        // call dispose to inform object which have a weak reference to this object
59
0
        dispose();
60
0
    }
61
0
}
62
63
void SAL_CALL ScAccessiblePreviewCell::disposing()
64
0
{
65
0
    SolarMutexGuard aGuard;
66
0
    if (mpViewShell)
67
0
    {
68
0
        mpViewShell->RemoveAccessibilityObject(*this);
69
0
        mpViewShell = nullptr;
70
0
    }
71
72
0
    mpTextHelper.reset();
73
74
0
    ScAccessibleCellBase::disposing();
75
0
}
76
77
void ScAccessiblePreviewCell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
78
0
{
79
0
    if (rHint.GetId() == SfxHintId::ScAccVisAreaChanged)
80
0
    {
81
0
        if (mpTextHelper)
82
0
            mpTextHelper->UpdateChildren();
83
0
    }
84
85
0
    ScAccessibleContextBase::Notify(rBC, rHint);
86
0
}
87
88
//=====  XAccessibleComponent  ============================================
89
90
uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewCell::getAccessibleAtPoint( const awt::Point& rPoint )
91
0
{
92
0
    rtl::Reference<comphelper::OAccessible> pRet;
93
0
    if (containsPoint(rPoint))
94
0
    {
95
0
        SolarMutexGuard aGuard;
96
0
        ensureAlive();
97
98
0
        if(!mpTextHelper)
99
0
            CreateTextHelper();
100
101
0
        pRet = mpTextHelper->GetAt(rPoint);
102
0
    }
103
104
0
    return pRet;
105
0
}
106
107
void SAL_CALL ScAccessiblePreviewCell::grabFocus()
108
0
{
109
0
    SolarMutexGuard aGuard;
110
0
    ensureAlive();
111
0
    if (getAccessibleParent().is())
112
0
    {
113
0
        uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
114
0
        if (xAccessibleComponent.is())
115
0
            xAccessibleComponent->grabFocus();
116
0
    }
117
0
}
118
119
//=====  XAccessibleContext  ==============================================
120
121
sal_Int64 SAL_CALL ScAccessiblePreviewCell::getAccessibleChildCount()
122
0
{
123
0
    SolarMutexGuard aGuard;
124
0
    ensureAlive();
125
0
    if (!mpTextHelper)
126
0
        CreateTextHelper();
127
0
    return mpTextHelper->GetChildCount();
128
0
}
129
130
uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewCell::getAccessibleChild(sal_Int64 nIndex)
131
0
{
132
0
    SolarMutexGuard aGuard;
133
0
    ensureAlive();
134
0
    if (!mpTextHelper)
135
0
        CreateTextHelper();
136
0
    return mpTextHelper->GetChild(nIndex);
137
0
}
138
139
sal_Int64 SAL_CALL ScAccessiblePreviewCell::getAccessibleStateSet()
140
0
{
141
0
    SolarMutexGuard aGuard;
142
143
0
    sal_Int64 nParentStates = 0;
144
0
    if (getAccessibleParent().is())
145
0
    {
146
0
        uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
147
0
        nParentStates = xParentContext->getAccessibleStateSet();
148
0
    }
149
0
    sal_Int64 nStateSet = 0;
150
0
    if (IsDefunc(nParentStates))
151
0
        nStateSet |= AccessibleStateType::DEFUNC;
152
0
    else
153
0
    {
154
0
        nStateSet |= AccessibleStateType::ENABLED;
155
0
        nStateSet |= AccessibleStateType::MULTI_LINE;
156
0
        if (IsOpaque())
157
0
            nStateSet |= AccessibleStateType::OPAQUE;
158
0
        if (isShowing())
159
0
            nStateSet |= AccessibleStateType::SHOWING;
160
0
        nStateSet |= AccessibleStateType::TRANSIENT;
161
0
        if (isVisible())
162
0
            nStateSet |= AccessibleStateType::VISIBLE;
163
        // MANAGES_DESCENDANTS (for paragraphs)
164
0
        nStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
165
0
    }
166
0
    return nStateSet;
167
0
}
168
169
AbsoluteScreenPixelRectangle ScAccessiblePreviewCell::GetBoundingBoxOnScreen()
170
0
{
171
0
    tools::Rectangle aCellRect;
172
0
    if (mpViewShell)
173
0
    {
174
0
        aCellRect = mpViewShell->GetLocationData().GetCellPosition(maCellAddress);
175
0
        vcl::Window* pWindow = mpViewShell->GetWindow();
176
0
        if (pWindow)
177
0
        {
178
0
            AbsoluteScreenPixelRectangle aRect = pWindow->GetWindowExtentsAbsolute();
179
0
            aCellRect.Move(aRect.Left(), aRect.Top());
180
0
        }
181
0
    }
182
0
    return AbsoluteScreenPixelRectangle(aCellRect);
183
0
}
184
185
tools::Rectangle ScAccessiblePreviewCell::GetBoundingBox()
186
0
{
187
0
    tools::Rectangle aCellRect;
188
0
    if (mpViewShell)
189
0
    {
190
0
        aCellRect = mpViewShell->GetLocationData().GetCellPosition(maCellAddress);
191
0
        uno::Reference<XAccessible> xAccParent = getAccessibleParent();
192
0
        if (xAccParent.is())
193
0
        {
194
0
            uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext();
195
0
            uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY);
196
0
            if (xAccParentComp.is())
197
0
            {
198
0
                tools::Rectangle aParentRect(
199
0
                    vcl::unohelper::ConvertToVCLRect(xAccParentComp->getBounds()));
200
0
                aCellRect.Move(-aParentRect.Left(), -aParentRect.Top());
201
0
            }
202
0
        }
203
0
    }
204
0
    return aCellRect;
205
0
}
206
207
bool ScAccessiblePreviewCell::IsDefunc(sal_Int64 nParentStates)
208
0
{
209
0
    return ScAccessibleContextBase::IsDefunc() || (mpDoc == nullptr) || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
210
0
         (nParentStates & AccessibleStateType::DEFUNC);
211
0
}
212
213
bool ScAccessiblePreviewCell::IsEditable(sal_Int64 /* nParentStates */)
214
0
{
215
0
    return false;
216
0
}
217
218
bool ScAccessiblePreviewCell::IsOpaque() const
219
0
{
220
    // test whether there is a background color
221
    //! could be moved to ScAccessibleCellBase
222
223
0
    bool bOpaque(true);
224
0
    if (mpDoc)
225
0
    {
226
0
        const SvxBrushItem& rItem = mpDoc->GetAttr(maCellAddress, ATTR_BACKGROUND);
227
0
        bOpaque = rItem.GetColor() != COL_TRANSPARENT;
228
0
    }
229
0
    return bOpaque;
230
0
}
231
232
void ScAccessiblePreviewCell::CreateTextHelper()
233
0
{
234
0
    if (mpTextHelper)
235
0
        return;
236
237
0
    mpTextHelper.reset( new ::accessibility::AccessibleTextHelper(
238
0
        std::make_unique<ScAccessibilityEditSource>(
239
0
            std::make_unique<ScAccessiblePreviewCellTextData>(
240
0
                mpViewShell, maCellAddress))) );
241
0
    mpTextHelper->SetEventSource( this );
242
243
    // paragraphs in preview are transient
244
0
    mpTextHelper->SetAdditionalChildStates( AccessibleStateType::TRANSIENT );
245
0
}
246
247
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */