LCOV - code coverage report
Current view: top level - libreoffice/svx/source/accessibility - ChildrenManagerImpl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 394 0.0 %
Date: 2012-12-27 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10