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