diff options
author | Caolán McNamara <caolanm@redhat.com> | 2021-08-17 15:43:00 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2021-08-17 22:36:51 +0200 |
commit | 3d45088a4885671a12dfa48e6c650cb896f7078e (patch) | |
tree | 8c49e11dddfea4423c94e2363071a60a170e4014 /svx | |
parent | 17f524a37c81a05e6d448a7186df858a69ada635 (diff) |
Resolves: tdf#139220 with ~1000 selected shapes a11y UpdateSelection crawls
so fetch the selected shapes once and sort them for quick lookup in the
loop over maVisibleChildren.
As an aside, not changed here, SvxShapeCollection::getByIndex looks
suboptimal with a body of
std::vector<Reference<uno::XInterface>> aElements(maShapeContainer.getElements());
return uno::makeAny(Reference<drawing::XShape>(aElements[Index].get()));
Change-Id: Idec7c003e7c5ee02000d4642d4fdb0d940548d97
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120610
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'svx')
-rw-r--r-- | svx/source/accessibility/ChildrenManagerImpl.cxx | 135 |
1 files changed, 75 insertions, 60 deletions
diff --git a/svx/source/accessibility/ChildrenManagerImpl.cxx b/svx/source/accessibility/ChildrenManagerImpl.cxx index 53d1e7596b6b..573427c4714e 100644 --- a/svx/source/accessibility/ChildrenManagerImpl.cxx +++ b/svx/source/accessibility/ChildrenManagerImpl.cxx @@ -38,6 +38,7 @@ #include <com/sun/star/container/XChild.hpp> #include <comphelper/types.hxx> #include <o3tl/safeint.hxx> +#include <o3tl/sorted_vector.hxx> #include <rtl/ustring.hxx> #include <tools/debug.hxx> #include <svx/SvxShapeTypes.hxx> @@ -793,20 +794,6 @@ uno::Reference<XAccessible> */ void ChildrenManagerImpl::UpdateSelection() { - Reference<frame::XController> xController(maShapeTreeInfo.GetController()); - Reference<view::XSelectionSupplier> xSelectionSupplier ( - xController, uno::UNO_QUERY); - - // Try to cast the selection both to a multi selection and to a single - // selection. - Reference<container::XIndexAccess> xSelectedShapeAccess; - Reference<drawing::XShape> xSelectedShape; - if (xSelectionSupplier.is()) - { - xSelectedShapeAccess.set( xSelectionSupplier->getSelection(), uno::UNO_QUERY); - xSelectedShape.set( xSelectionSupplier->getSelection(), uno::UNO_QUERY); - } - // Remember the current and new focused shape. AccessibleShape* pCurrentlyFocusedShape = nullptr; AccessibleShape* pNewFocusedShape = nullptr; @@ -815,73 +802,101 @@ void ChildrenManagerImpl::UpdateSelection() VEC_SHAPE vecSelect; int nAddSelect=0; bool bHasSelectedShape=false; - for (const auto& rChild : maVisibleChildren) + if (!maVisibleChildren.empty()) { - AccessibleShape* pAccessibleShape = rChild.GetAccessibleShape(); - if (rChild.mxAccessibleShape.is() && rChild.mxShape.is() && pAccessibleShape!=nullptr) + Reference<frame::XController> xController(maShapeTreeInfo.GetController()); + Reference<view::XSelectionSupplier> xSelectionSupplier ( + xController, uno::UNO_QUERY); + + // Try to cast the selection both to a multi selection and to a single + // selection. + Reference<container::XIndexAccess> xSelectedShapeAccess; + Reference<drawing::XShape> xSelectedShape; + if (xSelectionSupplier.is()) { - short nRole = pAccessibleShape->getAccessibleRole(); - bool bDrawShape = ( - nRole == AccessibleRole::GRAPHIC || - nRole == AccessibleRole::EMBEDDED_OBJECT || - nRole == AccessibleRole::SHAPE || - nRole == AccessibleRole::IMAGE_MAP || - nRole == AccessibleRole::TABLE_CELL || - nRole == AccessibleRole::TABLE ); - bool bShapeIsSelected = false; - - // Look up the shape in the (single or multi-) selection. - if (xSelectedShape.is()) + xSelectedShapeAccess.set( xSelectionSupplier->getSelection(), uno::UNO_QUERY); + xSelectedShape.set( xSelectionSupplier->getSelection(), uno::UNO_QUERY); + } + + // tdf#139220 to quickly find if a given drawing::XShape is selected + o3tl::sorted_vector<css::uno::Reference<css::drawing::XShape>> aSortedSelectedShapes; + if (!xSelectedShape.is() && xSelectedShapeAccess.is()) + { + sal_Int32 nCount = xSelectedShapeAccess->getCount(); + aSortedSelectedShapes.reserve(nCount); + for (sal_Int32 i = 0; i < nCount; ++i) { - if (rChild.mxShape == xSelectedShape) - { - bShapeIsSelected = true; - pNewFocusedShape = pAccessibleShape; - } + css::uno::Reference<css::drawing::XShape> xShape(xSelectedShapeAccess->getByIndex(i), uno::UNO_QUERY); + aSortedSelectedShapes.insert(xShape); } - else if (xSelectedShapeAccess.is()) + } + + for (const auto& rChild : maVisibleChildren) + { + AccessibleShape* pAccessibleShape = rChild.GetAccessibleShape(); + if (rChild.mxAccessibleShape.is() && rChild.mxShape.is() && pAccessibleShape!=nullptr) { - sal_Int32 nCount=xSelectedShapeAccess->getCount(); - for (sal_Int32 i=0; i<nCount&&!bShapeIsSelected; i++) - if (xSelectedShapeAccess->getByIndex(i) == rChild.mxShape) + short nRole = pAccessibleShape->getAccessibleRole(); + bool bDrawShape = ( + nRole == AccessibleRole::GRAPHIC || + nRole == AccessibleRole::EMBEDDED_OBJECT || + nRole == AccessibleRole::SHAPE || + nRole == AccessibleRole::IMAGE_MAP || + nRole == AccessibleRole::TABLE_CELL || + nRole == AccessibleRole::TABLE ); + bool bShapeIsSelected = false; + + // Look up the shape in the (single or multi-) selection. + if (xSelectedShape.is()) + { + if (rChild.mxShape == xSelectedShape) + { + bShapeIsSelected = true; + pNewFocusedShape = pAccessibleShape; + } + } + else if (!aSortedSelectedShapes.empty()) + { + if (aSortedSelectedShapes.find(rChild.mxShape) != aSortedSelectedShapes.end()) { bShapeIsSelected = true; // In a multi-selection no shape has the focus. - if (nCount == 1) + if (aSortedSelectedShapes.size() == 1) pNewFocusedShape = pAccessibleShape; } - } + } - // Set or reset the SELECTED state. - if (bShapeIsSelected) - { - if (pAccessibleShape->SetState (AccessibleStateType::SELECTED)) + // Set or reset the SELECTED state. + if (bShapeIsSelected) { - if (bDrawShape) + if (pAccessibleShape->SetState (AccessibleStateType::SELECTED)) { - vecSelect.emplace_back(pAccessibleShape,true); - ++nAddSelect; + if (bDrawShape) + { + vecSelect.emplace_back(pAccessibleShape,true); + ++nAddSelect; + } + } + else + {//Selected not change,has selected shape before + bHasSelectedShape=true; } } else - {//Selected not change,has selected shape before - bHasSelectedShape=true; - } - } - else - //pAccessibleShape->ResetState (AccessibleStateType::SELECTED); - { - if(pAccessibleShape->ResetState (AccessibleStateType::SELECTED)) + //pAccessibleShape->ResetState (AccessibleStateType::SELECTED); { - if(bDrawShape) + if(pAccessibleShape->ResetState (AccessibleStateType::SELECTED)) { - vecSelect.emplace_back(pAccessibleShape,false); + if(bDrawShape) + { + vecSelect.emplace_back(pAccessibleShape,false); + } } } + // Does the shape have the current selection? + if (pAccessibleShape->GetState (AccessibleStateType::FOCUSED)) + pCurrentlyFocusedShape = pAccessibleShape; } - // Does the shape have the current selection? - if (pAccessibleShape->GetState (AccessibleStateType::FOCUSED)) - pCurrentlyFocusedShape = pAccessibleShape; } } |