LibreOffice Module sc (master) 1
AccessiblePageHeader.cxx
Go to the documentation of this file.
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
22#include <prevwsh.hxx>
23#include <prevloc.hxx>
24#include <document.hxx>
25#include <stlpool.hxx>
26#include <scitems.hxx>
27#include <attrib.hxx>
28#include <scresid.hxx>
29#include <strings.hrc>
30#include <strings.hxx>
31
32#include <com/sun/star/accessibility/AccessibleRole.hpp>
33#include <com/sun/star/accessibility/AccessibleStateType.hpp>
34#include <com/sun/star/accessibility/AccessibleEventId.hpp>
35#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
37
38#include <vcl/window.hxx>
39#include <svl/hint.hxx>
40#include <svl/itemset.hxx>
41#include <vcl/svapp.hxx>
43#include <svl/style.hxx>
44#include <editeng/editobj.hxx>
45
46using namespace ::com::sun::star;
47using namespace ::com::sun::star::accessibility;
48
50
51ScAccessiblePageHeader::ScAccessiblePageHeader( const css::uno::Reference<css::accessibility::XAccessible>& rxParent,
52 ScPreviewShell* pViewShell, bool bHeader, sal_Int32 nIndex ) :
53ScAccessibleContextBase( rxParent, bHeader ? AccessibleRole::HEADER : AccessibleRole::FOOTER ),
54 mpViewShell( pViewShell ),
55 mnIndex( nIndex ),
56 mbHeader( bHeader ),
58 mnChildCount(-1)
59{
60 if (mpViewShell)
62}
63
65{
66 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
67 {
68 // increment refcount to prevent double call off dtor
69 osl_atomic_increment( &m_refCount );
70 dispose();
71 }
72}
73
75{
76 SolarMutexGuard aGuard;
77 if (mpViewShell)
78 {
80 mpViewShell = nullptr;
81 }
82 for (auto & i : maAreas)
83 {
84 if (i.is())
85 {
86 i->dispose();
87 i.clear();
88 }
89 }
90
92}
93
94//===== SfxListener =====================================================
95
97{
98 // only notify if child exist, otherwise it is not necessary
99 if (rHint.GetId() == SfxHintId::ScDataChanged)
100 {
101 std::vector<rtl::Reference<ScAccessiblePageHeaderArea>> aOldAreas(maAreas);
102 mnChildCount = -1;
104 for (sal_uInt8 i = 0; i < MAX_AREAS; ++i)
105 {
106 if ((aOldAreas[i].is() && maAreas[i].is() && !ScGlobal::EETextObjEqual(aOldAreas[i]->GetEditTextObject(), maAreas[i]->GetEditTextObject())) ||
107 (aOldAreas[i].is() && !maAreas[i].is()) || (!aOldAreas[i].is() && maAreas[i].is()))
108 {
109 if (aOldAreas[i].is() && aOldAreas[i]->GetEditTextObject())
110 {
111 AccessibleEventObject aEvent;
112 aEvent.EventId = AccessibleEventId::CHILD;
113 aEvent.Source = uno::Reference< XAccessibleContext >(this);
114 aEvent.OldValue <<= uno::Reference<XAccessible>(aOldAreas[i]);
115
116 CommitChange(aEvent); // child gone - event
117 aOldAreas[i]->dispose();
118 }
119 if (maAreas[i].is() && maAreas[i]->GetEditTextObject())
120 {
121 AccessibleEventObject aEvent;
122 aEvent.EventId = AccessibleEventId::CHILD;
123 aEvent.Source = uno::Reference< XAccessibleContext >(this);
124 aEvent.NewValue <<= uno::Reference<XAccessible>(maAreas[i]);
125
126 CommitChange(aEvent); // new child - event
127 }
128 }
129 }
130 }
131 else if (rHint.GetId() == SfxHintId::ScAccVisAreaChanged)
132 {
133 AccessibleEventObject aEvent;
134 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
135 aEvent.Source = uno::Reference< XAccessibleContext >(this);
137 }
138
140}
141
142//===== XAccessibleComponent ============================================
143
144uno::Reference< XAccessible > SAL_CALL ScAccessiblePageHeader::getAccessibleAtPoint( const awt::Point& aPoint )
145{
146 uno::Reference<XAccessible> xRet;
147
148 if (containsPoint(aPoint))
149 {
150 SolarMutexGuard aGuard;
152
153 sal_Int32 nCount(getAccessibleChildCount()); // fill the areas
154
155 if (nCount)
156 {
157 // return the first with content, because they have all the same Bounding Box
158 sal_uInt8 i(0);
159 while(!xRet.is() && i < MAX_AREAS)
160 {
161 if (maAreas[i].is())
162 xRet = maAreas[i].get();
163 else
164 ++i;
165 }
166 }
167 }
168
169 return xRet;
170}
171
173{
174 SolarMutexGuard aGuard;
176 if (getAccessibleParent().is())
177 {
178 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
179 if (xAccessibleComponent.is())
180 xAccessibleComponent->grabFocus();
181 }
182}
183
184//===== XAccessibleContext ==============================================
185
187{
188 SolarMutexGuard aGuard;
190
191 if((mnChildCount < 0) && mpViewShell)
192 {
193 mnChildCount = 0;
195 // find out how many regions (left,center, right) are with content
196
197 SfxStyleSheetBase* pStyle = rDoc.GetStyleSheetPool()->Find(rDoc.GetPageStyle(mpViewShell->GetLocationData().GetPrintTab()), SfxStyleFamily::Page);
198 if (pStyle)
199 {
200 sal_uInt16 nPageWhichId(0);
201 if (mbHeader)
203 else
205
206 const ScPageHFItem& rPageItem = static_cast<const ScPageHFItem&>(pStyle->GetItemSet().Get(nPageWhichId));
207 AddChild(rPageItem.GetLeftArea(), 0, SvxAdjust::Left);
208 AddChild(rPageItem.GetCenterArea(), 1, SvxAdjust::Center);
209 AddChild(rPageItem.GetRightArea(), 2, SvxAdjust::Right);
210 }
211 }
212
213 return mnChildCount;
214}
215
216uno::Reference< XAccessible > SAL_CALL ScAccessiblePageHeader::getAccessibleChild( sal_Int32 nIndex )
217{
218 SolarMutexGuard aGuard;
220
221 uno::Reference<XAccessible> xRet;
222
223 if(mnChildCount < 0)
225
226 if (nIndex >= 0)
227 for (const auto& rxArea : maAreas)
228 {
229 if (rxArea.is())
230 {
231 if (nIndex == 0)
232 {
233 xRet = rxArea.get();
234 break;
235 }
236 else
237 --nIndex;
238 }
239 }
240
241 if ( !xRet.is() )
242 throw lang::IndexOutOfBoundsException();
243
244 return xRet;
245}
246
248{
249 return mnIndex;
250}
251
252uno::Reference< XAccessibleStateSet > SAL_CALL ScAccessiblePageHeader::getAccessibleStateSet()
253{
254 SolarMutexGuard aGuard;
255 uno::Reference<XAccessibleStateSet> xParentStates;
256 if (getAccessibleParent().is())
257 {
258 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
259 xParentStates = xParentContext->getAccessibleStateSet();
260 }
262 if (IsDefunc(xParentStates))
263 pStateSet->AddState(AccessibleStateType::DEFUNC);
264 else
265 {
266 pStateSet->AddState(AccessibleStateType::ENABLED);
267 pStateSet->AddState(AccessibleStateType::OPAQUE);
268 if (isShowing())
269 pStateSet->AddState(AccessibleStateType::SHOWING);
270 if (isVisible())
271 pStateSet->AddState(AccessibleStateType::VISIBLE);
272 }
273 return pStateSet;
274}
275
276//===== XServiceInfo ====================================================
277
279{
280 return "ScAccessiblePageHeader";
281}
282
283uno::Sequence<OUString> SAL_CALL ScAccessiblePageHeader::getSupportedServiceNames()
284{
285 const css::uno::Sequence<OUString> vals { "com.sun.star.text.AccessibleHeaderFooterView" };
287}
288
289//==== internal =========================================================
290
292{
293 OUString sDesc(mbHeader ? OUString(STR_ACC_HEADER_DESCR) : OUString(STR_ACC_FOOTER_DESCR));
294 return sDesc.replaceFirst("%1", ScResId(SCSTR_UNKNOWN));
295}
296
298{
299 OUString sName(ScResId(mbHeader ? STR_ACC_HEADER_NAME : STR_ACC_FOOTER_NAME));
300 return sName.replaceFirst("%1", ScResId(SCSTR_UNKNOWN));
301}
302
304{
305 tools::Rectangle aCellRect(GetBoundingBox());
306 if (mpViewShell)
307 {
308 vcl::Window* pWindow = mpViewShell->GetWindow();
309 if (pWindow)
310 {
311 tools::Rectangle aRect = pWindow->GetWindowExtentsRelative(nullptr);
312 aCellRect.Move(aRect.Left(), aRect.Top());
313 }
314 }
315 return aCellRect;
316}
317
319{
320 tools::Rectangle aRect;
321 if (mpViewShell)
322 {
324 if ( mbHeader )
325 rData.GetHeaderPosition( aRect );
326 else
327 rData.GetFooterPosition( aRect );
328
329 // the Rectangle could contain negative coordinates so it should be clipped
330 tools::Rectangle aClipRect(Point(0, 0), aRect.GetSize());
331 vcl::Window* pWindow = mpViewShell->GetWindow();
332 if (pWindow)
333 aClipRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
334 aRect = aClipRect.GetIntersection(aRect);
335 }
336 if (aRect.IsEmpty())
337 aRect.SetSize(Size(-1, -1));
338
339 return aRect;
340}
341
342bool ScAccessiblePageHeader::IsDefunc( const uno::Reference<XAccessibleStateSet>& rxParentStates )
343{
344 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
345 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
346}
347
348void ScAccessiblePageHeader::AddChild(const EditTextObject* pArea, sal_uInt32 nIndex, SvxAdjust eAdjust)
349{
350 if (pArea && (!pArea->GetText(0).isEmpty() || (pArea->GetParagraphCount() > 1)))
351 {
352 if (maAreas[nIndex].is())
353 {
354 if (!ScGlobal::EETextObjEqual(maAreas[nIndex]->GetEditTextObject(), pArea))
355 {
356 maAreas[nIndex] = new ScAccessiblePageHeaderArea(this, mpViewShell, pArea, eAdjust);
357 }
358 }
359 else
360 {
361 maAreas[nIndex] = new ScAccessiblePageHeaderArea(this, mpViewShell, pArea, eAdjust);
362 }
363 ++mnChildCount;
364 }
365 else
366 {
367 maAreas[nIndex].clear();
368 }
369}
370
371/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_uInt8 MAX_AREAS
int mnIndex
AnyEventRef aEvent
virtual sal_Int32 GetParagraphCount() const=0
virtual OUString GetText(sal_Int32 nPara) const=0
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================
virtual void SAL_CALL disposing() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
void CommitChange(const css::accessibility::AccessibleEventObject &rEvent) const
Calls all Listener to tell they the change.
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
===== XAccessibleContext ==============================================
void AddChild(const EditTextObject *pArea, sal_uInt32 nIndex, SvxAdjust eAdjust)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ====================================================
ScAccessiblePageHeader(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, ScPreviewShell *pViewShell, bool bHeader, sal_Int32 nIndex)
virtual void SAL_CALL disposing() override
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override
Return the set of current states.
virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override
Return this objects index among the parents children.
std::vector< rtl::Reference< ScAccessiblePageHeaderArea > > maAreas
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 i) override
Return the specified child or NULL if index is invalid.
virtual tools::Rectangle GetBoundingBox() const override
Return the object's current bounding box relative to the parent object.
virtual tools::Rectangle GetBoundingBoxOnScreen() const override
Return the object's current bounding box relative to the desktop.
virtual void SAL_CALL grabFocus() override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &aPoint) override
virtual OUString createAccessibleDescription() override
Return this object's description.
virtual ~ScAccessiblePageHeader() override
virtual OUString createAccessibleName() override
Return the object's current name.
SC_DLLPUBLIC OUString GetPageStyle(SCTAB nTab) const
Definition: document.cxx:6295
SC_DLLPUBLIC ScStyleSheetPool * GetStyleSheetPool() const
Definition: document.cxx:6168
static bool EETextObjEqual(const EditTextObject *pObj1, const EditTextObject *pObj2)
Definition: global.cxx:758
const EditTextObject * GetCenterArea() const
Definition: attrib.hxx:186
const EditTextObject * GetLeftArea() const
Definition: attrib.hxx:185
const EditTextObject * GetRightArea() const
Definition: attrib.hxx:187
bool IsFooterLeft() const
Definition: prevloc.cxx:376
bool IsHeaderLeft() const
Definition: prevloc.cxx:362
SCTAB GetPrintTab() const
Definition: prevloc.hxx:117
const ScPreviewLocationData & GetLocationData()
Definition: prevwsh.cxx:1159
void AddAccessibilityObject(SfxListener &rObject)
Definition: prevwsh.cxx:1130
ScDocument & GetDocument()
Definition: prevwsh.cxx:1164
void RemoveAccessibilityObject(SfxListener &rObject)
Definition: prevwsh.cxx:1138
SfxHintId GetId() const
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
virtual SfxStyleSheetBase * Find(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All) const
virtual SfxItemSet & GetItemSet()
vcl::Window * GetWindow() const
tools::Rectangle GetIntersection(const tools::Rectangle &rRect) const
constexpr tools::Long Top() const
void SetSize(const Size &)
constexpr Size GetSize() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Left() const
constexpr bool IsEmpty() const
vcl::Window * GetAccessibleParentWindow() const
tools::Rectangle GetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
int nCount
ULONG m_refCount
sal_Int32 nIndex
const char * sName
const ContentProperties & rData
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
Reference
int i
void dispose()
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
constexpr TypedWhichId< ScPageHFItem > ATTR_PAGE_FOOTERLEFT(179)
constexpr TypedWhichId< ScPageHFItem > ATTR_PAGE_HEADERLEFT(178)
constexpr TypedWhichId< ScPageHFItem > ATTR_PAGE_FOOTERRIGHT(181)
constexpr TypedWhichId< ScPageHFItem > ATTR_PAGE_HEADERRIGHT(180)
constexpr OUStringLiteral STR_ACC_HEADER_DESCR
Definition: strings.hxx:25
constexpr OUStringLiteral STR_ACC_FOOTER_DESCR
Definition: strings.hxx:26
SvxAdjust
unsigned char sal_uInt8