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 .
21 #include <accessiblecell.hxx>
23 #include "svx/DescriptionGenerator.hxx"
25 #include <com/sun/star/accessibility/AccessibleRole.hpp>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <vcl/svapp.hxx>
30 #include <unotools/accessiblestatesethelper.hxx>
32 #include <editeng/outlobj.hxx>
33 #include <svx/unoshtxt.hxx>
34 #include <svx/svdotext.hxx>
36 using namespace ::sdr::table
;
37 using namespace ::com::sun::star
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::accessibility
;
40 using namespace ::com::sun::star::lang
;
41 using namespace ::com::sun::star::container
;
43 namespace accessibility
{
45 // --------------------------------------------------------------------
47 // --------------------------------------------------------------------
49 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
)
50 : AccessibleCellBase( rxParent
, AccessibleRole::TABLE_CELL
)
51 , maShapeTreeInfo( rShapeTreeInfo
)
52 , mnIndexInParent( nIndex
)
58 // --------------------------------------------------------------------
60 AccessibleCell::~AccessibleCell (void)
62 DBG_ASSERT( mpText
== 0, "svx::AccessibleCell::~AccessibleCell(), not disposed!?" );
65 // --------------------------------------------------------------------
67 void AccessibleCell::Init (void)
69 SdrView
* pView
= maShapeTreeInfo
.GetSdrView();
70 const Window
* pWindow
= maShapeTreeInfo
.GetWindow ();
71 if( (pView
!= NULL
) && (pWindow
!= NULL
) && mxCell
.is())
73 OutlinerParaObject
* pOutlinerParaObject
= mxCell
->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
75 bool bOwnParaObject
= pOutlinerParaObject
!= 0;
77 if( !pOutlinerParaObject
)
78 pOutlinerParaObject
= mxCell
->GetOutlinerParaObject();
80 // create AccessibleTextHelper to handle this shape's text
81 if( pOutlinerParaObject
)
83 // non-empty text -> use full-fledged edit source right away
84 SAL_WNODEPRECATED_DECLARATIONS_PUSH
85 ::std::auto_ptr
<SvxEditSource
> pEditSource( new SvxTextEditSource( mxCell
->GetObject(), mxCell
.get(), *pView
, *pWindow
) );
86 SAL_WNODEPRECATED_DECLARATIONS_POP
87 mpText
= new AccessibleTextHelper( pEditSource
);
88 mpText
->SetEventSource(this);
92 delete pOutlinerParaObject
;
96 // --------------------------------------------------------------------
98 sal_Bool
AccessibleCell::SetState (sal_Int16 aState
)
100 sal_Bool bStateHasChanged
= sal_False
;
102 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
104 // Offer FOCUSED state to edit engine and detect whether the state
106 sal_Bool bIsFocused
= mpText
->HaveFocus ();
107 mpText
->SetFocus (sal_True
);
108 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
111 bStateHasChanged
= AccessibleContextBase::SetState (aState
);
113 return bStateHasChanged
;
116 // --------------------------------------------------------------------
118 sal_Bool
AccessibleCell::ResetState (sal_Int16 aState
)
120 sal_Bool bStateHasChanged
= sal_False
;
122 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
124 // Try to remove FOCUSED state from the edit engine and detect
125 // whether the state changes.
126 sal_Bool bIsFocused
= mpText
->HaveFocus ();
127 mpText
->SetFocus (sal_False
);
128 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
131 bStateHasChanged
= AccessibleContextBase::ResetState (aState
);
133 return bStateHasChanged
;
136 //-----------------------------------------------------------------------------
138 bool AccessibleCell::operator== (const AccessibleCell
& rAccessibleCell
)
140 return this == &rAccessibleCell
;
143 //-----------------------------------------------------------------------------
145 //-----------------------------------------------------------------------------
147 Any SAL_CALL
AccessibleCell::queryInterface( const Type
& aType
) throw (RuntimeException
)
149 return AccessibleCellBase::queryInterface( aType
);
152 //-----------------------------------------------------------------------------
154 void SAL_CALL
AccessibleCell::acquire( ) throw ()
156 AccessibleCellBase::acquire();
159 //-----------------------------------------------------------------------------
161 void SAL_CALL
AccessibleCell::release( ) throw ()
163 AccessibleCellBase::release();
166 // --------------------------------------------------------------------
167 // XAccessibleContext
168 // --------------------------------------------------------------------
170 /** The children of this cell come from the paragraphs of text.
172 sal_Int32 SAL_CALL
AccessibleCell::getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException
)
174 SolarMutexGuard aSolarGuard
;
176 return mpText
!= NULL
? mpText
->GetChildCount () : 0;
179 // --------------------------------------------------------------------
181 /** Forward the request to the shape. Return the requested shape or throw
182 an exception for a wrong index.
184 Reference
<XAccessible
> SAL_CALL
AccessibleCell::getAccessibleChild (sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
186 SolarMutexGuard aSolarGuard
;
189 // todo: does GetChild throw IndexOutOfBoundsException?
190 return mpText
->GetChild (nIndex
);
193 // --------------------------------------------------------------------
195 /** Return a copy of the state set.
201 Reference
<XAccessibleStateSet
> SAL_CALL
AccessibleCell::getAccessibleStateSet (void) throw (RuntimeException
)
203 SolarMutexGuard aSolarGuard
;
204 ::osl::MutexGuard
aGuard (maMutex
);
205 Reference
<XAccessibleStateSet
> xStateSet
;
207 if (rBHelper
.bDisposed
|| mpText
== NULL
)
209 // Return a minimal state set that only contains the DEFUNC state.
210 xStateSet
= AccessibleContextBase::getAccessibleStateSet ();
214 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
218 // Merge current FOCUSED state from edit engine.
221 if (mpText
->HaveFocus())
222 pStateSet
->AddState (AccessibleStateType::FOCUSED
);
224 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
227 // Create a copy of the state set that may be modified by the
228 // caller without affecting the current state set.
229 xStateSet
= Reference
<XAccessibleStateSet
>(new ::utl::AccessibleStateSetHelper (*pStateSet
));
236 // --------------------------------------------------------------------
237 // XAccessibleComponent
238 // --------------------------------------------------------------------
240 sal_Bool SAL_CALL
AccessibleCell::containsPoint( const ::com::sun::star::awt::Point
& aPoint
) throw (::com::sun::star::uno::RuntimeException
)
242 return AccessibleComponentBase::containsPoint( aPoint
);
245 /** The implementation below is at the moment straightforward. It iterates
246 over all children (and thereby instances all children which have not
247 been already instatiated) until a child covering the specifed point is
249 This leaves room for improvement. For instance, first iterate only over
250 the already instantiated children and only if no match is found
251 instantiate the remaining ones.
253 Reference
<XAccessible
> SAL_CALL
AccessibleCell::getAccessibleAtPoint ( const ::com::sun::star::awt::Point
& aPoint
) throw(RuntimeException
)
255 SolarMutexGuard aSolarGuard
;
256 ::osl::MutexGuard
aGuard (maMutex
);
258 sal_Int32 nChildCount
= getAccessibleChildCount ();
259 for (sal_Int32 i
=0; i
<nChildCount
; ++i
)
261 Reference
<XAccessible
> xChild (getAccessibleChild (i
));
264 Reference
<XAccessibleComponent
> xChildComponent (xChild
->getAccessibleContext(), uno::UNO_QUERY
);
265 if (xChildComponent
.is())
267 awt::Rectangle
aBBox (xChildComponent
->getBounds());
268 if ( (aPoint
.X
>= aBBox
.X
)
269 && (aPoint
.Y
>= aBBox
.Y
)
270 && (aPoint
.X
< aBBox
.X
+aBBox
.Width
)
271 && (aPoint
.Y
< aBBox
.Y
+aBBox
.Height
) )
277 // Have not found a child under the given point. Returning empty
278 // reference to indicate this.
279 return uno::Reference
<XAccessible
>();
282 // --------------------------------------------------------------------
284 ::com::sun::star::awt::Rectangle SAL_CALL
AccessibleCell::getBounds(void) throw(RuntimeException
)
286 SolarMutexGuard aSolarGuard
;
287 ::osl::MutexGuard
aGuard (maMutex
);
290 ::com::sun::star::awt::Rectangle aBoundingBox
;
293 // Get the cell's bounding box in internal coordinates (in 100th of mm)
294 const ::Rectangle
aCellRect( mxCell
->getCellRect() );
296 // Transform coordinates from internal to pixel.
297 if (maShapeTreeInfo
.GetViewForwarder() == NULL
)
298 throw uno::RuntimeException (OUString("AccessibleCell has no valid view forwarder"),static_cast<uno::XWeak
*>(this));
300 ::Size
aPixelSize( maShapeTreeInfo
.GetViewForwarder()->LogicToPixel(::Size(aCellRect
.GetWidth(), aCellRect
.GetHeight())) );
301 ::Point
aPixelPosition( maShapeTreeInfo
.GetViewForwarder()->LogicToPixel( aCellRect
.TopLeft() ));
303 // Clip the shape's bounding box with the bounding box of its parent.
304 Reference
<XAccessibleComponent
> xParentComponent ( getAccessibleParent(), uno::UNO_QUERY
);
305 if (xParentComponent
.is())
307 // Make the coordinates relative to the parent.
308 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
309 int x
= aPixelPosition
.getX() - aParentLocation
.X
;
310 int y
= aPixelPosition
.getY() - aParentLocation
.Y
;
312 // Clip with parent (with coordinates relative to itself).
313 ::Rectangle
aBBox ( x
, y
, x
+ aPixelSize
.getWidth(), y
+ aPixelSize
.getHeight());
314 awt::Size
aParentSize (xParentComponent
->getSize());
315 ::Rectangle
aParentBBox (0,0, aParentSize
.Width
, aParentSize
.Height
);
316 aBBox
= aBBox
.GetIntersection (aParentBBox
);
317 aBoundingBox
= awt::Rectangle ( aBBox
.getX(), aBBox
.getY(), aBBox
.getWidth(), aBBox
.getHeight());
321 OSL_TRACE ("parent does not support component");
322 aBoundingBox
= awt::Rectangle (aPixelPosition
.getX(), aPixelPosition
.getY(),aPixelSize
.getWidth(), aPixelSize
.getHeight());
329 // --------------------------------------------------------------------
331 ::com::sun::star::awt::Point SAL_CALL
AccessibleCell::getLocation(void) throw (RuntimeException
)
334 ::com::sun::star::awt::Rectangle
aBoundingBox(getBounds());
335 return ::com::sun::star::awt::Point(aBoundingBox
.X
, aBoundingBox
.Y
);
338 // --------------------------------------------------------------------
340 ::com::sun::star::awt::Point SAL_CALL
AccessibleCell::getLocationOnScreen(void) throw(RuntimeException
)
344 // Get relative position...
345 ::com::sun::star::awt::Point
aLocation(getLocation ());
347 // ... and add absolute position of the parent.
348 Reference
<XAccessibleComponent
> xParentComponent( getAccessibleParent(), uno::UNO_QUERY
);
349 if(xParentComponent
.is())
351 ::com::sun::star::awt::Point
aParentLocation(xParentComponent
->getLocationOnScreen());
352 aLocation
.X
+= aParentLocation
.X
;
353 aLocation
.Y
+= aParentLocation
.Y
;
357 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
363 // --------------------------------------------------------------------
365 awt::Size SAL_CALL
AccessibleCell::getSize (void) throw (RuntimeException
)
368 awt::Rectangle
aBoundingBox (getBounds());
369 return awt::Size (aBoundingBox
.Width
, aBoundingBox
.Height
);
372 // --------------------------------------------------------------------
374 void SAL_CALL
AccessibleCell::addFocusListener ( const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XFocusListener
>& xListener
) throw (::com::sun::star::uno::RuntimeException
)
376 AccessibleComponentBase::addFocusListener( xListener
);
379 // --------------------------------------------------------------------
381 void SAL_CALL
AccessibleCell::removeFocusListener (const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XFocusListener
>& xListener
) throw (::com::sun::star::uno::RuntimeException
)
383 AccessibleComponentBase::removeFocusListener( xListener
);
386 // --------------------------------------------------------------------
388 void SAL_CALL
AccessibleCell::grabFocus (void) throw (::com::sun::star::uno::RuntimeException
)
390 AccessibleComponentBase::grabFocus();
393 // --------------------------------------------------------------------
395 sal_Int32 SAL_CALL
AccessibleCell::getForeground(void) throw (RuntimeException
)
398 sal_Int32
nColor (0x0ffffffL
);
404 // --------------------------------------------------------------------
406 sal_Int32 SAL_CALL
AccessibleCell::getBackground (void) throw (RuntimeException
)
409 sal_Int32
nColor (0L);
415 // --------------------------------------------------------------------
416 // XAccessibleExtendedComponent
417 // --------------------------------------------------------------------
419 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XFont
> SAL_CALL
AccessibleCell::getFont (void) throw (::com::sun::star::uno::RuntimeException
)
422 return AccessibleComponentBase::getFont();
425 // --------------------------------------------------------------------
427 OUString SAL_CALL
AccessibleCell::getTitledBorderText (void) throw (::com::sun::star::uno::RuntimeException
)
429 return AccessibleComponentBase::getTitledBorderText();
432 // --------------------------------------------------------------------
434 OUString SAL_CALL
AccessibleCell::getToolTipText (void) throw (::com::sun::star::uno::RuntimeException
)
436 return AccessibleComponentBase::getToolTipText();
439 // --------------------------------------------------------------------
440 // XAccessibleEventBroadcaster
441 // --------------------------------------------------------------------
443 void SAL_CALL
AccessibleCell::addAccessibleEventListener( const Reference
<XAccessibleEventListener
>& rxListener
) throw (RuntimeException
)
445 SolarMutexGuard aSolarGuard
;
446 ::osl::MutexGuard
aGuard (maMutex
);
447 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
449 Reference
<XInterface
> xSource( static_cast<XComponent
*>(this) );
450 lang::EventObject
aEventObj(xSource
);
451 rxListener
->disposing(aEventObj
);
455 AccessibleContextBase::addAccessibleEventListener (rxListener
);
457 mpText
->AddEventListener (rxListener
);
461 // --------------------------------------------------------------------
463 void SAL_CALL
AccessibleCell::removeAccessibleEventListener( const Reference
<XAccessibleEventListener
>& rxListener
) throw (RuntimeException
)
465 SolarMutexGuard aSolarGuard
;
466 AccessibleContextBase::removeAccessibleEventListener(rxListener
);
468 mpText
->RemoveEventListener (rxListener
);
471 // --------------------------------------------------------------------
473 // --------------------------------------------------------------------
475 OUString SAL_CALL
AccessibleCell::getImplementationName(void) throw (RuntimeException
)
477 return OUString("AccessibleCell");
480 // --------------------------------------------------------------------
482 Sequence
<OUString
> SAL_CALL
AccessibleCell::getSupportedServiceNames(void) throw (RuntimeException
)
486 // Get list of supported service names from base class...
487 uno::Sequence
<OUString
> aServiceNames
= AccessibleContextBase::getSupportedServiceNames();
488 sal_Int32
nCount (aServiceNames
.getLength());
490 // ...and add additional names.
491 aServiceNames
.realloc (nCount
+ 1);
492 static const OUString
sAdditionalServiceName ("com.sun.star.drawing.AccessibleCell");
493 aServiceNames
[nCount
] = sAdditionalServiceName
;
495 return aServiceNames
;
498 // --------------------------------------------------------------------
499 // IAccessibleViewForwarderListener
500 // --------------------------------------------------------------------
502 void AccessibleCell::ViewForwarderChanged (ChangeType
/*aChangeType*/, const IAccessibleViewForwarder
* /*pViewForwarder*/)
504 // Inform all listeners that the graphical representation (i.e. size
505 // and/or position) of the shape has changed.
506 CommitChange(AccessibleEventId::VISIBLE_DATA_CHANGED
, Any(), Any());
508 // update our children that our screen position might have changed
510 mpText
->UpdateChildren();
513 // --------------------------------------------------------------------
515 // --------------------------------------------------------------------
517 void AccessibleCell::disposing (void)
519 SolarMutexGuard aSolarGuard
;
520 ::osl::MutexGuard
aGuard (maMutex
);
522 // Make sure to send an event that this object looses the focus in the
523 // case that it has the focus.
524 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
525 if (pStateSet
!= NULL
)
526 pStateSet
->RemoveState(AccessibleStateType::FOCUSED
);
535 // Cleanup. Remove references to objects to allow them to be
538 maShapeTreeInfo
= AccessibleShapeTreeInfo();
540 // Call base classes.
541 AccessibleContextBase::dispose ();
544 sal_Int32 SAL_CALL
AccessibleCell::getAccessibleIndexInParent (void) throw (RuntimeException
)
547 return mnIndexInParent
;
550 OUString SAL_CALL
AccessibleCell::getAccessibleName (void) throw (::com::sun::star::uno::RuntimeException
)
553 SolarMutexGuard aSolarGuard
;
556 return mxCell
->getName();
558 return AccessibleCellBase::getAccessibleName();
561 } // end of namespace accessibility
563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */