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 <tools/gen.hxx>
21 #include <osl/mutex.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/settings.hxx>
24 #include <rtl/ustring.hxx>
25 #include <com/sun/star/awt/Point.hpp>
26 #include <com/sun/star/awt/Rectangle.hpp>
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <com/sun/star/accessibility/AccessibleRole.hpp>
29 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
30 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
31 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
32 #include <comphelper/accessibleeventnotifier.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <unotools/accessiblestatesethelper.hxx>
35 #include <editeng/unolingu.hxx>
36 #include "editeng/AccessibleEditableTextPara.hxx"
37 #include "editeng/AccessibleImageBullet.hxx"
38 #include <editeng/eerdll.hxx>
40 #include <editeng/editdata.hxx>
41 #include <editeng/editeng.hxx>
42 #include <editeng/outliner.hxx>
43 #include "editeng.hrc"
44 #include <svtools/colorcfg.hxx>
47 using namespace ::com::sun::star
;
48 using namespace ::com::sun::star::accessibility
;
50 namespace accessibility
53 AccessibleImageBullet::AccessibleImageBullet ( const uno::Reference
< XAccessible
>& rParent
) :
54 mnParagraphIndex( 0 ),
59 // well, that's strictly (UNO) exception safe, though not
60 // really robust. We rely on the fact that this member is
61 // constructed last, and that the constructor body catches
62 // exceptions, thus no chance for exceptions once the Id is
63 // fetched. Nevertheless, normally should employ RAII here...
64 mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient())
67 OSL_TRACE( "Received ID: %d", mnNotifierClientId
);
72 // Create the state set.
73 ::utl::AccessibleStateSetHelper
* pStateSet
= new ::utl::AccessibleStateSetHelper ();
74 mxStateSet
= pStateSet
;
76 // these are always on
77 pStateSet
->AddState( AccessibleStateType::VISIBLE
);
78 pStateSet
->AddState( AccessibleStateType::SHOWING
);
79 pStateSet
->AddState( AccessibleStateType::ENABLED
);
80 pStateSet
->AddState( AccessibleStateType::SENSITIVE
);
82 catch( const uno::Exception
& ) {}
85 AccessibleImageBullet::~AccessibleImageBullet()
88 // sign off from event notifier
89 if( getNotifierClientId() != -1 )
93 ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() );
95 OSL_TRACE( "AccessibleImageBullet revoked ID: %d", mnNotifierClientId
);
98 catch( const uno::Exception
& ) {}
102 uno::Any SAL_CALL
AccessibleImageBullet::queryInterface (const uno::Type
& rType
) throw (uno::RuntimeException
, std::exception
)
105 return AccessibleImageBulletInterfaceBase::queryInterface(rType
);
108 uno::Reference
< XAccessibleContext
> SAL_CALL
AccessibleImageBullet::getAccessibleContext( ) throw (uno::RuntimeException
, std::exception
)
111 // We implement the XAccessibleContext interface in the same object
112 return uno::Reference
< XAccessibleContext
> ( this );
115 sal_Int32 SAL_CALL
AccessibleImageBullet::getAccessibleChildCount() throw (uno::RuntimeException
, std::exception
)
121 uno::Reference
< XAccessible
> SAL_CALL
AccessibleImageBullet::getAccessibleChild( sal_Int32 i
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
125 throw lang::IndexOutOfBoundsException("No children available",
126 uno::Reference
< uno::XInterface
>
127 ( static_cast< ::cppu::OWeakObject
* > (this) ) ); // static_cast: disambiguate hierarchy
130 uno::Reference
< XAccessible
> SAL_CALL
AccessibleImageBullet::getAccessibleParent() throw (uno::RuntimeException
, std::exception
)
136 sal_Int32 SAL_CALL
AccessibleImageBullet::getAccessibleIndexInParent() throw (uno::RuntimeException
, std::exception
)
139 return mnIndexInParent
;
142 sal_Int16 SAL_CALL
AccessibleImageBullet::getAccessibleRole() throw (uno::RuntimeException
, std::exception
)
145 return AccessibleRole::GRAPHIC
;
148 OUString SAL_CALL
AccessibleImageBullet::getAccessibleDescription() throw (uno::RuntimeException
, std::exception
)
151 SolarMutexGuard aGuard
;
153 // Get the string from the resource for the specified id.
154 return EE_RESSTR(RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION
);
157 OUString SAL_CALL
AccessibleImageBullet::getAccessibleName() throw (uno::RuntimeException
, std::exception
)
160 SolarMutexGuard aGuard
;
162 // Get the string from the resource for the specified id.
163 return EE_RESSTR(RID_SVXSTR_A11Y_IMAGEBULLET_NAME
);
166 uno::Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleImageBullet::getAccessibleRelationSet() throw (uno::RuntimeException
, std::exception
)
169 // no relations, therefore empty
170 return uno::Reference
< XAccessibleRelationSet
>();
173 uno::Reference
< XAccessibleStateSet
> SAL_CALL
AccessibleImageBullet::getAccessibleStateSet() throw (uno::RuntimeException
, std::exception
)
176 SolarMutexGuard aGuard
;
178 // Create a copy of the state set and return it.
179 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
182 return uno::Reference
<XAccessibleStateSet
>();
184 return uno::Reference
<XAccessibleStateSet
>( new ::utl::AccessibleStateSetHelper (*pStateSet
) );
187 lang::Locale SAL_CALL
AccessibleImageBullet::getLocale() throw (IllegalAccessibleComponentStateException
, uno::RuntimeException
, std::exception
)
190 SolarMutexGuard aGuard
;
192 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX
,
193 "AccessibleImageBullet::getLocale: paragraph index value overflow");
195 // return locale of first character in the paragraph
196 return LanguageTag(GetTextForwarder().GetLanguage( GetParagraphIndex(), 0 )).getLocale();
199 void SAL_CALL
AccessibleImageBullet::addAccessibleEventListener( const uno::Reference
< XAccessibleEventListener
>& xListener
) throw (uno::RuntimeException
, std::exception
)
202 if( getNotifierClientId() != -1 )
203 ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener
);
206 void SAL_CALL
AccessibleImageBullet::removeAccessibleEventListener( const uno::Reference
< XAccessibleEventListener
>& xListener
) throw (uno::RuntimeException
, std::exception
)
209 if( getNotifierClientId() != -1 )
211 const sal_Int32 nListenerCount
= ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener
);
212 if ( !nListenerCount
)
214 // no listeners anymore
215 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
216 // and at least to us not firing any events anymore, in case somebody calls
217 // NotifyAccessibleEvent, again
218 ::comphelper::AccessibleEventNotifier::TClientId
nId( getNotifierClientId() );
219 mnNotifierClientId
= -1;
220 ::comphelper::AccessibleEventNotifier::revokeClient( nId
);
225 sal_Bool SAL_CALL
AccessibleImageBullet::containsPoint( const awt::Point
& rPoint
) throw (uno::RuntimeException
, std::exception
)
228 SolarMutexGuard aGuard
;
230 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX
,
231 "AccessibleEditableTextPara::contains: index value overflow");
233 awt::Rectangle aTmpRect
= getBounds();
234 Rectangle
aRect( Point(aTmpRect
.X
, aTmpRect
.Y
), Size(aTmpRect
.Width
, aTmpRect
.Height
) );
235 Point
aPoint( rPoint
.X
, rPoint
.Y
);
237 return aRect
.IsInside( aPoint
);
240 uno::Reference
< XAccessible
> SAL_CALL
AccessibleImageBullet::getAccessibleAtPoint( const awt::Point
& /*aPoint*/ ) throw (uno::RuntimeException
, std::exception
)
243 // as we have no children, empty reference
244 return uno::Reference
< XAccessible
>();
247 awt::Rectangle SAL_CALL
AccessibleImageBullet::getBounds( ) throw (uno::RuntimeException
, std::exception
)
250 SolarMutexGuard aGuard
;
252 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX
,
253 "AccessibleEditableTextPara::getBounds: index value overflow");
255 SvxTextForwarder
& rCacheTF
= GetTextForwarder();
256 EBulletInfo aBulletInfo
= rCacheTF
.GetBulletInfo( GetParagraphIndex() );
257 Rectangle aParentRect
= rCacheTF
.GetParaBounds( GetParagraphIndex() );
259 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
260 aBulletInfo
.bVisible
&&
261 aBulletInfo
.nType
== SVX_NUM_BITMAP
)
263 Rectangle aRect
= aBulletInfo
.aBounds
;
265 // subtract paragraph position (bullet pos is absolute in EditEngine/Outliner)
266 aRect
.Move( -aParentRect
.Left(), -aParentRect
.Top() );
268 // convert to screen coordinates
269 Rectangle aScreenRect
= AccessibleEditableTextPara::LogicToPixel( aRect
,
270 rCacheTF
.GetMapMode(),
271 GetViewForwarder() );
273 // offset from shape/cell
274 Point aOffset
= GetEEOffset();
276 return awt::Rectangle( aScreenRect
.Left() + aOffset
.X(),
277 aScreenRect
.Top() + aOffset
.Y(),
278 aScreenRect
.GetSize().Width(),
279 aScreenRect
.GetSize().Height() );
282 return awt::Rectangle();
285 awt::Point SAL_CALL
AccessibleImageBullet::getLocation( ) throw (uno::RuntimeException
, std::exception
)
288 SolarMutexGuard aGuard
;
290 awt::Rectangle aRect
= getBounds();
292 return awt::Point( aRect
.X
, aRect
.Y
);
295 awt::Point SAL_CALL
AccessibleImageBullet::getLocationOnScreen( ) throw (uno::RuntimeException
, std::exception
)
298 SolarMutexGuard aGuard
;
300 // relate us to parent
301 uno::Reference
< XAccessible
> xParent
= getAccessibleParent();
304 uno::Reference
< XAccessibleComponent
> xParentComponent( xParent
, uno::UNO_QUERY
);
305 if( xParentComponent
.is() )
307 awt::Point aRefPoint
= xParentComponent
->getLocationOnScreen();
308 awt::Point aPoint
= getLocation();
309 aPoint
.X
+= aRefPoint
.X
;
310 aPoint
.Y
+= aRefPoint
.Y
;
316 throw uno::RuntimeException("Cannot access parent",
317 uno::Reference
< uno::XInterface
>
318 ( static_cast< XAccessible
* > (this) ) ); // disambiguate hierarchy
321 awt::Size SAL_CALL
AccessibleImageBullet::getSize( ) throw (uno::RuntimeException
, std::exception
)
324 SolarMutexGuard aGuard
;
326 awt::Rectangle aRect
= getBounds();
328 return awt::Size( aRect
.Width
, aRect
.Height
);
331 void SAL_CALL
AccessibleImageBullet::grabFocus( ) throw (uno::RuntimeException
, std::exception
)
334 throw uno::RuntimeException("Not focusable",
335 uno::Reference
< uno::XInterface
>
336 ( static_cast< XAccessible
* > (this) ) ); // disambiguate hierarchy
339 sal_Int32 SAL_CALL
AccessibleImageBullet::getForeground( ) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
342 // #104444# Added to XAccessibleComponent interface
343 svtools::ColorConfig aColorConfig
;
344 sal_uInt32 nColor
= aColorConfig
.GetColorValue( svtools::FONTCOLOR
).nColor
;
345 return static_cast<sal_Int32
>(nColor
);
348 sal_Int32 SAL_CALL
AccessibleImageBullet::getBackground( ) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
351 // #104444# Added to XAccessibleComponent interface
352 Color
aColor( Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor() );
354 // the background is transparent
355 aColor
.SetTransparency( 0xFF);
357 return static_cast<sal_Int32
>( aColor
.GetColor() );
360 OUString SAL_CALL
AccessibleImageBullet::getImplementationName() throw (uno::RuntimeException
, std::exception
)
363 return OUString("AccessibleImageBullet");
366 sal_Bool SAL_CALL
AccessibleImageBullet::supportsService (const OUString
& sServiceName
) throw (uno::RuntimeException
, std::exception
)
369 return cppu::supportsService(this, sServiceName
);
372 uno::Sequence
< OUString
> SAL_CALL
AccessibleImageBullet::getSupportedServiceNames() throw (uno::RuntimeException
, std::exception
)
375 const OUString
sServiceName ("com.sun.star.accessibility.AccessibleContext");
376 return uno::Sequence
< OUString
> (&sServiceName
, 1);
379 void AccessibleImageBullet::SetIndexInParent( sal_Int32 nIndex
)
382 mnIndexInParent
= nIndex
;
385 void AccessibleImageBullet::SetEEOffset( const Point
& rOffset
)
388 maEEOffset
= rOffset
;
391 void AccessibleImageBullet::Dispose()
394 int nClientId( getNotifierClientId() );
396 // #108212# drop all references before notifying dispose
398 mnNotifierClientId
= -1;
402 if( nClientId
!= -1 )
406 uno::Reference
< XAccessibleContext
> xThis
= getAccessibleContext();
408 // #106234# Delegate to EventNotifier
409 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId
, xThis
);
411 OSL_TRACE( "AccessibleImageBullet disposed ID: %d", nClientId
);
414 catch( const uno::Exception
& ) {}
418 void AccessibleImageBullet::SetEditSource( SvxEditSource
* pEditSource
)
421 mpEditSource
= pEditSource
;
426 UnSetState( AccessibleStateType::SHOWING
);
427 UnSetState( AccessibleStateType::VISIBLE
);
428 SetState( AccessibleStateType::INVALID
);
429 SetState( AccessibleStateType::DEFUNC
);
435 void AccessibleImageBullet::FireEvent(const sal_Int16 nEventId
, const uno::Any
& rNewValue
, const uno::Any
& rOldValue
) const
438 uno::Reference
< XAccessibleContext
> xThis( const_cast< AccessibleImageBullet
* > (this)->getAccessibleContext() );
440 AccessibleEventObject
aEvent(xThis
, nEventId
, rNewValue
, rOldValue
);
442 // #106234# Delegate to EventNotifier
443 ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(),
447 void AccessibleImageBullet::GotPropertyEvent( const uno::Any
& rNewValue
, const sal_Int16 nEventId
) const
450 FireEvent( nEventId
, rNewValue
);
453 void AccessibleImageBullet::LostPropertyEvent( const uno::Any
& rOldValue
, const sal_Int16 nEventId
) const
456 FireEvent( nEventId
, uno::Any(), rOldValue
);
459 void AccessibleImageBullet::SetState( const sal_Int16 nStateId
)
462 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
463 if( pStateSet
!= NULL
&&
464 !pStateSet
->contains(nStateId
) )
466 pStateSet
->AddState( nStateId
);
467 GotPropertyEvent( uno::makeAny( nStateId
), AccessibleEventId::STATE_CHANGED
);
471 void AccessibleImageBullet::UnSetState( const sal_Int16 nStateId
)
474 ::utl::AccessibleStateSetHelper
* pStateSet
= static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
475 if( pStateSet
!= NULL
&&
476 pStateSet
->contains(nStateId
) )
478 pStateSet
->RemoveState( nStateId
);
479 LostPropertyEvent( uno::makeAny( nStateId
), AccessibleEventId::STATE_CHANGED
);
484 void AccessibleImageBullet::SetParagraphIndex( sal_Int32 nIndex
)
492 aOldDesc
<<= getAccessibleDescription();
493 aOldName
<<= getAccessibleName();
495 catch( const uno::Exception
& ) {} // optional behaviour
497 sal_Int32 nOldIndex
= mnParagraphIndex
;
499 mnParagraphIndex
= nIndex
;
503 if( nOldIndex
!= nIndex
)
505 // index and therefore description changed
506 FireEvent( AccessibleEventId::DESCRIPTION_CHANGED
, uno::makeAny( getAccessibleDescription() ), aOldDesc
);
507 FireEvent( AccessibleEventId::NAME_CHANGED
, uno::makeAny( getAccessibleName() ), aOldName
);
510 catch( const uno::Exception
& ) {} // optional behaviour
514 SvxEditSource
& AccessibleImageBullet::GetEditSource() const
518 return *mpEditSource
;
520 throw uno::RuntimeException("No edit source, object is defunct",
521 uno::Reference
< uno::XInterface
>
522 ( static_cast< ::cppu::OWeakObject
* >
523 ( const_cast< AccessibleImageBullet
* > (this) ) ) ); // disambiguate hierarchy
526 SvxTextForwarder
& AccessibleImageBullet::GetTextForwarder() const
529 SvxEditSource
& rEditSource
= GetEditSource();
530 SvxTextForwarder
* pTextForwarder
= rEditSource
.GetTextForwarder();
532 if( !pTextForwarder
)
533 throw uno::RuntimeException("Unable to fetch text forwarder, object is defunct",
534 uno::Reference
< uno::XInterface
>
535 ( static_cast< ::cppu::OWeakObject
* >
536 ( const_cast< AccessibleImageBullet
* > (this) ) ) ); // disambiguate hierarchy
538 if( pTextForwarder
->IsValid() )
539 return *pTextForwarder
;
541 throw uno::RuntimeException("Text forwarder is invalid, object is defunct",
542 uno::Reference
< uno::XInterface
>
543 ( static_cast< ::cppu::OWeakObject
* >
544 ( const_cast< AccessibleImageBullet
* > (this) ) ) ); // disambiguate hierarchy
547 SvxViewForwarder
& AccessibleImageBullet::GetViewForwarder() const
550 SvxEditSource
& rEditSource
= GetEditSource();
551 SvxViewForwarder
* pViewForwarder
= rEditSource
.GetViewForwarder();
553 if( !pViewForwarder
)
555 throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct",
556 uno::Reference
< uno::XInterface
>
557 ( static_cast< ::cppu::OWeakObject
* >
558 ( const_cast< AccessibleImageBullet
* > (this) ) ) ); // disambiguate hierarchy
561 if( pViewForwarder
->IsValid() )
562 return *pViewForwarder
;
564 throw uno::RuntimeException("View forwarder is invalid, object is defunct",
565 uno::Reference
< uno::XInterface
>
566 ( static_cast< ::cppu::OWeakObject
* >
567 ( const_cast< AccessibleImageBullet
* > (this) ) ) ); // disambiguate hierarchy
571 } // end of namespace accessibility
573 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */