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 {
140 ::com::sun::star::uno::Any aReturn = ScAccessibleContextBase::queryInterface (rType);
141 if ( ! aReturn.hasValue())
142 aReturn = ::cppu::queryInterface (rType,
143 static_cast< ::com::sun::star::accessibility::XAccessibleSelection* >(this)
144 );
145 return aReturn;
146 }
147 void SAL_CALL
acquire(void)148 ScAccessibleEditObject::acquire (void)
149 throw ()
150 {
151 ScAccessibleContextBase::acquire ();
152 }
153 void SAL_CALL
release(void)154 ScAccessibleEditObject::release (void)
155 throw ()
156 {
157 ScAccessibleContextBase::release ();
158 }
159 //===== XAccessibleComponent ============================================
160
getAccessibleAtPoint(const awt::Point & rPoint)161 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint(
162 const awt::Point& rPoint )
163 {
164 uno::Reference<XAccessible> xRet;
165 if (containsPoint(rPoint))
166 {
167 ScUnoGuard aGuard;
168 IsObjectValid();
169
170 if(!mpTextHelper)
171 CreateTextHelper();
172
173 xRet = mpTextHelper->GetAt(rPoint);
174 }
175
176 return xRet;
177 }
178
GetBoundingBoxOnScreen(void) const179 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const
180 {
181 Rectangle aScreenBounds;
182
183 if ( mpWindow )
184 {
185 if ( meObjectType == CellInEditMode )
186 {
187 if ( mpEditView && mpEditView->GetEditEngine() )
188 {
189 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() );
190 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode );
191 Point aCellLoc = aScreenBounds.TopLeft();
192 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL );
193 Point aWindowLoc = aWindowRect.TopLeft();
194 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() );
195 aScreenBounds.SetPos( aPos );
196 }
197 }
198 else
199 {
200 aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL );
201 }
202 }
203
204 return aScreenBounds;
205 }
206
GetBoundingBox(void) const207 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const
208 {
209 Rectangle aBounds( GetBoundingBoxOnScreen() );
210
211 if ( mpWindow )
212 {
213 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() );
214 if ( xThis.is() )
215 {
216 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() );
217 if ( xContext.is() )
218 {
219 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
220 if ( xParent.is() )
221 {
222 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
223 if ( xParentComponent.is() )
224 {
225 Point aScreenLoc = aBounds.TopLeft();
226 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
227 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
228 aBounds.SetPos( aPos );
229 }
230 }
231 }
232 }
233 }
234
235 return aBounds;
236 }
237
238 //===== XAccessibleContext ==============================================
239
240 sal_Int32 SAL_CALL
getAccessibleChildCount(void)241 ScAccessibleEditObject::getAccessibleChildCount(void)
242 {
243 ScUnoGuard aGuard;
244 IsObjectValid();
245 if (!mpTextHelper)
246 CreateTextHelper();
247 return mpTextHelper->GetChildCount();
248 }
249
250 uno::Reference< XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nIndex)251 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex)
252 {
253 ScUnoGuard aGuard;
254 IsObjectValid();
255 if (!mpTextHelper)
256 CreateTextHelper();
257 return mpTextHelper->GetChild(nIndex);
258 }
259
260 uno::Reference<XAccessibleStateSet> SAL_CALL
getAccessibleStateSet(void)261 ScAccessibleEditObject::getAccessibleStateSet(void)
262 {
263 ScUnoGuard aGuard;
264 uno::Reference<XAccessibleStateSet> xParentStates;
265 if (getAccessibleParent().is())
266 {
267 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
268 xParentStates = xParentContext->getAccessibleStateSet();
269 }
270 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
271 if (IsDefunc(xParentStates))
272 pStateSet->AddState(AccessibleStateType::DEFUNC);
273 else
274 {
275 // all states are const, because this object exists only in one state
276 pStateSet->AddState(AccessibleStateType::EDITABLE);
277 pStateSet->AddState(AccessibleStateType::ENABLED);
278 pStateSet->AddState(AccessibleStateType::SENSITIVE);
279 pStateSet->AddState(AccessibleStateType::MULTI_LINE);
280 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
281 pStateSet->AddState(AccessibleStateType::SHOWING);
282 pStateSet->AddState(AccessibleStateType::VISIBLE);
283 }
284 return pStateSet;
285 }
286
287 ::rtl::OUString SAL_CALL
createAccessibleDescription(void)288 ScAccessibleEditObject::createAccessibleDescription(void)
289 {
290 // DBG_ERRORFILE("Should never be called, because is set in the constructor.")
291 return rtl::OUString();
292 }
293
294 ::rtl::OUString SAL_CALL
createAccessibleName(void)295 ScAccessibleEditObject::createAccessibleName(void)
296 {
297 DBG_ERRORFILE("Should never be called, because is set in the constructor.");
298 return rtl::OUString();
299 }
300
301 ///===== XAccessibleEventBroadcaster =====================================
302
303 void SAL_CALL
addEventListener(const uno::Reference<XAccessibleEventListener> & xListener)304 ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
305 {
306 if (!mpTextHelper)
307 CreateTextHelper();
308
309 mpTextHelper->AddEventListener(xListener);
310
311 ScAccessibleContextBase::addEventListener(xListener);
312 }
313
314 void SAL_CALL
removeEventListener(const uno::Reference<XAccessibleEventListener> & xListener)315 ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
316 {
317 if (!mpTextHelper)
318 CreateTextHelper();
319
320 mpTextHelper->RemoveEventListener(xListener);
321
322 ScAccessibleContextBase::removeEventListener(xListener);
323 }
324
325 //===== XServiceInfo ====================================================
326
getImplementationName(void)327 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void)
328 {
329 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject"));
330 }
331
332 //===== XTypeProvider =======================================================
333
334 uno::Sequence<sal_Int8> SAL_CALL
getImplementationId(void)335 ScAccessibleEditObject::getImplementationId(void)
336 {
337 ScUnoGuard aGuard;
338 IsObjectValid();
339 static uno::Sequence<sal_Int8> aId;
340 if (aId.getLength() == 0)
341 {
342 aId.realloc (16);
343 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
344 }
345 return aId;
346 }
347
348 //==== internal =========================================================
349
IsDefunc(const uno::Reference<XAccessibleStateSet> & rxParentStates)350 sal_Bool ScAccessibleEditObject::IsDefunc(
351 const uno::Reference<XAccessibleStateSet>& rxParentStates)
352 {
353 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
354 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
355 }
356
CreateTextHelper()357 void ScAccessibleEditObject::CreateTextHelper()
358 {
359 if (!mpTextHelper)
360 {
361 ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData;
362 if (meObjectType == CellInEditMode || meObjectType == EditControl)
363 {
364 pAccessibleTextData.reset
365 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow));
366 }
367 else
368 {
369 pAccessibleTextData.reset
370 (new ScAccessibleEditLineTextData(NULL, mpWindow));
371 }
372
373 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData));
374 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource );
375 mpTextHelper->SetEventSource(this);
376 mpTextHelper->SetFocus(mbHasFocus);
377
378 // #i54814# activate cell in edit mode
379 if( meObjectType == CellInEditMode )
380 {
381 // do not activate cell object, if top edit line is active
382 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
383 if( pInputHdl && !pInputHdl->IsTopMode() )
384 {
385 SdrHint aHint( HINT_BEGEDIT );
386 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint );
387 }
388 }
389 }
390 }
getForeground()391 sal_Int32 SAL_CALL ScAccessibleEditObject::getForeground( )
392 {
393 return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CCOLOR)));
394 }
395
getBackground()396 sal_Int32 SAL_CALL ScAccessibleEditObject::getBackground( )
397 {
398 return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLBACK)));
399 }
GetFgBgColor(const rtl::OUString & strPropColor)400 sal_Int32 ScAccessibleEditObject::GetFgBgColor( const rtl::OUString &strPropColor)
401 {
402 ScUnoGuard aGuard;
403 sal_Int32 nColor(0);
404 if (m_pScDoc)
405 {
406 SfxObjectShell* pObjSh = m_pScDoc->GetDocumentShell();
407 if ( pObjSh )
408 {
409 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY );
410 if ( xSpreadDoc.is() )
411 {
412 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
413 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
414 if ( xIndex.is() )
415 {
416 uno::Any aTable = xIndex->getByIndex(m_curCellAddress.Tab());
417 uno::Reference<sheet::XSpreadsheet> xTable;
418 if (aTable>>=xTable)
419 {
420 uno::Reference<table::XCell> xCell = xTable->getCellByPosition(m_curCellAddress.Col(), m_curCellAddress.Row());
421 if (xCell.is())
422 {
423 uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY);
424 if (xCellProps.is())
425 {
426 uno::Any aAny = xCellProps->getPropertyValue(strPropColor);
427 aAny >>= nColor;
428 }
429 }
430 }
431 }
432 }
433 }
434 }
435 return nColor;
436 }
437 //===== XAccessibleSelection ============================================
438 //--------------------------------------------------------------------------------
selectAccessibleChild(sal_Int32)439 void SAL_CALL ScAccessibleEditObject::selectAccessibleChild( sal_Int32 )
440 {
441 }
442 //----------------------------------------------------------------------------------
isAccessibleChildSelected(sal_Int32 nChildIndex)443 sal_Bool SAL_CALL ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex )
444 {
445 uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex );
446 uno::Reference<XAccessibleContext> xContext;
447 if( xAcc.is() )
448 xContext = xAcc->getAccessibleContext();
449 if( xContext.is() )
450 {
451 if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
452 {
453 uno::Reference< ::com::sun::star::accessibility::XAccessibleText >
454 xText(xAcc, uno::UNO_QUERY);
455 if( xText.is() )
456 {
457 if( xText->getSelectionStart() >= 0 ) return sal_True;
458 }
459 }
460 }
461 return sal_False;
462 }
463 //---------------------------------------------------------------------
clearAccessibleSelection()464 void SAL_CALL ScAccessibleEditObject::clearAccessibleSelection( )
465 {
466 }
467 //-------------------------------------------------------------------------
selectAllAccessibleChildren()468 void SAL_CALL ScAccessibleEditObject::selectAllAccessibleChildren( )
469 {
470 }
471 //----------------------------------------------------------------------------
getSelectedAccessibleChildCount()472 sal_Int32 SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChildCount()
473 {
474 sal_Int32 nCount = 0;
475 sal_Int32 TotalCount = getAccessibleChildCount();
476 for( sal_Int32 i = 0; i < TotalCount; i++ )
477 if( isAccessibleChildSelected(i) ) nCount++;
478 return nCount;
479 }
480 //--------------------------------------------------------------------------------------
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)481 uno::Reference<XAccessible> SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
482 {
483 if ( nSelectedChildIndex > getSelectedAccessibleChildCount() )
484 throw IndexOutOfBoundsException();
485 sal_Int32 i1, i2;
486 for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ )
487 if( isAccessibleChildSelected(i1) )
488 {
489 if( i2 == nSelectedChildIndex )
490 return getAccessibleChild( i1 );
491 i2++;
492 }
493 return uno::Reference<XAccessible>();
494 }
495 //----------------------------------------------------------------------------------
deselectAccessibleChild(sal_Int32)496 void SAL_CALL ScAccessibleEditObject::deselectAccessibleChild(
497 sal_Int32 )
498 {
499 }
getAccessibleRelationSet()500 uno::Reference< XAccessibleRelationSet > ScAccessibleEditObject::getAccessibleRelationSet( )
501 {
502 ScUnoGuard aGuard;
503 Window* pWindow = mpWindow;
504 utl::AccessibleRelationSetHelper* rRelationSet = new utl::AccessibleRelationSetHelper;
505 uno::Reference< XAccessibleRelationSet > rSet = rRelationSet;
506 if ( pWindow )
507 {
508 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
509 if ( pLabeledBy && pLabeledBy != pWindow )
510 {
511 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
512 aSequence[0] = pLabeledBy->GetAccessible();
513 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) );
514 }
515 Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
516 if ( pMemberOf && pMemberOf != pWindow )
517 {
518 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
519 aSequence[0] = pMemberOf->GetAccessible();
520 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) );
521 }
522 return rSet;
523 }
524 return uno::Reference< XAccessibleRelationSet >();
525 }
526