1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: accessiblecell.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <accessiblecell.hxx>
36 #include "DescriptionGenerator.hxx"
38 #include <com/sun/star/accessibility/AccessibleRole.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
41 #include <vcl/svapp.hxx>
43 #include <unotools/accessiblestatesethelper.hxx>
45 #include <svx/outlobj.hxx>
46 #include <svx/unoshtxt.hxx>
47 #include <svx/svdotext.hxx>
49 using ::rtl::OUString
;
50 using namespace ::sdr::table
;
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::uno
;
53 using namespace ::com::sun::star::accessibility
;
54 using namespace ::com::sun::star::lang
;
55 using namespace ::com::sun::star::container
;
57 namespace accessibility
{
59 // --------------------------------------------------------------------
61 // --------------------------------------------------------------------
63 AccessibleCell::AccessibleCell( const ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
>& rxParent
, const sdr::table::CellRef
& rCell
, sal_Int32 nIndex
, const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
64 : AccessibleCellBase( rxParent
, AccessibleRole::TABLE_CELL
)
65 , maShapeTreeInfo( rShapeTreeInfo
)
66 , mnIndexInParent( nIndex
)
72 // --------------------------------------------------------------------
74 AccessibleCell::~AccessibleCell (void)
76 DBG_ASSERT( mpText
== 0, "svx::AccessibleCell::~AccessibleCell(), not disposed!?" );
79 // --------------------------------------------------------------------
81 void AccessibleCell::Init (void)
83 SdrView
* pView
= maShapeTreeInfo
.GetSdrView();
84 const Window
* pWindow
= maShapeTreeInfo
.GetWindow ();
85 if( (pView
!= NULL
) && (pWindow
!= NULL
) && mxCell
.is())
87 OutlinerParaObject
* pOutlinerParaObject
= mxCell
->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
89 bool bOwnParaObject
= pOutlinerParaObject
!= 0;
91 if( !pOutlinerParaObject
)
92 pOutlinerParaObject
= mxCell
->GetOutlinerParaObject();
94 // create AccessibleTextHelper to handle this shape's text
95 if( pOutlinerParaObject
)
97 // non-empty text -> use full-fledged edit source right away
98 ::std::auto_ptr
<SvxEditSource
> pEditSource( new SvxTextEditSource( mxCell
->GetObject(), mxCell
.get(), *pView
, *pWindow
) );
99 mpText
= new AccessibleTextHelper( pEditSource
);
100 mpText
->SetEventSource(this);
104 delete pOutlinerParaObject
;
108 // --------------------------------------------------------------------
110 sal_Bool
AccessibleCell::SetState (sal_Int16 aState
)
112 sal_Bool bStateHasChanged
= sal_False
;
114 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
116 // Offer FOCUSED state to edit engine and detect whether the state
118 sal_Bool bIsFocused
= mpText
->HaveFocus ();
119 mpText
->SetFocus (sal_True
);
120 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
123 bStateHasChanged
= AccessibleContextBase::SetState (aState
);
125 return bStateHasChanged
;
128 // --------------------------------------------------------------------
130 sal_Bool
AccessibleCell::ResetState (sal_Int16 aState
)
132 sal_Bool bStateHasChanged
= sal_False
;
134 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
136 // Try to remove FOCUSED state from the edit engine and detect
137 // whether the state changes.
138 sal_Bool bIsFocused
= mpText
->HaveFocus ();
139 mpText
->SetFocus (sal_False
);
140 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
143 bStateHasChanged
= AccessibleContextBase::ResetState (aState
);
145 return bStateHasChanged
;
148 // --------------------------------------------------------------------
150 sal_Bool
AccessibleCell::GetState (sal_Int16 aState
)
152 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
154 // Just delegate the call to the edit engine. The state is not
155 // merged into the state set.
156 return mpText
->HaveFocus();
159 return AccessibleContextBase::GetState (aState
);
162 //-----------------------------------------------------------------------------
164 bool AccessibleCell::operator== (const AccessibleCell
& rAccessibleCell
)
166 return this == &rAccessibleCell
;
169 //-----------------------------------------------------------------------------
171 //-----------------------------------------------------------------------------
173 Any SAL_CALL
AccessibleCell::queryInterface( const Type
& aType
) throw (RuntimeException
)
175 return AccessibleCellBase::queryInterface( aType
);
178 //-----------------------------------------------------------------------------
180 void SAL_CALL
AccessibleCell::acquire( ) throw ()
182 AccessibleCellBase::acquire();
185 //-----------------------------------------------------------------------------
187 void SAL_CALL
AccessibleCell::release( ) throw ()
189 AccessibleCellBase::release();
192 // --------------------------------------------------------------------
193 // XAccessibleContext
194 // --------------------------------------------------------------------
196 /** The children of this cell come from the paragraphs of text.
198 sal_Int32 SAL_CALL
AccessibleCell::getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException
)
200 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
202 return mpText
!= NULL
? mpText
->GetChildCount () : 0;
205 // --------------------------------------------------------------------
207 /** Forward the request to the shape. Return the requested shape or throw
208 an exception for a wrong index.
210 Reference
<XAccessible
> SAL_CALL
AccessibleCell::getAccessibleChild (sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
212 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
215 // todo: does GetChild throw IndexOutOfBoundsException?
216 return mpText
->GetChild (nIndex
);
219 // --------------------------------------------------------------------
221 /** Return a copy of the state set.
227 Reference
<XAccessibleStateSet
> SAL_CALL
AccessibleCell::getAccessibleStateSet (void) throw (RuntimeException
)
229 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
230 ::osl::MutexGuard
aGuard (maMutex
);
231 Reference
<XAccessibleStateSet
> xStateSet
;
233 if (rBHelper
.bDisposed
|| mpText
== NULL
)
235 // Return a minimal state set that only contains the DEFUNC state.
236 xStateSet
= AccessibleContextBase::getAccessibleStateSet ();
240 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
244 // Merge current FOCUSED state from edit engine.
247 if (mpText
->HaveFocus())
248 pStateSet
->AddState (AccessibleStateType::FOCUSED
);
250 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
253 // Create a copy of the state set that may be modified by the
254 // caller without affecting the current state set.
255 xStateSet
= Reference
<XAccessibleStateSet
>(new ::utl::AccessibleStateSetHelper (*pStateSet
));
262 // --------------------------------------------------------------------
263 // XAccessibleComponent
264 // --------------------------------------------------------------------
266 sal_Bool SAL_CALL
AccessibleCell::containsPoint( const ::com::sun::star::awt::Point
& aPoint
) throw (::com::sun::star::uno::RuntimeException
)
268 return AccessibleComponentBase::containsPoint( aPoint
);
271 /** The implementation below is at the moment straightforward. It iterates
272 over all children (and thereby instances all children which have not
273 been already instatiated) until a child covering the specifed point is
275 This leaves room for improvement. For instance, first iterate only over
276 the already instantiated children and only if no match is found
277 instantiate the remaining ones.
279 Reference
<XAccessible
> SAL_CALL
AccessibleCell::getAccessibleAtPoint ( const ::com::sun::star::awt::Point
& aPoint
) throw(RuntimeException
)
281 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
282 ::osl::MutexGuard
aGuard (maMutex
);
284 sal_Int32 nChildCount
= getAccessibleChildCount ();
285 for (sal_Int32 i
=0; i
<nChildCount
; ++i
)
287 Reference
<XAccessible
> xChild (getAccessibleChild (i
));
290 Reference
<XAccessibleComponent
> xChildComponent (xChild
->getAccessibleContext(), uno::UNO_QUERY
);
291 if (xChildComponent
.is())
293 awt::Rectangle
aBBox (xChildComponent
->getBounds());
294 if ( (aPoint
.X
>= aBBox
.X
)
295 && (aPoint
.Y
>= aBBox
.Y
)
296 && (aPoint
.X
< aBBox
.X
+aBBox
.Width
)
297 && (aPoint
.Y
< aBBox
.Y
+aBBox
.Height
) )
303 // Have not found a child under the given point. Returning empty
304 // reference to indicate this.
305 return uno::Reference
<XAccessible
>();
308 // --------------------------------------------------------------------
310 ::com::sun::star::awt::Rectangle SAL_CALL
AccessibleCell::getBounds(void) throw(RuntimeException
)
312 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
313 ::osl::MutexGuard
aGuard (maMutex
);
316 ::com::sun::star::awt::Rectangle aBoundingBox
;
319 // Get the cell's bounding box in internal coordinates (in 100th of mm)
320 const ::Rectangle
aCellRect( mxCell
->getCellRect() );
322 // Transform coordinates from internal to pixel.
323 if (maShapeTreeInfo
.GetViewForwarder() == NULL
)
324 throw uno::RuntimeException (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleCell has no valid view forwarder")),static_cast<uno::XWeak
*>(this));
326 ::Size
aPixelSize( maShapeTreeInfo
.GetViewForwarder()->LogicToPixel(::Size(aCellRect
.GetWidth(), aCellRect
.GetHeight())) );
327 ::Point
aPixelPosition( maShapeTreeInfo
.GetViewForwarder()->LogicToPixel( aCellRect
.TopLeft() ));
329 // Clip the shape's bounding box with the bounding box of its parent.
330 Reference
<XAccessibleComponent
> xParentComponent ( getAccessibleParent(), uno::UNO_QUERY
);
331 if (xParentComponent
.is())
333 // Make the coordinates relative to the parent.
334 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
335 int x
= aPixelPosition
.getX() - aParentLocation
.X
;
336 int y
= aPixelPosition
.getY() - aParentLocation
.Y
;
338 // Clip with parent (with coordinates relative to itself).
339 ::Rectangle
aBBox ( x
, y
, x
+ aPixelSize
.getWidth(), y
+ aPixelSize
.getHeight());
340 awt::Size
aParentSize (xParentComponent
->getSize());
341 ::Rectangle
aParentBBox (0,0, aParentSize
.Width
, aParentSize
.Height
);
342 aBBox
= aBBox
.GetIntersection (aParentBBox
);
343 aBoundingBox
= awt::Rectangle ( aBBox
.getX(), aBBox
.getY(), aBBox
.getWidth(), aBBox
.getHeight());
347 OSL_TRACE ("parent does not support component");
348 aBoundingBox
= awt::Rectangle (aPixelPosition
.getX(), aPixelPosition
.getY(),aPixelSize
.getWidth(), aPixelSize
.getHeight());
355 // --------------------------------------------------------------------
357 ::com::sun::star::awt::Point SAL_CALL
AccessibleCell::getLocation(void) throw (RuntimeException
)
360 ::com::sun::star::awt::Rectangle
aBoundingBox(getBounds());
361 return ::com::sun::star::awt::Point(aBoundingBox
.X
, aBoundingBox
.Y
);
364 // --------------------------------------------------------------------
366 ::com::sun::star::awt::Point SAL_CALL
AccessibleCell::getLocationOnScreen(void) throw(RuntimeException
)
370 // Get relative position...
371 ::com::sun::star::awt::Point
aLocation(getLocation ());
373 // ... and add absolute position of the parent.
374 Reference
<XAccessibleComponent
> xParentComponent( getAccessibleParent(), uno::UNO_QUERY
);
375 if(xParentComponent
.is())
377 ::com::sun::star::awt::Point
aParentLocation(xParentComponent
->getLocationOnScreen());
378 aLocation
.X
+= aParentLocation
.X
;
379 aLocation
.Y
+= aParentLocation
.Y
;
383 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
389 // --------------------------------------------------------------------
391 awt::Size SAL_CALL
AccessibleCell::getSize (void) throw (RuntimeException
)
394 awt::Rectangle
aBoundingBox (getBounds());
395 return awt::Size (aBoundingBox
.Width
, aBoundingBox
.Height
);
398 // --------------------------------------------------------------------
400 void SAL_CALL
AccessibleCell::addFocusListener ( const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XFocusListener
>& xListener
) throw (::com::sun::star::uno::RuntimeException
)
402 AccessibleComponentBase::addFocusListener( xListener
);
405 // --------------------------------------------------------------------
407 void SAL_CALL
AccessibleCell::removeFocusListener (const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XFocusListener
>& xListener
) throw (::com::sun::star::uno::RuntimeException
)
409 AccessibleComponentBase::removeFocusListener( xListener
);
412 // --------------------------------------------------------------------
414 void SAL_CALL
AccessibleCell::grabFocus (void) throw (::com::sun::star::uno::RuntimeException
)
416 AccessibleComponentBase::grabFocus();
419 // --------------------------------------------------------------------
421 sal_Int32 SAL_CALL
AccessibleCell::getForeground(void) throw (RuntimeException
)
424 sal_Int32
nColor (0x0ffffffL
);
430 // --------------------------------------------------------------------
432 sal_Int32 SAL_CALL
AccessibleCell::getBackground (void) throw (RuntimeException
)
435 sal_Int32
nColor (0L);
441 // --------------------------------------------------------------------
442 // XAccessibleExtendedComponent
443 // --------------------------------------------------------------------
445 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XFont
> SAL_CALL
AccessibleCell::getFont (void) throw (::com::sun::star::uno::RuntimeException
)
448 return AccessibleComponentBase::getFont();
451 // --------------------------------------------------------------------
453 ::rtl::OUString SAL_CALL
AccessibleCell::getTitledBorderText (void) throw (::com::sun::star::uno::RuntimeException
)
455 return AccessibleComponentBase::getTitledBorderText();
458 // --------------------------------------------------------------------
460 ::rtl::OUString SAL_CALL
AccessibleCell::getToolTipText (void) throw (::com::sun::star::uno::RuntimeException
)
462 return AccessibleComponentBase::getToolTipText();
465 // --------------------------------------------------------------------
466 // XAccessibleEventBroadcaster
467 // --------------------------------------------------------------------
469 void SAL_CALL
AccessibleCell::addEventListener( const Reference
<XAccessibleEventListener
>& rxListener
) throw (RuntimeException
)
471 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
472 ::osl::MutexGuard
aGuard (maMutex
);
473 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
475 Reference
<XInterface
> xSource( static_cast<XComponent
*>(this) );
476 lang::EventObject
aEventObj(xSource
);
477 rxListener
->disposing(aEventObj
);
481 AccessibleContextBase::addEventListener (rxListener
);
483 mpText
->AddEventListener (rxListener
);
487 // --------------------------------------------------------------------
489 void SAL_CALL
AccessibleCell::removeEventListener( const Reference
<XAccessibleEventListener
>& rxListener
) throw (RuntimeException
)
491 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
492 AccessibleContextBase::removeEventListener(rxListener
);
494 mpText
->RemoveEventListener (rxListener
);
497 // --------------------------------------------------------------------
499 // --------------------------------------------------------------------
501 OUString SAL_CALL
AccessibleCell::getImplementationName(void) throw (RuntimeException
)
503 return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleCell"));
506 // --------------------------------------------------------------------
508 Sequence
<OUString
> SAL_CALL
AccessibleCell::getSupportedServiceNames(void) throw (RuntimeException
)
512 // Get list of supported service names from base class...
513 uno::Sequence
<OUString
> aServiceNames
= AccessibleContextBase::getSupportedServiceNames();
514 sal_Int32
nCount (aServiceNames
.getLength());
516 // ...and add additional names.
517 aServiceNames
.realloc (nCount
+ 1);
518 static const OUString
sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.AccessibleCell"));
519 aServiceNames
[nCount
] = sAdditionalServiceName
;
521 return aServiceNames
;
524 // --------------------------------------------------------------------
525 // IAccessibleViewForwarderListener
526 // --------------------------------------------------------------------
528 void AccessibleCell::ViewForwarderChanged (ChangeType
/*aChangeType*/, const IAccessibleViewForwarder
* /*pViewForwarder*/)
530 // Inform all listeners that the graphical representation (i.e. size
531 // and/or position) of the shape has changed.
532 CommitChange(AccessibleEventId::VISIBLE_DATA_CHANGED
, Any(), Any());
534 // update our children that our screen position might have changed
536 mpText
->UpdateChildren();
539 // --------------------------------------------------------------------
541 // --------------------------------------------------------------------
543 void AccessibleCell::disposing (void)
545 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
546 ::osl::MutexGuard
aGuard (maMutex
);
548 // Make sure to send an event that this object looses the focus in the
549 // case that it has the focus.
550 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
551 if (pStateSet
!= NULL
)
552 pStateSet
->RemoveState(AccessibleStateType::FOCUSED
);
561 // Cleanup. Remove references to objects to allow them to be
564 maShapeTreeInfo
= AccessibleShapeTreeInfo();
566 // Call base classes.
567 AccessibleContextBase::dispose ();
570 sal_Int32 SAL_CALL
AccessibleCell::getAccessibleIndexInParent (void) throw (RuntimeException
)
573 return mnIndexInParent
;
576 ::rtl::OUString SAL_CALL
AccessibleCell::getAccessibleName (void) throw (::com::sun::star::uno::RuntimeException
)
579 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
582 return mxCell
->getName();
584 return AccessibleCellBase::getAccessibleName();
587 } // end of namespace accessibility