xref: /AOO41X/main/sc/source/ui/Accessibility/AccessibleEditObject.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 #include "AccessibleEditObject.hxx"
27 #include "scitems.hxx"
28 #include <editeng/eeitem.hxx>
29 #include "unoguard.hxx"
30 #include "AccessibleText.hxx"
31 #include "editsrc.hxx"
32 #include "scmod.hxx"
33 #include "inputhdl.hxx"
34 
35 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
36 #include <unotools/accessiblestatesethelper.hxx>
37 #endif
38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 #endif
41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
42 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
43 #endif
44 #include <rtl/uuid.h>
45 #include <tools/debug.hxx>
46 #include <svx/AccessibleTextHelper.hxx>
47 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
48 #include <com/sun/star/sheet/XSpreadsheet.hpp>
49 #include <editeng/editview.hxx>
50 #include <editeng/editeng.hxx>
51 #include <svx/svdmodel.hxx>
52 #include <sfx2/objsh.hxx>
53 
54 #include "unonames.hxx"
55 #include "document.hxx"
56 #include "AccessibleDocument.hxx"
57 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
58 #include <unotools/accessiblerelationsethelper.hxx>
59 #include <com/sun/star/accessibility/XAccessibleText.hpp>
60 using ::com::sun::star::lang::IndexOutOfBoundsException;
61 using ::com::sun::star::uno::RuntimeException;
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::accessibility;
64 
65 //=====  internal  ============================================================
66 
ScAccessibleEditObject(const uno::Reference<XAccessible> & rxParent,EditView * pEditView,Window * pWin,const rtl::OUString & rName,const rtl::OUString & rDescription,EditObjectType eObjectType)67 ScAccessibleEditObject::ScAccessibleEditObject(
68         const uno::Reference<XAccessible>& rxParent,
69         EditView* pEditView, Window* pWin, const rtl::OUString& rName,
70         const rtl::OUString& rDescription, EditObjectType eObjectType)
71     :
72     ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME),
73     mpTextHelper(NULL),
74     mpEditView(pEditView),
75     mpWindow(pWin),
76     meObjectType(eObjectType),
77     mbHasFocus(sal_False)
78 {
79     CreateTextHelper();
80     SetName(rName);
81     SetDescription(rDescription);
82     if( meObjectType == CellInEditMode)
83     {
84         const ScAccessibleDocument *pAccDoc = const_cast<ScAccessibleDocument*>(static_cast<ScAccessibleDocument*>(rxParent.get())) ;
85         if (pAccDoc)
86         {
87             m_pScDoc = pAccDoc->GetDocument();
88             m_curCellAddress =pAccDoc->GetCurCellAddress();
89         }
90         else
91         {
92             m_pScDoc=NULL;
93         }
94     }
95     else
96         m_pScDoc=NULL;
97 }
98 
~ScAccessibleEditObject()99 ScAccessibleEditObject::~ScAccessibleEditObject()
100 {
101     if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
102     {
103         // increment refcount to prevent double call off dtor
104         osl_incrementInterlockedCount( &m_refCount );
105         // call dispose to inform object wich have a weak reference to this object
106         dispose();
107     }
108 }
109 
disposing()110 void SAL_CALL ScAccessibleEditObject::disposing()
111 {
112     ScUnoGuard aGuard;
113     if (mpTextHelper)
114         DELETEZ(mpTextHelper);
115 
116     ScAccessibleContextBase::disposing();
117 }
118 
LostFocus()119 void ScAccessibleEditObject::LostFocus()
120 {
121     mbHasFocus = sal_False;
122     if (mpTextHelper)
123         mpTextHelper->SetFocus(sal_False);
124     CommitFocusLost();
125 }
126 
GotFocus()127 void ScAccessibleEditObject::GotFocus()
128 {
129     mbHasFocus = sal_True;
130     CommitFocusGained();
131     if (mpTextHelper)
132         mpTextHelper->SetFocus(sal_True);
133 }
134 
135 //=====  XInterface  ==========================================================
136 
137 com::sun::star::uno::Any SAL_CALL
queryInterface(const com::sun::star::uno::Type & rType)138     ScAccessibleEditObject::queryInterface (const com::sun::star::uno::Type & rType)
139     throw (::com::sun::star::uno::RuntimeException)
140 {
141     ::com::sun::star::uno::Any aReturn = ScAccessibleContextBase::queryInterface (rType);
142     if ( ! aReturn.hasValue())
143         aReturn = ::cppu::queryInterface (rType,
144             static_cast< ::com::sun::star::accessibility::XAccessibleSelection* >(this)
145             );
146     return aReturn;
147 }
148 void SAL_CALL
acquire(void)149     ScAccessibleEditObject::acquire (void)
150     throw ()
151 {
152     ScAccessibleContextBase::acquire ();
153 }
154 void SAL_CALL
release(void)155     ScAccessibleEditObject::release (void)
156     throw ()
157 {
158     ScAccessibleContextBase::release ();
159 }
160     //=====  XAccessibleComponent  ============================================
161 
getAccessibleAtPoint(const awt::Point & rPoint)162 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint(
163         const awt::Point& rPoint )
164         throw (uno::RuntimeException)
165 {
166     uno::Reference<XAccessible> xRet;
167     if (containsPoint(rPoint))
168     {
169         ScUnoGuard aGuard;
170         IsObjectValid();
171 
172         if(!mpTextHelper)
173             CreateTextHelper();
174 
175         xRet = mpTextHelper->GetAt(rPoint);
176     }
177 
178     return xRet;
179 }
180 
GetBoundingBoxOnScreen(void) const181 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const
182         throw (uno::RuntimeException)
183 {
184     Rectangle aScreenBounds;
185 
186     if ( mpWindow )
187     {
188         if ( meObjectType == CellInEditMode )
189         {
190             if ( mpEditView && mpEditView->GetEditEngine() )
191             {
192                 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() );
193                 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode );
194                 Point aCellLoc = aScreenBounds.TopLeft();
195                 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL );
196                 Point aWindowLoc = aWindowRect.TopLeft();
197                 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() );
198                 aScreenBounds.SetPos( aPos );
199             }
200         }
201         else
202         {
203             aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL );
204         }
205     }
206 
207     return aScreenBounds;
208 }
209 
GetBoundingBox(void) const210 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const
211         throw (uno::RuntimeException)
212 {
213     Rectangle aBounds( GetBoundingBoxOnScreen() );
214 
215     if ( mpWindow )
216     {
217         uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() );
218         if ( xThis.is() )
219         {
220             uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() );
221             if ( xContext.is() )
222             {
223                 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
224                 if ( xParent.is() )
225                 {
226                     uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
227                     if ( xParentComponent.is() )
228                     {
229                         Point aScreenLoc = aBounds.TopLeft();
230                         awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
231                         Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
232                         aBounds.SetPos( aPos );
233                     }
234                 }
235             }
236         }
237     }
238 
239     return aBounds;
240 }
241 
242     //=====  XAccessibleContext  ==============================================
243 
244 sal_Int32 SAL_CALL
getAccessibleChildCount(void)245     ScAccessibleEditObject::getAccessibleChildCount(void)
246                     throw (uno::RuntimeException)
247 {
248     ScUnoGuard aGuard;
249     IsObjectValid();
250     if (!mpTextHelper)
251         CreateTextHelper();
252     return mpTextHelper->GetChildCount();
253 }
254 
255 uno::Reference< XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nIndex)256     ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex)
257         throw (uno::RuntimeException,
258         lang::IndexOutOfBoundsException)
259 {
260     ScUnoGuard aGuard;
261     IsObjectValid();
262     if (!mpTextHelper)
263         CreateTextHelper();
264     return mpTextHelper->GetChild(nIndex);
265 }
266 
267 uno::Reference<XAccessibleStateSet> SAL_CALL
getAccessibleStateSet(void)268     ScAccessibleEditObject::getAccessibleStateSet(void)
269     throw (uno::RuntimeException)
270 {
271     ScUnoGuard aGuard;
272     uno::Reference<XAccessibleStateSet> xParentStates;
273     if (getAccessibleParent().is())
274     {
275         uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
276         xParentStates = xParentContext->getAccessibleStateSet();
277     }
278     utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
279     if (IsDefunc(xParentStates))
280         pStateSet->AddState(AccessibleStateType::DEFUNC);
281     else
282     {
283         // all states are const, because this object exists only in one state
284         pStateSet->AddState(AccessibleStateType::EDITABLE);
285         pStateSet->AddState(AccessibleStateType::ENABLED);
286         pStateSet->AddState(AccessibleStateType::SENSITIVE);
287         pStateSet->AddState(AccessibleStateType::MULTI_LINE);
288         pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
289         pStateSet->AddState(AccessibleStateType::SHOWING);
290         pStateSet->AddState(AccessibleStateType::VISIBLE);
291     }
292     return pStateSet;
293 }
294 
295 ::rtl::OUString SAL_CALL
createAccessibleDescription(void)296     ScAccessibleEditObject::createAccessibleDescription(void)
297     throw (uno::RuntimeException)
298 {
299 //    DBG_ERRORFILE("Should never be called, because is set in the constructor.")
300     return rtl::OUString();
301 }
302 
303 ::rtl::OUString SAL_CALL
createAccessibleName(void)304     ScAccessibleEditObject::createAccessibleName(void)
305     throw (uno::RuntimeException)
306 {
307     DBG_ERRORFILE("Should never be called, because is set in the constructor.");
308     return rtl::OUString();
309 }
310 
311     ///=====  XAccessibleEventBroadcaster  =====================================
312 
313 void SAL_CALL
addEventListener(const uno::Reference<XAccessibleEventListener> & xListener)314     ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
315         throw (uno::RuntimeException)
316 {
317     if (!mpTextHelper)
318         CreateTextHelper();
319 
320     mpTextHelper->AddEventListener(xListener);
321 
322     ScAccessibleContextBase::addEventListener(xListener);
323 }
324 
325 void SAL_CALL
removeEventListener(const uno::Reference<XAccessibleEventListener> & xListener)326     ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
327         throw (uno::RuntimeException)
328 {
329     if (!mpTextHelper)
330         CreateTextHelper();
331 
332     mpTextHelper->RemoveEventListener(xListener);
333 
334     ScAccessibleContextBase::removeEventListener(xListener);
335 }
336 
337     //=====  XServiceInfo  ====================================================
338 
getImplementationName(void)339 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void)
340         throw (uno::RuntimeException)
341 {
342     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject"));
343 }
344 
345 //=====  XTypeProvider  =======================================================
346 
347 uno::Sequence<sal_Int8> SAL_CALL
getImplementationId(void)348     ScAccessibleEditObject::getImplementationId(void)
349     throw (uno::RuntimeException)
350 {
351     ScUnoGuard aGuard;
352     IsObjectValid();
353     static uno::Sequence<sal_Int8> aId;
354     if (aId.getLength() == 0)
355     {
356         aId.realloc (16);
357         rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
358     }
359     return aId;
360 }
361 
362     //====  internal  =========================================================
363 
IsDefunc(const uno::Reference<XAccessibleStateSet> & rxParentStates)364 sal_Bool ScAccessibleEditObject::IsDefunc(
365     const uno::Reference<XAccessibleStateSet>& rxParentStates)
366 {
367     return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
368          (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
369 }
370 
CreateTextHelper()371 void ScAccessibleEditObject::CreateTextHelper()
372 {
373     if (!mpTextHelper)
374     {
375         ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData;
376         if (meObjectType == CellInEditMode || meObjectType == EditControl)
377         {
378             pAccessibleTextData.reset
379                 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow));
380         }
381         else
382         {
383             pAccessibleTextData.reset
384                 (new ScAccessibleEditLineTextData(NULL, mpWindow));
385         }
386 
387         ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData));
388         mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource );
389         mpTextHelper->SetEventSource(this);
390         mpTextHelper->SetFocus(mbHasFocus);
391 
392         // #i54814# activate cell in edit mode
393         if( meObjectType == CellInEditMode )
394         {
395             // do not activate cell object, if top edit line is active
396             const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
397             if( pInputHdl && !pInputHdl->IsTopMode() )
398             {
399                 SdrHint aHint( HINT_BEGEDIT );
400                 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint );
401             }
402         }
403     }
404 }
getForeground()405 sal_Int32 SAL_CALL ScAccessibleEditObject::getForeground(  )
406         throw (::com::sun::star::uno::RuntimeException)
407 {
408     return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CCOLOR)));
409 }
410 
getBackground()411 sal_Int32 SAL_CALL ScAccessibleEditObject::getBackground(  )
412         throw (::com::sun::star::uno::RuntimeException)
413 {
414     return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLBACK)));
415 }
GetFgBgColor(const rtl::OUString & strPropColor)416 sal_Int32 ScAccessibleEditObject::GetFgBgColor( const rtl::OUString &strPropColor)
417 {
418     ScUnoGuard aGuard;
419     sal_Int32 nColor(0);
420     if (m_pScDoc)
421     {
422         SfxObjectShell* pObjSh = m_pScDoc->GetDocumentShell();
423         if ( pObjSh )
424         {
425             uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY );
426             if ( xSpreadDoc.is() )
427             {
428                 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
429                 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
430                 if ( xIndex.is() )
431                 {
432                     uno::Any aTable = xIndex->getByIndex(m_curCellAddress.Tab());
433                     uno::Reference<sheet::XSpreadsheet> xTable;
434                     if (aTable>>=xTable)
435                     {
436                         uno::Reference<table::XCell> xCell = xTable->getCellByPosition(m_curCellAddress.Col(), m_curCellAddress.Row());
437                         if (xCell.is())
438                         {
439                             uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY);
440                             if (xCellProps.is())
441                             {
442                                 uno::Any aAny = xCellProps->getPropertyValue(strPropColor);
443                                 aAny >>= nColor;
444                             }
445                         }
446                     }
447                 }
448             }
449         }
450     }
451     return nColor;
452 }
453 //=====  XAccessibleSelection  ============================================
454 //--------------------------------------------------------------------------------
selectAccessibleChild(sal_Int32)455 void SAL_CALL ScAccessibleEditObject::selectAccessibleChild( sal_Int32 )
456 throw ( IndexOutOfBoundsException, RuntimeException )
457 {
458 }
459 //----------------------------------------------------------------------------------
isAccessibleChildSelected(sal_Int32 nChildIndex)460 sal_Bool SAL_CALL ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex )
461 throw ( IndexOutOfBoundsException,
462        RuntimeException )
463 {
464     uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex );
465     uno::Reference<XAccessibleContext> xContext;
466     if( xAcc.is() )
467         xContext = xAcc->getAccessibleContext();
468     if( xContext.is() )
469     {
470         if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
471         {
472             uno::Reference< ::com::sun::star::accessibility::XAccessibleText >
473                 xText(xAcc, uno::UNO_QUERY);
474             if( xText.is() )
475             {
476                 if( xText->getSelectionStart() >= 0 ) return sal_True;
477             }
478         }
479     }
480     return sal_False;
481 }
482 //---------------------------------------------------------------------
clearAccessibleSelection()483 void SAL_CALL ScAccessibleEditObject::clearAccessibleSelection(  )
484 throw ( RuntimeException )
485 {
486 }
487 //-------------------------------------------------------------------------
selectAllAccessibleChildren()488 void SAL_CALL ScAccessibleEditObject::selectAllAccessibleChildren(  )
489 throw ( RuntimeException )
490 {
491 }
492 //----------------------------------------------------------------------------
getSelectedAccessibleChildCount()493 sal_Int32 SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChildCount()
494 throw ( RuntimeException )
495 {
496     sal_Int32 nCount = 0;
497     sal_Int32 TotalCount = getAccessibleChildCount();
498     for( sal_Int32 i = 0; i < TotalCount; i++ )
499         if( isAccessibleChildSelected(i) ) nCount++;
500     return nCount;
501 }
502 //--------------------------------------------------------------------------------------
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)503 uno::Reference<XAccessible> SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
504 throw ( IndexOutOfBoundsException, RuntimeException)
505 {
506     if ( nSelectedChildIndex > getSelectedAccessibleChildCount() )
507         throw IndexOutOfBoundsException();
508     sal_Int32 i1, i2;
509     for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ )
510         if( isAccessibleChildSelected(i1) )
511         {
512             if( i2 == nSelectedChildIndex )
513                 return getAccessibleChild( i1 );
514             i2++;
515         }
516     return uno::Reference<XAccessible>();
517 }
518 //----------------------------------------------------------------------------------
deselectAccessibleChild(sal_Int32)519 void SAL_CALL ScAccessibleEditObject::deselectAccessibleChild(
520                                                             sal_Int32 )
521                                                             throw ( IndexOutOfBoundsException,
522                                                             RuntimeException )
523 {
524 }
getAccessibleRelationSet()525 uno::Reference< XAccessibleRelationSet > ScAccessibleEditObject::getAccessibleRelationSet(  )
526     throw (uno::RuntimeException)
527 {
528        ScUnoGuard aGuard;
529     Window* pWindow = mpWindow;
530     utl::AccessibleRelationSetHelper* rRelationSet = new utl::AccessibleRelationSetHelper;
531     uno::Reference< XAccessibleRelationSet > rSet = rRelationSet;
532     if ( pWindow )
533     {
534         Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
535         if ( pLabeledBy && pLabeledBy != pWindow )
536         {
537             uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
538             aSequence[0] = pLabeledBy->GetAccessible();
539             rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) );
540         }
541         Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
542         if ( pMemberOf && pMemberOf != pWindow )
543         {
544             uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
545             aSequence[0] = pMemberOf->GetAccessible();
546             rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) );
547         }
548         return rSet;
549     }
550     return uno::Reference< XAccessibleRelationSet >();
551 }
552 
553