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 which 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