1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
25 #include "AccessibleEditObject.hxx"
26 #include "scitems.hxx"
27 #include <editeng/eeitem.hxx>
28 #include "AccessibleText.hxx"
29 #include "editsrc.hxx"
31 #include "inputhdl.hxx"
33 #include <unotools/accessiblestatesethelper.hxx>
34 #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
36 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
37 #include <com/sun/star/sheet/XSpreadsheet.hpp>
38 #include <comphelper/servicehelper.hxx>
39 #include <svx/AccessibleTextHelper.hxx>
40 #include <editeng/editview.hxx>
41 #include <editeng/editeng.hxx>
42 #include <svx/svdmodel.hxx>
43 #include <vcl/svapp.hxx>
44 #include <sfx2/objsh.hxx>
46 #include "unonames.hxx"
47 #include "document.hxx"
48 #include "AccessibleDocument.hxx"
49 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
50 #include <unotools/accessiblerelationsethelper.hxx>
51 #include <com/sun/star/accessibility/XAccessibleText.hpp>
53 using ::com::sun::star::lang::IndexOutOfBoundsException
;
54 using ::com::sun::star::uno::RuntimeException
;
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
)
65 ScAccessibleContextBase(rxParent
, AccessibleRole::TEXT_FRAME
),
67 mpEditView(pEditView
),
69 meObjectType(eObjectType
),
74 SetDescription(rDescription
);
75 if( meObjectType
== CellInEditMode
)
77 const ScAccessibleDocument
*pAccDoc
= static_cast<ScAccessibleDocument
*>(rxParent
.get());
80 m_pScDoc
= pAccDoc
->GetDocument();
81 m_curCellAddress
=pAccDoc
->GetCurCellAddress();
92 ScAccessibleEditObject::~ScAccessibleEditObject()
94 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper
.bInDispose
)
96 // increment refcount to prevent double call off dtor
97 osl_atomic_increment( &m_refCount
);
98 // call dispose to inform object which have a weak reference to this object
103 void SAL_CALL
ScAccessibleEditObject::disposing()
105 SolarMutexGuard aGuard
;
107 DELETEZ(mpTextHelper
);
109 ScAccessibleContextBase::disposing();
112 void ScAccessibleEditObject::LostFocus()
116 mpTextHelper
->SetFocus(false);
120 void ScAccessibleEditObject::GotFocus()
125 mpTextHelper
->SetFocus(true);
128 //===== XInterface ==========================================================
130 com::sun::star::uno::Any SAL_CALL
131 ScAccessibleEditObject::queryInterface (const com::sun::star::uno::Type
& rType
)
132 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
134 ::com::sun::star::uno::Any aReturn
= ScAccessibleContextBase::queryInterface (rType
);
135 if ( ! aReturn
.hasValue())
136 aReturn
= ::cppu::queryInterface (rType
,
137 static_cast< ::com::sun::star::accessibility::XAccessibleSelection
* >(this)
142 ScAccessibleEditObject::acquire()
145 ScAccessibleContextBase::acquire ();
148 ScAccessibleEditObject::release()
151 ScAccessibleContextBase::release ();
153 //===== XAccessibleComponent ============================================
155 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleEditObject::getAccessibleAtPoint(
156 const awt::Point
& rPoint
)
157 throw (uno::RuntimeException
, std::exception
)
159 uno::Reference
<XAccessible
> xRet
;
160 if (containsPoint(rPoint
))
162 SolarMutexGuard aGuard
;
168 xRet
= mpTextHelper
->GetAt(rPoint
);
174 Rectangle
ScAccessibleEditObject::GetBoundingBoxOnScreen() const
175 throw (uno::RuntimeException
, std::exception
)
177 Rectangle aScreenBounds
;
181 if ( meObjectType
== CellInEditMode
)
183 if ( mpEditView
&& mpEditView
->GetEditEngine() )
185 MapMode
aMapMode( mpEditView
->GetEditEngine()->GetRefMapMode() );
186 aScreenBounds
= mpWindow
->LogicToPixel( mpEditView
->GetOutputArea(), aMapMode
);
187 Point aCellLoc
= aScreenBounds
.TopLeft();
188 Rectangle aWindowRect
= mpWindow
->GetWindowExtentsRelative( NULL
);
189 Point aWindowLoc
= aWindowRect
.TopLeft();
190 Point
aPos( aCellLoc
.getX() + aWindowLoc
.getX(), aCellLoc
.getY() + aWindowLoc
.getY() );
191 aScreenBounds
.SetPos( aPos
);
196 aScreenBounds
= mpWindow
->GetWindowExtentsRelative( NULL
);
200 return aScreenBounds
;
203 Rectangle
ScAccessibleEditObject::GetBoundingBox() const
204 throw (uno::RuntimeException
, std::exception
)
206 Rectangle
aBounds( GetBoundingBoxOnScreen() );
210 uno::Reference
< XAccessible
> xThis( mpWindow
->GetAccessible() );
213 uno::Reference
< XAccessibleContext
> xContext( xThis
->getAccessibleContext() );
216 uno::Reference
< XAccessible
> xParent( xContext
->getAccessibleParent() );
219 uno::Reference
< XAccessibleComponent
> xParentComponent( xParent
->getAccessibleContext(), uno::UNO_QUERY
);
220 if ( xParentComponent
.is() )
222 Point aScreenLoc
= aBounds
.TopLeft();
223 awt::Point aParentScreenLoc
= xParentComponent
->getLocationOnScreen();
224 Point
aPos( aScreenLoc
.getX() - aParentScreenLoc
.X
, aScreenLoc
.getY() - aParentScreenLoc
.Y
);
225 aBounds
.SetPos( aPos
);
235 //===== XAccessibleContext ==============================================
238 ScAccessibleEditObject::getAccessibleChildCount()
239 throw (uno::RuntimeException
, std::exception
)
241 SolarMutexGuard aGuard
;
245 return mpTextHelper
->GetChildCount();
248 uno::Reference
< XAccessible
> SAL_CALL
249 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex
)
250 throw (uno::RuntimeException
,
251 lang::IndexOutOfBoundsException
, std::exception
)
253 SolarMutexGuard aGuard
;
257 return mpTextHelper
->GetChild(nIndex
);
260 uno::Reference
<XAccessibleStateSet
> SAL_CALL
261 ScAccessibleEditObject::getAccessibleStateSet()
262 throw (uno::RuntimeException
, std::exception
)
264 SolarMutexGuard aGuard
;
265 uno::Reference
<XAccessibleStateSet
> xParentStates
;
266 if (getAccessibleParent().is())
268 uno::Reference
<XAccessibleContext
> xParentContext
= getAccessibleParent()->getAccessibleContext();
269 xParentStates
= xParentContext
->getAccessibleStateSet();
271 utl::AccessibleStateSetHelper
* pStateSet
= new utl::AccessibleStateSetHelper();
272 if (IsDefunc(xParentStates
))
273 pStateSet
->AddState(AccessibleStateType::DEFUNC
);
276 // all states are const, because this object exists only in one state
277 pStateSet
->AddState(AccessibleStateType::EDITABLE
);
278 pStateSet
->AddState(AccessibleStateType::ENABLED
);
279 pStateSet
->AddState(AccessibleStateType::SENSITIVE
);
280 pStateSet
->AddState(AccessibleStateType::MULTI_LINE
);
281 pStateSet
->AddState(AccessibleStateType::MULTI_SELECTABLE
);
282 pStateSet
->AddState(AccessibleStateType::SHOWING
);
283 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
289 ScAccessibleEditObject::createAccessibleDescription()
290 throw (uno::RuntimeException
)
292 // OSL_FAIL("Should never be called, because is set in the constructor.")
297 ScAccessibleEditObject::createAccessibleName()
298 throw (uno::RuntimeException
, std::exception
)
300 OSL_FAIL("Should never be called, because is set in the constructor.");
304 ///===== XAccessibleEventBroadcaster =====================================
307 ScAccessibleEditObject::addAccessibleEventListener(const uno::Reference
<XAccessibleEventListener
>& xListener
)
308 throw (uno::RuntimeException
, std::exception
)
313 mpTextHelper
->AddEventListener(xListener
);
315 ScAccessibleContextBase::addAccessibleEventListener(xListener
);
319 ScAccessibleEditObject::removeAccessibleEventListener(const uno::Reference
<XAccessibleEventListener
>& xListener
)
320 throw (uno::RuntimeException
, std::exception
)
325 mpTextHelper
->RemoveEventListener(xListener
);
327 ScAccessibleContextBase::removeAccessibleEventListener(xListener
);
330 //===== XServiceInfo ====================================================
332 OUString SAL_CALL
ScAccessibleEditObject::getImplementationName()
333 throw (uno::RuntimeException
, std::exception
)
335 return OUString("ScAccessibleEditObject");
338 //===== XTypeProvider =======================================================
340 uno::Sequence
<sal_Int8
> SAL_CALL
341 ScAccessibleEditObject::getImplementationId()
342 throw (uno::RuntimeException
, std::exception
)
344 return css::uno::Sequence
<sal_Int8
>();
347 //==== internal =========================================================
349 bool ScAccessibleEditObject::IsDefunc(
350 const uno::Reference
<XAccessibleStateSet
>& rxParentStates
)
352 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
353 (rxParentStates
.is() && rxParentStates
->contains(AccessibleStateType::DEFUNC
));
356 void ScAccessibleEditObject::CreateTextHelper()
360 ::std::unique_ptr
< ScAccessibleTextData
> pAccessibleTextData
;
361 if (meObjectType
== CellInEditMode
|| meObjectType
== EditControl
)
363 pAccessibleTextData
.reset
364 (new ScAccessibleEditObjectTextData(mpEditView
, mpWindow
));
368 pAccessibleTextData
.reset
369 (new ScAccessibleEditLineTextData(NULL
, mpWindow
));
372 ::std::unique_ptr
< SvxEditSource
> pEditSource (new ScAccessibilityEditSource(std::move(pAccessibleTextData
)));
373 mpTextHelper
= new ::accessibility::AccessibleTextHelper(std::move(pEditSource
));
374 mpTextHelper
->SetEventSource(this);
376 const ScInputHandler
* pInputHdl
= SC_MOD()->GetInputHdl();
377 if ( pInputHdl
&& pInputHdl
->IsEditMode() )
379 mpTextHelper
->SetFocus(true);
383 mpTextHelper
->SetFocus(mbHasFocus
);
386 // #i54814# activate cell in edit mode
387 if( meObjectType
== CellInEditMode
)
389 // do not activate cell object, if top edit line is active
390 if( pInputHdl
&& !pInputHdl
->IsTopMode() )
392 SdrHint
aHint( HINT_BEGEDIT
);
393 mpTextHelper
->GetEditSource().GetBroadcaster().Broadcast( aHint
);
399 sal_Int32 SAL_CALL
ScAccessibleEditObject::getForeground( )
400 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
402 return GetFgBgColor(OUString(SC_UNONAME_CCOLOR
));
405 sal_Int32 SAL_CALL
ScAccessibleEditObject::getBackground( )
406 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
408 return GetFgBgColor(OUString(SC_UNONAME_CELLBACK
));
411 sal_Int32
ScAccessibleEditObject::GetFgBgColor( const OUString
&strPropColor
)
413 SolarMutexGuard aGuard
;
417 SfxObjectShell
* pObjSh
= m_pScDoc
->GetDocumentShell();
420 uno::Reference
<sheet::XSpreadsheetDocument
> xSpreadDoc( pObjSh
->GetModel(), uno::UNO_QUERY
);
421 if ( xSpreadDoc
.is() )
423 uno::Reference
<sheet::XSpreadsheets
> xSheets
= xSpreadDoc
->getSheets();
424 uno::Reference
<container::XIndexAccess
> xIndex( xSheets
, uno::UNO_QUERY
);
427 uno::Any aTable
= xIndex
->getByIndex(m_curCellAddress
.Tab());
428 uno::Reference
<sheet::XSpreadsheet
> xTable
;
431 uno::Reference
<table::XCell
> xCell
= xTable
->getCellByPosition(m_curCellAddress
.Col(), m_curCellAddress
.Row());
434 uno::Reference
<beans::XPropertySet
> xCellProps(xCell
, uno::UNO_QUERY
);
437 uno::Any aAny
= xCellProps
->getPropertyValue(strPropColor
);
448 //===== XAccessibleSelection ============================================
450 void SAL_CALL
ScAccessibleEditObject::selectAccessibleChild( sal_Int32
)
451 throw ( IndexOutOfBoundsException
, RuntimeException
, std::exception
)
455 sal_Bool SAL_CALL
ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex
)
456 throw ( IndexOutOfBoundsException
,
457 RuntimeException
, std::exception
)
459 uno::Reference
<XAccessible
> xAcc
= getAccessibleChild( nChildIndex
);
460 uno::Reference
<XAccessibleContext
> xContext
;
462 xContext
= xAcc
->getAccessibleContext();
465 if( xContext
->getAccessibleRole() == AccessibleRole::PARAGRAPH
)
467 uno::Reference
< ::com::sun::star::accessibility::XAccessibleText
>
468 xText(xAcc
, uno::UNO_QUERY
);
471 if( xText
->getSelectionStart() >= 0 ) return sal_True
;
478 void SAL_CALL
ScAccessibleEditObject::clearAccessibleSelection( )
479 throw ( RuntimeException
, std::exception
)
483 void SAL_CALL
ScAccessibleEditObject::selectAllAccessibleChildren( )
484 throw ( RuntimeException
, std::exception
)
488 sal_Int32 SAL_CALL
ScAccessibleEditObject::getSelectedAccessibleChildCount()
489 throw ( RuntimeException
, std::exception
)
491 sal_Int32 nCount
= 0;
492 sal_Int32 TotalCount
= getAccessibleChildCount();
493 for( sal_Int32 i
= 0; i
< TotalCount
; i
++ )
494 if( isAccessibleChildSelected(i
) ) nCount
++;
498 uno::Reference
<XAccessible
> SAL_CALL
ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
)
499 throw ( IndexOutOfBoundsException
, RuntimeException
, std::exception
)
501 if ( nSelectedChildIndex
> getSelectedAccessibleChildCount() )
502 throw IndexOutOfBoundsException();
504 for( i1
= 0, i2
= 0; i1
< getAccessibleChildCount(); i1
++ )
505 if( isAccessibleChildSelected(i1
) )
507 if( i2
== nSelectedChildIndex
)
508 return getAccessibleChild( i1
);
511 return uno::Reference
<XAccessible
>();
514 void SAL_CALL
ScAccessibleEditObject::deselectAccessibleChild(
516 throw ( IndexOutOfBoundsException
,
517 RuntimeException
, std::exception
)
521 uno::Reference
< XAccessibleRelationSet
> ScAccessibleEditObject::getAccessibleRelationSet( )
522 throw (uno::RuntimeException
, std::exception
)
524 SolarMutexGuard aGuard
;
525 vcl::Window
* pWindow
= mpWindow
;
526 utl::AccessibleRelationSetHelper
* rRelationSet
= new utl::AccessibleRelationSetHelper
;
527 uno::Reference
< XAccessibleRelationSet
> rSet
= rRelationSet
;
530 vcl::Window
*pLabeledBy
= pWindow
->GetAccessibleRelationLabeledBy();
531 if ( pLabeledBy
&& pLabeledBy
!= pWindow
)
533 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
534 aSequence
[0] = pLabeledBy
->GetAccessible();
535 rRelationSet
->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY
, aSequence
) );
537 vcl::Window
* pMemberOf
= pWindow
->GetAccessibleRelationMemberOf();
538 if ( pMemberOf
&& pMemberOf
!= pWindow
)
540 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
541 aSequence
[0] = pMemberOf
->GetAccessible();
542 rRelationSet
->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF
, aSequence
) );
546 return uno::Reference
< XAccessibleRelationSet
>();
549 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */