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