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