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 "AccessibleEditObject.hxx"
21 #include "scitems.hxx"
22 #include <editeng/eeitem.hxx>
23 #include "AccessibleText.hxx"
24 #include "editsrc.hxx"
26 #include "inputhdl.hxx"
28 #include <unotools/accessiblestatesethelper.hxx>
29 #include <com/sun/star/accessibility/AccessibleRole.hpp>
30 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
31 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
32 #include <com/sun/star/sheet/XSpreadsheet.hpp>
33 #include <comphelper/servicehelper.hxx>
34 #include <svx/AccessibleTextHelper.hxx>
35 #include <editeng/editview.hxx>
36 #include <editeng/editeng.hxx>
37 #include <svx/svdmodel.hxx>
38 #include <vcl/svapp.hxx>
39 #include <sfx2/objsh.hxx>
41 #include "unonames.hxx"
42 #include "document.hxx"
43 #include "AccessibleDocument.hxx"
44 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
45 #include <unotools/accessiblerelationsethelper.hxx>
46 #include <com/sun/star/accessibility/XAccessibleText.hpp>
48 using ::com::sun::star::lang::IndexOutOfBoundsException
;
49 using ::com::sun::star::uno::RuntimeException
;
50 using namespace ::com::sun::star
;
51 using namespace ::com::sun::star::accessibility
;
53 //===== internal ============================================================
55 ScAccessibleEditObject::ScAccessibleEditObject(
56 const uno::Reference
<XAccessible
>& rxParent
,
57 EditView
* pEditView
, Window
* pWin
, const OUString
& rName
,
58 const OUString
& rDescription
, EditObjectType eObjectType
)
60 ScAccessibleContextBase(rxParent
, AccessibleRole::TEXT_FRAME
),
62 mpEditView(pEditView
),
64 meObjectType(eObjectType
),
69 SetDescription(rDescription
);
70 if( meObjectType
== CellInEditMode
)
72 const ScAccessibleDocument
*pAccDoc
= const_cast<ScAccessibleDocument
*>(static_cast<ScAccessibleDocument
*>(rxParent
.get())) ;
75 m_pScDoc
= pAccDoc
->GetDocument();
76 m_curCellAddress
=pAccDoc
->GetCurCellAddress();
87 ScAccessibleEditObject::~ScAccessibleEditObject()
89 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper
.bInDispose
)
91 // increment refcount to prevent double call off dtor
92 osl_atomic_increment( &m_refCount
);
93 // call dispose to inform object which have a weak reference to this object
98 void SAL_CALL
ScAccessibleEditObject::disposing()
100 SolarMutexGuard aGuard
;
102 DELETEZ(mpTextHelper
);
104 ScAccessibleContextBase::disposing();
107 void ScAccessibleEditObject::LostFocus()
111 mpTextHelper
->SetFocus(false);
115 void ScAccessibleEditObject::GotFocus()
120 mpTextHelper
->SetFocus(true);
123 //===== XInterface ==========================================================
125 com::sun::star::uno::Any SAL_CALL
126 ScAccessibleEditObject::queryInterface (const com::sun::star::uno::Type
& rType
)
127 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
129 ::com::sun::star::uno::Any aReturn
= ScAccessibleContextBase::queryInterface (rType
);
130 if ( ! aReturn
.hasValue())
131 aReturn
= ::cppu::queryInterface (rType
,
132 static_cast< ::com::sun::star::accessibility::XAccessibleSelection
* >(this)
137 ScAccessibleEditObject::acquire (void)
140 ScAccessibleContextBase::acquire ();
143 ScAccessibleEditObject::release (void)
146 ScAccessibleContextBase::release ();
148 //===== XAccessibleComponent ============================================
150 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleEditObject::getAccessibleAtPoint(
151 const awt::Point
& rPoint
)
152 throw (uno::RuntimeException
, std::exception
)
154 uno::Reference
<XAccessible
> xRet
;
155 if (containsPoint(rPoint
))
157 SolarMutexGuard aGuard
;
163 xRet
= mpTextHelper
->GetAt(rPoint
);
169 Rectangle
ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const
170 throw (uno::RuntimeException
, std::exception
)
172 Rectangle aScreenBounds
;
176 if ( meObjectType
== CellInEditMode
)
178 if ( mpEditView
&& mpEditView
->GetEditEngine() )
180 MapMode
aMapMode( mpEditView
->GetEditEngine()->GetRefMapMode() );
181 aScreenBounds
= mpWindow
->LogicToPixel( mpEditView
->GetOutputArea(), aMapMode
);
182 Point aCellLoc
= aScreenBounds
.TopLeft();
183 Rectangle aWindowRect
= mpWindow
->GetWindowExtentsRelative( NULL
);
184 Point aWindowLoc
= aWindowRect
.TopLeft();
185 Point
aPos( aCellLoc
.getX() + aWindowLoc
.getX(), aCellLoc
.getY() + aWindowLoc
.getY() );
186 aScreenBounds
.SetPos( aPos
);
191 aScreenBounds
= mpWindow
->GetWindowExtentsRelative( NULL
);
195 return aScreenBounds
;
198 Rectangle
ScAccessibleEditObject::GetBoundingBox(void) const
199 throw (uno::RuntimeException
, std::exception
)
201 Rectangle
aBounds( GetBoundingBoxOnScreen() );
205 uno::Reference
< XAccessible
> xThis( mpWindow
->GetAccessible() );
208 uno::Reference
< XAccessibleContext
> xContext( xThis
->getAccessibleContext() );
211 uno::Reference
< XAccessible
> xParent( xContext
->getAccessibleParent() );
214 uno::Reference
< XAccessibleComponent
> xParentComponent( xParent
->getAccessibleContext(), uno::UNO_QUERY
);
215 if ( xParentComponent
.is() )
217 Point aScreenLoc
= aBounds
.TopLeft();
218 awt::Point aParentScreenLoc
= xParentComponent
->getLocationOnScreen();
219 Point
aPos( aScreenLoc
.getX() - aParentScreenLoc
.X
, aScreenLoc
.getY() - aParentScreenLoc
.Y
);
220 aBounds
.SetPos( aPos
);
230 //===== XAccessibleContext ==============================================
233 ScAccessibleEditObject::getAccessibleChildCount(void)
234 throw (uno::RuntimeException
, std::exception
)
236 SolarMutexGuard aGuard
;
240 return mpTextHelper
->GetChildCount();
243 uno::Reference
< XAccessible
> SAL_CALL
244 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex
)
245 throw (uno::RuntimeException
,
246 lang::IndexOutOfBoundsException
, std::exception
)
248 SolarMutexGuard aGuard
;
252 return mpTextHelper
->GetChild(nIndex
);
255 uno::Reference
<XAccessibleStateSet
> SAL_CALL
256 ScAccessibleEditObject::getAccessibleStateSet(void)
257 throw (uno::RuntimeException
, std::exception
)
259 SolarMutexGuard aGuard
;
260 uno::Reference
<XAccessibleStateSet
> xParentStates
;
261 if (getAccessibleParent().is())
263 uno::Reference
<XAccessibleContext
> xParentContext
= getAccessibleParent()->getAccessibleContext();
264 xParentStates
= xParentContext
->getAccessibleStateSet();
266 utl::AccessibleStateSetHelper
* pStateSet
= new utl::AccessibleStateSetHelper();
267 if (IsDefunc(xParentStates
))
268 pStateSet
->AddState(AccessibleStateType::DEFUNC
);
271 // all states are const, because this object exists only in one state
272 pStateSet
->AddState(AccessibleStateType::EDITABLE
);
273 pStateSet
->AddState(AccessibleStateType::ENABLED
);
274 pStateSet
->AddState(AccessibleStateType::SENSITIVE
);
275 pStateSet
->AddState(AccessibleStateType::MULTI_LINE
);
276 pStateSet
->AddState(AccessibleStateType::MULTI_SELECTABLE
);
277 pStateSet
->AddState(AccessibleStateType::SHOWING
);
278 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
284 ScAccessibleEditObject::createAccessibleDescription(void)
285 throw (uno::RuntimeException
)
287 // OSL_FAIL("Should never be called, because is set in the constructor.")
292 ScAccessibleEditObject::createAccessibleName(void)
293 throw (uno::RuntimeException
, std::exception
)
295 OSL_FAIL("Should never be called, because is set in the constructor.");
299 ///===== XAccessibleEventBroadcaster =====================================
302 ScAccessibleEditObject::addAccessibleEventListener(const uno::Reference
<XAccessibleEventListener
>& xListener
)
303 throw (uno::RuntimeException
, std::exception
)
308 mpTextHelper
->AddEventListener(xListener
);
310 ScAccessibleContextBase::addAccessibleEventListener(xListener
);
314 ScAccessibleEditObject::removeAccessibleEventListener(const uno::Reference
<XAccessibleEventListener
>& xListener
)
315 throw (uno::RuntimeException
, std::exception
)
320 mpTextHelper
->RemoveEventListener(xListener
);
322 ScAccessibleContextBase::removeAccessibleEventListener(xListener
);
325 //===== XServiceInfo ====================================================
327 OUString SAL_CALL
ScAccessibleEditObject::getImplementationName(void)
328 throw (uno::RuntimeException
, std::exception
)
330 return OUString("ScAccessibleEditObject");
333 //===== XTypeProvider =======================================================
335 uno::Sequence
<sal_Int8
> SAL_CALL
336 ScAccessibleEditObject::getImplementationId(void)
337 throw (uno::RuntimeException
, std::exception
)
339 return css::uno::Sequence
<sal_Int8
>();
342 //==== internal =========================================================
344 bool ScAccessibleEditObject::IsDefunc(
345 const uno::Reference
<XAccessibleStateSet
>& rxParentStates
)
347 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
348 (rxParentStates
.is() && rxParentStates
->contains(AccessibleStateType::DEFUNC
));
351 void ScAccessibleEditObject::CreateTextHelper()
355 SAL_WNODEPRECATED_DECLARATIONS_PUSH
356 ::std::auto_ptr
< ScAccessibleTextData
> pAccessibleTextData
;
357 SAL_WNODEPRECATED_DECLARATIONS_POP
358 if (meObjectType
== CellInEditMode
|| meObjectType
== EditControl
)
360 pAccessibleTextData
.reset
361 (new ScAccessibleEditObjectTextData(mpEditView
, mpWindow
));
365 pAccessibleTextData
.reset
366 (new ScAccessibleEditLineTextData(NULL
, mpWindow
));
369 SAL_WNODEPRECATED_DECLARATIONS_PUSH
370 ::std::auto_ptr
< SvxEditSource
> pEditSource (new ScAccessibilityEditSource(pAccessibleTextData
));
371 SAL_WNODEPRECATED_DECLARATIONS_POP
372 mpTextHelper
= new ::accessibility::AccessibleTextHelper(pEditSource
);
373 mpTextHelper
->SetEventSource(this);
374 mpTextHelper
->SetFocus(mbHasFocus
);
376 // #i54814# activate cell in edit mode
377 if( meObjectType
== CellInEditMode
)
379 // do not activate cell object, if top edit line is active
380 const ScInputHandler
* pInputHdl
= SC_MOD()->GetInputHdl();
381 if( pInputHdl
&& !pInputHdl
->IsTopMode() )
383 SdrHint
aHint( HINT_BEGEDIT
);
384 mpTextHelper
->GetEditSource().GetBroadcaster().Broadcast( aHint
);
390 sal_Int32 SAL_CALL
ScAccessibleEditObject::getForeground( )
391 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
393 return GetFgBgColor(OUString(SC_UNONAME_CCOLOR
));
396 sal_Int32 SAL_CALL
ScAccessibleEditObject::getBackground( )
397 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
399 return GetFgBgColor(OUString(SC_UNONAME_CELLBACK
));
402 sal_Int32
ScAccessibleEditObject::GetFgBgColor( const OUString
&strPropColor
)
404 SolarMutexGuard aGuard
;
408 SfxObjectShell
* pObjSh
= m_pScDoc
->GetDocumentShell();
411 uno::Reference
<sheet::XSpreadsheetDocument
> xSpreadDoc( pObjSh
->GetModel(), uno::UNO_QUERY
);
412 if ( xSpreadDoc
.is() )
414 uno::Reference
<sheet::XSpreadsheets
> xSheets
= xSpreadDoc
->getSheets();
415 uno::Reference
<container::XIndexAccess
> xIndex( xSheets
, uno::UNO_QUERY
);
418 uno::Any aTable
= xIndex
->getByIndex(m_curCellAddress
.Tab());
419 uno::Reference
<sheet::XSpreadsheet
> xTable
;
422 uno::Reference
<table::XCell
> xCell
= xTable
->getCellByPosition(m_curCellAddress
.Col(), m_curCellAddress
.Row());
425 uno::Reference
<beans::XPropertySet
> xCellProps(xCell
, uno::UNO_QUERY
);
428 uno::Any aAny
= xCellProps
->getPropertyValue(strPropColor
);
439 //===== XAccessibleSelection ============================================
441 void SAL_CALL
ScAccessibleEditObject::selectAccessibleChild( sal_Int32
)
442 throw ( IndexOutOfBoundsException
, RuntimeException
, std::exception
)
446 sal_Bool SAL_CALL
ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex
)
447 throw ( IndexOutOfBoundsException
,
448 RuntimeException
, std::exception
)
450 uno::Reference
<XAccessible
> xAcc
= getAccessibleChild( nChildIndex
);
451 uno::Reference
<XAccessibleContext
> xContext
;
453 xContext
= xAcc
->getAccessibleContext();
456 if( xContext
->getAccessibleRole() == AccessibleRole::PARAGRAPH
)
458 uno::Reference
< ::com::sun::star::accessibility::XAccessibleText
>
459 xText(xAcc
, uno::UNO_QUERY
);
462 if( xText
->getSelectionStart() >= 0 ) return sal_True
;
469 void SAL_CALL
ScAccessibleEditObject::clearAccessibleSelection( )
470 throw ( RuntimeException
, std::exception
)
474 void SAL_CALL
ScAccessibleEditObject::selectAllAccessibleChildren( )
475 throw ( RuntimeException
, std::exception
)
479 sal_Int32 SAL_CALL
ScAccessibleEditObject::getSelectedAccessibleChildCount()
480 throw ( RuntimeException
, std::exception
)
482 sal_Int32 nCount
= 0;
483 sal_Int32 TotalCount
= getAccessibleChildCount();
484 for( sal_Int32 i
= 0; i
< TotalCount
; i
++ )
485 if( isAccessibleChildSelected(i
) ) nCount
++;
489 uno::Reference
<XAccessible
> SAL_CALL
ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
)
490 throw ( IndexOutOfBoundsException
, RuntimeException
, std::exception
)
492 if ( nSelectedChildIndex
> getSelectedAccessibleChildCount() )
493 throw IndexOutOfBoundsException();
495 for( i1
= 0, i2
= 0; i1
< getAccessibleChildCount(); i1
++ )
496 if( isAccessibleChildSelected(i1
) )
498 if( i2
== nSelectedChildIndex
)
499 return getAccessibleChild( i1
);
502 return uno::Reference
<XAccessible
>();
505 void SAL_CALL
ScAccessibleEditObject::deselectAccessibleChild(
507 throw ( IndexOutOfBoundsException
,
508 RuntimeException
, std::exception
)
512 uno::Reference
< XAccessibleRelationSet
> ScAccessibleEditObject::getAccessibleRelationSet( )
513 throw (uno::RuntimeException
, std::exception
)
515 SolarMutexGuard aGuard
;
516 Window
* pWindow
= mpWindow
;
517 utl::AccessibleRelationSetHelper
* rRelationSet
= new utl::AccessibleRelationSetHelper
;
518 uno::Reference
< XAccessibleRelationSet
> rSet
= rRelationSet
;
521 Window
*pLabeledBy
= pWindow
->GetAccessibleRelationLabeledBy();
522 if ( pLabeledBy
&& pLabeledBy
!= pWindow
)
524 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
525 aSequence
[0] = pLabeledBy
->GetAccessible();
526 rRelationSet
->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY
, aSequence
) );
528 Window
* pMemberOf
= pWindow
->GetAccessibleRelationMemberOf();
529 if ( pMemberOf
&& pMemberOf
!= pWindow
)
531 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
532 aSequence
[0] = pMemberOf
->GetAccessible();
533 rRelationSet
->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF
, aSequence
) );
537 return uno::Reference
< XAccessibleRelationSet
>();
540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */