LibreOffice Module editeng (master) 1
AccessibleImageBullet.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <tools/gen.hxx>
21#include <tools/debug.hxx>
22#include <utility>
23#include <vcl/svapp.hxx>
24#include <vcl/settings.hxx>
25#include <rtl/ustring.hxx>
26#include <com/sun/star/awt/Point.hpp>
27#include <com/sun/star/awt/Rectangle.hpp>
28#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
29#include <com/sun/star/accessibility/AccessibleRole.hpp>
30#include <com/sun/star/accessibility/AccessibleStateType.hpp>
31#include <com/sun/star/accessibility/AccessibleEventId.hpp>
36#include <editeng/eerdll.hxx>
37
38#include <editeng/editdata.hxx>
39#include <editeng/outliner.hxx>
40#include <editeng/editrids.hrc>
41#include <editeng/unoedsrc.hxx>
42#include <svtools/colorcfg.hxx>
43
45
46using namespace ::com::sun::star;
47using namespace ::com::sun::star::accessibility;
48
49namespace accessibility
50{
51
52 AccessibleImageBullet::AccessibleImageBullet ( uno::Reference< XAccessible > xParent ) :
54 mnIndexInParent( 0 ),
55 mpEditSource( nullptr ),
56 maEEOffset( 0, 0 ),
57 mxParent(std::move( xParent )),
58 // well, that's strictly (UNO) exception safe, though not
59 // really robust. We rely on the fact that this member is
60 // constructed last, and that the constructor body catches
61 // exceptions, thus no chance for exceptions once the Id is
62 // fetched. Nevertheless, normally should employ RAII here...
63 mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient())
64 {
65 try
66 {
67 // Create the state set.
68 mnStateSet = 0;
69
70 // these are always on
71 mnStateSet |= AccessibleStateType::VISIBLE;
72 mnStateSet |= AccessibleStateType::SHOWING;
73 mnStateSet |= AccessibleStateType::ENABLED;
74 mnStateSet |= AccessibleStateType::SENSITIVE;
75 }
76 catch( const uno::Exception& ) {}
77 }
78
79 AccessibleImageBullet::~AccessibleImageBullet()
80 {
81
82 // sign off from event notifier
83 if( getNotifierClientId() != -1 )
84 {
85 try
86 {
88 }
89 catch( const uno::Exception& ) {}
90 }
91 }
92
93 uno::Reference< XAccessibleContext > SAL_CALL AccessibleImageBullet::getAccessibleContext( )
94 {
95
96 // We implement the XAccessibleContext interface in the same object
97 return uno::Reference< XAccessibleContext > ( this );
98 }
99
100 sal_Int64 SAL_CALL AccessibleImageBullet::getAccessibleChildCount()
101 {
102
103 return 0;
104 }
105
106 uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleChild( sal_Int64 )
107 {
108 throw lang::IndexOutOfBoundsException("No children available",
109 getXWeak() );
110 }
111
112 uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleParent()
113 {
114
115 return mxParent;
116 }
117
118 sal_Int64 SAL_CALL AccessibleImageBullet::getAccessibleIndexInParent()
119 {
120
121 return mnIndexInParent;
122 }
123
124 sal_Int16 SAL_CALL AccessibleImageBullet::getAccessibleRole()
125 {
126
127 return AccessibleRole::GRAPHIC;
128 }
129
130 OUString SAL_CALL AccessibleImageBullet::getAccessibleDescription()
131 {
132 // Get the string from the resource for the specified id.
133 return EditResId(RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION);
134 }
135
136 OUString SAL_CALL AccessibleImageBullet::getAccessibleName()
137 {
138 // Get the string from the resource for the specified id.
139 return EditResId(RID_SVXSTR_A11Y_IMAGEBULLET_NAME);
140 }
141
142 uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleImageBullet::getAccessibleRelationSet()
143 {
144
145 // no relations, therefore empty
146 return uno::Reference< XAccessibleRelationSet >();
147 }
148
149 sal_Int64 SAL_CALL AccessibleImageBullet::getAccessibleStateSet()
150 {
151 SolarMutexGuard aGuard;
152
153 // Create a copy of the state set and return it.
154
155 return mnStateSet;
156 }
157
158 lang::Locale SAL_CALL AccessibleImageBullet::getLocale()
159 {
160
161 SolarMutexGuard aGuard;
162
163 DBG_ASSERT(GetParagraphIndex() >= 0,
164 "AccessibleImageBullet::getLocale: paragraph index value overflow");
165
166 // return locale of first character in the paragraph
167 return LanguageTag(GetTextForwarder().GetLanguage( GetParagraphIndex(), 0 )).getLocale();
168 }
169
170 void SAL_CALL AccessibleImageBullet::addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
171 {
172
173 if( getNotifierClientId() != -1 )
174 ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener );
175 }
176
177 void SAL_CALL AccessibleImageBullet::removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
178 {
179
180 if( getNotifierClientId() == -1 )
181 return;
182
183 const sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener );
184 if ( !nListenerCount )
185 {
186 // no listeners anymore
187 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
188 // and at least to us not firing any events anymore, in case somebody calls
189 // NotifyAccessibleEvent, again
191 mnNotifierClientId = -1;
193 }
194 }
195
196 sal_Bool SAL_CALL AccessibleImageBullet::containsPoint( const awt::Point& rPoint )
197 {
198
199 SolarMutexGuard aGuard;
200
201 DBG_ASSERT(GetParagraphIndex() >= 0,
202 "AccessibleEditableTextPara::contains: index value overflow");
203
204 awt::Rectangle aTmpRect = implGetBounds();
205 tools::Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) );
206 Point aPoint( rPoint.X, rPoint.Y );
207
208 return aRect.Contains( aPoint );
209 }
210
211 uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleAtPoint( const awt::Point& /*aPoint*/ )
212 {
213
214 // as we have no children, empty reference
215 return uno::Reference< XAccessible >();
216 }
217
218 awt::Rectangle SAL_CALL AccessibleImageBullet::getBounds( )
219 {
220 SolarMutexGuard aGuard;
221
222 return implGetBounds();
223 }
224 awt::Rectangle AccessibleImageBullet::implGetBounds( )
225 {
226
227 DBG_ASSERT(GetParagraphIndex() >= 0,
228 "AccessibleEditableTextPara::implGetBounds: index value overflow");
229
230 SvxTextForwarder& rCacheTF = GetTextForwarder();
231 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( GetParagraphIndex() );
232 tools::Rectangle aParentRect = rCacheTF.GetParaBounds( GetParagraphIndex() );
233
234 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
235 aBulletInfo.bVisible &&
236 aBulletInfo.nType == SVX_NUM_BITMAP )
237 {
238 tools::Rectangle aRect = aBulletInfo.aBounds;
239
240 // subtract paragraph position (bullet pos is absolute in EditEngine/Outliner)
241 aRect.Move( -aParentRect.Left(), -aParentRect.Top() );
242
243 // convert to screen coordinates
244 tools::Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect,
245 rCacheTF.GetMapMode(),
246 GetViewForwarder() );
247
248 // offset from shape/cell
249 Point aOffset = maEEOffset;
250
251 return awt::Rectangle( aScreenRect.Left() + aOffset.X(),
252 aScreenRect.Top() + aOffset.Y(),
253 aScreenRect.GetSize().Width(),
254 aScreenRect.GetSize().Height() );
255 }
256
257 return awt::Rectangle();
258 }
259
260 awt::Point SAL_CALL AccessibleImageBullet::getLocation( )
261 {
262
263 SolarMutexGuard aGuard;
264
265 awt::Rectangle aRect = implGetBounds();
266
267 return awt::Point( aRect.X, aRect.Y );
268 }
269
270 awt::Point SAL_CALL AccessibleImageBullet::getLocationOnScreen( )
271 {
272
273 SolarMutexGuard aGuard;
274
275 // relate us to parent
276 uno::Reference< XAccessible > xParent = getAccessibleParent();
277 if( xParent.is() )
278 {
279 uno::Reference< XAccessibleComponent > xParentComponent( xParent, uno::UNO_QUERY );
280 if( xParentComponent.is() )
281 {
282 awt::Point aRefPoint = xParentComponent->getLocationOnScreen();
283 awt::Point aPoint = getLocation();
284 aPoint.X += aRefPoint.X;
285 aPoint.Y += aRefPoint.Y;
286
287 return aPoint;
288 }
289 }
290
291 throw uno::RuntimeException("Cannot access parent",
292 uno::Reference< uno::XInterface >
293 ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
294 }
295
296 awt::Size SAL_CALL AccessibleImageBullet::getSize( )
297 {
298
299 SolarMutexGuard aGuard;
300
301 awt::Rectangle aRect = implGetBounds();
302
303 return awt::Size( aRect.Width, aRect.Height );
304 }
305
306 void SAL_CALL AccessibleImageBullet::grabFocus( )
307 {
308
309 throw uno::RuntimeException("Not focusable",
310 uno::Reference< uno::XInterface >
311 ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
312 }
313
314 sal_Int32 SAL_CALL AccessibleImageBullet::getForeground( )
315 {
316
317 // #104444# Added to XAccessibleComponent interface
318 svtools::ColorConfig aColorConfig;
319 Color nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
320 return static_cast<sal_Int32>(nColor);
321 }
322
323 sal_Int32 SAL_CALL AccessibleImageBullet::getBackground( )
324 {
325
326 // #104444# Added to XAccessibleComponent interface
327 Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor() );
328
329 // the background is transparent
330 aColor.SetAlpha(0);
331
332 return static_cast<sal_Int32>( aColor );
333 }
334
335 OUString SAL_CALL AccessibleImageBullet::getImplementationName()
336 {
337
338 return "AccessibleImageBullet";
339 }
340
341 sal_Bool SAL_CALL AccessibleImageBullet::supportsService (const OUString& sServiceName)
342 {
343
345 }
346
347 uno::Sequence< OUString > SAL_CALL AccessibleImageBullet::getSupportedServiceNames()
348 {
349 return { "com.sun.star.accessibility.AccessibleContext" };
350 }
351
352 void AccessibleImageBullet::SetIndexInParent( sal_Int32 nIndex )
353 {
354
355 mnIndexInParent = nIndex;
356 }
357
358 void AccessibleImageBullet::SetEEOffset( const Point& rOffset )
359 {
360
361 maEEOffset = rOffset;
362 }
363
364 void AccessibleImageBullet::Dispose()
365 {
366
367 int nClientId( getNotifierClientId() );
368
369 // #108212# drop all references before notifying dispose
370 mxParent = nullptr;
371 mnNotifierClientId = -1;
372 mpEditSource = nullptr;
373
374 // notify listeners
375 if( nClientId != -1 )
376 {
377 try
378 {
379 uno::Reference < XAccessibleContext > xThis = getAccessibleContext();
380
381 // #106234# Delegate to EventNotifier
383 }
384 catch( const uno::Exception& ) {}
385 }
386 }
387
388 void AccessibleImageBullet::SetEditSource( SvxEditSource* pEditSource )
389 {
390
391 mpEditSource = pEditSource;
392
393 if( !mpEditSource )
394 {
395 // going defunc
396 UnSetState( AccessibleStateType::SHOWING );
397 UnSetState( AccessibleStateType::VISIBLE );
398 SetState( AccessibleStateType::INVALID );
399 SetState( AccessibleStateType::DEFUNC );
400
401 Dispose();
402 }
403 }
404
405 void AccessibleImageBullet::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
406 {
407
408 uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleImageBullet* > (this)->getAccessibleContext() );
409
410 AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue, -1);
411
412 // #106234# Delegate to EventNotifier
414 aEvent );
415 }
416
417 void AccessibleImageBullet::SetState( const sal_Int64 nStateId )
418 {
419 if( !(mnStateSet & nStateId) )
420 {
421 mnStateSet |= nStateId;
422 FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any( nStateId ) );
423 }
424 }
425
426 void AccessibleImageBullet::UnSetState( const sal_Int64 nStateId )
427 {
428 if( mnStateSet & nStateId )
429 {
430 mnStateSet &= ~nStateId;
431 FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::Any( nStateId ) );
432 }
433 }
434
435
436 void AccessibleImageBullet::SetParagraphIndex( sal_Int32 nIndex )
437 {
438
439 uno::Any aOldDesc;
440 uno::Any aOldName;
441
442 try
443 {
444 aOldDesc <<= getAccessibleDescription();
445 aOldName <<= getAccessibleName();
446 }
447 catch( const uno::Exception& ) {} // optional behaviour
448
449 sal_Int32 nOldIndex = mnParagraphIndex;
450
452
453 try
454 {
455 if( nOldIndex != nIndex )
456 {
457 // index and therefore description changed
458 FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::Any( getAccessibleDescription() ), aOldDesc );
459 FireEvent( AccessibleEventId::NAME_CHANGED, uno::Any( getAccessibleName() ), aOldName );
460 }
461 }
462 catch( const uno::Exception& ) {} // optional behaviour
463 }
464
465
466 SvxEditSource& AccessibleImageBullet::GetEditSource() const
467 {
468
469 if( !mpEditSource )
470 throw uno::RuntimeException("No edit source, object is defunct",
471 cppu::getXWeak
472 ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy
473 return *mpEditSource;
474 }
475
476 SvxTextForwarder& AccessibleImageBullet::GetTextForwarder() const
477 {
478
479 SvxEditSource& rEditSource = GetEditSource();
480 SvxTextForwarder* pTextForwarder = rEditSource.GetTextForwarder();
481
482 if( !pTextForwarder )
483 throw uno::RuntimeException("Unable to fetch text forwarder, object is defunct",
484 cppu::getXWeak
485 ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy
486
487 if( !pTextForwarder->IsValid() )
488 throw uno::RuntimeException("Text forwarder is invalid, object is defunct",
489 cppu::getXWeak
490 ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy
491 return *pTextForwarder;
492 }
493
494 SvxViewForwarder& AccessibleImageBullet::GetViewForwarder() const
495 {
496
497 SvxEditSource& rEditSource = GetEditSource();
498 SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder();
499
500 if( !pViewForwarder )
501 {
502 throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct",
503 cppu::getXWeak
504 ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy
505 }
506
507 if( !pViewForwarder->IsValid() )
508 throw uno::RuntimeException("View forwarder is invalid, object is defunct",
509 cppu::getXWeak
510 ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy
511 return *pViewForwarder;
512 }
513
514
515} // end of namespace accessibility
516
517/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr OUStringLiteral sServiceName
unotools::WeakReference< AnimationNode > mxParent
AnyEventRef aEvent
static const AllSettings & GetSettings()
void SetAlpha(sal_uInt8 nAlpha)
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
constexpr tools::Long Y() const
constexpr tools::Long X() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
Wrapper class for unified EditEngine/Outliner access.
Definition: unoedsrc.hxx:56
virtual SvxTextForwarder * GetTextForwarder()=0
Query the text forwarder.
virtual SvxViewForwarder * GetViewForwarder()
Query the view forwarder.
Definition: unoedsrc.cxx:58
Contains an EditEngine or an Outliner and unifies access to them.
Definition: unoedsrc.hxx:142
virtual bool IsValid() const =0
Query state of forwarder.
virtual MapMode GetMapMode() const =0
Query the map mode of the underlying EditEngine/Outliner.
virtual EBulletInfo GetBulletInfo(sal_Int32 nPara) const =0
Query information regarding bullets for given paragraph on the underlying edit engine.
virtual tools::Rectangle GetParaBounds(sal_Int32 nPara) const =0
Query the bounding rectangle of the given paragraph.
Encapsulates the document view for the purpose of unified EditEngine/Outliner access.
Definition: unoedsrc.hxx:452
virtual bool IsValid() const =0
Query state of forwarder.
This class implements the image bullets for the EditEngine/Outliner UAA.
AccessibleImageBullet(css::uno::Reference< css::accessibility::XAccessible > xParent)
Create accessible object for given parent.
static sal_Int32 addEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
static void addEvent(const TClientId _nClient, const css::accessibility::AccessibleEventObject &_rEvent)
static sal_Int32 removeEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
static void revokeClient(const TClientId _nClient)
static void revokeClientNotifyDisposing(const TClientId _nClient, const css::uno::Reference< css::uno::XInterface > &_rxEventSource)
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
bool Contains(const Point &rPOINT) const
constexpr tools::Long Top() const
constexpr Size GetSize() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Left() const
#define DBG_ASSERT(sCon, aError)
#define EE_PARA_NOT_FOUND
Definition: editdata.hxx:48
OUString EditResId(TranslateId aId)
Definition: eerdll.cxx:192
sal_Int32 nIndex
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
void Dispose(const T &xInterface)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
sal_Int16 nId
sal_uInt16 nType
Definition: outliner.hxx:557
tools::Rectangle aBounds
Definition: outliner.hxx:554
sal_Int32 nParagraph
Definition: outliner.hxx:556
bool bVisible
Definition: outliner.hxx:558
@ SVX_NUM_BITMAP
Definition: svxenum.hxx:153
sal_Int16 mnParagraphIndex
unsigned char sal_Bool