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 <editeng/editview.hxx> 48 #include <editeng/editeng.hxx> 49 #include <svx/svdmodel.hxx> 50 51 using namespace ::com::sun::star; 52 using namespace ::com::sun::star::accessibility; 53 54 //===== internal ============================================================ 55 56 ScAccessibleEditObject::ScAccessibleEditObject( 57 const uno::Reference<XAccessible>& rxParent, 58 EditView* pEditView, Window* pWin, const rtl::OUString& rName, 59 const rtl::OUString& rDescription, EditObjectType eObjectType) 60 : 61 ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME), 62 mpTextHelper(NULL), 63 mpEditView(pEditView), 64 mpWindow(pWin), 65 meObjectType(eObjectType), 66 mbHasFocus(sal_False) 67 { 68 CreateTextHelper(); 69 SetName(rName); 70 SetDescription(rDescription); 71 } 72 73 ScAccessibleEditObject::~ScAccessibleEditObject() 74 { 75 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose) 76 { 77 // increment refcount to prevent double call off dtor 78 osl_incrementInterlockedCount( &m_refCount ); 79 // call dispose to inform object wich have a weak reference to this object 80 dispose(); 81 } 82 } 83 84 void SAL_CALL ScAccessibleEditObject::disposing() 85 { 86 ScUnoGuard aGuard; 87 if (mpTextHelper) 88 DELETEZ(mpTextHelper); 89 90 ScAccessibleContextBase::disposing(); 91 } 92 93 void ScAccessibleEditObject::LostFocus() 94 { 95 mbHasFocus = sal_False; 96 if (mpTextHelper) 97 mpTextHelper->SetFocus(sal_False); 98 CommitFocusLost(); 99 } 100 101 void ScAccessibleEditObject::GotFocus() 102 { 103 mbHasFocus = sal_True; 104 CommitFocusGained(); 105 if (mpTextHelper) 106 mpTextHelper->SetFocus(sal_True); 107 } 108 109 //===== XAccessibleComponent ============================================ 110 111 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint( 112 const awt::Point& rPoint ) 113 throw (uno::RuntimeException) 114 { 115 uno::Reference<XAccessible> xRet; 116 if (containsPoint(rPoint)) 117 { 118 ScUnoGuard aGuard; 119 IsObjectValid(); 120 121 if(!mpTextHelper) 122 CreateTextHelper(); 123 124 xRet = mpTextHelper->GetAt(rPoint); 125 } 126 127 return xRet; 128 } 129 130 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const 131 throw (uno::RuntimeException) 132 { 133 Rectangle aScreenBounds; 134 135 if ( mpWindow ) 136 { 137 if ( meObjectType == CellInEditMode ) 138 { 139 if ( mpEditView && mpEditView->GetEditEngine() ) 140 { 141 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() ); 142 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode ); 143 Point aCellLoc = aScreenBounds.TopLeft(); 144 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL ); 145 Point aWindowLoc = aWindowRect.TopLeft(); 146 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() ); 147 aScreenBounds.SetPos( aPos ); 148 } 149 } 150 else 151 { 152 aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL ); 153 } 154 } 155 156 return aScreenBounds; 157 } 158 159 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const 160 throw (uno::RuntimeException) 161 { 162 Rectangle aBounds( GetBoundingBoxOnScreen() ); 163 164 if ( mpWindow ) 165 { 166 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() ); 167 if ( xThis.is() ) 168 { 169 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() ); 170 if ( xContext.is() ) 171 { 172 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() ); 173 if ( xParent.is() ) 174 { 175 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY ); 176 if ( xParentComponent.is() ) 177 { 178 Point aScreenLoc = aBounds.TopLeft(); 179 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen(); 180 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y ); 181 aBounds.SetPos( aPos ); 182 } 183 } 184 } 185 } 186 } 187 188 return aBounds; 189 } 190 191 //===== XAccessibleContext ============================================== 192 193 sal_Int32 SAL_CALL 194 ScAccessibleEditObject::getAccessibleChildCount(void) 195 throw (uno::RuntimeException) 196 { 197 ScUnoGuard aGuard; 198 IsObjectValid(); 199 if (!mpTextHelper) 200 CreateTextHelper(); 201 return mpTextHelper->GetChildCount(); 202 } 203 204 uno::Reference< XAccessible > SAL_CALL 205 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex) 206 throw (uno::RuntimeException, 207 lang::IndexOutOfBoundsException) 208 { 209 ScUnoGuard aGuard; 210 IsObjectValid(); 211 if (!mpTextHelper) 212 CreateTextHelper(); 213 return mpTextHelper->GetChild(nIndex); 214 } 215 216 uno::Reference<XAccessibleStateSet> SAL_CALL 217 ScAccessibleEditObject::getAccessibleStateSet(void) 218 throw (uno::RuntimeException) 219 { 220 ScUnoGuard aGuard; 221 uno::Reference<XAccessibleStateSet> xParentStates; 222 if (getAccessibleParent().is()) 223 { 224 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 225 xParentStates = xParentContext->getAccessibleStateSet(); 226 } 227 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 228 if (IsDefunc(xParentStates)) 229 pStateSet->AddState(AccessibleStateType::DEFUNC); 230 else 231 { 232 // all states are const, because this object exists only in one state 233 pStateSet->AddState(AccessibleStateType::EDITABLE); 234 pStateSet->AddState(AccessibleStateType::ENABLED); 235 pStateSet->AddState(AccessibleStateType::SENSITIVE); 236 pStateSet->AddState(AccessibleStateType::MULTI_LINE); 237 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE); 238 pStateSet->AddState(AccessibleStateType::SHOWING); 239 pStateSet->AddState(AccessibleStateType::VISIBLE); 240 } 241 return pStateSet; 242 } 243 244 ::rtl::OUString SAL_CALL 245 ScAccessibleEditObject::createAccessibleDescription(void) 246 throw (uno::RuntimeException) 247 { 248 // DBG_ERRORFILE("Should never be called, because is set in the constructor.") 249 return rtl::OUString(); 250 } 251 252 ::rtl::OUString SAL_CALL 253 ScAccessibleEditObject::createAccessibleName(void) 254 throw (uno::RuntimeException) 255 { 256 DBG_ERRORFILE("Should never be called, because is set in the constructor."); 257 return rtl::OUString(); 258 } 259 260 ///===== XAccessibleEventBroadcaster ===================================== 261 262 void SAL_CALL 263 ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 264 throw (uno::RuntimeException) 265 { 266 if (!mpTextHelper) 267 CreateTextHelper(); 268 269 mpTextHelper->AddEventListener(xListener); 270 271 ScAccessibleContextBase::addEventListener(xListener); 272 } 273 274 void SAL_CALL 275 ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 276 throw (uno::RuntimeException) 277 { 278 if (!mpTextHelper) 279 CreateTextHelper(); 280 281 mpTextHelper->RemoveEventListener(xListener); 282 283 ScAccessibleContextBase::removeEventListener(xListener); 284 } 285 286 //===== XServiceInfo ==================================================== 287 288 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void) 289 throw (uno::RuntimeException) 290 { 291 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject")); 292 } 293 294 //===== XTypeProvider ======================================================= 295 296 uno::Sequence<sal_Int8> SAL_CALL 297 ScAccessibleEditObject::getImplementationId(void) 298 throw (uno::RuntimeException) 299 { 300 ScUnoGuard aGuard; 301 IsObjectValid(); 302 static uno::Sequence<sal_Int8> aId; 303 if (aId.getLength() == 0) 304 { 305 aId.realloc (16); 306 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 307 } 308 return aId; 309 } 310 311 //==== internal ========================================================= 312 313 sal_Bool ScAccessibleEditObject::IsDefunc( 314 const uno::Reference<XAccessibleStateSet>& rxParentStates) 315 { 316 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() || 317 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 318 } 319 320 void ScAccessibleEditObject::CreateTextHelper() 321 { 322 if (!mpTextHelper) 323 { 324 ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData; 325 if (meObjectType == CellInEditMode || meObjectType == EditControl) 326 { 327 pAccessibleTextData.reset 328 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow)); 329 } 330 else 331 { 332 pAccessibleTextData.reset 333 (new ScAccessibleEditLineTextData(NULL, mpWindow)); 334 } 335 336 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData)); 337 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource ); 338 mpTextHelper->SetEventSource(this); 339 mpTextHelper->SetFocus(mbHasFocus); 340 341 // #i54814# activate cell in edit mode 342 if( meObjectType == CellInEditMode ) 343 { 344 // do not activate cell object, if top edit line is active 345 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); 346 if( pInputHdl && !pInputHdl->IsTopMode() ) 347 { 348 SdrHint aHint( HINT_BEGEDIT ); 349 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint ); 350 } 351 } 352 } 353 } 354 355