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