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