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