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 <sal/config.h>
24 #include <com/sun/star/accessibility/AccessibleRole.hpp>
25 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
26 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
27 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
28 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <unotools/accessiblerelationsethelper.hxx>
32 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
33 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
34 #include <com/sun/star/i18n/WordType.hpp>
35 #include <unotools/accessiblestatesethelper.hxx>
36 #include <comphelper/accessibleeventnotifier.hxx>
37 #include <cppuhelper/supportsservice.hxx>
38 #include <osl/diagnose.h>
39 #include <svx/AccessibleTextHelper.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/window.hxx>
42 #include <vcl/unohelp2.hxx>
43 #include <vcl/settings.hxx>
45 #include <tools/gen.hxx>
46 #include <svl/itemset.hxx>
48 #include <editeng/editobj.hxx>
49 #include <editeng/editdata.hxx>
50 #include <editeng/editview.hxx>
51 #include <editeng/eeitem.hxx>
52 #include <editeng/outliner.hxx>
53 #include <editeng/unoedhlp.hxx>
56 #include "accessibility.hxx"
57 #include <document.hxx>
59 #include <o3tl/make_unique.hxx>
60 #include <strings.hrc>
62 using namespace com::sun::star
;
63 using namespace com::sun::star::lang
;
64 using namespace com::sun::star::uno
;
65 using namespace com::sun::star::accessibility
;
68 static awt::Rectangle
lcl_GetBounds( vcl::Window
const *pWin
)
70 // !! see VCLXAccessibleComponent::implGetBounds()
72 //! the coordinates returned are relative to the parent window !
73 //! Thus the top-left point may be different from (0, 0) !
75 awt::Rectangle aBounds
;
78 tools::Rectangle aRect
= pWin
->GetWindowExtentsRelative( nullptr );
79 aBounds
.X
= aRect
.Left();
80 aBounds
.Y
= aRect
.Top();
81 aBounds
.Width
= aRect
.GetWidth();
82 aBounds
.Height
= aRect
.GetHeight();
83 vcl::Window
* pParent
= pWin
->GetAccessibleParentWindow();
86 tools::Rectangle aParentRect
= pParent
->GetWindowExtentsRelative( nullptr );
87 awt::Point
aParentScreenLoc( aParentRect
.Left(), aParentRect
.Top() );
88 aBounds
.X
-= aParentScreenLoc
.X
;
89 aBounds
.Y
-= aParentScreenLoc
.Y
;
95 static awt::Point
lcl_GetLocationOnScreen( vcl::Window
const *pWin
)
97 // !! see VCLXAccessibleComponent::getLocationOnScreen()
102 tools::Rectangle aRect
= pWin
->GetWindowExtentsRelative( nullptr );
103 aPos
.X
= aRect
.Left();
104 aPos
.Y
= aRect
.Top();
110 SmGraphicAccessible::SmGraphicAccessible( SmGraphicWindow
*pGraphicWin
) :
111 aAccName (SmResId(RID_DOCUMENTSTR
)),
115 OSL_ENSURE( pWin
, "SmGraphicAccessible: window missing" );
118 SmGraphicAccessible::~SmGraphicAccessible()
123 SmDocShell
* SmGraphicAccessible::GetDoc_Impl()
125 SmViewShell
*pView
= pWin
? pWin
->GetView() : nullptr;
126 return pView
? pView
->GetDoc() : nullptr;
129 OUString
SmGraphicAccessible::GetAccessibleText_Impl()
132 SmDocShell
*pDoc
= GetDoc_Impl();
134 aTxt
= pDoc
->GetAccessibleText();
138 void SmGraphicAccessible::ClearWin()
140 pWin
= nullptr; // implicitly results in AccessibleStateType::DEFUNC set
144 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId
, *this );
149 void SmGraphicAccessible::LaunchEvent(
150 const sal_Int16 nAccessibleEventId
,
151 const uno::Any
&rOldVal
,
152 const uno::Any
&rNewVal
)
154 AccessibleEventObject aEvt
;
155 aEvt
.Source
= static_cast<XAccessible
*>(this);
156 aEvt
.EventId
= nAccessibleEventId
;
157 aEvt
.OldValue
= rOldVal
;
158 aEvt
.NewValue
= rNewVal
;
160 // pass event on to event-listener's
162 comphelper::AccessibleEventNotifier::addEvent( nClientId
, aEvt
);
165 uno::Reference
< XAccessibleContext
> SAL_CALL
SmGraphicAccessible::getAccessibleContext()
170 sal_Bool SAL_CALL
SmGraphicAccessible::containsPoint( const awt::Point
& aPoint
)
172 //! the arguments coordinates are relative to the current window !
173 //! Thus the top-left point is (0, 0)
175 SolarMutexGuard aGuard
;
177 throw RuntimeException();
179 Size
aSz( pWin
->GetSizePixel() );
180 return aPoint
.X
>= 0 && aPoint
.Y
>= 0 &&
181 aPoint
.X
< aSz
.Width() && aPoint
.Y
< aSz
.Height();
184 uno::Reference
< XAccessible
> SAL_CALL
SmGraphicAccessible::getAccessibleAtPoint(
185 const awt::Point
& aPoint
)
187 SolarMutexGuard aGuard
;
188 XAccessible
*pRes
= nullptr;
189 if (containsPoint( aPoint
))
194 awt::Rectangle SAL_CALL
SmGraphicAccessible::getBounds()
196 SolarMutexGuard aGuard
;
198 throw RuntimeException();
199 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
200 "mismatch of window parent and accessible parent" );
201 return lcl_GetBounds( pWin
);
204 awt::Point SAL_CALL
SmGraphicAccessible::getLocation()
206 SolarMutexGuard aGuard
;
208 throw RuntimeException();
209 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
210 "mismatch of window parent and accessible parent" );
211 awt::Rectangle
aRect( lcl_GetBounds( pWin
) );
212 return awt::Point( aRect
.X
, aRect
.Y
);
215 awt::Point SAL_CALL
SmGraphicAccessible::getLocationOnScreen()
217 SolarMutexGuard aGuard
;
219 throw RuntimeException();
220 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
221 "mismatch of window parent and accessible parent" );
222 return lcl_GetLocationOnScreen( pWin
);
225 awt::Size SAL_CALL
SmGraphicAccessible::getSize()
227 SolarMutexGuard aGuard
;
229 throw RuntimeException();
230 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
231 "mismatch of window parent and accessible parent" );
233 Size
aSz( pWin
->GetSizePixel() );
234 #if OSL_DEBUG_LEVEL > 0
235 awt::Rectangle
aRect( lcl_GetBounds( pWin
) );
236 Size
aSz2( aRect
.Width
, aRect
.Height
);
237 assert(aSz
== aSz2
&& "mismatch in width" );
239 return awt::Size( aSz
.Width(), aSz
.Height() );
242 void SAL_CALL
SmGraphicAccessible::grabFocus()
244 SolarMutexGuard aGuard
;
246 throw RuntimeException();
251 sal_Int32 SAL_CALL
SmGraphicAccessible::getForeground()
253 SolarMutexGuard aGuard
;
256 throw RuntimeException();
257 return static_cast<sal_Int32
>(pWin
->GetTextColor());
260 sal_Int32 SAL_CALL
SmGraphicAccessible::getBackground()
262 SolarMutexGuard aGuard
;
265 throw RuntimeException();
266 Wallpaper
aWall( pWin
->GetDisplayBackground() );
268 if (aWall
.IsBitmap() || aWall
.IsGradient())
269 nCol
= pWin
->GetSettings().GetStyleSettings().GetWindowColor();
271 nCol
= aWall
.GetColor();
272 return static_cast<sal_Int32
>(nCol
);
275 sal_Int32 SAL_CALL
SmGraphicAccessible::getAccessibleChildCount()
280 Reference
< XAccessible
> SAL_CALL
SmGraphicAccessible::getAccessibleChild(
283 throw IndexOutOfBoundsException(); // there is no child...
286 Reference
< XAccessible
> SAL_CALL
SmGraphicAccessible::getAccessibleParent()
288 SolarMutexGuard aGuard
;
290 throw RuntimeException();
292 vcl::Window
*pAccParent
= pWin
->GetAccessibleParentWindow();
293 OSL_ENSURE( pAccParent
, "accessible parent missing" );
294 return pAccParent
? pAccParent
->GetAccessible() : Reference
< XAccessible
>();
297 sal_Int32 SAL_CALL
SmGraphicAccessible::getAccessibleIndexInParent()
299 SolarMutexGuard aGuard
;
301 vcl::Window
*pAccParent
= pWin
? pWin
->GetAccessibleParentWindow() : nullptr;
304 sal_uInt16 nCnt
= pAccParent
->GetAccessibleChildWindowCount();
305 for (sal_uInt16 i
= 0; i
< nCnt
&& nIdx
== -1; ++i
)
306 if (pAccParent
->GetAccessibleChildWindow( i
) == pWin
)
312 sal_Int16 SAL_CALL
SmGraphicAccessible::getAccessibleRole()
314 return AccessibleRole::DOCUMENT
;
317 OUString SAL_CALL
SmGraphicAccessible::getAccessibleDescription()
319 SolarMutexGuard aGuard
;
320 SmDocShell
*pDoc
= GetDoc_Impl();
321 return pDoc
? pDoc
->GetText() : OUString();
324 OUString SAL_CALL
SmGraphicAccessible::getAccessibleName()
326 SolarMutexGuard aGuard
;
330 Reference
< XAccessibleRelationSet
> SAL_CALL
SmGraphicAccessible::getAccessibleRelationSet()
332 SolarMutexGuard aGuard
;
333 Reference
< XAccessibleRelationSet
> xRelSet
= new utl::AccessibleRelationSetHelper();
334 return xRelSet
; // empty relation set
337 Reference
< XAccessibleStateSet
> SAL_CALL
SmGraphicAccessible::getAccessibleStateSet()
339 SolarMutexGuard aGuard
;
340 ::utl::AccessibleStateSetHelper
*pStateSet
=
341 new ::utl::AccessibleStateSetHelper
;
343 Reference
<XAccessibleStateSet
> xStateSet( pStateSet
);
346 pStateSet
->AddState( AccessibleStateType::DEFUNC
);
349 pStateSet
->AddState( AccessibleStateType::ENABLED
);
350 pStateSet
->AddState( AccessibleStateType::FOCUSABLE
);
351 if (pWin
->HasFocus())
352 pStateSet
->AddState( AccessibleStateType::FOCUSED
);
353 if (pWin
->IsActive())
354 pStateSet
->AddState( AccessibleStateType::ACTIVE
);
355 if (pWin
->IsVisible())
356 pStateSet
->AddState( AccessibleStateType::SHOWING
);
357 if (pWin
->IsReallyVisible())
358 pStateSet
->AddState( AccessibleStateType::VISIBLE
);
359 if (COL_TRANSPARENT
!= pWin
->GetBackground().GetColor())
360 pStateSet
->AddState( AccessibleStateType::OPAQUE
);
366 Locale SAL_CALL
SmGraphicAccessible::getLocale()
368 SolarMutexGuard aGuard
;
369 // should be the document language...
370 // We use the language of the localized symbol names here.
371 return Application::GetSettings().GetUILanguageTag().getLocale();
375 void SAL_CALL
SmGraphicAccessible::addAccessibleEventListener(
376 const Reference
< XAccessibleEventListener
>& xListener
)
380 SolarMutexGuard aGuard
;
384 nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
385 comphelper::AccessibleEventNotifier::addEventListener( nClientId
, xListener
);
390 void SAL_CALL
SmGraphicAccessible::removeAccessibleEventListener(
391 const Reference
< XAccessibleEventListener
>& xListener
)
393 if (xListener
.is() && nClientId
)
395 SolarMutexGuard aGuard
;
396 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( nClientId
, xListener
);
397 if ( !nListenerCount
)
399 // no listeners anymore
400 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
401 // and at least to us not firing any events anymore, in case somebody calls
402 // NotifyAccessibleEvent, again
403 comphelper::AccessibleEventNotifier::revokeClient( nClientId
);
409 sal_Int32 SAL_CALL
SmGraphicAccessible::getCaretPosition()
414 sal_Bool SAL_CALL
SmGraphicAccessible::setCaretPosition( sal_Int32 nIndex
)
416 SolarMutexGuard aGuard
;
417 OUString
aTxt( GetAccessibleText_Impl() );
418 if (nIndex
>= aTxt
.getLength())
419 throw IndexOutOfBoundsException();
423 sal_Unicode SAL_CALL
SmGraphicAccessible::getCharacter( sal_Int32 nIndex
)
425 SolarMutexGuard aGuard
;
426 OUString
aTxt( GetAccessibleText_Impl() );
427 if (nIndex
>= aTxt
.getLength())
428 throw IndexOutOfBoundsException();
432 Sequence
< beans::PropertyValue
> SAL_CALL
SmGraphicAccessible::getCharacterAttributes(
434 const uno::Sequence
< OUString
> & /*rRequestedAttributes*/ )
436 SolarMutexGuard aGuard
;
437 sal_Int32 nLen
= GetAccessibleText_Impl().getLength();
438 if (!(0 <= nIndex
&& nIndex
< nLen
))
439 throw IndexOutOfBoundsException();
440 return Sequence
< beans::PropertyValue
>();
443 awt::Rectangle SAL_CALL
SmGraphicAccessible::getCharacterBounds( sal_Int32 nIndex
)
445 SolarMutexGuard aGuard
;
450 throw RuntimeException();
452 // get accessible text
453 SmViewShell
*pView
= pWin
->GetView();
454 SmDocShell
*pDoc
= pView
? pView
->GetDoc() : nullptr;
456 throw RuntimeException();
457 OUString
aTxt( GetAccessibleText_Impl() );
458 if (!(0 <= nIndex
&& nIndex
<= aTxt
.getLength())) // aTxt.getLength() is valid
459 throw IndexOutOfBoundsException();
461 // find a reasonable rectangle for position aTxt.getLength().
462 bool bWasBehindText
= (nIndex
== aTxt
.getLength());
463 if (bWasBehindText
&& nIndex
)
466 const SmNode
*pTree
= pDoc
->GetFormulaTree();
467 const SmNode
*pNode
= pTree
->FindNodeWithAccessibleIndex( nIndex
);
468 //! pNode may be 0 if the index belongs to a char that was inserted
469 //! only for the accessible text!
472 sal_Int32 nAccIndex
= pNode
->GetAccessibleIndex();
473 OSL_ENSURE( nAccIndex
>= 0, "invalid accessible index" );
474 OSL_ENSURE( nIndex
>= nAccIndex
, "index out of range" );
477 pNode
->GetAccessibleText(aBuf
);
478 OUString aNodeText
= aBuf
.makeStringAndClear();
479 sal_Int32 nNodeIndex
= nIndex
- nAccIndex
;
480 if (0 <= nNodeIndex
&& nNodeIndex
< aNodeText
.getLength())
482 // get appropriate rectangle
483 Point
aOffset(pNode
->GetTopLeft() - pTree
->GetTopLeft());
484 Point
aTLPos (pWin
->GetFormulaDrawPos() + aOffset
);
485 Size
aSize (pNode
->GetSize());
487 long* pXAry
= new long[ aNodeText
.getLength() ];
488 pWin
->SetFont( pNode
->GetFont() );
489 pWin
->GetTextArray( aNodeText
, pXAry
, 0, aNodeText
.getLength() );
490 aTLPos
.AdjustX(nNodeIndex
> 0 ? pXAry
[nNodeIndex
- 1] : 0 );
491 aSize
.setWidth( nNodeIndex
> 0 ? pXAry
[nNodeIndex
] - pXAry
[nNodeIndex
- 1] : pXAry
[nNodeIndex
] );
494 aTLPos
= pWin
->LogicToPixel( aTLPos
);
495 aSize
= pWin
->LogicToPixel( aSize
);
498 aRes
.Width
= aSize
.Width();
499 aRes
.Height
= aSize
.Height();
503 // take rectangle from last character and move it to the right
505 aRes
.X
+= aRes
.Width
;
510 sal_Int32 SAL_CALL
SmGraphicAccessible::getCharacterCount()
512 SolarMutexGuard aGuard
;
513 return GetAccessibleText_Impl().getLength();
516 sal_Int32 SAL_CALL
SmGraphicAccessible::getIndexAtPoint( const awt::Point
& aPoint
)
518 SolarMutexGuard aGuard
;
523 const SmNode
*pTree
= pWin
->GetView()->GetDoc()->GetFormulaTree();
524 // can be NULL! e.g. if one clicks within the window already during loading of the
525 // document (before the parser even started)
529 // get position relative to formula draw position
530 Point
aPos( aPoint
.X
, aPoint
.Y
);
531 aPos
= pWin
->PixelToLogic( aPos
);
532 aPos
-= pWin
->GetFormulaDrawPos();
534 // if it was inside the formula then get the appropriate node
535 const SmNode
*pNode
= nullptr;
536 if (pTree
->OrientedDist(aPos
) <= 0)
537 pNode
= pTree
->FindRectClosestTo(aPos
);
541 // get appropriate rectangle
542 Point
aOffset( pNode
->GetTopLeft() - pTree
->GetTopLeft() );
543 Point
aTLPos ( aOffset
);
544 Size
aSize( pNode
->GetSize() );
546 tools::Rectangle
aRect( aTLPos
, aSize
);
547 if (aRect
.IsInside( aPos
))
549 OSL_ENSURE( pNode
->IsVisible(), "node is not a leaf" );
551 pNode
->GetAccessibleText(aBuf
);
552 OUString aTxt
= aBuf
.makeStringAndClear();
553 OSL_ENSURE( !aTxt
.isEmpty(), "no accessible text available" );
555 long nNodeX
= pNode
->GetLeft();
557 long* pXAry
= new long[ aTxt
.getLength() ];
558 pWin
->SetFont( pNode
->GetFont() );
559 pWin
->GetTextArray( aTxt
, pXAry
, 0, aTxt
.getLength() );
560 for (sal_Int32 i
= 0; i
< aTxt
.getLength() && nRes
== -1; ++i
)
562 if (pXAry
[i
] + nNodeX
> aPos
.X())
566 OSL_ENSURE( nRes
>= 0 && nRes
< aTxt
.getLength(), "index out of range" );
567 OSL_ENSURE( pNode
->GetAccessibleIndex() >= 0,
568 "invalid accessible index" );
570 nRes
= pNode
->GetAccessibleIndex() + nRes
;
577 OUString SAL_CALL
SmGraphicAccessible::getSelectedText()
582 sal_Int32 SAL_CALL
SmGraphicAccessible::getSelectionStart()
587 sal_Int32 SAL_CALL
SmGraphicAccessible::getSelectionEnd()
592 sal_Bool SAL_CALL
SmGraphicAccessible::setSelection(
593 sal_Int32 nStartIndex
,
594 sal_Int32 nEndIndex
)
596 SolarMutexGuard aGuard
;
597 sal_Int32 nLen
= GetAccessibleText_Impl().getLength();
598 if (!(0 <= nStartIndex
&& nStartIndex
< nLen
) ||
599 !(0 <= nEndIndex
&& nEndIndex
< nLen
))
600 throw IndexOutOfBoundsException();
604 OUString SAL_CALL
SmGraphicAccessible::getText()
606 SolarMutexGuard aGuard
;
607 return GetAccessibleText_Impl();
610 OUString SAL_CALL
SmGraphicAccessible::getTextRange(
611 sal_Int32 nStartIndex
,
612 sal_Int32 nEndIndex
)
614 //!! nEndIndex may be the string length per definition of the interface !!
615 //!! text should be copied exclusive that end index though. And arguments
616 //!! may be switched.
618 SolarMutexGuard aGuard
;
619 OUString
aTxt( GetAccessibleText_Impl() );
620 sal_Int32 nStart
= std::min(nStartIndex
, nEndIndex
);
621 sal_Int32 nEnd
= std::max(nStartIndex
, nEndIndex
);
622 if ((nStart
> aTxt
.getLength()) ||
623 (nEnd
> aTxt
.getLength()))
624 throw IndexOutOfBoundsException();
625 return aTxt
.copy( nStart
, nEnd
- nStart
);
628 css::accessibility::TextSegment SAL_CALL
SmGraphicAccessible::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
630 SolarMutexGuard aGuard
;
631 OUString
aTxt( GetAccessibleText_Impl() );
632 //!! nIndex is allowed to be the string length
633 if (nIndex
> aTxt
.getLength())
634 throw IndexOutOfBoundsException();
636 css::accessibility::TextSegment aResult
;
637 aResult
.SegmentStart
= -1;
638 aResult
.SegmentEnd
= -1;
639 if ( (AccessibleTextType::CHARACTER
== aTextType
) && (nIndex
< aTxt
.getLength()) )
641 aResult
.SegmentText
= aTxt
.copy(nIndex
, 1);
642 aResult
.SegmentStart
= nIndex
;
643 aResult
.SegmentEnd
= nIndex
+1;
648 css::accessibility::TextSegment SAL_CALL
SmGraphicAccessible::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
650 SolarMutexGuard aGuard
;
651 OUString
aTxt( GetAccessibleText_Impl() );
652 //!! nIndex is allowed to be the string length
653 if (nIndex
> aTxt
.getLength())
654 throw IndexOutOfBoundsException();
656 css::accessibility::TextSegment aResult
;
657 aResult
.SegmentStart
= -1;
658 aResult
.SegmentEnd
= -1;
660 if ( (AccessibleTextType::CHARACTER
== aTextType
) && nIndex
)
662 aResult
.SegmentText
= aTxt
.copy(nIndex
-1, 1);
663 aResult
.SegmentStart
= nIndex
-1;
664 aResult
.SegmentEnd
= nIndex
;
669 css::accessibility::TextSegment SAL_CALL
SmGraphicAccessible::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
671 SolarMutexGuard aGuard
;
672 OUString
aTxt( GetAccessibleText_Impl() );
673 //!! nIndex is allowed to be the string length
674 if (nIndex
> aTxt
.getLength())
675 throw IndexOutOfBoundsException();
677 css::accessibility::TextSegment aResult
;
678 aResult
.SegmentStart
= -1;
679 aResult
.SegmentEnd
= -1;
681 nIndex
++; // text *behind*
682 if ( (AccessibleTextType::CHARACTER
== aTextType
) && (nIndex
< aTxt
.getLength()) )
684 aResult
.SegmentText
= aTxt
.copy(nIndex
, 1);
685 aResult
.SegmentStart
= nIndex
;
686 aResult
.SegmentEnd
= nIndex
+1;
691 sal_Bool SAL_CALL
SmGraphicAccessible::copyText(
692 sal_Int32 nStartIndex
,
693 sal_Int32 nEndIndex
)
695 SolarMutexGuard aGuard
;
696 bool bReturn
= false;
699 throw RuntimeException();
701 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= pWin
->GetClipboard();
702 if ( xClipboard
.is() )
704 OUString
sText( getTextRange(nStartIndex
, nEndIndex
) );
706 vcl::unohelper::TextDataObject
* pDataObj
= new vcl::unohelper::TextDataObject( sText
);
707 SolarMutexReleaser aReleaser
;
708 xClipboard
->setContents( pDataObj
, nullptr );
710 Reference
< datatransfer::clipboard::XFlushableClipboard
> xFlushableClipboard( xClipboard
, uno::UNO_QUERY
);
711 if( xFlushableClipboard
.is() )
712 xFlushableClipboard
->flushClipboard();
721 OUString SAL_CALL
SmGraphicAccessible::getImplementationName()
723 return OUString("SmGraphicAccessible");
726 sal_Bool SAL_CALL
SmGraphicAccessible::supportsService(
727 const OUString
& rServiceName
)
729 return cppu::supportsService(this, rServiceName
);
732 Sequence
< OUString
> SAL_CALL
SmGraphicAccessible::getSupportedServiceNames()
734 return Sequence
< OUString
>{
735 "css::accessibility::Accessible",
736 "css::accessibility::AccessibleComponent",
737 "css::accessibility::AccessibleContext",
738 "css::accessibility::AccessibleText"
743 SmEditSource::SmEditSource( SmEditAccessible
&rAcc
) :
745 aTextFwd (rAcc
, *this),
751 SmEditSource::SmEditSource( const SmEditSource
&rSrc
) :
753 aViewFwd (rSrc
.rEditAcc
),
754 aTextFwd (rSrc
.rEditAcc
, *this),
755 aEditViewFwd(rSrc
.rEditAcc
),
756 rEditAcc (rSrc
.rEditAcc
)
760 SmEditSource::~SmEditSource()
764 std::unique_ptr
<SvxEditSource
> SmEditSource::Clone() const
766 return std::unique_ptr
<SvxEditSource
>(new SmEditSource( *this ));
769 SvxTextForwarder
* SmEditSource::GetTextForwarder()
774 SvxViewForwarder
* SmEditSource::GetViewForwarder()
779 SvxEditViewForwarder
* SmEditSource::GetEditViewForwarder( bool /*bCreate*/ )
781 return &aEditViewFwd
;
784 void SmEditSource::UpdateData()
786 // would possibly only by needed if the XText interface is implemented
787 // and its text needs to be updated.
790 SfxBroadcaster
& SmEditSource::GetBroadcaster() const
792 return const_cast<SmEditSource
*>(this)->aBroadCaster
;
795 SmViewForwarder::SmViewForwarder( SmEditAccessible
&rAcc
) :
800 SmViewForwarder::~SmViewForwarder()
804 bool SmViewForwarder::IsValid() const
806 return rEditAcc
.GetEditView() != nullptr;
809 tools::Rectangle
SmViewForwarder::GetVisArea() const
811 EditView
*pEditView
= rEditAcc
.GetEditView();
812 OutputDevice
* pOutDev
= pEditView
? pEditView
->GetWindow() : nullptr;
814 if( pOutDev
&& pEditView
)
816 tools::Rectangle aVisArea
= pEditView
->GetVisArea();
818 // figure out map mode from edit engine
819 EditEngine
* pEditEngine
= pEditView
->GetEditEngine();
823 MapMode
aMapMode(pOutDev
->GetMapMode());
824 aVisArea
= OutputDevice::LogicToLogic( aVisArea
,
825 pEditEngine
->GetRefMapMode(),
826 MapMode(aMapMode
.GetMapUnit()));
827 aMapMode
.SetOrigin(Point());
828 return pOutDev
->LogicToPixel( aVisArea
, aMapMode
);
832 return tools::Rectangle();
835 Point
SmViewForwarder::LogicToPixel( const Point
& rPoint
, const MapMode
& rMapMode
) const
837 EditView
*pEditView
= rEditAcc
.GetEditView();
838 OutputDevice
* pOutDev
= pEditView
? pEditView
->GetWindow() : nullptr;
842 MapMode
aMapMode(pOutDev
->GetMapMode());
843 Point
aPoint( OutputDevice::LogicToLogic( rPoint
, rMapMode
,
844 MapMode(aMapMode
.GetMapUnit())) );
845 aMapMode
.SetOrigin(Point());
846 return pOutDev
->LogicToPixel( aPoint
, aMapMode
);
852 Point
SmViewForwarder::PixelToLogic( const Point
& rPoint
, const MapMode
& rMapMode
) const
854 EditView
*pEditView
= rEditAcc
.GetEditView();
855 OutputDevice
* pOutDev
= pEditView
? pEditView
->GetWindow() : nullptr;
859 MapMode
aMapMode(pOutDev
->GetMapMode());
860 aMapMode
.SetOrigin(Point());
861 Point
aPoint( pOutDev
->PixelToLogic( rPoint
, aMapMode
) );
862 return OutputDevice::LogicToLogic( aPoint
,
863 MapMode(aMapMode
.GetMapUnit()),
871 SmTextForwarder::SmTextForwarder( SmEditAccessible
& rAcc
, SmEditSource
& rSource
) :
873 rEditSource (rSource
)
875 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
877 pEditEngine
->SetNotifyHdl( LINK(this, SmTextForwarder
, NotifyHdl
) );
880 SmTextForwarder::~SmTextForwarder()
882 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
884 pEditEngine
->SetNotifyHdl( Link
<EENotify
&,void>() );
887 IMPL_LINK(SmTextForwarder
, NotifyHdl
, EENotify
&, rNotify
, void)
889 ::std::unique_ptr
< SfxHint
> aHint
= SvxEditSourceHelper::EENotification2Hint( &rNotify
);
891 rEditSource
.GetBroadcaster().Broadcast( *aHint
.get() );
894 sal_Int32
SmTextForwarder::GetParagraphCount() const
896 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
897 return pEditEngine
? pEditEngine
->GetParagraphCount() : 0;
900 sal_Int32
SmTextForwarder::GetTextLen( sal_Int32 nParagraph
) const
902 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
903 return pEditEngine
? pEditEngine
->GetTextLen( nParagraph
) : 0;
906 OUString
SmTextForwarder::GetText( const ESelection
& rSel
) const
908 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
911 aRet
= pEditEngine
->GetText( rSel
);
912 return convertLineEnd(aRet
, GetSystemLineEnd());
915 SfxItemSet
SmTextForwarder::GetAttribs( const ESelection
& rSel
, EditEngineAttribs nOnlyHardAttrib
) const
917 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
918 assert(pEditEngine
&& "EditEngine missing");
919 if( rSel
.nStartPara
== rSel
.nEndPara
)
921 GetAttribsFlags nFlags
= GetAttribsFlags::NONE
;
922 switch( nOnlyHardAttrib
)
924 case EditEngineAttribs::All
:
925 nFlags
= GetAttribsFlags::ALL
;
927 case EditEngineAttribs::OnlyHard
:
928 nFlags
= GetAttribsFlags::CHARATTRIBS
;
931 SAL_WARN("starmath", "unknown flags for SmTextForwarder::GetAttribs");
934 return pEditEngine
->GetAttribs( rSel
.nStartPara
, rSel
.nStartPos
, rSel
.nEndPos
, nFlags
);
938 return pEditEngine
->GetAttribs( rSel
, nOnlyHardAttrib
);
942 SfxItemSet
SmTextForwarder::GetParaAttribs( sal_Int32 nPara
) const
944 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
945 assert(pEditEngine
&& "EditEngine missing");
947 SfxItemSet
aSet( pEditEngine
->GetParaAttribs( nPara
) );
949 sal_uInt16 nWhich
= EE_PARA_START
;
950 while( nWhich
<= EE_PARA_END
)
952 if( aSet
.GetItemState( nWhich
) != SfxItemState::SET
)
954 if( pEditEngine
->HasParaAttrib( nPara
, nWhich
) )
955 aSet
.Put( pEditEngine
->GetParaAttrib( nPara
, nWhich
) );
963 void SmTextForwarder::SetParaAttribs( sal_Int32 nPara
, const SfxItemSet
& rSet
)
965 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
967 pEditEngine
->SetParaAttribs( nPara
, rSet
);
970 SfxItemPool
* SmTextForwarder::GetPool() const
972 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
973 return pEditEngine
? pEditEngine
->GetEmptyItemSet().GetPool() : nullptr;
976 void SmTextForwarder::RemoveAttribs( const ESelection
& rSelection
)
978 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
980 pEditEngine
->RemoveAttribs( rSelection
, false/*bRemoveParaAttribs*/, 0 );
983 void SmTextForwarder::GetPortions( sal_Int32 nPara
, std::vector
<sal_Int32
>& rList
) const
985 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
987 pEditEngine
->GetPortions( nPara
, rList
);
990 void SmTextForwarder::QuickInsertText( const OUString
& rText
, const ESelection
& rSel
)
992 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
994 pEditEngine
->QuickInsertText( rText
, rSel
);
997 void SmTextForwarder::QuickInsertLineBreak( const ESelection
& rSel
)
999 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1001 pEditEngine
->QuickInsertLineBreak( rSel
);
1004 void SmTextForwarder::QuickInsertField( const SvxFieldItem
& rFld
, const ESelection
& rSel
)
1006 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1008 pEditEngine
->QuickInsertField( rFld
, rSel
);
1011 void SmTextForwarder::QuickSetAttribs( const SfxItemSet
& rSet
, const ESelection
& rSel
)
1013 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1015 pEditEngine
->QuickSetAttribs( rSet
, rSel
);
1018 bool SmTextForwarder::IsValid() const
1020 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1021 // cannot reliably query EditEngine state
1022 // while in the middle of an update
1023 return pEditEngine
&& pEditEngine
->GetUpdateMode();
1026 OUString
SmTextForwarder::CalcFieldValue( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
, boost::optional
<Color
>& rpTxtColor
, boost::optional
<Color
>& rpFldColor
)
1028 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1029 return pEditEngine
? pEditEngine
->CalcFieldValue(rField
, nPara
, nPos
, rpTxtColor
, rpFldColor
) : OUString();
1032 void SmTextForwarder::FieldClicked(const SvxFieldItem
&, sal_Int32
, sal_Int32
)
1036 static SfxItemState
GetSvxEditEngineItemState( EditEngine
const & rEditEngine
, const ESelection
& rSel
, sal_uInt16 nWhich
)
1038 std::vector
<EECharAttrib
> aAttribs
;
1040 const SfxPoolItem
* pLastItem
= nullptr;
1042 SfxItemState eState
= SfxItemState::DEFAULT
;
1044 // check all paragraphs inside the selection
1045 for( sal_Int32 nPara
= rSel
.nStartPara
; nPara
<= rSel
.nEndPara
; nPara
++ )
1047 SfxItemState eParaState
= SfxItemState::DEFAULT
;
1049 // calculate start and endpos for this paragraph
1051 if( rSel
.nStartPara
== nPara
)
1052 nPos
= rSel
.nStartPos
;
1054 sal_Int32 nEndPos
= rSel
.nEndPos
;
1055 if( rSel
.nEndPara
!= nPara
)
1056 nEndPos
= rEditEngine
.GetTextLen( nPara
);
1059 // get list of char attribs
1060 rEditEngine
.GetCharAttribs( nPara
, aAttribs
);
1062 bool bEmpty
= true; // we found no item inside the selection of this paragraph
1063 bool bGaps
= false; // we found items but theire gaps between them
1064 sal_Int32 nLastEnd
= nPos
;
1066 const SfxPoolItem
* pParaItem
= nullptr;
1068 for(std::vector
<EECharAttrib
>::const_iterator i
= aAttribs
.begin(); i
< aAttribs
.end(); ++i
)
1070 OSL_ENSURE( i
->pAttr
, "GetCharAttribs gives corrupt data" );
1072 const bool bEmptyPortion
= (i
->nStart
== i
->nEnd
);
1073 if( (!bEmptyPortion
&& (i
->nStart
>= nEndPos
)) || (bEmptyPortion
&& (i
->nStart
> nEndPos
)) )
1074 break; // break if we are already behind our selection
1076 if( (!bEmptyPortion
&& (i
->nEnd
<= nPos
)) || (bEmptyPortion
&& (i
->nEnd
< nPos
)) )
1077 continue; // or if the attribute ends before our selection
1079 if( i
->pAttr
->Which() != nWhich
)
1080 continue; // skip if is not the searched item
1082 // if we already found an item
1085 // ... and its different to this one than the state is don't care
1086 if( *pParaItem
!= *(i
->pAttr
) )
1087 return SfxItemState::DONTCARE
;
1091 pParaItem
= i
->pAttr
;
1097 if( !bGaps
&& i
->nStart
> nLastEnd
)
1103 if( !bEmpty
&& !bGaps
&& nLastEnd
< ( nEndPos
- 1 ) )
1106 eParaState
= SfxItemState::DEFAULT
;
1108 eParaState
= SfxItemState::DONTCARE
;
1110 eParaState
= SfxItemState::SET
;
1112 // if we already found an item check if we found the same
1115 if( (pParaItem
== nullptr) || (*pLastItem
!= *pParaItem
) )
1116 return SfxItemState::DONTCARE
;
1120 pLastItem
= pParaItem
;
1121 eState
= eParaState
;
1128 SfxItemState
SmTextForwarder::GetItemState( const ESelection
& rSel
, sal_uInt16 nWhich
) const
1130 SfxItemState nState
= SfxItemState::DISABLED
;
1131 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1133 nState
= GetSvxEditEngineItemState( *pEditEngine
, rSel
, nWhich
);
1137 SfxItemState
SmTextForwarder::GetItemState( sal_Int32 nPara
, sal_uInt16 nWhich
) const
1139 SfxItemState nState
= SfxItemState::DISABLED
;
1140 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1143 const SfxItemSet
& rSet
= pEditEngine
->GetParaAttribs( nPara
);
1144 nState
= rSet
.GetItemState( nWhich
);
1149 LanguageType
SmTextForwarder::GetLanguage( sal_Int32 nPara
, sal_Int32 nIndex
) const
1151 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1152 return pEditEngine
? pEditEngine
->GetLanguage(nPara
, nIndex
) : LANGUAGE_NONE
;
1155 sal_Int32
SmTextForwarder::GetFieldCount( sal_Int32 nPara
) const
1157 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1158 return pEditEngine
? pEditEngine
->GetFieldCount(nPara
) : 0;
1161 EFieldInfo
SmTextForwarder::GetFieldInfo( sal_Int32 nPara
, sal_uInt16 nField
) const
1163 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1164 return pEditEngine
? pEditEngine
->GetFieldInfo( nPara
, nField
) : EFieldInfo();
1167 EBulletInfo
SmTextForwarder::GetBulletInfo( sal_Int32
/*nPara*/ ) const
1169 return EBulletInfo();
1172 tools::Rectangle
SmTextForwarder::GetCharBounds( sal_Int32 nPara
, sal_Int32 nIndex
) const
1174 tools::Rectangle
aRect(0,0,0,0);
1175 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1179 // Handle virtual position one-past-the end of the string
1180 if( nIndex
>= pEditEngine
->GetTextLen(nPara
) )
1183 aRect
= pEditEngine
->GetCharacterBounds( EPosition(nPara
, nIndex
-1) );
1185 aRect
.Move( aRect
.Right() - aRect
.Left(), 0 );
1186 aRect
.SetSize( Size(1, pEditEngine
->GetTextHeight()) );
1190 aRect
= pEditEngine
->GetCharacterBounds( EPosition(nPara
, nIndex
) );
1196 tools::Rectangle
SmTextForwarder::GetParaBounds( sal_Int32 nPara
) const
1198 tools::Rectangle
aRect(0,0,0,0);
1199 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1203 const Point aPnt
= pEditEngine
->GetDocPosTopLeft( nPara
);
1204 const sal_uLong nWidth
= pEditEngine
->CalcTextWidth();
1205 const sal_uLong nHeight
= pEditEngine
->GetTextHeight( nPara
);
1206 aRect
= tools::Rectangle( aPnt
.X(), aPnt
.Y(), aPnt
.X() + nWidth
, aPnt
.Y() + nHeight
);
1212 MapMode
SmTextForwarder::GetMapMode() const
1214 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1215 return pEditEngine
? pEditEngine
->GetRefMapMode() : MapMode( MapUnit::Map100thMM
);
1218 OutputDevice
* SmTextForwarder::GetRefDevice() const
1220 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1221 return pEditEngine
? pEditEngine
->GetRefDevice() : nullptr;
1224 bool SmTextForwarder::GetIndexAtPoint( const Point
& rPos
, sal_Int32
& nPara
, sal_Int32
& nIndex
) const
1227 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1230 EPosition aDocPos
= pEditEngine
->FindDocPosition( rPos
);
1231 nPara
= aDocPos
.nPara
;
1232 nIndex
= aDocPos
.nIndex
;
1238 bool SmTextForwarder::GetWordIndices( sal_Int32 nPara
, sal_Int32 nIndex
, sal_Int32
& nStart
, sal_Int32
& nEnd
) const
1241 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1244 ESelection aRes
= pEditEngine
->GetWord( ESelection(nPara
, nIndex
, nPara
, nIndex
), css::i18n::WordType::DICTIONARY_WORD
);
1246 if( aRes
.nStartPara
== nPara
&&
1247 aRes
.nStartPara
== aRes
.nEndPara
)
1249 nStart
= aRes
.nStartPos
;
1250 nEnd
= aRes
.nEndPos
;
1259 bool SmTextForwarder::GetAttributeRun( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
, sal_Int32 nPara
, sal_Int32 nIndex
, bool bInCell
) const
1261 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1262 return pEditEngine
&&
1263 SvxEditSourceHelper::GetAttributeRun( nStartIndex
, nEndIndex
, *pEditEngine
, nPara
, nIndex
, bInCell
);
1266 sal_Int32
SmTextForwarder::GetLineCount( sal_Int32 nPara
) const
1268 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1269 return pEditEngine
? pEditEngine
->GetLineCount(nPara
) : 0;
1272 sal_Int32
SmTextForwarder::GetLineLen( sal_Int32 nPara
, sal_Int32 nLine
) const
1274 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1275 return pEditEngine
? pEditEngine
->GetLineLen(nPara
, nLine
) : 0;
1278 void SmTextForwarder::GetLineBoundaries( /*out*/sal_Int32
&rStart
, /*out*/sal_Int32
&rEnd
, sal_Int32 nPara
, sal_Int32 nLine
) const
1280 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1282 pEditEngine
->GetLineBoundaries(rStart
, rEnd
, nPara
, nLine
);
1287 sal_Int32
SmTextForwarder::GetLineNumberAtIndex( sal_Int32 nPara
, sal_Int32 nIndex
) const
1289 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1290 return pEditEngine
? pEditEngine
->GetLineNumberAtIndex(nPara
, nIndex
) : 0;
1293 bool SmTextForwarder::QuickFormatDoc( bool /*bFull*/ )
1296 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1299 pEditEngine
->QuickFormatDoc();
1305 sal_Int16
SmTextForwarder::GetDepth( sal_Int32
/*nPara*/ ) const
1307 // math has no outliner...
1311 bool SmTextForwarder::SetDepth( sal_Int32
/*nPara*/, sal_Int16 nNewDepth
)
1313 // math has no outliner...
1314 return -1 == nNewDepth
; // is it the value from 'GetDepth' ?
1317 bool SmTextForwarder::Delete( const ESelection
& rSelection
)
1320 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1323 pEditEngine
->QuickDelete( rSelection
);
1324 pEditEngine
->QuickFormatDoc();
1330 bool SmTextForwarder::InsertText( const OUString
& rStr
, const ESelection
& rSelection
)
1333 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1336 pEditEngine
->QuickInsertText( rStr
, rSelection
);
1337 pEditEngine
->QuickFormatDoc();
1343 const SfxItemSet
* SmTextForwarder::GetEmptyItemSetPtr()
1345 const SfxItemSet
*pItemSet
= nullptr;
1346 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1349 pItemSet
= &pEditEngine
->GetEmptyItemSet();
1354 void SmTextForwarder::AppendParagraph()
1356 // append an empty paragraph
1357 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1360 sal_Int32 nParaCount
= pEditEngine
->GetParagraphCount();
1361 pEditEngine
->InsertParagraph( nParaCount
, OUString() );
1365 sal_Int32
SmTextForwarder::AppendTextPortion( sal_Int32 nPara
, const OUString
&rText
, const SfxItemSet
&rSet
)
1367 sal_uInt16 nRes
= 0;
1368 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1369 if (pEditEngine
&& nPara
< pEditEngine
->GetParagraphCount())
1372 ESelection
aSel( nPara
, pEditEngine
->GetTextLen( nPara
) );
1373 pEditEngine
->QuickInsertText( rText
, aSel
);
1375 // set attributes for new appended text
1376 nRes
= aSel
.nEndPos
= pEditEngine
->GetTextLen( nPara
);
1377 pEditEngine
->QuickSetAttribs( rSet
, aSel
);
1382 void SmTextForwarder::CopyText(const SvxTextForwarder
& rSource
)
1385 const SmTextForwarder
* pSourceForwarder
= dynamic_cast< const SmTextForwarder
* >( &rSource
);
1386 if( !pSourceForwarder
)
1388 EditEngine
* pSourceEditEngine
= pSourceForwarder
->rEditAcc
.GetEditEngine();
1389 EditEngine
*pEditEngine
= rEditAcc
.GetEditEngine();
1390 if (pEditEngine
&& pSourceEditEngine
)
1392 std::unique_ptr
<EditTextObject
> pNewTextObject
= pSourceEditEngine
->CreateTextObject();
1393 pEditEngine
->SetText( *pNewTextObject
);
1398 SmEditViewForwarder::SmEditViewForwarder( SmEditAccessible
& rAcc
) :
1403 SmEditViewForwarder::~SmEditViewForwarder()
1407 bool SmEditViewForwarder::IsValid() const
1409 return rEditAcc
.GetEditView() != nullptr;
1412 tools::Rectangle
SmEditViewForwarder::GetVisArea() const
1414 tools::Rectangle
aRect(0,0,0,0);
1416 EditView
*pEditView
= rEditAcc
.GetEditView();
1417 OutputDevice
* pOutDev
= pEditView
? pEditView
->GetWindow() : nullptr;
1419 if( pOutDev
&& pEditView
)
1421 tools::Rectangle aVisArea
= pEditView
->GetVisArea();
1423 // figure out map mode from edit engine
1424 EditEngine
* pEditEngine
= pEditView
->GetEditEngine();
1428 MapMode
aMapMode(pOutDev
->GetMapMode());
1429 aVisArea
= OutputDevice::LogicToLogic( aVisArea
,
1430 pEditEngine
->GetRefMapMode(),
1431 MapMode(aMapMode
.GetMapUnit()));
1432 aMapMode
.SetOrigin(Point());
1433 aRect
= pOutDev
->LogicToPixel( aVisArea
, aMapMode
);
1440 Point
SmEditViewForwarder::LogicToPixel( const Point
& rPoint
, const MapMode
& rMapMode
) const
1442 EditView
*pEditView
= rEditAcc
.GetEditView();
1443 OutputDevice
* pOutDev
= pEditView
? pEditView
->GetWindow() : nullptr;
1447 MapMode
aMapMode(pOutDev
->GetMapMode());
1448 Point
aPoint( OutputDevice::LogicToLogic( rPoint
, rMapMode
,
1449 MapMode(aMapMode
.GetMapUnit())));
1450 aMapMode
.SetOrigin(Point());
1451 return pOutDev
->LogicToPixel( aPoint
, aMapMode
);
1457 Point
SmEditViewForwarder::PixelToLogic( const Point
& rPoint
, const MapMode
& rMapMode
) const
1459 EditView
*pEditView
= rEditAcc
.GetEditView();
1460 OutputDevice
* pOutDev
= pEditView
? pEditView
->GetWindow() : nullptr;
1464 MapMode
aMapMode(pOutDev
->GetMapMode());
1465 aMapMode
.SetOrigin(Point());
1466 Point
aPoint( pOutDev
->PixelToLogic( rPoint
, aMapMode
) );
1467 return OutputDevice::LogicToLogic( aPoint
,
1468 MapMode(aMapMode
.GetMapUnit()),
1475 bool SmEditViewForwarder::GetSelection( ESelection
& rSelection
) const
1478 EditView
*pEditView
= rEditAcc
.GetEditView();
1481 rSelection
= pEditView
->GetSelection();
1487 bool SmEditViewForwarder::SetSelection( const ESelection
& rSelection
)
1490 EditView
*pEditView
= rEditAcc
.GetEditView();
1493 pEditView
->SetSelection( rSelection
);
1499 bool SmEditViewForwarder::Copy()
1502 EditView
*pEditView
= rEditAcc
.GetEditView();
1511 bool SmEditViewForwarder::Cut()
1514 EditView
*pEditView
= rEditAcc
.GetEditView();
1523 bool SmEditViewForwarder::Paste()
1526 EditView
*pEditView
= rEditAcc
.GetEditView();
1536 SmEditAccessible::SmEditAccessible( SmEditWindow
*pEditWin
) :
1537 aAccName (SmResId(STR_CMDBOXWINDOW
)),
1541 OSL_ENSURE( pWin
, "SmEditAccessible: window missing" );
1544 SmEditAccessible::~SmEditAccessible()
1548 ::accessibility::AccessibleTextHelper
*SmEditAccessible::GetTextHelper()
1550 return pTextHelper
.get();
1553 void SmEditAccessible::Init()
1555 OSL_ENSURE( pWin
, "SmEditAccessible: window missing" );
1558 EditEngine
*pEditEngine
= pWin
->GetEditEngine();
1559 EditView
*pEditView
= pWin
->GetEditView();
1560 if (pEditEngine
&& pEditView
)
1562 assert(!pTextHelper
);
1563 pTextHelper
.reset(new ::accessibility::AccessibleTextHelper( o3tl::make_unique
<SmEditSource
>( *this ) ));
1564 pTextHelper
->SetEventSource( this );
1569 void SmEditAccessible::ClearWin()
1571 // remove handler before current object gets destroyed
1572 // (avoid handler being called for already dead object)
1573 EditEngine
*pEditEngine
= GetEditEngine();
1575 pEditEngine
->SetNotifyHdl( Link
<EENotify
&,void>() );
1577 pWin
= nullptr; // implicitly results in AccessibleStateType::DEFUNC set
1579 //! make TextHelper implicitly release C++ references to some core objects
1580 pTextHelper
->SetEditSource( ::std::unique_ptr
<SvxEditSource
>() );
1581 //! make TextHelper release references
1582 //! (e.g. the one set by the 'SetEventSource' call)
1583 pTextHelper
->Dispose();
1584 pTextHelper
.reset();
1588 uno::Reference
< XAccessibleContext
> SAL_CALL
SmEditAccessible::getAccessibleContext( )
1593 // XAccessibleComponent
1594 sal_Bool SAL_CALL
SmEditAccessible::containsPoint( const awt::Point
& aPoint
)
1596 //! the arguments coordinates are relative to the current window !
1597 //! Thus the top left-point is (0, 0)
1599 SolarMutexGuard aGuard
;
1601 throw RuntimeException();
1603 Size
aSz( pWin
->GetSizePixel() );
1604 return aPoint
.X
>= 0 && aPoint
.Y
>= 0 &&
1605 aPoint
.X
< aSz
.Width() && aPoint
.Y
< aSz
.Height();
1608 uno::Reference
< XAccessible
> SAL_CALL
SmEditAccessible::getAccessibleAtPoint( const awt::Point
& aPoint
)
1610 SolarMutexGuard aGuard
;
1612 throw RuntimeException();
1613 return pTextHelper
->GetAt( aPoint
);
1616 awt::Rectangle SAL_CALL
SmEditAccessible::getBounds( )
1618 SolarMutexGuard aGuard
;
1620 throw RuntimeException();
1621 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
1622 "mismatch of window parent and accessible parent" );
1623 return lcl_GetBounds( pWin
);
1626 awt::Point SAL_CALL
SmEditAccessible::getLocation( )
1628 SolarMutexGuard aGuard
;
1630 throw RuntimeException();
1631 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
1632 "mismatch of window parent and accessible parent" );
1633 awt::Rectangle
aRect( lcl_GetBounds( pWin
) );
1634 return awt::Point( aRect
.X
, aRect
.Y
);
1637 awt::Point SAL_CALL
SmEditAccessible::getLocationOnScreen( )
1639 SolarMutexGuard aGuard
;
1641 throw RuntimeException();
1642 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
1643 "mismatch of window parent and accessible parent" );
1644 return lcl_GetLocationOnScreen( pWin
);
1647 awt::Size SAL_CALL
SmEditAccessible::getSize( )
1649 SolarMutexGuard aGuard
;
1651 throw RuntimeException();
1652 OSL_ENSURE(pWin
->GetParent()->GetAccessible() == getAccessibleParent(),
1653 "mismatch of window parent and accessible parent" );
1655 Size
aSz( pWin
->GetSizePixel() );
1656 #if OSL_DEBUG_LEVEL > 0
1657 awt::Rectangle
aRect( lcl_GetBounds( pWin
) );
1658 Size
aSz2( aRect
.Width
, aRect
.Height
);
1659 assert(aSz
== aSz2
&& "mismatch in width");
1661 return awt::Size( aSz
.Width(), aSz
.Height() );
1664 void SAL_CALL
SmEditAccessible::grabFocus( )
1666 SolarMutexGuard aGuard
;
1668 throw RuntimeException();
1673 sal_Int32 SAL_CALL
SmEditAccessible::getForeground()
1675 SolarMutexGuard aGuard
;
1678 throw RuntimeException();
1679 return static_cast<sal_Int32
>(pWin
->GetTextColor());
1682 sal_Int32 SAL_CALL
SmEditAccessible::getBackground()
1684 SolarMutexGuard aGuard
;
1687 throw RuntimeException();
1688 Wallpaper
aWall( pWin
->GetDisplayBackground() );
1690 if (aWall
.IsBitmap() || aWall
.IsGradient())
1691 nCol
= pWin
->GetSettings().GetStyleSettings().GetWindowColor();
1693 nCol
= aWall
.GetColor();
1694 return static_cast<sal_Int32
>(nCol
);
1697 // XAccessibleContext
1698 sal_Int32 SAL_CALL
SmEditAccessible::getAccessibleChildCount( )
1700 SolarMutexGuard aGuard
;
1702 throw RuntimeException();
1703 return pTextHelper
->GetChildCount();
1706 uno::Reference
< XAccessible
> SAL_CALL
SmEditAccessible::getAccessibleChild( sal_Int32 i
)
1708 SolarMutexGuard aGuard
;
1710 throw RuntimeException();
1711 return pTextHelper
->GetChild( i
);
1714 uno::Reference
< XAccessible
> SAL_CALL
SmEditAccessible::getAccessibleParent( )
1716 SolarMutexGuard aGuard
;
1718 throw RuntimeException();
1720 vcl::Window
*pAccParent
= pWin
->GetAccessibleParentWindow();
1721 OSL_ENSURE( pAccParent
, "accessible parent missing" );
1722 return pAccParent
? pAccParent
->GetAccessible() : Reference
< XAccessible
>();
1725 sal_Int32 SAL_CALL
SmEditAccessible::getAccessibleIndexInParent( )
1727 SolarMutexGuard aGuard
;
1728 sal_Int32 nIdx
= -1;
1729 vcl::Window
*pAccParent
= pWin
? pWin
->GetAccessibleParentWindow() : nullptr;
1732 sal_uInt16 nCnt
= pAccParent
->GetAccessibleChildWindowCount();
1733 for (sal_uInt16 i
= 0; i
< nCnt
&& nIdx
== -1; ++i
)
1734 if (pAccParent
->GetAccessibleChildWindow( i
) == pWin
)
1740 sal_Int16 SAL_CALL
SmEditAccessible::getAccessibleRole( )
1742 return AccessibleRole::PANEL
/*TEXT ?*/;
1745 OUString SAL_CALL
SmEditAccessible::getAccessibleDescription( )
1747 return OUString(); // empty as agreed with product-management
1750 OUString SAL_CALL
SmEditAccessible::getAccessibleName( )
1752 SolarMutexGuard aGuard
;
1753 // same name as displayed by the window when not docked
1757 uno::Reference
< XAccessibleRelationSet
> SAL_CALL
SmEditAccessible::getAccessibleRelationSet( )
1759 Reference
< XAccessibleRelationSet
> xRelSet
= new utl::AccessibleRelationSetHelper();
1760 return xRelSet
; // empty relation set
1763 uno::Reference
< XAccessibleStateSet
> SAL_CALL
SmEditAccessible::getAccessibleStateSet( )
1765 SolarMutexGuard aGuard
;
1766 ::utl::AccessibleStateSetHelper
*pStateSet
=
1767 new ::utl::AccessibleStateSetHelper
;
1769 Reference
<XAccessibleStateSet
> xStateSet( pStateSet
);
1771 if (!pWin
|| !pTextHelper
)
1772 pStateSet
->AddState( AccessibleStateType::DEFUNC
);
1775 pStateSet
->AddState( AccessibleStateType::MULTI_LINE
);
1776 pStateSet
->AddState( AccessibleStateType::ENABLED
);
1777 pStateSet
->AddState( AccessibleStateType::FOCUSABLE
);
1778 if (pWin
->HasFocus())
1779 pStateSet
->AddState( AccessibleStateType::FOCUSED
);
1780 if (pWin
->IsActive())
1781 pStateSet
->AddState( AccessibleStateType::ACTIVE
);
1782 if (pWin
->IsVisible())
1783 pStateSet
->AddState( AccessibleStateType::SHOWING
);
1784 if (pWin
->IsReallyVisible())
1785 pStateSet
->AddState( AccessibleStateType::VISIBLE
);
1786 if (COL_TRANSPARENT
!= pWin
->GetBackground().GetColor())
1787 pStateSet
->AddState( AccessibleStateType::OPAQUE
);
1793 Locale SAL_CALL
SmEditAccessible::getLocale( )
1795 SolarMutexGuard aGuard
;
1796 // should be the document language...
1797 // We use the language of the localized symbol names here.
1798 return Application::GetSettings().GetUILanguageTag().getLocale();
1802 // XAccessibleEventBroadcaster
1803 void SAL_CALL
SmEditAccessible::addAccessibleEventListener( const uno::Reference
< XAccessibleEventListener
>& xListener
)
1805 if (pTextHelper
) // not disposing (about to destroy view shell)
1806 pTextHelper
->AddEventListener( xListener
);
1809 void SAL_CALL
SmEditAccessible::removeAccessibleEventListener( const uno::Reference
< XAccessibleEventListener
>& xListener
)
1811 if (pTextHelper
) // not disposing (about to destroy view shell)
1812 pTextHelper
->RemoveEventListener( xListener
);
1815 OUString SAL_CALL
SmEditAccessible::getImplementationName()
1817 return OUString("SmEditAccessible");
1820 sal_Bool SAL_CALL
SmEditAccessible::supportsService(
1821 const OUString
& rServiceName
)
1823 return cppu::supportsService(this, rServiceName
);
1826 Sequence
< OUString
> SAL_CALL
SmEditAccessible::getSupportedServiceNames()
1828 return Sequence
< OUString
>{
1829 "css::accessibility::Accessible",
1830 "css::accessibility::AccessibleComponent",
1831 "css::accessibility::AccessibleContext"
1836 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */