1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 #include "AccessibleEditObject.hxx" 31 #include "scitems.hxx" 32 #include <editeng/eeitem.hxx> 33 #include "unoguard.hxx" 34 #include "AccessibleText.hxx" 35 #include "editsrc.hxx" 36 #include "scmod.hxx" 37 #include "inputhdl.hxx" 38 39 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX 40 #include <unotools/accessiblestatesethelper.hxx> 41 #endif 42 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_ 43 #include <com/sun/star/accessibility/AccessibleRole.hpp> 44 #endif 45 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ 46 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 47 #endif 48 #include <rtl/uuid.h> 49 #include <tools/debug.hxx> 50 #include <svx/AccessibleTextHelper.hxx> 51 #include <editeng/editview.hxx> 52 #include <editeng/editeng.hxx> 53 #include <svx/svdmodel.hxx> 54 55 using namespace ::com::sun::star; 56 using namespace ::com::sun::star::accessibility; 57 58 //===== internal ============================================================ 59 60 ScAccessibleEditObject::ScAccessibleEditObject( 61 const uno::Reference<XAccessible>& rxParent, 62 EditView* pEditView, Window* pWin, const rtl::OUString& rName, 63 const rtl::OUString& rDescription, EditObjectType eObjectType) 64 : 65 ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME), 66 mpTextHelper(NULL), 67 mpEditView(pEditView), 68 mpWindow(pWin), 69 meObjectType(eObjectType), 70 mbHasFocus(sal_False) 71 { 72 CreateTextHelper(); 73 SetName(rName); 74 SetDescription(rDescription); 75 } 76 77 ScAccessibleEditObject::~ScAccessibleEditObject() 78 { 79 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose) 80 { 81 // increment refcount to prevent double call off dtor 82 osl_incrementInterlockedCount( &m_refCount ); 83 // call dispose to inform object wich have a weak reference to this object 84 dispose(); 85 } 86 } 87 88 void SAL_CALL ScAccessibleEditObject::disposing() 89 { 90 ScUnoGuard aGuard; 91 if (mpTextHelper) 92 DELETEZ(mpTextHelper); 93 94 ScAccessibleContextBase::disposing(); 95 } 96 97 void ScAccessibleEditObject::LostFocus() 98 { 99 mbHasFocus = sal_False; 100 if (mpTextHelper) 101 mpTextHelper->SetFocus(sal_False); 102 CommitFocusLost(); 103 } 104 105 void ScAccessibleEditObject::GotFocus() 106 { 107 mbHasFocus = sal_True; 108 CommitFocusGained(); 109 if (mpTextHelper) 110 mpTextHelper->SetFocus(sal_True); 111 } 112 113 //===== XAccessibleComponent ============================================ 114 115 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint( 116 const awt::Point& rPoint ) 117 throw (uno::RuntimeException) 118 { 119 uno::Reference<XAccessible> xRet; 120 if (containsPoint(rPoint)) 121 { 122 ScUnoGuard aGuard; 123 IsObjectValid(); 124 125 if(!mpTextHelper) 126 CreateTextHelper(); 127 128 xRet = mpTextHelper->GetAt(rPoint); 129 } 130 131 return xRet; 132 } 133 134 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const 135 throw (uno::RuntimeException) 136 { 137 Rectangle aScreenBounds; 138 139 if ( mpWindow ) 140 { 141 if ( meObjectType == CellInEditMode ) 142 { 143 if ( mpEditView && mpEditView->GetEditEngine() ) 144 { 145 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() ); 146 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode ); 147 Point aCellLoc = aScreenBounds.TopLeft(); 148 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL ); 149 Point aWindowLoc = aWindowRect.TopLeft(); 150 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() ); 151 aScreenBounds.SetPos( aPos ); 152 } 153 } 154 else 155 { 156 aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL ); 157 } 158 } 159 160 return aScreenBounds; 161 } 162 163 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const 164 throw (uno::RuntimeException) 165 { 166 Rectangle aBounds( GetBoundingBoxOnScreen() ); 167 168 if ( mpWindow ) 169 { 170 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() ); 171 if ( xThis.is() ) 172 { 173 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() ); 174 if ( xContext.is() ) 175 { 176 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() ); 177 if ( xParent.is() ) 178 { 179 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY ); 180 if ( xParentComponent.is() ) 181 { 182 Point aScreenLoc = aBounds.TopLeft(); 183 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen(); 184 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y ); 185 aBounds.SetPos( aPos ); 186 } 187 } 188 } 189 } 190 } 191 192 return aBounds; 193 } 194 195 //===== XAccessibleContext ============================================== 196 197 sal_Int32 SAL_CALL 198 ScAccessibleEditObject::getAccessibleChildCount(void) 199 throw (uno::RuntimeException) 200 { 201 ScUnoGuard aGuard; 202 IsObjectValid(); 203 if (!mpTextHelper) 204 CreateTextHelper(); 205 return mpTextHelper->GetChildCount(); 206 } 207 208 uno::Reference< XAccessible > SAL_CALL 209 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex) 210 throw (uno::RuntimeException, 211 lang::IndexOutOfBoundsException) 212 { 213 ScUnoGuard aGuard; 214 IsObjectValid(); 215 if (!mpTextHelper) 216 CreateTextHelper(); 217 return mpTextHelper->GetChild(nIndex); 218 } 219 220 uno::Reference<XAccessibleStateSet> SAL_CALL 221 ScAccessibleEditObject::getAccessibleStateSet(void) 222 throw (uno::RuntimeException) 223 { 224 ScUnoGuard aGuard; 225 uno::Reference<XAccessibleStateSet> xParentStates; 226 if (getAccessibleParent().is()) 227 { 228 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 229 xParentStates = xParentContext->getAccessibleStateSet(); 230 } 231 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 232 if (IsDefunc(xParentStates)) 233 pStateSet->AddState(AccessibleStateType::DEFUNC); 234 else 235 { 236 // all states are const, because this object exists only in one state 237 pStateSet->AddState(AccessibleStateType::EDITABLE); 238 pStateSet->AddState(AccessibleStateType::ENABLED); 239 pStateSet->AddState(AccessibleStateType::SENSITIVE); 240 pStateSet->AddState(AccessibleStateType::MULTI_LINE); 241 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE); 242 pStateSet->AddState(AccessibleStateType::SHOWING); 243 pStateSet->AddState(AccessibleStateType::VISIBLE); 244 } 245 return pStateSet; 246 } 247 248 ::rtl::OUString SAL_CALL 249 ScAccessibleEditObject::createAccessibleDescription(void) 250 throw (uno::RuntimeException) 251 { 252 // DBG_ERRORFILE("Should never be called, because is set in the constructor.") 253 return rtl::OUString(); 254 } 255 256 ::rtl::OUString SAL_CALL 257 ScAccessibleEditObject::createAccessibleName(void) 258 throw (uno::RuntimeException) 259 { 260 DBG_ERRORFILE("Should never be called, because is set in the constructor."); 261 return rtl::OUString(); 262 } 263 264 ///===== XAccessibleEventBroadcaster ===================================== 265 266 void SAL_CALL 267 ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 268 throw (uno::RuntimeException) 269 { 270 if (!mpTextHelper) 271 CreateTextHelper(); 272 273 mpTextHelper->AddEventListener(xListener); 274 275 ScAccessibleContextBase::addEventListener(xListener); 276 } 277 278 void SAL_CALL 279 ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 280 throw (uno::RuntimeException) 281 { 282 if (!mpTextHelper) 283 CreateTextHelper(); 284 285 mpTextHelper->RemoveEventListener(xListener); 286 287 ScAccessibleContextBase::removeEventListener(xListener); 288 } 289 290 //===== XServiceInfo ==================================================== 291 292 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void) 293 throw (uno::RuntimeException) 294 { 295 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject")); 296 } 297 298 //===== XTypeProvider ======================================================= 299 300 uno::Sequence<sal_Int8> SAL_CALL 301 ScAccessibleEditObject::getImplementationId(void) 302 throw (uno::RuntimeException) 303 { 304 ScUnoGuard aGuard; 305 IsObjectValid(); 306 static uno::Sequence<sal_Int8> aId; 307 if (aId.getLength() == 0) 308 { 309 aId.realloc (16); 310 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 311 } 312 return aId; 313 } 314 315 //==== internal ========================================================= 316 317 sal_Bool ScAccessibleEditObject::IsDefunc( 318 const uno::Reference<XAccessibleStateSet>& rxParentStates) 319 { 320 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() || 321 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 322 } 323 324 void ScAccessibleEditObject::CreateTextHelper() 325 { 326 if (!mpTextHelper) 327 { 328 ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData; 329 if (meObjectType == CellInEditMode || meObjectType == EditControl) 330 { 331 pAccessibleTextData.reset 332 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow)); 333 } 334 else 335 { 336 pAccessibleTextData.reset 337 (new ScAccessibleEditLineTextData(NULL, mpWindow)); 338 } 339 340 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData)); 341 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource ); 342 mpTextHelper->SetEventSource(this); 343 mpTextHelper->SetFocus(mbHasFocus); 344 345 // #i54814# activate cell in edit mode 346 if( meObjectType == CellInEditMode ) 347 { 348 // do not activate cell object, if top edit line is active 349 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); 350 if( pInputHdl && !pInputHdl->IsTopMode() ) 351 { 352 SdrHint aHint( HINT_BEGEDIT ); 353 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint ); 354 } 355 } 356 } 357 } 358 359