LibreOffice Module sc (master) 1
AccessibleEditObject.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
20#include <sal/config.h>
21
22#include <memory>
23#include <utility>
24
26#include <AccessibleText.hxx>
27#include <editsrc.hxx>
28#include <scmod.hxx>
29#include <inputhdl.hxx>
30#include <inputwin.hxx>
31
32#include <com/sun/star/accessibility/AccessibleRole.hpp>
33#include <com/sun/star/accessibility/AccessibleStateType.hpp>
34#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
35#include <com/sun/star/sheet/XSpreadsheet.hpp>
36#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
38#include <editeng/editview.hxx>
39#include <editeng/editeng.hxx>
40#include <svx/svdmodel.hxx>
41#include <vcl/svapp.hxx>
42#include <vcl/window.hxx>
43#include <sfx2/objsh.hxx>
45
46#include <unonames.hxx>
47#include <document.hxx>
49#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
51#include <com/sun/star/accessibility/XAccessibleText.hpp>
52
53using ::com::sun::star::lang::IndexOutOfBoundsException;
54using namespace ::com::sun::star;
55using namespace ::com::sun::star::accessibility;
56
57//===== internal ============================================================
58
60 const uno::Reference<XAccessible>& rxParent,
61 EditView* pEditView, vcl::Window* pWin, const OUString& rName,
62 const OUString& rDescription, EditObjectType eObjectType)
63 : ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME)
64 , mpEditView(pEditView)
65 , mpWindow(pWin)
66 , mpTextWnd(nullptr)
67 , meObjectType(eObjectType)
68 , mbHasFocus(false)
69 , m_pScDoc(nullptr)
70{
71 InitAcc(rxParent, pEditView, rName, rDescription);
72}
73
75 : ScAccessibleContextBase(nullptr, AccessibleRole::TEXT_FRAME)
76 , mpEditView(nullptr)
77 , mpWindow(nullptr)
78 , mpTextWnd(nullptr)
79 , meObjectType(eObjectType)
80 , mbHasFocus(false)
81 , m_pScDoc(nullptr)
82{
83}
84
86 const uno::Reference<XAccessible>& rxParent,
87 EditView* pEditView,
88 const OUString& rName,
89 const OUString& rDescription)
90{
91 SetParent(rxParent);
92 mpEditView = pEditView;
93
95 SetName(rName);
96 SetDescription(rDescription);
98 {
99 const ScAccessibleDocument *pAccDoc = static_cast<ScAccessibleDocument*>(rxParent.get());
100 if (pAccDoc)
101 {
102 m_pScDoc = pAccDoc->GetDocument();
104 }
105 }
106}
107
109{
110 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
111 {
112 // increment refcount to prevent double call off dtor
113 osl_atomic_increment( &m_refCount );
114 // call dispose to inform object which have a weak reference to this object
115 dispose();
116 }
117}
118
120{
121 SolarMutexGuard aGuard;
122 mpTextHelper.reset();
123
125}
126
128{
129 mbHasFocus = false;
130 if (mpTextHelper)
131 mpTextHelper->SetFocus(false);
133}
134
136{
137 mbHasFocus = true;
139 if (mpTextHelper)
140 mpTextHelper->SetFocus();
141}
142
143//===== XInterface ==========================================================
144
145css::uno::Any SAL_CALL
146 ScAccessibleEditObject::queryInterface (const css::uno::Type & rType)
147{
148 css::uno::Any aReturn = ScAccessibleContextBase::queryInterface (rType);
149 if ( ! aReturn.hasValue())
150 aReturn = ::cppu::queryInterface (rType,
151 static_cast< css::accessibility::XAccessibleSelection* >(this)
152 );
153 return aReturn;
154}
155void SAL_CALL
157 noexcept
158{
160}
161void SAL_CALL
163 noexcept
164{
166}
167 //===== XAccessibleComponent ============================================
168
169uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint(
170 const awt::Point& rPoint )
171{
172 uno::Reference<XAccessible> xRet;
173 if (containsPoint(rPoint))
174 {
175 SolarMutexGuard aGuard;
177
179
180 xRet = mpTextHelper->GetAt(rPoint);
181 }
182
183 return xRet;
184}
185
187{
188 tools::Rectangle aScreenBounds;
189
190 if ( mpWindow )
191 {
193 {
195 {
197 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode );
198 Point aCellLoc = aScreenBounds.TopLeft();
199 tools::Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( nullptr );
200 Point aWindowLoc = aWindowRect.TopLeft();
201 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() );
202 aScreenBounds.SetPos( aPos );
203 }
204 }
205 else
206 {
207 aScreenBounds = mpWindow->GetWindowExtentsRelative( nullptr );
208 }
209 }
210
211 return aScreenBounds;
212}
213
215{
217
218 if ( mpWindow )
219 {
220 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() );
221 if ( xThis.is() )
222 {
223 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() );
224 if ( xContext.is() )
225 {
226 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
227 if ( xParent.is() )
228 {
229 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
230 if ( xParentComponent.is() )
231 {
232 Point aScreenLoc = aBounds.TopLeft();
233 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
234 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
235 aBounds.SetPos( aPos );
236 }
237 }
238 }
239 }
240 }
241
242 return aBounds;
243}
244
245 //===== XAccessibleContext ==============================================
246
247sal_Int64 SAL_CALL
249{
250 SolarMutexGuard aGuard;
253 return mpTextHelper->GetChildCount();
254}
255
256uno::Reference< XAccessible > SAL_CALL
258{
259 SolarMutexGuard aGuard;
262 return mpTextHelper->GetChild(nIndex);
263}
264
266{
267 SolarMutexGuard aGuard;
268 sal_Int64 nParentStates = 0;
269 if (getAccessibleParent().is())
270 {
271 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
272 nParentStates = xParentContext->getAccessibleStateSet();
273 }
274 sal_Int64 nStateSet = 0;
275 if (IsDefunc(nParentStates))
276 nStateSet |= AccessibleStateType::DEFUNC;
277 else
278 {
279 // all states are const, because this object exists only in one state
280 nStateSet |= AccessibleStateType::EDITABLE;
281 nStateSet |= AccessibleStateType::ENABLED;
282 nStateSet |= AccessibleStateType::SENSITIVE;
283 nStateSet |= AccessibleStateType::MULTI_LINE;
284 nStateSet |= AccessibleStateType::MULTI_SELECTABLE;
285 nStateSet |= AccessibleStateType::SHOWING;
286 nStateSet |= AccessibleStateType::VISIBLE;
287 }
288 return nStateSet;
289}
290
291OUString
293{
294// OSL_FAIL("Should never be called, because is set in the constructor.")
295 return OUString();
296}
297
298OUString
300{
301 OSL_FAIL("Should never be called, because is set in the constructor.");
302 return OUString();
303}
304
306
307void SAL_CALL
308 ScAccessibleEditObject::addAccessibleEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
309{
311
312 mpTextHelper->AddEventListener(xListener);
313
315}
316
317void SAL_CALL
318 ScAccessibleEditObject::removeAccessibleEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
319{
321
322 mpTextHelper->RemoveEventListener(xListener);
323
325}
326
327 //===== XServiceInfo ====================================================
328
330{
331 return "ScAccessibleEditObject";
332}
333
334//===== XTypeProvider =======================================================
335
336uno::Sequence<sal_Int8> SAL_CALL
338{
339 return css::uno::Sequence<sal_Int8>();
340}
341
342 //==== internal =========================================================
343
344bool ScAccessibleEditObject::IsDefunc(sal_Int64 nParentStates)
345{
347 (nParentStates & AccessibleStateType::DEFUNC);
348}
349
351{
352 return mpWindow->GetOutDev();
353}
354
356{
357 if (mpTextHelper)
358 return;
359
360 ::std::unique_ptr < ScAccessibleTextData > pAccessibleTextData;
362 {
363 pAccessibleTextData.reset
365 }
366 else
367 {
368 pAccessibleTextData.reset
370 }
371
372 std::unique_ptr<ScAccessibilityEditSource> pEditSrc =
373 std::make_unique<ScAccessibilityEditSource>(std::move(pAccessibleTextData));
374
375 mpTextHelper = std::make_unique<::accessibility::AccessibleTextHelper>(std::move(pEditSrc));
376 mpTextHelper->SetEventSource(this);
377
378 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
379 if ( pInputHdl && pInputHdl->IsEditMode() )
380 {
381 mpTextHelper->SetFocus();
382 }
383 else
384 {
385 mpTextHelper->SetFocus(mbHasFocus);
386 }
387
388 // #i54814# activate cell in edit mode
390 {
391 // do not activate cell object, if top edit line is active
392 if( pInputHdl && !pInputHdl->IsTopMode() )
393 {
394 SdrHint aHint( SdrHintKind::BeginEdit );
395 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint );
396 }
397 }
398}
399
401{
403}
404
406{
408}
409
410sal_Int32 ScAccessibleEditObject::GetFgBgColor( const OUString &strPropColor)
411{
412 SolarMutexGuard aGuard;
413 sal_Int32 nColor(0);
414 if (m_pScDoc)
415 {
417 if ( pObjSh )
418 {
419 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY );
420 if ( xSpreadDoc.is() )
421 {
422 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
423 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
424 if ( xIndex.is() )
425 {
426 uno::Any aTable = xIndex->getByIndex(m_curCellAddress.Tab());
427 uno::Reference<sheet::XSpreadsheet> xTable;
428 if (aTable>>=xTable)
429 {
430 uno::Reference<table::XCell> xCell = xTable->getCellByPosition(m_curCellAddress.Col(), m_curCellAddress.Row());
431 if (xCell.is())
432 {
433 uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY);
434 if (xCellProps.is())
435 {
436 uno::Any aAny = xCellProps->getPropertyValue(strPropColor);
437 aAny >>= nColor;
438 }
439 }
440 }
441 }
442 }
443 }
444 }
445 return nColor;
446}
447//===== XAccessibleSelection ============================================
448
450{
451}
452
454{
455 uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex );
456 uno::Reference<XAccessibleContext> xContext;
457 if( xAcc.is() )
458 xContext = xAcc->getAccessibleContext();
459 if( xContext.is() )
460 {
461 if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
462 {
463 uno::Reference< css::accessibility::XAccessibleText >
464 xText(xAcc, uno::UNO_QUERY);
465 if( xText.is() )
466 {
467 if( xText->getSelectionStart() >= 0 ) return true;
468 }
469 }
470 }
471 return false;
472}
473
475{
476}
477
479{
480}
481
483{
484 sal_Int64 nCount = 0;
485 sal_Int64 TotalCount = getAccessibleChildCount();
486 for( sal_Int64 i = 0; i < TotalCount; i++ )
488 return nCount;
489}
490
491uno::Reference<XAccessible> SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex )
492{
493 if ( nSelectedChildIndex < 0 || nSelectedChildIndex > getSelectedAccessibleChildCount() )
494 throw IndexOutOfBoundsException();
495
496 for (sal_Int64 i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ )
498 {
499 if( i2 == nSelectedChildIndex )
500 return getAccessibleChild( i1 );
501 i2++;
502 }
503 return uno::Reference<XAccessible>();
504}
505
507{
508}
509
510uno::Reference< XAccessibleRelationSet > ScAccessibleEditObject::getAccessibleRelationSet( )
511{
512 SolarMutexGuard aGuard;
513 vcl::Window* pWindow = mpWindow;
515 if ( pWindow )
516 {
517 vcl::Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
518 if ( pLabeledBy && pLabeledBy != pWindow )
519 {
520 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabeledBy->GetAccessible() };
521 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) );
522 }
523 vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
524 if ( pMemberOf && pMemberOf != pWindow )
525 {
526 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pMemberOf->GetAccessible() };
527 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) );
528 }
529 return rRelationSet;
530 }
531 return uno::Reference< XAccessibleRelationSet >();
532}
533
535{
536 tools::Rectangle aScreenBounds;
537
539 {
542 }
543
544 return aScreenBounds;
545}
546
548{
550
551 uno::Reference< XAccessibleContext > xContext(const_cast<ScAccessibleEditControlObject*>(this)->getAccessibleContext());
552 if ( xContext.is() )
553 {
554 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
555 if ( xParent.is() )
556 {
557 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
558 if ( xParentComponent.is() )
559 {
560 Point aScreenLoc = aBounds.TopLeft();
561 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
562 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
563 aBounds.SetPos( aPos );
564 }
565 }
566 }
567
568 return aBounds;
569}
570
572{
574 m_pController = nullptr;
575}
576
577uno::Reference< XAccessibleRelationSet > ScAccessibleEditControlObject::getAccessibleRelationSet()
578{
579 SolarMutexGuard aGuard;
581 return uno::Reference< XAccessibleRelationSet >();
583}
584
586{
588 return nullptr;
590}
591
594{
595 // tdf#141769 set this early so its always available, even before the on-demand
596 // editview is created
597 mpTextWnd = pTextWnd;
598}
599
600/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
MapMode const & GetRefMapMode() const
EditEngine * GetEditEngine() const
const tools::Rectangle & GetOutputArea() const
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================
virtual void SAL_CALL disposing() override
void SetDescription(const OUString &rDesc)
Use this method to set initial Description without notification.
virtual void SAL_CALL addAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
===== XAccessibleEventBroadcaster =====================================
void CommitFocusLost() const
Calls all FocusListener to tell they that the focus is lost.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
void CommitFocusGained() const
Calls all FocusListener to tell they that the focus is gained.
virtual void SAL_CALL removeAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
void SetName(const OUString &rName)
Use this method to set initial Name without notification.
virtual void SAL_CALL release() noexcept override
virtual void SAL_CALL acquire() noexcept override
void SetParent(const css::uno::Reference< css::accessibility::XAccessible > &rParent)
ScAddress GetCurCellAddress() const
ScDocument * GetDocument() const
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 disposing() override
weld::CustomWidgetController * m_pController
virtual OutputDevice * GetOutputDeviceForView() override
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
Return NULL to indicate that an empty relation set.
ScAccessibleEditLineObject(ScTextWnd *pTextWnd)
@descr This base class provides an implementation of the AccessibleCell service.
std::unique_ptr< accessibility::AccessibleTextHelper > mpTextHelper
virtual void SAL_CALL deselectAccessibleChild(sal_Int64 nSelectedChildIndex) override
virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
Return the set of current states.
virtual OutputDevice * GetOutputDeviceForView()
virtual void SAL_CALL selectAllAccessibleChildren() override
virtual tools::Rectangle GetBoundingBox() const override
Return the object's current bounding box relative to the parent object.
VclPtr< vcl::Window > mpWindow
virtual void SAL_CALL addAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
===== XAccessibleEventBroadcaster =====================================
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int64 nIndex) override
Return the specified child or NULL if index is invalid.
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ====================================================
virtual void SAL_CALL removeAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
virtual void SAL_CALL disposing() override
virtual void SAL_CALL selectAccessibleChild(sal_Int64 nChildIndex) override
virtual sal_Int32 SAL_CALL getBackground() override
ScAccessibleEditObject(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, EditView *pEditView, vcl::Window *pWin, const OUString &rName, const OUString &rDescription, EditObjectType eObjectType)
void InitAcc(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, EditView *pEditView, const OUString &rName, const OUString &rDescription)
virtual sal_Int32 SAL_CALL getForeground() override
===== XAccessibleComponent ============================================
sal_Int32 GetFgBgColor(const OUString &strPropColor)
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(sal_Int64 nSelectedChildIndex) override
virtual tools::Rectangle GetBoundingBoxOnScreen() const override
Return the object's current bounding box relative to the desktop.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
virtual OUString createAccessibleDescription() override
Return this object's description.
virtual sal_Int64 SAL_CALL getSelectedAccessibleChildCount() override
virtual sal_Bool SAL_CALL isAccessibleChildSelected(sal_Int64 nChildIndex) override
virtual OUString createAccessibleName() override
Return the object's current name.
virtual void SAL_CALL acquire() noexcept override
virtual ~ScAccessibleEditObject() override
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
===== XTypeProvider ===================================================
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
Return NULL to indicate that an empty relation set.
virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
===== XAccessibleContext ==============================================
virtual void SAL_CALL clearAccessibleSelection() override
virtual void SAL_CALL release() noexcept override
SCTAB Tab() const
Definition: address.hxx:283
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1081
bool IsTopMode() const
Definition: inputhdl.hxx:189
bool IsEditMode() const
Definition: inputhdl.hxx:187
css::uno::Reference< css::frame::XModel3 > GetModel() const
constexpr Point TopLeft() const
void SetPos(const Point &rPoint)
vcl::Window * GetAccessibleRelationLabeledBy() const
css::uno::Reference< css::accessibility::XAccessible > GetAccessible(bool bCreate=true)
vcl::Window * GetAccessibleRelationMemberOf() const
weld::DrawingArea * GetDrawingArea() const
Size const & GetOutputSizePixel() const
virtual OutputDevice & get_ref_device()=0
virtual a11yrelationset get_accessible_relation_set()=0
virtual Point get_accessible_location_on_screen()=0
int nCount
ULONG m_refCount
sal_Int32 nIndex
int i
void dispose()
#define SC_MOD()
Definition: scmod.hxx:249
unsigned char sal_Bool
#define SC_UNONAME_CCOLOR
Definition: unonames.hxx:52
#define SC_UNONAME_CELLBACK
Definition: unonames.hxx:99
VclPtr< vcl::Window > mpWindow