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