nss: upgrade to release 3.73
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleEditObject.cxx
blobea6787478abd0405330988261356ab07c436ccf8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <memory>
23 #include <utility>
25 #include <AccessibleEditObject.hxx>
26 #include <AccessibleText.hxx>
27 #include <editsrc.hxx>
28 #include <scmod.hxx>
29 #include <inputhdl.hxx>
30 #include <inputwin.hxx>
32 #include <unotools/accessiblestatesethelper.hxx>
33 #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
35 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
36 #include <com/sun/star/sheet/XSpreadsheet.hpp>
37 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
38 #include <svx/AccessibleTextHelper.hxx>
39 #include <editeng/editview.hxx>
40 #include <editeng/editeng.hxx>
41 #include <svx/svdmodel.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/window.hxx>
44 #include <sfx2/objsh.hxx>
45 #include <cppuhelper/queryinterface.hxx>
47 #include <unonames.hxx>
48 #include <document.hxx>
49 #include <AccessibleDocument.hxx>
50 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
51 #include <unotools/accessiblerelationsethelper.hxx>
52 #include <com/sun/star/accessibility/XAccessibleText.hpp>
54 using ::com::sun::star::lang::IndexOutOfBoundsException;
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::accessibility;
58 //===== internal ============================================================
60 ScAccessibleEditObject::ScAccessibleEditObject(
61 const uno::Reference<XAccessible>& rxParent,
62 EditView* pEditView, vcl::Window* pWin, const OUString& rName,
63 const OUString& rDescription, EditObjectType eObjectType)
64 : ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME)
65 , mpEditView(pEditView)
66 , mpWindow(pWin)
67 , mpTextWnd(nullptr)
68 , meObjectType(eObjectType)
69 , mbHasFocus(false)
70 , m_pScDoc(nullptr)
72 InitAcc(rxParent, pEditView, pWin, nullptr, rName, rDescription);
75 ScAccessibleEditObject::ScAccessibleEditObject(EditObjectType eObjectType)
76 : ScAccessibleContextBase(nullptr, AccessibleRole::TEXT_FRAME)
77 , mpEditView(nullptr)
78 , mpWindow(nullptr)
79 , mpTextWnd(nullptr)
80 , meObjectType(eObjectType)
81 , mbHasFocus(false)
82 , m_pScDoc(nullptr)
86 void ScAccessibleEditObject::InitAcc(
87 const uno::Reference<XAccessible>& rxParent,
88 EditView* pEditView, vcl::Window* pWin,
89 ScTextWnd* pTxtWnd, const OUString& rName,
90 const OUString& rDescription)
92 SetParent(rxParent);
93 mpEditView = pEditView;
94 mpWindow = pWin;
95 mpTextWnd = pTxtWnd;
97 CreateTextHelper();
98 SetName(rName);
99 SetDescription(rDescription);
100 if( meObjectType == CellInEditMode)
102 const ScAccessibleDocument *pAccDoc = static_cast<ScAccessibleDocument*>(rxParent.get());
103 if (pAccDoc)
105 m_pScDoc = pAccDoc->GetDocument();
106 m_curCellAddress =pAccDoc->GetCurCellAddress();
111 ScAccessibleEditObject::~ScAccessibleEditObject()
113 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
115 // increment refcount to prevent double call off dtor
116 osl_atomic_increment( &m_refCount );
117 // call dispose to inform object which have a weak reference to this object
118 dispose();
122 void SAL_CALL ScAccessibleEditObject::disposing()
124 SolarMutexGuard aGuard;
125 mpTextHelper.reset();
127 ScAccessibleContextBase::disposing();
130 void ScAccessibleEditObject::LostFocus()
132 mbHasFocus = false;
133 if (mpTextHelper)
134 mpTextHelper->SetFocus(false);
135 CommitFocusLost();
138 void ScAccessibleEditObject::GotFocus()
140 mbHasFocus = true;
141 CommitFocusGained();
142 if (mpTextHelper)
143 mpTextHelper->SetFocus();
146 //===== XInterface ==========================================================
148 css::uno::Any SAL_CALL
149 ScAccessibleEditObject::queryInterface (const css::uno::Type & rType)
151 css::uno::Any aReturn = ScAccessibleContextBase::queryInterface (rType);
152 if ( ! aReturn.hasValue())
153 aReturn = ::cppu::queryInterface (rType,
154 static_cast< css::accessibility::XAccessibleSelection* >(this)
156 return aReturn;
158 void SAL_CALL
159 ScAccessibleEditObject::acquire()
160 throw ()
162 ScAccessibleContextBase::acquire ();
164 void SAL_CALL
165 ScAccessibleEditObject::release()
166 throw ()
168 ScAccessibleContextBase::release ();
170 //===== XAccessibleComponent ============================================
172 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint(
173 const awt::Point& rPoint )
175 uno::Reference<XAccessible> xRet;
176 if (containsPoint(rPoint))
178 SolarMutexGuard aGuard;
179 IsObjectValid();
181 CreateTextHelper();
183 xRet = mpTextHelper->GetAt(rPoint);
186 return xRet;
189 tools::Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen() const
191 tools::Rectangle aScreenBounds;
193 if ( mpWindow )
195 if ( meObjectType == CellInEditMode )
197 if ( mpEditView && mpEditView->GetEditEngine() )
199 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() );
200 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode );
201 Point aCellLoc = aScreenBounds.TopLeft();
202 tools::Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( nullptr );
203 Point aWindowLoc = aWindowRect.TopLeft();
204 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() );
205 aScreenBounds.SetPos( aPos );
208 else
210 aScreenBounds = mpWindow->GetWindowExtentsRelative( nullptr );
214 return aScreenBounds;
217 tools::Rectangle ScAccessibleEditObject::GetBoundingBox() const
219 tools::Rectangle aBounds( GetBoundingBoxOnScreen() );
221 if ( mpWindow )
223 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() );
224 if ( xThis.is() )
226 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() );
227 if ( xContext.is() )
229 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
230 if ( xParent.is() )
232 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
233 if ( xParentComponent.is() )
235 Point aScreenLoc = aBounds.TopLeft();
236 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
237 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
238 aBounds.SetPos( aPos );
245 return aBounds;
248 //===== XAccessibleContext ==============================================
250 sal_Int32 SAL_CALL
251 ScAccessibleEditObject::getAccessibleChildCount()
253 SolarMutexGuard aGuard;
254 IsObjectValid();
255 CreateTextHelper();
256 return mpTextHelper->GetChildCount();
259 uno::Reference< XAccessible > SAL_CALL
260 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex)
262 SolarMutexGuard aGuard;
263 IsObjectValid();
264 CreateTextHelper();
265 return mpTextHelper->GetChild(nIndex);
268 uno::Reference<XAccessibleStateSet> SAL_CALL
269 ScAccessibleEditObject::getAccessibleStateSet()
271 SolarMutexGuard aGuard;
272 uno::Reference<XAccessibleStateSet> xParentStates;
273 if (getAccessibleParent().is())
275 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
276 xParentStates = xParentContext->getAccessibleStateSet();
278 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
279 if (IsDefunc(xParentStates))
280 pStateSet->AddState(AccessibleStateType::DEFUNC);
281 else
283 // all states are const, because this object exists only in one state
284 pStateSet->AddState(AccessibleStateType::EDITABLE);
285 pStateSet->AddState(AccessibleStateType::ENABLED);
286 pStateSet->AddState(AccessibleStateType::SENSITIVE);
287 pStateSet->AddState(AccessibleStateType::MULTI_LINE);
288 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
289 pStateSet->AddState(AccessibleStateType::SHOWING);
290 pStateSet->AddState(AccessibleStateType::VISIBLE);
292 return pStateSet;
295 OUString
296 ScAccessibleEditObject::createAccessibleDescription()
298 // OSL_FAIL("Should never be called, because is set in the constructor.")
299 return OUString();
302 OUString
303 ScAccessibleEditObject::createAccessibleName()
305 OSL_FAIL("Should never be called, because is set in the constructor.");
306 return OUString();
309 ///===== XAccessibleEventBroadcaster =====================================
311 void SAL_CALL
312 ScAccessibleEditObject::addAccessibleEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
314 CreateTextHelper();
316 mpTextHelper->AddEventListener(xListener);
318 ScAccessibleContextBase::addAccessibleEventListener(xListener);
321 void SAL_CALL
322 ScAccessibleEditObject::removeAccessibleEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
324 CreateTextHelper();
326 mpTextHelper->RemoveEventListener(xListener);
328 ScAccessibleContextBase::removeAccessibleEventListener(xListener);
331 //===== XServiceInfo ====================================================
333 OUString SAL_CALL ScAccessibleEditObject::getImplementationName()
335 return "ScAccessibleEditObject";
338 //===== XTypeProvider =======================================================
340 uno::Sequence<sal_Int8> SAL_CALL
341 ScAccessibleEditObject::getImplementationId()
343 return css::uno::Sequence<sal_Int8>();
346 //==== internal =========================================================
348 bool ScAccessibleEditObject::IsDefunc(
349 const uno::Reference<XAccessibleStateSet>& rxParentStates)
351 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
352 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
355 OutputDevice* ScAccessibleEditObject::GetOutputDeviceForView()
357 return mpWindow;
360 void ScAccessibleEditObject::CreateTextHelper()
362 if (mpTextHelper)
363 return;
365 ::std::unique_ptr < ScAccessibleTextData > pAccessibleTextData;
366 if (meObjectType == CellInEditMode || meObjectType == EditControl)
368 pAccessibleTextData.reset
369 (new ScAccessibleEditObjectTextData(mpEditView, GetOutputDeviceForView()));
371 else
373 pAccessibleTextData.reset
374 (new ScAccessibleEditLineTextData(nullptr, GetOutputDeviceForView(), mpTextWnd));
377 std::unique_ptr<ScAccessibilityEditSource> pEditSrc =
378 std::make_unique<ScAccessibilityEditSource>(std::move(pAccessibleTextData));
380 mpTextHelper = std::make_unique<::accessibility::AccessibleTextHelper>(std::move(pEditSrc));
381 mpTextHelper->SetEventSource(this);
383 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
384 if ( pInputHdl && pInputHdl->IsEditMode() )
386 mpTextHelper->SetFocus();
388 else
390 mpTextHelper->SetFocus(mbHasFocus);
393 // #i54814# activate cell in edit mode
394 if( meObjectType == CellInEditMode )
396 // do not activate cell object, if top edit line is active
397 if( pInputHdl && !pInputHdl->IsTopMode() )
399 SdrHint aHint( SdrHintKind::BeginEdit );
400 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint );
405 sal_Int32 SAL_CALL ScAccessibleEditObject::getForeground( )
407 return GetFgBgColor(SC_UNONAME_CCOLOR);
410 sal_Int32 SAL_CALL ScAccessibleEditObject::getBackground( )
412 return GetFgBgColor(SC_UNONAME_CELLBACK);
415 sal_Int32 ScAccessibleEditObject::GetFgBgColor( const OUString &strPropColor)
417 SolarMutexGuard aGuard;
418 sal_Int32 nColor(0);
419 if (m_pScDoc)
421 SfxObjectShell* pObjSh = m_pScDoc->GetDocumentShell();
422 if ( pObjSh )
424 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY );
425 if ( xSpreadDoc.is() )
427 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
428 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
429 if ( xIndex.is() )
431 uno::Any aTable = xIndex->getByIndex(m_curCellAddress.Tab());
432 uno::Reference<sheet::XSpreadsheet> xTable;
433 if (aTable>>=xTable)
435 uno::Reference<table::XCell> xCell = xTable->getCellByPosition(m_curCellAddress.Col(), m_curCellAddress.Row());
436 if (xCell.is())
438 uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY);
439 if (xCellProps.is())
441 uno::Any aAny = xCellProps->getPropertyValue(strPropColor);
442 aAny >>= nColor;
450 return nColor;
452 //===== XAccessibleSelection ============================================
454 void SAL_CALL ScAccessibleEditObject::selectAccessibleChild( sal_Int32 )
458 sal_Bool SAL_CALL ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex )
460 uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex );
461 uno::Reference<XAccessibleContext> xContext;
462 if( xAcc.is() )
463 xContext = xAcc->getAccessibleContext();
464 if( xContext.is() )
466 if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
468 uno::Reference< css::accessibility::XAccessibleText >
469 xText(xAcc, uno::UNO_QUERY);
470 if( xText.is() )
472 if( xText->getSelectionStart() >= 0 ) return true;
476 return false;
479 void SAL_CALL ScAccessibleEditObject::clearAccessibleSelection( )
483 void SAL_CALL ScAccessibleEditObject::selectAllAccessibleChildren( )
487 sal_Int32 SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChildCount()
489 sal_Int32 nCount = 0;
490 sal_Int32 TotalCount = getAccessibleChildCount();
491 for( sal_Int32 i = 0; i < TotalCount; i++ )
492 if( isAccessibleChildSelected(i) ) nCount++;
493 return nCount;
496 uno::Reference<XAccessible> SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
498 if ( nSelectedChildIndex > getSelectedAccessibleChildCount() )
499 throw IndexOutOfBoundsException();
500 sal_Int32 i1, i2;
501 for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ )
502 if( isAccessibleChildSelected(i1) )
504 if( i2 == nSelectedChildIndex )
505 return getAccessibleChild( i1 );
506 i2++;
508 return uno::Reference<XAccessible>();
511 void SAL_CALL ScAccessibleEditObject::deselectAccessibleChild(
512 sal_Int32 )
516 uno::Reference< XAccessibleRelationSet > ScAccessibleEditObject::getAccessibleRelationSet( )
518 SolarMutexGuard aGuard;
519 vcl::Window* pWindow = mpWindow;
520 utl::AccessibleRelationSetHelper* rRelationSet = new utl::AccessibleRelationSetHelper;
521 uno::Reference< XAccessibleRelationSet > rSet = rRelationSet;
522 if ( pWindow )
524 vcl::Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
525 if ( pLabeledBy && pLabeledBy != pWindow )
527 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabeledBy->GetAccessible() };
528 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) );
530 vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
531 if ( pMemberOf && pMemberOf != pWindow )
533 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pMemberOf->GetAccessible() };
534 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) );
536 return rSet;
538 return uno::Reference< XAccessibleRelationSet >();
541 tools::Rectangle ScAccessibleEditControlObject::GetBoundingBoxOnScreen() const
543 tools::Rectangle aScreenBounds;
545 if (m_pController && m_pController->GetDrawingArea())
547 aScreenBounds = tools::Rectangle(m_pController->GetDrawingArea()->get_accessible_location(),
548 m_pController->GetOutputSizePixel());
551 return aScreenBounds;
554 tools::Rectangle ScAccessibleEditControlObject::GetBoundingBox() const
556 tools::Rectangle aBounds( GetBoundingBoxOnScreen() );
558 uno::Reference< XAccessibleContext > xContext(const_cast<ScAccessibleEditControlObject*>(this)->getAccessibleContext());
559 if ( xContext.is() )
561 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
562 if ( xParent.is() )
564 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
565 if ( xParentComponent.is() )
567 Point aScreenLoc = aBounds.TopLeft();
568 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
569 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
570 aBounds.SetPos( aPos );
575 return aBounds;
578 void SAL_CALL ScAccessibleEditControlObject::disposing()
580 ScAccessibleEditObject::disposing();
581 m_pController = nullptr;
584 uno::Reference< XAccessibleRelationSet > ScAccessibleEditControlObject::getAccessibleRelationSet()
586 SolarMutexGuard aGuard;
587 if (!m_pController || !m_pController->GetDrawingArea())
588 return uno::Reference< XAccessibleRelationSet >();
589 return m_pController->GetDrawingArea()->get_accessible_relation_set();
592 OutputDevice* ScAccessibleEditControlObject::GetOutputDeviceForView()
594 if (!m_pController || !m_pController->GetDrawingArea())
595 return nullptr;
596 return &m_pController->GetDrawingArea()->get_ref_device();
599 ScAccessibleEditLineObject::ScAccessibleEditLineObject(ScTextWnd* pTextWnd)
600 : ScAccessibleEditControlObject(pTextWnd, ScAccessibleEditObject::EditLine)
602 // tdf#141769 set this early so its always available, even before the on-demand
603 // editview is created
604 mpTextWnd = pTextWnd;
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */