fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / accessibility / ChildrenManagerImpl.cxx
blob1828ebf22dde54b99c72bcb70f5006a7cb26c620
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "ChildrenManagerImpl.hxx"
22 #include <svx/ShapeTypeHandler.hxx>
23 #include <svx/AccessibleShapeInfo.hxx>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/view/XSelectionSupplier.hpp>
26 #include <com/sun/star/container/XChild.hpp>
27 #include <comphelper/uno3.hxx>
29 #include <rtl/ustring.hxx>
30 #include <tools/debug.hxx>
32 using namespace ::com::sun::star;
33 using namespace ::com::sun::star::accessibility;
34 using ::com::sun::star::uno::Reference;
37 namespace accessibility {
39 namespace
41 void adjustIndexInParentOfShapes(ChildDescriptorListType& _rList)
43 ChildDescriptorListType::iterator aEnd = _rList.end();
44 sal_Int32 i=0;
45 for ( ChildDescriptorListType::iterator aIter = _rList.begin(); aIter != aEnd; ++aIter,++i)
46 aIter->setIndexAtAccessibleShape(i);
50 //===== AccessibleChildrenManager ===========================================
52 ChildrenManagerImpl::ChildrenManagerImpl (
53 const uno::Reference<XAccessible>& rxParent,
54 const uno::Reference<drawing::XShapes>& rxShapeList,
55 const AccessibleShapeTreeInfo& rShapeTreeInfo,
56 AccessibleContextBase& rContext)
57 : ::cppu::WeakComponentImplHelper2<
58 ::com::sun::star::document::XEventListener,
59 ::com::sun::star::view::XSelectionChangeListener>(maMutex),
60 mxShapeList (rxShapeList),
61 mxParent (rxParent),
62 maShapeTreeInfo (rShapeTreeInfo),
63 mrContext (rContext),
64 mnNewNameIndex(1),
65 mpFocusedShape(NULL)
72 ChildrenManagerImpl::~ChildrenManagerImpl (void)
74 DBG_ASSERT (rBHelper.bDisposed || rBHelper.bInDispose,
75 "~AccessibleDrawDocumentView: object has not been disposed");
81 void ChildrenManagerImpl::Init (void)
83 // Register as view::XSelectionChangeListener.
84 Reference<frame::XController> xController(maShapeTreeInfo.GetController());
85 Reference<view::XSelectionSupplier> xSelectionSupplier (
86 xController, uno::UNO_QUERY);
87 if (xSelectionSupplier.is())
89 xController->addEventListener(
90 static_cast<document::XEventListener*>(this));
92 xSelectionSupplier->addSelectionChangeListener (
93 static_cast<view::XSelectionChangeListener*>(this));
96 // Register at model as document::XEventListener.
97 if (maShapeTreeInfo.GetModelBroadcaster().is())
98 maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
99 static_cast<document::XEventListener*>(this));
105 long ChildrenManagerImpl::GetChildCount (void) const throw ()
107 return maVisibleChildren.size();
113 /** Return the requested accessible child object. Create it if it is not
114 yet in the cache.
116 uno::Reference<XAccessible>
117 ChildrenManagerImpl::GetChild (long nIndex)
118 throw (::com::sun::star::uno::RuntimeException,
119 ::com::sun::star::lang::IndexOutOfBoundsException)
121 // Check whether the given index is valid.
122 if (nIndex < 0 || (unsigned long)nIndex >= maVisibleChildren.size())
123 throw lang::IndexOutOfBoundsException (
124 "no accessible child with index " + OUString::valueOf(nIndex),
125 mxParent);
127 return GetChild (maVisibleChildren[nIndex],nIndex);
133 /** Return the requested accessible child object. Create it if it is not
134 yet in the cache.
136 uno::Reference<XAccessible>
137 ChildrenManagerImpl::GetChild (ChildDescriptor& rChildDescriptor,sal_Int32 _nIndex)
138 throw (::com::sun::star::uno::RuntimeException)
140 if ( ! rChildDescriptor.mxAccessibleShape.is())
142 ::osl::MutexGuard aGuard (maMutex);
143 // Make sure that the requested accessible object has not been
144 // created while locking the global mutex.
145 if ( ! rChildDescriptor.mxAccessibleShape.is())
147 AccessibleShapeInfo aShapeInfo(
148 rChildDescriptor.mxShape,
149 mxParent,
150 this,
151 mnNewNameIndex++);
152 // Create accessible object that corresponds to the descriptor's
153 // shape.
154 AccessibleShape* pShape =
155 ShapeTypeHandler::Instance().CreateAccessibleObject (
156 aShapeInfo,
157 maShapeTreeInfo);
158 rChildDescriptor.mxAccessibleShape = uno::Reference<XAccessible> (
159 static_cast<uno::XWeak*>(pShape),
160 uno::UNO_QUERY);
161 // Now that there is a reference to the new accessible shape we
162 // can safely call its Init() method.
163 if ( pShape != NULL )
165 pShape->Init();
166 pShape->setIndexInParent(_nIndex);
171 return rChildDescriptor.mxAccessibleShape;
177 /** Find all shapes among the specified shapes that lie fully or partially
178 inside the visible area. Put those shapes into the cleared cache. The
179 corresponding accessible objects will be created on demand.
181 At the moment, first all accessible objects are removed from the cache
182 and the appropriate listeners are informed of this. Next, the list is
183 created again. This should be optimized in the future to not remove and
184 create objects that will be in the list before and after the update
185 method.
187 void ChildrenManagerImpl::Update (bool bCreateNewObjectsOnDemand)
189 if (maShapeTreeInfo.GetViewForwarder() == NULL)
190 return;
191 Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea();
193 // 1. Create a local list of visible shapes.
194 ChildDescriptorListType aChildList;
195 CreateListOfVisibleShapes (aChildList);
197 // 2. Merge the information that is already known about the visible
198 // shapes from the current list into the new list.
199 MergeAccessibilityInformation (aChildList);
201 // 3. Replace the current list of visible shapes with the new one. Do
202 // the same with the visible area.
204 ::osl::MutexGuard aGuard (maMutex);
205 adjustIndexInParentOfShapes(aChildList);
207 // Use swap to copy the contents of the new list in constant time.
208 maVisibleChildren.swap (aChildList);
210 // aChildList now contains all the old children, while maVisibleChildren
211 // contains all the current children
213 // 4. Find all shapes in the old list that are not in the current list,
214 // send appropriate events and remove the accessible shape.
216 // Do this *after* we have set our new list of children, because
217 // removing a child may cause
219 // ChildDescriptor::disposeAccessibleObject -->
220 // AccessibleContextBase::CommitChange -->
221 // AtkListener::notifyEvent ->
222 // AtkListener::handleChildRemoved ->
223 // AtkListener::updateChildList
224 // AccessibleDrawDocumentView::getAccessibleChildCount ->
225 // ChildrenManagerImpl::GetChildCount ->
226 // maVisibleChildren.size()
228 // to be fired, and so the operations will take place on
229 // the list we are trying to replace
231 RemoveNonVisibleChildren (maVisibleChildren, aChildList);
233 aChildList.clear();
235 maVisibleArea = aVisibleArea;
238 // 5. If the visible area has changed then send events that signal a
239 // change of their bounding boxes for all shapes that are members of
240 // both the current and the new list of visible shapes.
241 if (maVisibleArea != aVisibleArea)
242 SendVisibleAreaEvents (maVisibleChildren);
244 // 6. If children have to be created immediately and not on demand then
245 // create the missing accessible objects now.
246 if ( ! bCreateNewObjectsOnDemand)
247 CreateAccessibilityObjects (maVisibleChildren);
253 void ChildrenManagerImpl::CreateListOfVisibleShapes (
254 ChildDescriptorListType& raDescriptorList)
256 ::osl::MutexGuard aGuard (maMutex);
258 OSL_ASSERT (maShapeTreeInfo.GetViewForwarder() != NULL);
260 Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea();
262 // Add the visible shapes for which the accessible objects already exist.
263 AccessibleShapeList::iterator I,aEnd = maAccessibleShapes.end();
264 for (I=maAccessibleShapes.begin(); I != aEnd; ++I)
266 if (I->is())
268 uno::Reference<XAccessibleComponent> xComponent (
269 (*I)->getAccessibleContext(), uno::UNO_QUERY);
270 if (xComponent.is())
272 // The bounding box of the object already is clipped to the
273 // visible area. The object is therefore visible if the
274 // bounding box has non-zero extensions.
275 awt::Rectangle aPixelBBox (xComponent->getBounds());
276 if ((aPixelBBox.Width > 0) && (aPixelBBox.Height > 0))
277 raDescriptorList.push_back (ChildDescriptor (*I));
282 // Add the visible shapes for which only the XShapes exist.
283 uno::Reference<container::XIndexAccess> xShapeAccess (mxShapeList, uno::UNO_QUERY);
284 if (xShapeAccess.is())
286 sal_Int32 nShapeCount = xShapeAccess->getCount();
287 raDescriptorList.reserve( nShapeCount );
288 awt::Point aPos;
289 awt::Size aSize;
290 Rectangle aBoundingBox;
291 uno::Reference<drawing::XShape> xShape;
292 for (sal_Int32 i=0; i<nShapeCount; ++i)
294 xShapeAccess->getByIndex(i) >>= xShape;
295 aPos = xShape->getPosition();
296 aSize = xShape->getSize();
298 aBoundingBox.Left() = aPos.X;
299 aBoundingBox.Top() = aPos.Y;
300 aBoundingBox.Right() = aPos.X + aSize.Width;
301 aBoundingBox.Bottom() = aPos.Y + aSize.Height;
303 // Insert shape if it is visible, i.e. its bounding box overlaps
304 // the visible area.
305 if ( aBoundingBox.IsOver (aVisibleArea) )
306 raDescriptorList.push_back (ChildDescriptor (xShape));
314 void ChildrenManagerImpl::RemoveNonVisibleChildren (
315 const ChildDescriptorListType& rNewChildList,
316 ChildDescriptorListType& rOldChildList)
318 // Iterate over list of formerly visible children and remove those that
319 // are not visible anymore, i.e. member of the new list of visible
320 // children.
321 ChildDescriptorListType::iterator I, aEnd = rOldChildList.end();
322 for (I=rOldChildList.begin(); I != aEnd; ++I)
324 if (::std::find(rNewChildList.begin(), rNewChildList.end(), *I) == rNewChildList.end())
326 // The child is disposed when there is a UNO shape from which
327 // the accessible shape can be created when the shape becomes
328 // visible again. When there is no such UNO shape then simply
329 // reset the descriptor but keep the accessibility object.
330 if (I->mxShape.is())
332 UnregisterAsDisposeListener (I->mxShape);
333 I->disposeAccessibleObject (mrContext);
335 else
337 AccessibleShape* pAccessibleShape = I->GetAccessibleShape();
338 pAccessibleShape->ResetState (AccessibleStateType::VISIBLE);
339 I->mxAccessibleShape = NULL;
348 void ChildrenManagerImpl::MergeAccessibilityInformation (
349 ChildDescriptorListType& raNewChildList)
351 ChildDescriptorListType::iterator aOldChildDescriptor;
352 ChildDescriptorListType::iterator I, aEnd = raNewChildList.end();
353 for (I=raNewChildList.begin(); I != aEnd; ++I)
355 aOldChildDescriptor = ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(), *I);
357 // Copy accessible shape if that exists in the old descriptor.
358 bool bRegistrationIsNecessary = true;
359 if (aOldChildDescriptor != maVisibleChildren.end())
360 if (aOldChildDescriptor->mxAccessibleShape.is())
362 I->mxAccessibleShape = aOldChildDescriptor->mxAccessibleShape;
363 I->mbCreateEventPending = false;
364 bRegistrationIsNecessary = false;
366 if (bRegistrationIsNecessary)
367 RegisterAsDisposeListener (I->mxShape);
374 void ChildrenManagerImpl::SendVisibleAreaEvents (
375 ChildDescriptorListType& raNewChildList)
377 ChildDescriptorListType::iterator I,aEnd = raNewChildList.end();
378 for (I=raNewChildList.begin(); I != aEnd; ++I)
380 // Tell shape of changed visible area. To do this, fake a
381 // change of the view forwarder. (Actually we usually get here
382 // as a result of a change of the view forwarder).
383 AccessibleShape* pShape = I->GetAccessibleShape ();
384 if (pShape != NULL)
385 pShape->ViewForwarderChanged (
386 IAccessibleViewForwarderListener::VISIBLE_AREA,
387 maShapeTreeInfo.GetViewForwarder());
394 void ChildrenManagerImpl::CreateAccessibilityObjects (
395 ChildDescriptorListType& raNewChildList)
397 ChildDescriptorListType::iterator I, aEnd = raNewChildList.end();
398 sal_Int32 nPos = 0;
399 for ( I = raNewChildList.begin(); I != aEnd; ++I,++nPos)
401 // Create the associated accessible object when the flag says so and
402 // it does not yet exist.
403 if ( ! I->mxAccessibleShape.is() )
404 GetChild (*I,nPos);
405 if (I->mxAccessibleShape.is() && I->mbCreateEventPending)
407 I->mbCreateEventPending = false;
408 mrContext.CommitChange (
409 AccessibleEventId::CHILD,
410 uno::makeAny(I->mxAccessibleShape),
411 uno::Any());
419 void ChildrenManagerImpl::AddShape (const Reference<drawing::XShape>& rxShape)
421 if (rxShape.is())
423 ::osl::ClearableMutexGuard aGuard (maMutex);
425 // Test visibility of the shape.
426 Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea();
427 awt::Point aPos = rxShape->getPosition();
428 awt::Size aSize = rxShape->getSize();
430 Rectangle aBoundingBox (
431 aPos.X,
432 aPos.Y,
433 aPos.X + aSize.Width,
434 aPos.Y + aSize.Height);
436 // Add the shape only when it belongs to the list of shapes stored
437 // in mxShapeList (which is either a page or a group shape).
438 Reference<container::XChild> xChild (rxShape, uno::UNO_QUERY);
439 if (xChild.is())
441 Reference<drawing::XShapes> xParent (xChild->getParent(), uno::UNO_QUERY);
442 if (xParent == mxShapeList)
443 if (aBoundingBox.IsOver (aVisibleArea))
445 // Add shape to list of visible shapes.
446 maVisibleChildren.push_back (ChildDescriptor (rxShape));
448 // Create accessibility object.
449 ChildDescriptor& rDescriptor = maVisibleChildren.back();
450 GetChild (rDescriptor, maVisibleChildren.size()-1);
452 // Inform listeners about new child.
453 uno::Any aNewShape;
454 aNewShape <<= rDescriptor.mxAccessibleShape;
455 aGuard.clear();
456 mrContext.CommitChange (
457 AccessibleEventId::CHILD,
458 aNewShape,
459 uno::Any());
460 RegisterAsDisposeListener (rDescriptor.mxShape);
469 void ChildrenManagerImpl::RemoveShape (const Reference<drawing::XShape>& rxShape)
471 if (rxShape.is())
473 ::osl::ClearableMutexGuard aGuard (maMutex);
475 // Search shape in list of visible children.
476 ChildDescriptorListType::iterator I (
477 ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(),
478 ChildDescriptor (rxShape)));
479 if (I != maVisibleChildren.end())
481 // Remove descriptor from that list.
482 Reference<XAccessible> xAccessibleShape (I->mxAccessibleShape);
484 UnregisterAsDisposeListener (I->mxShape);
485 // Dispose the accessible object.
486 I->disposeAccessibleObject (mrContext);
488 // Now we can safely remove the child descriptor and thus
489 // invalidate the iterator.
490 maVisibleChildren.erase (I);
492 adjustIndexInParentOfShapes(maVisibleChildren);
500 void ChildrenManagerImpl::SetShapeList (const ::com::sun::star::uno::Reference<
501 ::com::sun::star::drawing::XShapes>& xShapeList)
503 mxShapeList = xShapeList;
509 void ChildrenManagerImpl::AddAccessibleShape (std::auto_ptr<AccessibleShape> pShape)
511 if (pShape.get() != NULL)
512 maAccessibleShapes.push_back (pShape.release());
518 void ChildrenManagerImpl::ClearAccessibleShapeList (void)
520 // Copy the list of (visible) shapes to local lists and clear the
521 // originals.
522 ChildDescriptorListType aLocalVisibleChildren;
523 aLocalVisibleChildren.swap(maVisibleChildren);
524 AccessibleShapeList aLocalAccessibleShapes;
525 aLocalAccessibleShapes.swap(maAccessibleShapes);
527 // Tell the listeners that all children are gone.
528 mrContext.CommitChange (
529 AccessibleEventId::INVALIDATE_ALL_CHILDREN,
530 uno::Any(),
531 uno::Any());
533 // There are no accessible shapes left so the index assigned to new
534 // accessible shapes can be reset.
535 mnNewNameIndex = 1;
537 // Now the objects in the local lists can be safely disposed without
538 // having problems with callers that want to update their child lists.
540 // Clear the list of visible accessible objects. Objects not created on
541 // demand for XShapes are treated below.
542 ChildDescriptorListType::iterator I,aEnd = aLocalVisibleChildren.end();
543 for (I=aLocalVisibleChildren.begin(); I != aEnd; ++I)
544 if ( I->mxAccessibleShape.is() && I->mxShape.is() )
546 ::comphelper::disposeComponent(I->mxAccessibleShape);
547 I->mxAccessibleShape = NULL;
550 // Dispose all objects in the accessible shape list.
551 AccessibleShapeList::iterator J,aEnd2 = aLocalAccessibleShapes.end();
552 for (J=aLocalAccessibleShapes.begin(); J != aEnd2; ++J)
553 if (J->is())
555 // Dispose the object.
556 ::comphelper::disposeComponent(*J);
557 *J = NULL;
564 /** If the broadcasters change at which this object is registered then
565 unregister at old and register at new broadcasters.
567 void ChildrenManagerImpl::SetInfo (const AccessibleShapeTreeInfo& rShapeTreeInfo)
569 // Remember the current broadcasters and exchange the shape tree info.
570 Reference<document::XEventBroadcaster> xCurrentBroadcaster;
571 Reference<frame::XController> xCurrentController;
572 Reference<view::XSelectionSupplier> xCurrentSelectionSupplier;
574 ::osl::MutexGuard aGuard (maMutex);
575 xCurrentBroadcaster = maShapeTreeInfo.GetModelBroadcaster();
576 xCurrentController = maShapeTreeInfo.GetController();
577 xCurrentSelectionSupplier = Reference<view::XSelectionSupplier> (
578 xCurrentController, uno::UNO_QUERY);
579 maShapeTreeInfo = rShapeTreeInfo;
582 // Move registration to new model.
583 if (maShapeTreeInfo.GetModelBroadcaster() != xCurrentBroadcaster)
585 // Register at new broadcaster.
586 if (maShapeTreeInfo.GetModelBroadcaster().is())
587 maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
588 static_cast<document::XEventListener*>(this));
590 // Unregister at old broadcaster.
591 if (xCurrentBroadcaster.is())
592 xCurrentBroadcaster->removeEventListener (
593 static_cast<document::XEventListener*>(this));
596 // Move registration to new selection supplier.
597 Reference<frame::XController> xNewController(maShapeTreeInfo.GetController());
598 Reference<view::XSelectionSupplier> xNewSelectionSupplier (
599 xNewController, uno::UNO_QUERY);
600 if (xNewSelectionSupplier != xCurrentSelectionSupplier)
602 // Register at new broadcaster.
603 if (xNewSelectionSupplier.is())
605 xNewController->addEventListener(
606 static_cast<document::XEventListener*>(this));
608 xNewSelectionSupplier->addSelectionChangeListener (
609 static_cast<view::XSelectionChangeListener*>(this));
612 // Unregister at old broadcaster.
613 if (xCurrentSelectionSupplier.is())
615 xCurrentSelectionSupplier->removeSelectionChangeListener (
616 static_cast<view::XSelectionChangeListener*>(this));
618 xCurrentController->removeEventListener(
619 static_cast<document::XEventListener*>(this));
627 //===== lang::XEventListener ================================================
629 void SAL_CALL
630 ChildrenManagerImpl::disposing (const lang::EventObject& rEventObject)
631 throw (uno::RuntimeException)
633 if (rEventObject.Source == maShapeTreeInfo.GetModelBroadcaster()
634 || rEventObject.Source == maShapeTreeInfo.GetController())
636 impl_dispose();
639 // Handle disposing UNO shapes.
640 else
642 Reference<drawing::XShape> xShape (rEventObject.Source, uno::UNO_QUERY);
644 // Find the descriptor for the given shape.
645 ChildDescriptorListType::iterator I (
646 ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(),
647 ChildDescriptor (xShape)));
648 if (I != maVisibleChildren.end())
650 // Clear the descriptor.
651 I->disposeAccessibleObject (mrContext);
652 I->mxShape = NULL;
660 //===== document::XEventListener ============================================
662 /** Listen for new and removed shapes.
664 void SAL_CALL
665 ChildrenManagerImpl::notifyEvent (
666 const document::EventObject& rEventObject)
667 throw (uno::RuntimeException)
669 static const OUString sShapeInserted ("ShapeInserted");
670 static const OUString sShapeRemoved ("ShapeRemoved");
673 if (rEventObject.EventName == sShapeInserted)
674 AddShape (Reference<drawing::XShape>(rEventObject.Source, uno::UNO_QUERY));
675 else if (rEventObject.EventName == sShapeRemoved)
676 RemoveShape (Reference<drawing::XShape>(rEventObject.Source, uno::UNO_QUERY));
677 // else ignore unknown event.
683 //===== view::XSelectionChangeListener ======================================
685 void SAL_CALL
686 ChildrenManagerImpl::selectionChanged (const lang::EventObject& /*rEvent*/)
687 throw (uno::RuntimeException)
689 UpdateSelection ();
695 void ChildrenManagerImpl::impl_dispose (void)
697 Reference<frame::XController> xController(maShapeTreeInfo.GetController());
698 // Remove from broadcasters.
701 Reference<view::XSelectionSupplier> xSelectionSupplier (
702 xController, uno::UNO_QUERY);
703 if (xSelectionSupplier.is())
705 xSelectionSupplier->removeSelectionChangeListener (
706 static_cast<view::XSelectionChangeListener*>(this));
709 catch( uno::RuntimeException&)
714 if (xController.is())
715 xController->removeEventListener(
716 static_cast<document::XEventListener*>(this));
718 catch( uno::RuntimeException&)
721 maShapeTreeInfo.SetController (NULL);
725 // Remove from broadcaster.
726 if (maShapeTreeInfo.GetModelBroadcaster().is())
727 maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
728 static_cast<document::XEventListener*>(this));
729 maShapeTreeInfo.SetModelBroadcaster (NULL);
731 catch( uno::RuntimeException& )
734 ClearAccessibleShapeList ();
735 SetShapeList (NULL);
740 void SAL_CALL ChildrenManagerImpl::disposing (void)
742 impl_dispose();
745 //===== IAccessibleViewForwarderListener ====================================
747 void ChildrenManagerImpl::ViewForwarderChanged (ChangeType aChangeType,
748 const IAccessibleViewForwarder* pViewForwarder)
750 if (aChangeType == IAccessibleViewForwarderListener::VISIBLE_AREA)
751 Update (false);
752 else
754 ::osl::MutexGuard aGuard (maMutex);
755 ChildDescriptorListType::iterator I, aEnd = maVisibleChildren.end();
756 for (I=maVisibleChildren.begin(); I != aEnd; ++I)
758 AccessibleShape* pShape = I->GetAccessibleShape();
759 if (pShape != NULL)
760 pShape->ViewForwarderChanged (aChangeType, pViewForwarder);
768 //===== IAccessibleParent ===================================================
770 sal_Bool ChildrenManagerImpl::ReplaceChild (
771 AccessibleShape* pCurrentChild,
772 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
773 const long _nIndex,
774 const AccessibleShapeTreeInfo& _rShapeTreeInfo)
775 throw (uno::RuntimeException)
777 AccessibleShapeInfo aShapeInfo( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex );
778 // create the new child
779 AccessibleShape* pNewChild = ShapeTypeHandler::Instance().CreateAccessibleObject (
780 aShapeInfo,
781 _rShapeTreeInfo
783 Reference< XAccessible > xNewChild( pNewChild ); // keep this alive (do this before calling Init!)
784 if ( pNewChild )
785 pNewChild->Init();
787 sal_Bool bResult = sal_False;
789 // Iterate over the visible children. If one of them has an already
790 // created accessible object that matches pCurrentChild then replace
791 // it. Otherwise the child to replace is either not in the list or has
792 // not ye been created (and is therefore not in the list, too) and a
793 // replacement is not necessary.
794 ChildDescriptorListType::iterator I,aEnd = maVisibleChildren.end();
795 for (I=maVisibleChildren.begin(); I != aEnd; ++I)
797 if (I->GetAccessibleShape() == pCurrentChild)
799 // Dispose the current child and send an event about its deletion.
800 pCurrentChild->dispose();
801 mrContext.CommitChange (
802 AccessibleEventId::CHILD,
803 uno::Any(),
804 uno::makeAny (I->mxAccessibleShape));
806 // Replace with replacement and send an event about existance
807 // of the new child.
808 I->mxAccessibleShape = pNewChild;
809 mrContext.CommitChange (
810 AccessibleEventId::CHILD,
811 uno::makeAny (I->mxAccessibleShape),
812 uno::Any());
813 bResult = sal_True;
814 break;
818 // When not found among the visible children we have to search the list
819 // of accessible shapes. This is not yet implemented.
821 return bResult;
827 /** Update the <const>SELECTED</const> and the <const>FOCUSED</const> state
828 of all visible children. Maybe this should be changed to all children.
830 Iterate over all descriptors of visible accessible shapes and look them
831 up in the selection.
833 If there is no valid controller then all shapes are deselected and
834 unfocused. If the controller's frame is not active then all shapes are
835 unfocused.
837 void ChildrenManagerImpl::UpdateSelection (void)
839 Reference<frame::XController> xController(maShapeTreeInfo.GetController());
840 Reference<view::XSelectionSupplier> xSelectionSupplier (
841 xController, uno::UNO_QUERY);
843 // Try to cast the selection both to a multi selection and to a single
844 // selection.
845 Reference<container::XIndexAccess> xSelectedShapeAccess;
846 Reference<drawing::XShape> xSelectedShape;
847 if (xSelectionSupplier.is())
849 xSelectedShapeAccess = Reference<container::XIndexAccess> (
850 xSelectionSupplier->getSelection(), uno::UNO_QUERY);
851 xSelectedShape = Reference<drawing::XShape> (
852 xSelectionSupplier->getSelection(), uno::UNO_QUERY);
855 // Remember the current and new focused shape.
856 AccessibleShape* pCurrentlyFocusedShape = NULL;
857 AccessibleShape* pNewFocusedShape = NULL;
859 ChildDescriptorListType::iterator I, aEnd = maVisibleChildren.end();
860 for (I=maVisibleChildren.begin(); I != aEnd; ++I)
862 AccessibleShape* pAccessibleShape = I->GetAccessibleShape();
863 if (I->mxAccessibleShape.is() && I->mxShape.is() && pAccessibleShape!=NULL)
865 bool bShapeIsSelected = false;
867 // Look up the shape in the (single or multi-) selection.
868 if (xSelectedShape.is())
870 if (I->mxShape == xSelectedShape)
872 bShapeIsSelected = true;
873 pNewFocusedShape = pAccessibleShape;
876 else if (xSelectedShapeAccess.is())
878 sal_Int32 nCount=xSelectedShapeAccess->getCount();
879 for (sal_Int32 i=0; i<nCount&&!bShapeIsSelected; i++)
880 if (xSelectedShapeAccess->getByIndex(i) == I->mxShape)
882 bShapeIsSelected = true;
883 // In a multi-selection no shape has the focus.
884 if (nCount == 1)
885 pNewFocusedShape = pAccessibleShape;
889 // Set or reset the SELECTED state.
890 if (bShapeIsSelected)
891 pAccessibleShape->SetState (AccessibleStateType::SELECTED);
892 else
893 pAccessibleShape->ResetState (AccessibleStateType::SELECTED);
895 // Does the shape have the current selection?
896 if (pAccessibleShape->GetState (AccessibleStateType::FOCUSED))
897 pCurrentlyFocusedShape = pAccessibleShape;
901 // Check if the frame we are in is currently active. If not then make
902 // sure to not send a FOCUSED state change.
903 if (xController.is())
905 Reference<frame::XFrame> xFrame (xController->getFrame());
906 if (xFrame.is())
907 if ( ! xFrame->isActive())
908 pNewFocusedShape = NULL;
911 // Move focus from current to newly focused shape.
912 if (pCurrentlyFocusedShape != pNewFocusedShape)
914 if (pCurrentlyFocusedShape != NULL)
915 pCurrentlyFocusedShape->ResetState (AccessibleStateType::FOCUSED);
916 if (pNewFocusedShape != NULL)
917 pNewFocusedShape->SetState (AccessibleStateType::FOCUSED);
920 // Remember whether there is a shape that now has the focus.
921 mpFocusedShape = pNewFocusedShape;
927 bool ChildrenManagerImpl::HasFocus (void)
929 return mpFocusedShape != NULL;
935 void ChildrenManagerImpl::RemoveFocus (void)
937 if (mpFocusedShape != NULL)
939 mpFocusedShape->ResetState (AccessibleStateType::FOCUSED);
940 mpFocusedShape = NULL;
946 void ChildrenManagerImpl::RegisterAsDisposeListener (
947 const Reference<drawing::XShape>& xShape)
949 Reference<lang::XComponent> xComponent (xShape, uno::UNO_QUERY);
950 if (xComponent.is())
951 xComponent->addEventListener (
952 static_cast<document::XEventListener*>(this));
958 void ChildrenManagerImpl::UnregisterAsDisposeListener (
959 const Reference<drawing::XShape>& xShape)
961 Reference<lang::XComponent> xComponent (xShape, uno::UNO_QUERY);
962 if (xComponent.is())
963 xComponent->removeEventListener (
964 static_cast<document::XEventListener*>(this));
970 //===== AccessibleChildDescriptor ===========================================
972 ChildDescriptor::ChildDescriptor (const Reference<drawing::XShape>& xShape)
973 : mxShape (xShape),
974 mxAccessibleShape (NULL),
975 mbCreateEventPending (true)
977 // Empty.
983 ChildDescriptor::ChildDescriptor (const Reference<XAccessible>& rxAccessibleShape)
984 : mxShape (NULL),
985 mxAccessibleShape (rxAccessibleShape),
986 mbCreateEventPending (true)
988 // Make sure that the accessible object has the <const>VISIBLE</const>
989 // state set.
990 AccessibleShape* pAccessibleShape = GetAccessibleShape();
991 pAccessibleShape->SetState (AccessibleStateType::VISIBLE);
997 ChildDescriptor::~ChildDescriptor (void)
1004 AccessibleShape* ChildDescriptor::GetAccessibleShape (void) const
1006 return static_cast<AccessibleShape*> (mxAccessibleShape.get());
1008 // -----------------------------------------------------------------------------
1009 void ChildDescriptor::setIndexAtAccessibleShape(sal_Int32 _nIndex)
1011 AccessibleShape* pShape = GetAccessibleShape();
1012 if ( pShape )
1013 pShape->setIndexInParent(_nIndex);
1015 // -----------------------------------------------------------------------------
1020 void ChildDescriptor::disposeAccessibleObject (AccessibleContextBase& rParent)
1022 if (mxAccessibleShape.is())
1024 // Send event that the shape has been removed.
1025 uno::Any aOldValue;
1026 aOldValue <<= mxAccessibleShape;
1027 rParent.CommitChange (
1028 AccessibleEventId::CHILD,
1029 uno::Any(),
1030 aOldValue);
1032 // Dispose and remove the object.
1033 Reference<lang::XComponent> xComponent (mxAccessibleShape, uno::UNO_QUERY);
1034 if (xComponent.is())
1035 xComponent->dispose ();
1037 mxAccessibleShape = NULL;
1042 } // end of namespace accessibility
1044 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */