1*f6e50924SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*f6e50924SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*f6e50924SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*f6e50924SAndrew Rist * distributed with this work for additional information 6*f6e50924SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*f6e50924SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*f6e50924SAndrew Rist * "License"); you may not use this file except in compliance 9*f6e50924SAndrew Rist * with the License. You may obtain a copy of the License at 10*f6e50924SAndrew Rist * 11*f6e50924SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*f6e50924SAndrew Rist * 13*f6e50924SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*f6e50924SAndrew Rist * software distributed under the License is distributed on an 15*f6e50924SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*f6e50924SAndrew Rist * KIND, either express or implied. See the License for the 17*f6e50924SAndrew Rist * specific language governing permissions and limitations 18*f6e50924SAndrew Rist * under the License. 19*f6e50924SAndrew Rist * 20*f6e50924SAndrew Rist *************************************************************/ 21*f6e50924SAndrew Rist 22*f6e50924SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_svx.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "ChildrenManagerImpl.hxx" 28cdf0e10cSrcweir #include <svx/ShapeTypeHandler.hxx> 29cdf0e10cSrcweir #include <svx/AccessibleShapeInfo.hxx> 30cdf0e10cSrcweir #ifndef _COM_SUN_STAR_ACCESSIBLE_ACCESSIBLESTATETYPE_HPP_ 31cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleStateType.hpp> 32cdf0e10cSrcweir #endif 33cdf0e10cSrcweir #include <com/sun/star/view/XSelectionSupplier.hpp> 34cdf0e10cSrcweir #include <com/sun/star/container/XChild.hpp> 35cdf0e10cSrcweir #include <comphelper/uno3.hxx> 36cdf0e10cSrcweir #include <com/sun/star/container/XChild.hpp> 37cdf0e10cSrcweir 38cdf0e10cSrcweir #include <rtl/ustring.hxx> 39cdf0e10cSrcweir #include <tools/debug.hxx> 40cdf0e10cSrcweir 41cdf0e10cSrcweir using namespace ::com::sun::star; 42cdf0e10cSrcweir using namespace ::com::sun::star::accessibility; 43cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 44cdf0e10cSrcweir 45cdf0e10cSrcweir 46cdf0e10cSrcweir namespace accessibility { 47cdf0e10cSrcweir 48cdf0e10cSrcweir namespace 49cdf0e10cSrcweir { 50cdf0e10cSrcweir void adjustIndexInParentOfShapes(ChildDescriptorListType& _rList) 51cdf0e10cSrcweir { 52cdf0e10cSrcweir ChildDescriptorListType::iterator aEnd = _rList.end(); 53cdf0e10cSrcweir sal_Int32 i=0; 54cdf0e10cSrcweir for ( ChildDescriptorListType::iterator aIter = _rList.begin(); aIter != aEnd; ++aIter,++i) 55cdf0e10cSrcweir aIter->setIndexAtAccessibleShape(i); 56cdf0e10cSrcweir } 57cdf0e10cSrcweir } 58cdf0e10cSrcweir 59cdf0e10cSrcweir //===== AccessibleChildrenManager =========================================== 60cdf0e10cSrcweir 61cdf0e10cSrcweir ChildrenManagerImpl::ChildrenManagerImpl ( 62cdf0e10cSrcweir const uno::Reference<XAccessible>& rxParent, 63cdf0e10cSrcweir const uno::Reference<drawing::XShapes>& rxShapeList, 64cdf0e10cSrcweir const AccessibleShapeTreeInfo& rShapeTreeInfo, 65cdf0e10cSrcweir AccessibleContextBase& rContext) 66cdf0e10cSrcweir : ::cppu::WeakComponentImplHelper2< 67cdf0e10cSrcweir ::com::sun::star::document::XEventListener, 68cdf0e10cSrcweir ::com::sun::star::view::XSelectionChangeListener>(maMutex), 69cdf0e10cSrcweir mxShapeList (rxShapeList), 70cdf0e10cSrcweir mxParent (rxParent), 71cdf0e10cSrcweir maShapeTreeInfo (rShapeTreeInfo), 72cdf0e10cSrcweir mrContext (rContext), 73cdf0e10cSrcweir mnNewNameIndex(1), 74cdf0e10cSrcweir mpFocusedShape(NULL) 75cdf0e10cSrcweir { 76cdf0e10cSrcweir } 77cdf0e10cSrcweir 78cdf0e10cSrcweir 79cdf0e10cSrcweir 80cdf0e10cSrcweir 81cdf0e10cSrcweir ChildrenManagerImpl::~ChildrenManagerImpl (void) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir DBG_ASSERT (rBHelper.bDisposed || rBHelper.bInDispose, 84cdf0e10cSrcweir "~AccessibleDrawDocumentView: object has not been disposed"); 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 87cdf0e10cSrcweir 88cdf0e10cSrcweir 89cdf0e10cSrcweir 90cdf0e10cSrcweir void ChildrenManagerImpl::Init (void) 91cdf0e10cSrcweir { 92cdf0e10cSrcweir // Register as view::XSelectionChangeListener. 93cdf0e10cSrcweir Reference<frame::XController> xController(maShapeTreeInfo.GetController()); 94cdf0e10cSrcweir Reference<view::XSelectionSupplier> xSelectionSupplier ( 95cdf0e10cSrcweir xController, uno::UNO_QUERY); 96cdf0e10cSrcweir if (xSelectionSupplier.is()) 97cdf0e10cSrcweir { 98cdf0e10cSrcweir xController->addEventListener( 99cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 100cdf0e10cSrcweir 101cdf0e10cSrcweir xSelectionSupplier->addSelectionChangeListener ( 102cdf0e10cSrcweir static_cast<view::XSelectionChangeListener*>(this)); 103cdf0e10cSrcweir } 104cdf0e10cSrcweir 105cdf0e10cSrcweir // Register at model as document::XEventListener. 106cdf0e10cSrcweir if (maShapeTreeInfo.GetModelBroadcaster().is()) 107cdf0e10cSrcweir maShapeTreeInfo.GetModelBroadcaster()->addEventListener ( 108cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 109cdf0e10cSrcweir } 110cdf0e10cSrcweir 111cdf0e10cSrcweir 112cdf0e10cSrcweir 113cdf0e10cSrcweir 114cdf0e10cSrcweir long ChildrenManagerImpl::GetChildCount (void) const throw () 115cdf0e10cSrcweir { 116cdf0e10cSrcweir return maVisibleChildren.size(); 117cdf0e10cSrcweir } 118cdf0e10cSrcweir 119cdf0e10cSrcweir 120cdf0e10cSrcweir 121cdf0e10cSrcweir 122cdf0e10cSrcweir /** Return the requested accessible child object. Create it if it is not 123cdf0e10cSrcweir yet in the cache. 124cdf0e10cSrcweir */ 125cdf0e10cSrcweir uno::Reference<XAccessible> 126cdf0e10cSrcweir ChildrenManagerImpl::GetChild (long nIndex) 127cdf0e10cSrcweir throw (::com::sun::star::uno::RuntimeException, 128cdf0e10cSrcweir ::com::sun::star::lang::IndexOutOfBoundsException) 129cdf0e10cSrcweir { 130cdf0e10cSrcweir // Check wether the given index is valid. 131cdf0e10cSrcweir if (nIndex < 0 || (unsigned long)nIndex >= maVisibleChildren.size()) 132cdf0e10cSrcweir throw lang::IndexOutOfBoundsException ( 133cdf0e10cSrcweir ::rtl::OUString::createFromAscii( 134cdf0e10cSrcweir "no accessible child with index ") + nIndex, 135cdf0e10cSrcweir mxParent); 136cdf0e10cSrcweir 137cdf0e10cSrcweir return GetChild (maVisibleChildren[nIndex],nIndex); 138cdf0e10cSrcweir } 139cdf0e10cSrcweir 140cdf0e10cSrcweir 141cdf0e10cSrcweir 142cdf0e10cSrcweir 143cdf0e10cSrcweir /** Return the requested accessible child object. Create it if it is not 144cdf0e10cSrcweir yet in the cache. 145cdf0e10cSrcweir */ 146cdf0e10cSrcweir uno::Reference<XAccessible> 147cdf0e10cSrcweir ChildrenManagerImpl::GetChild (ChildDescriptor& rChildDescriptor,sal_Int32 _nIndex) 148cdf0e10cSrcweir throw (::com::sun::star::uno::RuntimeException) 149cdf0e10cSrcweir { 150cdf0e10cSrcweir if ( ! rChildDescriptor.mxAccessibleShape.is()) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir ::osl::MutexGuard aGuard (maMutex); 153cdf0e10cSrcweir // Make sure that the requested accessible object has not been 154cdf0e10cSrcweir // created while locking the global mutex. 155cdf0e10cSrcweir if ( ! rChildDescriptor.mxAccessibleShape.is()) 156cdf0e10cSrcweir { 157cdf0e10cSrcweir AccessibleShapeInfo aShapeInfo( 158cdf0e10cSrcweir rChildDescriptor.mxShape, 159cdf0e10cSrcweir mxParent, 160cdf0e10cSrcweir this, 161cdf0e10cSrcweir mnNewNameIndex++); 162cdf0e10cSrcweir // Create accessible object that corresponds to the descriptor's 163cdf0e10cSrcweir // shape. 164cdf0e10cSrcweir AccessibleShape* pShape = 165cdf0e10cSrcweir ShapeTypeHandler::Instance().CreateAccessibleObject ( 166cdf0e10cSrcweir aShapeInfo, 167cdf0e10cSrcweir maShapeTreeInfo); 168cdf0e10cSrcweir rChildDescriptor.mxAccessibleShape = uno::Reference<XAccessible> ( 169cdf0e10cSrcweir static_cast<uno::XWeak*>(pShape), 170cdf0e10cSrcweir uno::UNO_QUERY); 171cdf0e10cSrcweir // Now that there is a reference to the new accessible shape we 172cdf0e10cSrcweir // can safely call its Init() method. 173cdf0e10cSrcweir if ( pShape != NULL ) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir pShape->Init(); 176cdf0e10cSrcweir pShape->setIndexInParent(_nIndex); 177cdf0e10cSrcweir } 178cdf0e10cSrcweir } 179cdf0e10cSrcweir } 180cdf0e10cSrcweir 181cdf0e10cSrcweir return rChildDescriptor.mxAccessibleShape; 182cdf0e10cSrcweir } 183cdf0e10cSrcweir 184cdf0e10cSrcweir 185cdf0e10cSrcweir 186cdf0e10cSrcweir 187cdf0e10cSrcweir uno::Reference<XAccessible> 188cdf0e10cSrcweir ChildrenManagerImpl::GetChild (const uno::Reference<drawing::XShape>& xShape) 189cdf0e10cSrcweir throw (uno::RuntimeException) 190cdf0e10cSrcweir { 191cdf0e10cSrcweir ChildDescriptorListType::iterator I, aEnd = maVisibleChildren.end(); 192cdf0e10cSrcweir for (I = maVisibleChildren.begin(); I != aEnd; ++I) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir if ( I->mxShape.get() == xShape.get() ) 195cdf0e10cSrcweir return I->mxAccessibleShape; 196cdf0e10cSrcweir } 197cdf0e10cSrcweir return uno::Reference<XAccessible> (); 198cdf0e10cSrcweir } 199cdf0e10cSrcweir 200cdf0e10cSrcweir 201cdf0e10cSrcweir 202cdf0e10cSrcweir 203cdf0e10cSrcweir /** Find all shapes among the specified shapes that lie fully or partially 204cdf0e10cSrcweir inside the visible area. Put those shapes into the cleared cache. The 205cdf0e10cSrcweir corresponding accessible objects will be created on demand. 206cdf0e10cSrcweir 207cdf0e10cSrcweir At the moment, first all accessible objects are removed from the cache 208cdf0e10cSrcweir and the appropriate listeners are informed of this. Next, the list is 209cdf0e10cSrcweir created again. This should be optimized in the future to not remove and 210cdf0e10cSrcweir create objects that will be in the list before and after the update 211cdf0e10cSrcweir method. 212cdf0e10cSrcweir */ 213cdf0e10cSrcweir void ChildrenManagerImpl::Update (bool bCreateNewObjectsOnDemand) 214cdf0e10cSrcweir { 215cdf0e10cSrcweir if (maShapeTreeInfo.GetViewForwarder() == NULL) 216cdf0e10cSrcweir return; 217cdf0e10cSrcweir Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea(); 218cdf0e10cSrcweir 219cdf0e10cSrcweir // 1. Create a local list of visible shapes. 220cdf0e10cSrcweir ChildDescriptorListType aChildList; 221cdf0e10cSrcweir CreateListOfVisibleShapes (aChildList); 222cdf0e10cSrcweir 223cdf0e10cSrcweir // 2. Merge the information that is already known about the visible 224cdf0e10cSrcweir // shapes from the current list into the new list. 225cdf0e10cSrcweir MergeAccessibilityInformation (aChildList); 226cdf0e10cSrcweir 227cdf0e10cSrcweir // 3. Replace the current list of visible shapes with the new one. Do 228cdf0e10cSrcweir // the same with the visible area. 229cdf0e10cSrcweir { 230cdf0e10cSrcweir ::osl::MutexGuard aGuard (maMutex); 231cdf0e10cSrcweir adjustIndexInParentOfShapes(aChildList); 232cdf0e10cSrcweir 233cdf0e10cSrcweir // Use swap to copy the contents of the new list in constant time. 234cdf0e10cSrcweir maVisibleChildren.swap (aChildList); 235cdf0e10cSrcweir 236cdf0e10cSrcweir // aChildList now contains all the old children, while maVisibleChildren 237cdf0e10cSrcweir // contains all the current children 238cdf0e10cSrcweir 239cdf0e10cSrcweir // 4. Find all shapes in the old list that are not in the current list, 240cdf0e10cSrcweir // send appropriate events and remove the accessible shape. 241cdf0e10cSrcweir // 242cdf0e10cSrcweir // Do this *after* we have set our new list of children, because 243cdf0e10cSrcweir // removing a child may cause 244cdf0e10cSrcweir // 245cdf0e10cSrcweir // ChildDescriptor::disposeAccessibleObject --> 246cdf0e10cSrcweir // AccessibleContextBase::CommitChange --> 247cdf0e10cSrcweir // AtkListener::notifyEvent -> 248cdf0e10cSrcweir // AtkListener::handleChildRemoved -> 249cdf0e10cSrcweir // AtkListener::updateChildList 250cdf0e10cSrcweir // AccessibleDrawDocumentView::getAccessibleChildCount -> 251cdf0e10cSrcweir // ChildrenManagerImpl::GetChildCount -> 252cdf0e10cSrcweir // maVisibleChildren.size() 253cdf0e10cSrcweir // 254cdf0e10cSrcweir // to be fired, and so the operations will take place on 255cdf0e10cSrcweir // the list we are trying to replace 256cdf0e10cSrcweir // 257cdf0e10cSrcweir RemoveNonVisibleChildren (maVisibleChildren, aChildList); 258cdf0e10cSrcweir 259cdf0e10cSrcweir aChildList.clear(); 260cdf0e10cSrcweir 261cdf0e10cSrcweir maVisibleArea = aVisibleArea; 262cdf0e10cSrcweir } 263cdf0e10cSrcweir 264cdf0e10cSrcweir // 5. If the visible area has changed then send events that signal a 265cdf0e10cSrcweir // change of their bounding boxes for all shapes that are members of 266cdf0e10cSrcweir // both the current and the new list of visible shapes. 267cdf0e10cSrcweir if (maVisibleArea != aVisibleArea) 268cdf0e10cSrcweir SendVisibleAreaEvents (maVisibleChildren); 269cdf0e10cSrcweir 270cdf0e10cSrcweir // 6. If children have to be created immediately and not on demand then 271cdf0e10cSrcweir // create the missing accessible objects now. 272cdf0e10cSrcweir if ( ! bCreateNewObjectsOnDemand) 273cdf0e10cSrcweir CreateAccessibilityObjects (maVisibleChildren); 274cdf0e10cSrcweir } 275cdf0e10cSrcweir 276cdf0e10cSrcweir 277cdf0e10cSrcweir 278cdf0e10cSrcweir 279cdf0e10cSrcweir void ChildrenManagerImpl::CreateListOfVisibleShapes ( 280cdf0e10cSrcweir ChildDescriptorListType& raDescriptorList) 281cdf0e10cSrcweir { 282cdf0e10cSrcweir ::osl::MutexGuard aGuard (maMutex); 283cdf0e10cSrcweir 284cdf0e10cSrcweir OSL_ASSERT (maShapeTreeInfo.GetViewForwarder() != NULL); 285cdf0e10cSrcweir 286cdf0e10cSrcweir Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea(); 287cdf0e10cSrcweir 288cdf0e10cSrcweir // Add the visible shapes for wich the accessible objects already exist. 289cdf0e10cSrcweir AccessibleShapeList::iterator I,aEnd = maAccessibleShapes.end(); 290cdf0e10cSrcweir for (I=maAccessibleShapes.begin(); I != aEnd; ++I) 291cdf0e10cSrcweir { 292cdf0e10cSrcweir if (I->is()) 293cdf0e10cSrcweir { 294cdf0e10cSrcweir uno::Reference<XAccessibleComponent> xComponent ( 295cdf0e10cSrcweir (*I)->getAccessibleContext(), uno::UNO_QUERY); 296cdf0e10cSrcweir if (xComponent.is()) 297cdf0e10cSrcweir { 298cdf0e10cSrcweir // The bounding box of the object already is clipped to the 299cdf0e10cSrcweir // visible area. The object is therefore visible if the 300cdf0e10cSrcweir // bounding box has non-zero extensions. 301cdf0e10cSrcweir awt::Rectangle aPixelBBox (xComponent->getBounds()); 302cdf0e10cSrcweir if ((aPixelBBox.Width > 0) && (aPixelBBox.Height > 0)) 303cdf0e10cSrcweir raDescriptorList.push_back (ChildDescriptor (*I)); 304cdf0e10cSrcweir } 305cdf0e10cSrcweir } 306cdf0e10cSrcweir } 307cdf0e10cSrcweir 308cdf0e10cSrcweir // Add the visible shapes for which only the XShapes exist. 309cdf0e10cSrcweir uno::Reference<container::XIndexAccess> xShapeAccess (mxShapeList, uno::UNO_QUERY); 310cdf0e10cSrcweir if (xShapeAccess.is()) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir sal_Int32 nShapeCount = xShapeAccess->getCount(); 313cdf0e10cSrcweir raDescriptorList.reserve( nShapeCount ); 314cdf0e10cSrcweir awt::Point aPos; 315cdf0e10cSrcweir awt::Size aSize; 316cdf0e10cSrcweir Rectangle aBoundingBox; 317cdf0e10cSrcweir uno::Reference<drawing::XShape> xShape; 318cdf0e10cSrcweir for (sal_Int32 i=0; i<nShapeCount; ++i) 319cdf0e10cSrcweir { 320cdf0e10cSrcweir xShapeAccess->getByIndex(i) >>= xShape; 321cdf0e10cSrcweir aPos = xShape->getPosition(); 322cdf0e10cSrcweir aSize = xShape->getSize(); 323cdf0e10cSrcweir 324cdf0e10cSrcweir aBoundingBox.nLeft = aPos.X; 325cdf0e10cSrcweir aBoundingBox.nTop = aPos.Y; 326cdf0e10cSrcweir aBoundingBox.nRight = aPos.X + aSize.Width; 327cdf0e10cSrcweir aBoundingBox.nBottom = aPos.Y + aSize.Height; 328cdf0e10cSrcweir 329cdf0e10cSrcweir // Insert shape if it is visible, i.e. its bounding box overlaps 330cdf0e10cSrcweir // the visible area. 331cdf0e10cSrcweir if ( aBoundingBox.IsOver (aVisibleArea) ) 332cdf0e10cSrcweir raDescriptorList.push_back (ChildDescriptor (xShape)); 333cdf0e10cSrcweir } 334cdf0e10cSrcweir } 335cdf0e10cSrcweir } 336cdf0e10cSrcweir 337cdf0e10cSrcweir 338cdf0e10cSrcweir 339cdf0e10cSrcweir 340cdf0e10cSrcweir void ChildrenManagerImpl::RemoveNonVisibleChildren ( 341cdf0e10cSrcweir const ChildDescriptorListType& rNewChildList, 342cdf0e10cSrcweir ChildDescriptorListType& rOldChildList) 343cdf0e10cSrcweir { 344cdf0e10cSrcweir // Iterate over list of formerly visible children and remove those that 345cdf0e10cSrcweir // are not visible anymore, i.e. member of the new list of visible 346cdf0e10cSrcweir // children. 347cdf0e10cSrcweir ChildDescriptorListType::iterator I, aEnd = rOldChildList.end(); 348cdf0e10cSrcweir for (I=rOldChildList.begin(); I != aEnd; ++I) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir if (::std::find(rNewChildList.begin(), rNewChildList.end(), *I) == rNewChildList.end()) 351cdf0e10cSrcweir { 352cdf0e10cSrcweir // The child is disposed when there is a UNO shape from which 353cdf0e10cSrcweir // the accessible shape can be created when the shape becomes 354cdf0e10cSrcweir // visible again. When there is no such UNO shape then simply 355cdf0e10cSrcweir // reset the descriptor but keep the accessibility object. 356cdf0e10cSrcweir if (I->mxShape.is()) 357cdf0e10cSrcweir { 358cdf0e10cSrcweir UnregisterAsDisposeListener (I->mxShape); 359cdf0e10cSrcweir I->disposeAccessibleObject (mrContext); 360cdf0e10cSrcweir } 361cdf0e10cSrcweir else 362cdf0e10cSrcweir { 363cdf0e10cSrcweir AccessibleShape* pAccessibleShape = I->GetAccessibleShape(); 364cdf0e10cSrcweir pAccessibleShape->ResetState (AccessibleStateType::VISIBLE); 365cdf0e10cSrcweir I->mxAccessibleShape = NULL; 366cdf0e10cSrcweir } 367cdf0e10cSrcweir } 368cdf0e10cSrcweir } 369cdf0e10cSrcweir } 370cdf0e10cSrcweir 371cdf0e10cSrcweir 372cdf0e10cSrcweir 373cdf0e10cSrcweir 374cdf0e10cSrcweir void ChildrenManagerImpl::MergeAccessibilityInformation ( 375cdf0e10cSrcweir ChildDescriptorListType& raNewChildList) 376cdf0e10cSrcweir { 377cdf0e10cSrcweir ChildDescriptorListType::iterator aOldChildDescriptor; 378cdf0e10cSrcweir ChildDescriptorListType::iterator I, aEnd = raNewChildList.end(); 379cdf0e10cSrcweir for (I=raNewChildList.begin(); I != aEnd; ++I) 380cdf0e10cSrcweir { 381cdf0e10cSrcweir aOldChildDescriptor = ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(), *I); 382cdf0e10cSrcweir 383cdf0e10cSrcweir // Copy accessible shape if that exists in the old descriptor. 384cdf0e10cSrcweir bool bRegistrationIsNecessary = true; 385cdf0e10cSrcweir if (aOldChildDescriptor != maVisibleChildren.end()) 386cdf0e10cSrcweir if (aOldChildDescriptor->mxAccessibleShape.is()) 387cdf0e10cSrcweir { 388cdf0e10cSrcweir I->mxAccessibleShape = aOldChildDescriptor->mxAccessibleShape; 389cdf0e10cSrcweir I->mbCreateEventPending = false; 390cdf0e10cSrcweir bRegistrationIsNecessary = false; 391cdf0e10cSrcweir } 392cdf0e10cSrcweir if (bRegistrationIsNecessary) 393cdf0e10cSrcweir RegisterAsDisposeListener (I->mxShape); 394cdf0e10cSrcweir } 395cdf0e10cSrcweir } 396cdf0e10cSrcweir 397cdf0e10cSrcweir 398cdf0e10cSrcweir 399cdf0e10cSrcweir 400cdf0e10cSrcweir void ChildrenManagerImpl::SendVisibleAreaEvents ( 401cdf0e10cSrcweir ChildDescriptorListType& raNewChildList) 402cdf0e10cSrcweir { 403cdf0e10cSrcweir ChildDescriptorListType::iterator I,aEnd = raNewChildList.end(); 404cdf0e10cSrcweir for (I=raNewChildList.begin(); I != aEnd; ++I) 405cdf0e10cSrcweir { 406cdf0e10cSrcweir // Tell shape of changed visible area. To do this, fake a 407cdf0e10cSrcweir // change of the view forwarder. (Actually we usually get here 408cdf0e10cSrcweir // as a result of a change of the view forwarder). 409cdf0e10cSrcweir AccessibleShape* pShape = I->GetAccessibleShape (); 410cdf0e10cSrcweir if (pShape != NULL) 411cdf0e10cSrcweir pShape->ViewForwarderChanged ( 412cdf0e10cSrcweir IAccessibleViewForwarderListener::VISIBLE_AREA, 413cdf0e10cSrcweir maShapeTreeInfo.GetViewForwarder()); 414cdf0e10cSrcweir } 415cdf0e10cSrcweir } 416cdf0e10cSrcweir 417cdf0e10cSrcweir 418cdf0e10cSrcweir 419cdf0e10cSrcweir 420cdf0e10cSrcweir void ChildrenManagerImpl::CreateAccessibilityObjects ( 421cdf0e10cSrcweir ChildDescriptorListType& raNewChildList) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir ChildDescriptorListType::iterator I, aEnd = raNewChildList.end(); 424cdf0e10cSrcweir sal_Int32 nPos = 0; 425cdf0e10cSrcweir for ( I = raNewChildList.begin(); I != aEnd; ++I,++nPos) 426cdf0e10cSrcweir { 427cdf0e10cSrcweir // Create the associated accessible object when the flag says so and 428cdf0e10cSrcweir // it does not yet exist. 429cdf0e10cSrcweir if ( ! I->mxAccessibleShape.is() ) 430cdf0e10cSrcweir GetChild (*I,nPos); 431cdf0e10cSrcweir if (I->mxAccessibleShape.is() && I->mbCreateEventPending) 432cdf0e10cSrcweir { 433cdf0e10cSrcweir I->mbCreateEventPending = false; 434cdf0e10cSrcweir mrContext.CommitChange ( 435cdf0e10cSrcweir AccessibleEventId::CHILD, 436cdf0e10cSrcweir uno::makeAny(I->mxAccessibleShape), 437cdf0e10cSrcweir uno::Any()); 438cdf0e10cSrcweir } 439cdf0e10cSrcweir } 440cdf0e10cSrcweir } 441cdf0e10cSrcweir 442cdf0e10cSrcweir 443cdf0e10cSrcweir 444cdf0e10cSrcweir 445cdf0e10cSrcweir void ChildrenManagerImpl::AddShape (const Reference<drawing::XShape>& rxShape) 446cdf0e10cSrcweir { 447cdf0e10cSrcweir if (rxShape.is()) 448cdf0e10cSrcweir { 449cdf0e10cSrcweir ::osl::ClearableMutexGuard aGuard (maMutex); 450cdf0e10cSrcweir 451cdf0e10cSrcweir // Test visibility of the shape. 452cdf0e10cSrcweir Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea(); 453cdf0e10cSrcweir awt::Point aPos = rxShape->getPosition(); 454cdf0e10cSrcweir awt::Size aSize = rxShape->getSize(); 455cdf0e10cSrcweir 456cdf0e10cSrcweir Rectangle aBoundingBox ( 457cdf0e10cSrcweir aPos.X, 458cdf0e10cSrcweir aPos.Y, 459cdf0e10cSrcweir aPos.X + aSize.Width, 460cdf0e10cSrcweir aPos.Y + aSize.Height); 461cdf0e10cSrcweir 462cdf0e10cSrcweir // Add the shape only when it belongs to the list of shapes stored 463cdf0e10cSrcweir // in mxShapeList (which is either a page or a group shape). 464cdf0e10cSrcweir Reference<container::XChild> xChild (rxShape, uno::UNO_QUERY); 465cdf0e10cSrcweir if (xChild.is()) 466cdf0e10cSrcweir { 467cdf0e10cSrcweir Reference<drawing::XShapes> xParent (xChild->getParent(), uno::UNO_QUERY); 468cdf0e10cSrcweir if (xParent == mxShapeList) 469cdf0e10cSrcweir if (aBoundingBox.IsOver (aVisibleArea)) 470cdf0e10cSrcweir { 471cdf0e10cSrcweir // Add shape to list of visible shapes. 472cdf0e10cSrcweir maVisibleChildren.push_back (ChildDescriptor (rxShape)); 473cdf0e10cSrcweir 474cdf0e10cSrcweir // Create accessibility object. 475cdf0e10cSrcweir ChildDescriptor& rDescriptor = maVisibleChildren.back(); 476cdf0e10cSrcweir GetChild (rDescriptor, maVisibleChildren.size()-1); 477cdf0e10cSrcweir 478cdf0e10cSrcweir // Inform listeners about new child. 479cdf0e10cSrcweir uno::Any aNewShape; 480cdf0e10cSrcweir aNewShape <<= rDescriptor.mxAccessibleShape; 481cdf0e10cSrcweir aGuard.clear(); 482cdf0e10cSrcweir mrContext.CommitChange ( 483cdf0e10cSrcweir AccessibleEventId::CHILD, 484cdf0e10cSrcweir aNewShape, 485cdf0e10cSrcweir uno::Any()); 486cdf0e10cSrcweir RegisterAsDisposeListener (rDescriptor.mxShape); 487cdf0e10cSrcweir } 488cdf0e10cSrcweir } 489cdf0e10cSrcweir } 490cdf0e10cSrcweir } 491cdf0e10cSrcweir 492cdf0e10cSrcweir 493cdf0e10cSrcweir 494cdf0e10cSrcweir 495cdf0e10cSrcweir void ChildrenManagerImpl::RemoveShape (const Reference<drawing::XShape>& rxShape) 496cdf0e10cSrcweir { 497cdf0e10cSrcweir if (rxShape.is()) 498cdf0e10cSrcweir { 499cdf0e10cSrcweir ::osl::ClearableMutexGuard aGuard (maMutex); 500cdf0e10cSrcweir 501cdf0e10cSrcweir // Search shape in list of visible children. 502cdf0e10cSrcweir ChildDescriptorListType::iterator I ( 503cdf0e10cSrcweir ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(), 504cdf0e10cSrcweir ChildDescriptor (rxShape))); 505cdf0e10cSrcweir if (I != maVisibleChildren.end()) 506cdf0e10cSrcweir { 507cdf0e10cSrcweir // Remove descriptor from that list. 508cdf0e10cSrcweir Reference<XAccessible> xAccessibleShape (I->mxAccessibleShape); 509cdf0e10cSrcweir 510cdf0e10cSrcweir UnregisterAsDisposeListener (I->mxShape); 511cdf0e10cSrcweir // Dispose the accessible object. 512cdf0e10cSrcweir I->disposeAccessibleObject (mrContext); 513cdf0e10cSrcweir 514cdf0e10cSrcweir // Now we can safely remove the child descriptor and thus 515cdf0e10cSrcweir // invalidate the iterator. 516cdf0e10cSrcweir maVisibleChildren.erase (I); 517cdf0e10cSrcweir 518cdf0e10cSrcweir adjustIndexInParentOfShapes(maVisibleChildren); 519cdf0e10cSrcweir } 520cdf0e10cSrcweir } 521cdf0e10cSrcweir } 522cdf0e10cSrcweir 523cdf0e10cSrcweir 524cdf0e10cSrcweir 525cdf0e10cSrcweir 526cdf0e10cSrcweir void ChildrenManagerImpl::SetShapeList (const ::com::sun::star::uno::Reference< 527cdf0e10cSrcweir ::com::sun::star::drawing::XShapes>& xShapeList) 528cdf0e10cSrcweir { 529cdf0e10cSrcweir mxShapeList = xShapeList; 530cdf0e10cSrcweir } 531cdf0e10cSrcweir 532cdf0e10cSrcweir 533cdf0e10cSrcweir 534cdf0e10cSrcweir 535cdf0e10cSrcweir void ChildrenManagerImpl::AddAccessibleShape (std::auto_ptr<AccessibleShape> pShape) 536cdf0e10cSrcweir { 537cdf0e10cSrcweir if (pShape.get() != NULL) 538cdf0e10cSrcweir maAccessibleShapes.push_back (pShape.release()); 539cdf0e10cSrcweir } 540cdf0e10cSrcweir 541cdf0e10cSrcweir 542cdf0e10cSrcweir 543cdf0e10cSrcweir 544cdf0e10cSrcweir void ChildrenManagerImpl::ClearAccessibleShapeList (void) 545cdf0e10cSrcweir { 546cdf0e10cSrcweir // Copy the list of (visible) shapes to local lists and clear the 547cdf0e10cSrcweir // originals. 548cdf0e10cSrcweir ChildDescriptorListType aLocalVisibleChildren; 549cdf0e10cSrcweir aLocalVisibleChildren.swap(maVisibleChildren); 550cdf0e10cSrcweir AccessibleShapeList aLocalAccessibleShapes; 551cdf0e10cSrcweir aLocalAccessibleShapes.swap(maAccessibleShapes); 552cdf0e10cSrcweir 553cdf0e10cSrcweir // Tell the listeners that all children are gone. 554cdf0e10cSrcweir mrContext.CommitChange ( 555cdf0e10cSrcweir AccessibleEventId::INVALIDATE_ALL_CHILDREN, 556cdf0e10cSrcweir uno::Any(), 557cdf0e10cSrcweir uno::Any()); 558cdf0e10cSrcweir 559cdf0e10cSrcweir // There are no accessible shapes left so the index assigned to new 560cdf0e10cSrcweir // accessible shapes can be reset. 561cdf0e10cSrcweir mnNewNameIndex = 1; 562cdf0e10cSrcweir 563cdf0e10cSrcweir // Now the objects in the local lists can be safely disposed without 564cdf0e10cSrcweir // having problems with callers that want to update their child lists. 565cdf0e10cSrcweir 566cdf0e10cSrcweir // Clear the list of visible accessible objects. Objects not created on 567cdf0e10cSrcweir // demand for XShapes are treated below. 568cdf0e10cSrcweir ChildDescriptorListType::iterator I,aEnd = aLocalVisibleChildren.end(); 569cdf0e10cSrcweir for (I=aLocalVisibleChildren.begin(); I != aEnd; ++I) 570cdf0e10cSrcweir if ( I->mxAccessibleShape.is() && I->mxShape.is() ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir ::comphelper::disposeComponent(I->mxAccessibleShape); 573cdf0e10cSrcweir I->mxAccessibleShape = NULL; 574cdf0e10cSrcweir } 575cdf0e10cSrcweir 576cdf0e10cSrcweir // Dispose all objects in the accessible shape list. 577cdf0e10cSrcweir AccessibleShapeList::iterator J,aEnd2 = aLocalAccessibleShapes.end(); 578cdf0e10cSrcweir for (J=aLocalAccessibleShapes.begin(); J != aEnd2; ++J) 579cdf0e10cSrcweir if (J->is()) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir // Dispose the object. 582cdf0e10cSrcweir ::comphelper::disposeComponent(*J); 583cdf0e10cSrcweir *J = NULL; 584cdf0e10cSrcweir } 585cdf0e10cSrcweir } 586cdf0e10cSrcweir 587cdf0e10cSrcweir 588cdf0e10cSrcweir 589cdf0e10cSrcweir 590cdf0e10cSrcweir /** If the broadcasters change at which this object is registered then 591cdf0e10cSrcweir unregister at old and register at new broadcasters. 592cdf0e10cSrcweir */ 593cdf0e10cSrcweir void ChildrenManagerImpl::SetInfo (const AccessibleShapeTreeInfo& rShapeTreeInfo) 594cdf0e10cSrcweir { 595cdf0e10cSrcweir // Remember the current broadcasters and exchange the shape tree info. 596cdf0e10cSrcweir Reference<document::XEventBroadcaster> xCurrentBroadcaster; 597cdf0e10cSrcweir Reference<frame::XController> xCurrentController; 598cdf0e10cSrcweir Reference<view::XSelectionSupplier> xCurrentSelectionSupplier; 599cdf0e10cSrcweir { 600cdf0e10cSrcweir ::osl::MutexGuard aGuard (maMutex); 601cdf0e10cSrcweir xCurrentBroadcaster = maShapeTreeInfo.GetModelBroadcaster(); 602cdf0e10cSrcweir xCurrentController = maShapeTreeInfo.GetController(); 603cdf0e10cSrcweir xCurrentSelectionSupplier = Reference<view::XSelectionSupplier> ( 604cdf0e10cSrcweir xCurrentController, uno::UNO_QUERY); 605cdf0e10cSrcweir maShapeTreeInfo = rShapeTreeInfo; 606cdf0e10cSrcweir } 607cdf0e10cSrcweir 608cdf0e10cSrcweir // Move registration to new model. 609cdf0e10cSrcweir if (maShapeTreeInfo.GetModelBroadcaster() != xCurrentBroadcaster) 610cdf0e10cSrcweir { 611cdf0e10cSrcweir // Register at new broadcaster. 612cdf0e10cSrcweir if (maShapeTreeInfo.GetModelBroadcaster().is()) 613cdf0e10cSrcweir maShapeTreeInfo.GetModelBroadcaster()->addEventListener ( 614cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 615cdf0e10cSrcweir 616cdf0e10cSrcweir // Unregister at old broadcaster. 617cdf0e10cSrcweir if (xCurrentBroadcaster.is()) 618cdf0e10cSrcweir xCurrentBroadcaster->removeEventListener ( 619cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 620cdf0e10cSrcweir } 621cdf0e10cSrcweir 622cdf0e10cSrcweir // Move registration to new selection supplier. 623cdf0e10cSrcweir Reference<frame::XController> xNewController(maShapeTreeInfo.GetController()); 624cdf0e10cSrcweir Reference<view::XSelectionSupplier> xNewSelectionSupplier ( 625cdf0e10cSrcweir xNewController, uno::UNO_QUERY); 626cdf0e10cSrcweir if (xNewSelectionSupplier != xCurrentSelectionSupplier) 627cdf0e10cSrcweir { 628cdf0e10cSrcweir // Register at new broadcaster. 629cdf0e10cSrcweir if (xNewSelectionSupplier.is()) 630cdf0e10cSrcweir { 631cdf0e10cSrcweir xNewController->addEventListener( 632cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 633cdf0e10cSrcweir 634cdf0e10cSrcweir xNewSelectionSupplier->addSelectionChangeListener ( 635cdf0e10cSrcweir static_cast<view::XSelectionChangeListener*>(this)); 636cdf0e10cSrcweir } 637cdf0e10cSrcweir 638cdf0e10cSrcweir // Unregister at old broadcaster. 639cdf0e10cSrcweir if (xCurrentSelectionSupplier.is()) 640cdf0e10cSrcweir { 641cdf0e10cSrcweir xCurrentSelectionSupplier->removeSelectionChangeListener ( 642cdf0e10cSrcweir static_cast<view::XSelectionChangeListener*>(this)); 643cdf0e10cSrcweir 644cdf0e10cSrcweir xCurrentController->removeEventListener( 645cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 646cdf0e10cSrcweir } 647cdf0e10cSrcweir } 648cdf0e10cSrcweir } 649cdf0e10cSrcweir 650cdf0e10cSrcweir 651cdf0e10cSrcweir 652cdf0e10cSrcweir 653cdf0e10cSrcweir //===== lang::XEventListener ================================================ 654cdf0e10cSrcweir 655cdf0e10cSrcweir void SAL_CALL 656cdf0e10cSrcweir ChildrenManagerImpl::disposing (const lang::EventObject& rEventObject) 657cdf0e10cSrcweir throw (uno::RuntimeException) 658cdf0e10cSrcweir { 659cdf0e10cSrcweir if (rEventObject.Source == maShapeTreeInfo.GetModelBroadcaster() 660cdf0e10cSrcweir || rEventObject.Source == maShapeTreeInfo.GetController()) 661cdf0e10cSrcweir { 662cdf0e10cSrcweir impl_dispose(); 663cdf0e10cSrcweir } 664cdf0e10cSrcweir 665cdf0e10cSrcweir // Handle disposing UNO shapes. 666cdf0e10cSrcweir else 667cdf0e10cSrcweir { 668cdf0e10cSrcweir Reference<drawing::XShape> xShape (rEventObject.Source, uno::UNO_QUERY); 669cdf0e10cSrcweir 670cdf0e10cSrcweir // Find the descriptor for the given shape. 671cdf0e10cSrcweir ChildDescriptorListType::iterator I ( 672cdf0e10cSrcweir ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(), 673cdf0e10cSrcweir ChildDescriptor (xShape))); 674cdf0e10cSrcweir if (I != maVisibleChildren.end()) 675cdf0e10cSrcweir { 676cdf0e10cSrcweir // Clear the descriptor. 677cdf0e10cSrcweir I->disposeAccessibleObject (mrContext); 678cdf0e10cSrcweir I->mxShape = NULL; 679cdf0e10cSrcweir } 680cdf0e10cSrcweir } 681cdf0e10cSrcweir } 682cdf0e10cSrcweir 683cdf0e10cSrcweir 684cdf0e10cSrcweir 685cdf0e10cSrcweir 686cdf0e10cSrcweir //===== document::XEventListener ============================================ 687cdf0e10cSrcweir 688cdf0e10cSrcweir /** Listen for new and removed shapes. 689cdf0e10cSrcweir */ 690cdf0e10cSrcweir void SAL_CALL 691cdf0e10cSrcweir ChildrenManagerImpl::notifyEvent ( 692cdf0e10cSrcweir const document::EventObject& rEventObject) 693cdf0e10cSrcweir throw (uno::RuntimeException) 694cdf0e10cSrcweir { 695cdf0e10cSrcweir static const ::rtl::OUString sShapeInserted ( 696cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("ShapeInserted")); 697cdf0e10cSrcweir static const ::rtl::OUString sShapeRemoved ( 698cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("ShapeRemoved")); 699cdf0e10cSrcweir 700cdf0e10cSrcweir 701cdf0e10cSrcweir if (rEventObject.EventName.equals (sShapeInserted)) 702cdf0e10cSrcweir AddShape (Reference<drawing::XShape>(rEventObject.Source, uno::UNO_QUERY)); 703cdf0e10cSrcweir else if (rEventObject.EventName.equals (sShapeRemoved)) 704cdf0e10cSrcweir RemoveShape (Reference<drawing::XShape>(rEventObject.Source, uno::UNO_QUERY)); 705cdf0e10cSrcweir // else ignore unknown event. 706cdf0e10cSrcweir } 707cdf0e10cSrcweir 708cdf0e10cSrcweir 709cdf0e10cSrcweir 710cdf0e10cSrcweir 711cdf0e10cSrcweir //===== view::XSelectionChangeListener ====================================== 712cdf0e10cSrcweir 713cdf0e10cSrcweir void SAL_CALL 714cdf0e10cSrcweir ChildrenManagerImpl::selectionChanged (const lang::EventObject& /*rEvent*/) 715cdf0e10cSrcweir throw (uno::RuntimeException) 716cdf0e10cSrcweir { 717cdf0e10cSrcweir UpdateSelection (); 718cdf0e10cSrcweir } 719cdf0e10cSrcweir 720cdf0e10cSrcweir 721cdf0e10cSrcweir 722cdf0e10cSrcweir 723cdf0e10cSrcweir void ChildrenManagerImpl::impl_dispose (void) 724cdf0e10cSrcweir { 725cdf0e10cSrcweir Reference<frame::XController> xController(maShapeTreeInfo.GetController()); 726cdf0e10cSrcweir // Remove from broadcasters. 727cdf0e10cSrcweir try 728cdf0e10cSrcweir { 729cdf0e10cSrcweir Reference<view::XSelectionSupplier> xSelectionSupplier ( 730cdf0e10cSrcweir xController, uno::UNO_QUERY); 731cdf0e10cSrcweir if (xSelectionSupplier.is()) 732cdf0e10cSrcweir { 733cdf0e10cSrcweir xSelectionSupplier->removeSelectionChangeListener ( 734cdf0e10cSrcweir static_cast<view::XSelectionChangeListener*>(this)); 735cdf0e10cSrcweir } 736cdf0e10cSrcweir } 737cdf0e10cSrcweir catch( uno::RuntimeException&) 738cdf0e10cSrcweir {} 739cdf0e10cSrcweir 740cdf0e10cSrcweir try 741cdf0e10cSrcweir { 742cdf0e10cSrcweir if (xController.is()) 743cdf0e10cSrcweir xController->removeEventListener( 744cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 745cdf0e10cSrcweir } 746cdf0e10cSrcweir catch( uno::RuntimeException&) 747cdf0e10cSrcweir {} 748cdf0e10cSrcweir 749cdf0e10cSrcweir maShapeTreeInfo.SetController (NULL); 750cdf0e10cSrcweir 751cdf0e10cSrcweir try 752cdf0e10cSrcweir { 753cdf0e10cSrcweir // Remove from broadcaster. 754cdf0e10cSrcweir if (maShapeTreeInfo.GetModelBroadcaster().is()) 755cdf0e10cSrcweir maShapeTreeInfo.GetModelBroadcaster()->removeEventListener ( 756cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 757cdf0e10cSrcweir maShapeTreeInfo.SetModelBroadcaster (NULL); 758cdf0e10cSrcweir } 759cdf0e10cSrcweir catch( uno::RuntimeException& ) 760cdf0e10cSrcweir {} 761cdf0e10cSrcweir 762cdf0e10cSrcweir ClearAccessibleShapeList (); 763cdf0e10cSrcweir SetShapeList (NULL); 764cdf0e10cSrcweir } 765cdf0e10cSrcweir 766cdf0e10cSrcweir 767cdf0e10cSrcweir 768cdf0e10cSrcweir void SAL_CALL ChildrenManagerImpl::disposing (void) 769cdf0e10cSrcweir { 770cdf0e10cSrcweir impl_dispose(); 771cdf0e10cSrcweir } 772cdf0e10cSrcweir 773cdf0e10cSrcweir 774cdf0e10cSrcweir 775cdf0e10cSrcweir 776cdf0e10cSrcweir // This method is experimental. Use with care. 777cdf0e10cSrcweir long int ChildrenManagerImpl::GetChildIndex (const ::com::sun::star::uno::Reference< 778cdf0e10cSrcweir ::com::sun::star::accessibility::XAccessible>& xChild) const 779cdf0e10cSrcweir throw (::com::sun::star::uno::RuntimeException) 780cdf0e10cSrcweir { 781cdf0e10cSrcweir ::osl::MutexGuard aGuard (maMutex); 782cdf0e10cSrcweir sal_Int32 nCount = maVisibleChildren.size(); 783cdf0e10cSrcweir for (sal_Int32 i=0; i < nCount; ++i) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir // Is this equality comparison valid? 786cdf0e10cSrcweir if (maVisibleChildren[i].mxAccessibleShape == xChild) 787cdf0e10cSrcweir return i; 788cdf0e10cSrcweir } 789cdf0e10cSrcweir 790cdf0e10cSrcweir return -1; 791cdf0e10cSrcweir } 792cdf0e10cSrcweir 793cdf0e10cSrcweir 794cdf0e10cSrcweir 795cdf0e10cSrcweir 796cdf0e10cSrcweir //===== IAccessibleViewForwarderListener ==================================== 797cdf0e10cSrcweir 798cdf0e10cSrcweir void ChildrenManagerImpl::ViewForwarderChanged (ChangeType aChangeType, 799cdf0e10cSrcweir const IAccessibleViewForwarder* pViewForwarder) 800cdf0e10cSrcweir { 801cdf0e10cSrcweir if (aChangeType == IAccessibleViewForwarderListener::VISIBLE_AREA) 802cdf0e10cSrcweir Update (false); 803cdf0e10cSrcweir else 804cdf0e10cSrcweir { 805cdf0e10cSrcweir ::osl::MutexGuard aGuard (maMutex); 806cdf0e10cSrcweir ChildDescriptorListType::iterator I, aEnd = maVisibleChildren.end(); 807cdf0e10cSrcweir for (I=maVisibleChildren.begin(); I != aEnd; ++I) 808cdf0e10cSrcweir { 809cdf0e10cSrcweir AccessibleShape* pShape = I->GetAccessibleShape(); 810cdf0e10cSrcweir if (pShape != NULL) 811cdf0e10cSrcweir pShape->ViewForwarderChanged (aChangeType, pViewForwarder); 812cdf0e10cSrcweir } 813cdf0e10cSrcweir } 814cdf0e10cSrcweir } 815cdf0e10cSrcweir 816cdf0e10cSrcweir 817cdf0e10cSrcweir 818cdf0e10cSrcweir 819cdf0e10cSrcweir //===== IAccessibleParent =================================================== 820cdf0e10cSrcweir 821cdf0e10cSrcweir sal_Bool ChildrenManagerImpl::ReplaceChild ( 822cdf0e10cSrcweir AccessibleShape* pCurrentChild, 823cdf0e10cSrcweir const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape, 824cdf0e10cSrcweir const long _nIndex, 825cdf0e10cSrcweir const AccessibleShapeTreeInfo& _rShapeTreeInfo) 826cdf0e10cSrcweir throw (uno::RuntimeException) 827cdf0e10cSrcweir { 828cdf0e10cSrcweir AccessibleShapeInfo aShapeInfo( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex ); 829cdf0e10cSrcweir // create the new child 830cdf0e10cSrcweir AccessibleShape* pNewChild = ShapeTypeHandler::Instance().CreateAccessibleObject ( 831cdf0e10cSrcweir aShapeInfo, 832cdf0e10cSrcweir _rShapeTreeInfo 833cdf0e10cSrcweir ); 834cdf0e10cSrcweir Reference< XAccessible > xNewChild( pNewChild ); // keep this alive (do this before calling Init!) 835cdf0e10cSrcweir if ( pNewChild ) 836cdf0e10cSrcweir pNewChild->Init(); 837cdf0e10cSrcweir 838cdf0e10cSrcweir sal_Bool bResult = sal_False; 839cdf0e10cSrcweir 840cdf0e10cSrcweir // Iterate over the visible children. If one of them has an already 841cdf0e10cSrcweir // created accessible object that matches pCurrentChild then replace 842cdf0e10cSrcweir // it. Otherwise the child to replace is either not in the list or has 843cdf0e10cSrcweir // not ye been created (and is therefore not in the list, too) and a 844cdf0e10cSrcweir // replacement is not necessary. 845cdf0e10cSrcweir ChildDescriptorListType::iterator I,aEnd = maVisibleChildren.end(); 846cdf0e10cSrcweir for (I=maVisibleChildren.begin(); I != aEnd; ++I) 847cdf0e10cSrcweir { 848cdf0e10cSrcweir if (I->GetAccessibleShape() == pCurrentChild) 849cdf0e10cSrcweir { 850cdf0e10cSrcweir // Dispose the current child and send an event about its deletion. 851cdf0e10cSrcweir pCurrentChild->dispose(); 852cdf0e10cSrcweir mrContext.CommitChange ( 853cdf0e10cSrcweir AccessibleEventId::CHILD, 854cdf0e10cSrcweir uno::Any(), 855cdf0e10cSrcweir uno::makeAny (I->mxAccessibleShape)); 856cdf0e10cSrcweir 857cdf0e10cSrcweir // Replace with replacement and send an event about existance 858cdf0e10cSrcweir // of the new child. 859cdf0e10cSrcweir I->mxAccessibleShape = pNewChild; 860cdf0e10cSrcweir mrContext.CommitChange ( 861cdf0e10cSrcweir AccessibleEventId::CHILD, 862cdf0e10cSrcweir uno::makeAny (I->mxAccessibleShape), 863cdf0e10cSrcweir uno::Any()); 864cdf0e10cSrcweir bResult = sal_True; 865cdf0e10cSrcweir break; 866cdf0e10cSrcweir } 867cdf0e10cSrcweir } 868cdf0e10cSrcweir 869cdf0e10cSrcweir // When not found among the visible children we have to search the list 870cdf0e10cSrcweir // of accessible shapes. This is not yet implemented. 871cdf0e10cSrcweir 872cdf0e10cSrcweir return bResult; 873cdf0e10cSrcweir } 874cdf0e10cSrcweir 875cdf0e10cSrcweir 876cdf0e10cSrcweir 877cdf0e10cSrcweir 878cdf0e10cSrcweir /** Update the <const>SELECTED</const> and the <const>FOCUSED</const> state 879cdf0e10cSrcweir of all visible children. Maybe this should be changed to all children. 880cdf0e10cSrcweir 881cdf0e10cSrcweir Iterate over all descriptors of visible accessible shapes and look them 882cdf0e10cSrcweir up in the selection. 883cdf0e10cSrcweir 884cdf0e10cSrcweir If there is no valid controller then all shapes are deselected and 885cdf0e10cSrcweir unfocused. If the controller's frame is not active then all shapes are 886cdf0e10cSrcweir unfocused. 887cdf0e10cSrcweir */ 888cdf0e10cSrcweir void ChildrenManagerImpl::UpdateSelection (void) 889cdf0e10cSrcweir { 890cdf0e10cSrcweir Reference<frame::XController> xController(maShapeTreeInfo.GetController()); 891cdf0e10cSrcweir Reference<view::XSelectionSupplier> xSelectionSupplier ( 892cdf0e10cSrcweir xController, uno::UNO_QUERY); 893cdf0e10cSrcweir 894cdf0e10cSrcweir // Try to cast the selection both to a multi selection and to a single 895cdf0e10cSrcweir // selection. 896cdf0e10cSrcweir Reference<container::XIndexAccess> xSelectedShapeAccess; 897cdf0e10cSrcweir Reference<drawing::XShape> xSelectedShape; 898cdf0e10cSrcweir if (xSelectionSupplier.is()) 899cdf0e10cSrcweir { 900cdf0e10cSrcweir xSelectedShapeAccess = Reference<container::XIndexAccess> ( 901cdf0e10cSrcweir xSelectionSupplier->getSelection(), uno::UNO_QUERY); 902cdf0e10cSrcweir xSelectedShape = Reference<drawing::XShape> ( 903cdf0e10cSrcweir xSelectionSupplier->getSelection(), uno::UNO_QUERY); 904cdf0e10cSrcweir } 905cdf0e10cSrcweir 906cdf0e10cSrcweir // Remember the current and new focused shape. 907cdf0e10cSrcweir AccessibleShape* pCurrentlyFocusedShape = NULL; 908cdf0e10cSrcweir AccessibleShape* pNewFocusedShape = NULL; 909cdf0e10cSrcweir 910cdf0e10cSrcweir ChildDescriptorListType::iterator I, aEnd = maVisibleChildren.end(); 911cdf0e10cSrcweir for (I=maVisibleChildren.begin(); I != aEnd; ++I) 912cdf0e10cSrcweir { 913cdf0e10cSrcweir AccessibleShape* pAccessibleShape = I->GetAccessibleShape(); 914cdf0e10cSrcweir if (I->mxAccessibleShape.is() && I->mxShape.is() && pAccessibleShape!=NULL) 915cdf0e10cSrcweir { 916cdf0e10cSrcweir bool bShapeIsSelected = false; 917cdf0e10cSrcweir 918cdf0e10cSrcweir // Look up the shape in the (single or multi-) selection. 919cdf0e10cSrcweir if (xSelectedShape.is()) 920cdf0e10cSrcweir { 921cdf0e10cSrcweir if (I->mxShape == xSelectedShape) 922cdf0e10cSrcweir { 923cdf0e10cSrcweir bShapeIsSelected = true; 924cdf0e10cSrcweir pNewFocusedShape = pAccessibleShape; 925cdf0e10cSrcweir } 926cdf0e10cSrcweir } 927cdf0e10cSrcweir else if (xSelectedShapeAccess.is()) 928cdf0e10cSrcweir { 929cdf0e10cSrcweir sal_Int32 nCount=xSelectedShapeAccess->getCount(); 930cdf0e10cSrcweir for (sal_Int32 i=0; i<nCount&&!bShapeIsSelected; i++) 931cdf0e10cSrcweir if (xSelectedShapeAccess->getByIndex(i) == I->mxShape) 932cdf0e10cSrcweir { 933cdf0e10cSrcweir bShapeIsSelected = true; 934cdf0e10cSrcweir // In a multi-selection no shape has the focus. 935cdf0e10cSrcweir if (nCount == 1) 936cdf0e10cSrcweir pNewFocusedShape = pAccessibleShape; 937cdf0e10cSrcweir } 938cdf0e10cSrcweir } 939cdf0e10cSrcweir 940cdf0e10cSrcweir // Set or reset the SELECTED state. 941cdf0e10cSrcweir if (bShapeIsSelected) 942cdf0e10cSrcweir pAccessibleShape->SetState (AccessibleStateType::SELECTED); 943cdf0e10cSrcweir else 944cdf0e10cSrcweir pAccessibleShape->ResetState (AccessibleStateType::SELECTED); 945cdf0e10cSrcweir 946cdf0e10cSrcweir // Does the shape have the current selection? 947cdf0e10cSrcweir if (pAccessibleShape->GetState (AccessibleStateType::FOCUSED)) 948cdf0e10cSrcweir pCurrentlyFocusedShape = pAccessibleShape; 949cdf0e10cSrcweir } 950cdf0e10cSrcweir } 951cdf0e10cSrcweir 952cdf0e10cSrcweir // Check if the frame we are in is currently active. If not then make 953cdf0e10cSrcweir // sure to not send a FOCUSED state change. 954cdf0e10cSrcweir if (xController.is()) 955cdf0e10cSrcweir { 956cdf0e10cSrcweir Reference<frame::XFrame> xFrame (xController->getFrame()); 957cdf0e10cSrcweir if (xFrame.is()) 958cdf0e10cSrcweir if ( ! xFrame->isActive()) 959cdf0e10cSrcweir pNewFocusedShape = NULL; 960cdf0e10cSrcweir } 961cdf0e10cSrcweir 962cdf0e10cSrcweir // Move focus from current to newly focused shape. 963cdf0e10cSrcweir if (pCurrentlyFocusedShape != pNewFocusedShape) 964cdf0e10cSrcweir { 965cdf0e10cSrcweir if (pCurrentlyFocusedShape != NULL) 966cdf0e10cSrcweir pCurrentlyFocusedShape->ResetState (AccessibleStateType::FOCUSED); 967cdf0e10cSrcweir if (pNewFocusedShape != NULL) 968cdf0e10cSrcweir pNewFocusedShape->SetState (AccessibleStateType::FOCUSED); 969cdf0e10cSrcweir } 970cdf0e10cSrcweir 971cdf0e10cSrcweir // Remember whether there is a shape that now has the focus. 972cdf0e10cSrcweir mpFocusedShape = pNewFocusedShape; 973cdf0e10cSrcweir } 974cdf0e10cSrcweir 975cdf0e10cSrcweir 976cdf0e10cSrcweir 977cdf0e10cSrcweir 978cdf0e10cSrcweir bool ChildrenManagerImpl::HasFocus (void) 979cdf0e10cSrcweir { 980cdf0e10cSrcweir return mpFocusedShape != NULL; 981cdf0e10cSrcweir } 982cdf0e10cSrcweir 983cdf0e10cSrcweir 984cdf0e10cSrcweir 985cdf0e10cSrcweir 986cdf0e10cSrcweir void ChildrenManagerImpl::RemoveFocus (void) 987cdf0e10cSrcweir { 988cdf0e10cSrcweir if (mpFocusedShape != NULL) 989cdf0e10cSrcweir { 990cdf0e10cSrcweir mpFocusedShape->ResetState (AccessibleStateType::FOCUSED); 991cdf0e10cSrcweir mpFocusedShape = NULL; 992cdf0e10cSrcweir } 993cdf0e10cSrcweir } 994cdf0e10cSrcweir 995cdf0e10cSrcweir 996cdf0e10cSrcweir 997cdf0e10cSrcweir void ChildrenManagerImpl::RegisterAsDisposeListener ( 998cdf0e10cSrcweir const Reference<drawing::XShape>& xShape) 999cdf0e10cSrcweir { 1000cdf0e10cSrcweir Reference<lang::XComponent> xComponent (xShape, uno::UNO_QUERY); 1001cdf0e10cSrcweir if (xComponent.is()) 1002cdf0e10cSrcweir xComponent->addEventListener ( 1003cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 1004cdf0e10cSrcweir } 1005cdf0e10cSrcweir 1006cdf0e10cSrcweir 1007cdf0e10cSrcweir 1008cdf0e10cSrcweir 1009cdf0e10cSrcweir void ChildrenManagerImpl::UnregisterAsDisposeListener ( 1010cdf0e10cSrcweir const Reference<drawing::XShape>& xShape) 1011cdf0e10cSrcweir { 1012cdf0e10cSrcweir Reference<lang::XComponent> xComponent (xShape, uno::UNO_QUERY); 1013cdf0e10cSrcweir if (xComponent.is()) 1014cdf0e10cSrcweir xComponent->removeEventListener ( 1015cdf0e10cSrcweir static_cast<document::XEventListener*>(this)); 1016cdf0e10cSrcweir } 1017cdf0e10cSrcweir 1018cdf0e10cSrcweir 1019cdf0e10cSrcweir 1020cdf0e10cSrcweir 1021cdf0e10cSrcweir //===== AccessibleChildDescriptor =========================================== 1022cdf0e10cSrcweir 1023cdf0e10cSrcweir ChildDescriptor::ChildDescriptor (const Reference<drawing::XShape>& xShape) 1024cdf0e10cSrcweir : mxShape (xShape), 1025cdf0e10cSrcweir mxAccessibleShape (NULL), 1026cdf0e10cSrcweir mbCreateEventPending (true) 1027cdf0e10cSrcweir { 1028cdf0e10cSrcweir // Empty. 1029cdf0e10cSrcweir } 1030cdf0e10cSrcweir 1031cdf0e10cSrcweir 1032cdf0e10cSrcweir 1033cdf0e10cSrcweir 1034cdf0e10cSrcweir ChildDescriptor::ChildDescriptor (const Reference<XAccessible>& rxAccessibleShape) 1035cdf0e10cSrcweir : mxShape (NULL), 1036cdf0e10cSrcweir mxAccessibleShape (rxAccessibleShape), 1037cdf0e10cSrcweir mbCreateEventPending (true) 1038cdf0e10cSrcweir { 1039cdf0e10cSrcweir // Make sure that the accessible object has the <const>VISIBLE</const> 1040cdf0e10cSrcweir // state set. 1041cdf0e10cSrcweir AccessibleShape* pAccessibleShape = GetAccessibleShape(); 1042cdf0e10cSrcweir pAccessibleShape->SetState (AccessibleStateType::VISIBLE); 1043cdf0e10cSrcweir } 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir 1046cdf0e10cSrcweir 1047cdf0e10cSrcweir 1048cdf0e10cSrcweir ChildDescriptor::~ChildDescriptor (void) 1049cdf0e10cSrcweir { 1050cdf0e10cSrcweir } 1051cdf0e10cSrcweir 1052cdf0e10cSrcweir 1053cdf0e10cSrcweir 1054cdf0e10cSrcweir 1055cdf0e10cSrcweir AccessibleShape* ChildDescriptor::GetAccessibleShape (void) const 1056cdf0e10cSrcweir { 1057cdf0e10cSrcweir return static_cast<AccessibleShape*> (mxAccessibleShape.get()); 1058cdf0e10cSrcweir } 1059cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1060cdf0e10cSrcweir void ChildDescriptor::setIndexAtAccessibleShape(sal_Int32 _nIndex) 1061cdf0e10cSrcweir { 1062cdf0e10cSrcweir AccessibleShape* pShape = GetAccessibleShape(); 1063cdf0e10cSrcweir if ( pShape ) 1064cdf0e10cSrcweir pShape->setIndexInParent(_nIndex); 1065cdf0e10cSrcweir } 1066cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1067cdf0e10cSrcweir 1068cdf0e10cSrcweir 1069cdf0e10cSrcweir 1070cdf0e10cSrcweir 1071cdf0e10cSrcweir void ChildDescriptor::disposeAccessibleObject (AccessibleContextBase& rParent) 1072cdf0e10cSrcweir { 1073cdf0e10cSrcweir if (mxAccessibleShape.is()) 1074cdf0e10cSrcweir { 1075cdf0e10cSrcweir // Send event that the shape has been removed. 1076cdf0e10cSrcweir uno::Any aOldValue; 1077cdf0e10cSrcweir aOldValue <<= mxAccessibleShape; 1078cdf0e10cSrcweir rParent.CommitChange ( 1079cdf0e10cSrcweir AccessibleEventId::CHILD, 1080cdf0e10cSrcweir uno::Any(), 1081cdf0e10cSrcweir aOldValue); 1082cdf0e10cSrcweir 1083cdf0e10cSrcweir // Dispose and remove the object. 1084cdf0e10cSrcweir Reference<lang::XComponent> xComponent (mxAccessibleShape, uno::UNO_QUERY); 1085cdf0e10cSrcweir if (xComponent.is()) 1086cdf0e10cSrcweir xComponent->dispose (); 1087cdf0e10cSrcweir 1088cdf0e10cSrcweir mxAccessibleShape = NULL; 1089cdf0e10cSrcweir } 1090cdf0e10cSrcweir } 1091cdf0e10cSrcweir 1092cdf0e10cSrcweir 1093cdf0e10cSrcweir } // end of namespace accessibility 1094cdf0e10cSrcweir 1095