| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| |
| #include "precompiled_sc.hxx" |
| #include "AccessibleGlobal.hxx" |
| #include "AccessibleFilterMenu.hxx" |
| #include "AccessibleFilterMenuItem.hxx" |
| #include "unoguard.hxx" |
| #include "global.hxx" |
| #include "document.hxx" |
| #include "docpool.hxx" |
| |
| #include "tools/gen.hxx" |
| #include "editeng/unoedsrc.hxx" |
| #include "editeng/editdata.hxx" |
| #include "editeng/outliner.hxx" |
| #include "vcl/unohelp.hxx" |
| #include "dpcontrol.hxx" |
| |
| #include <com/sun/star/accessibility/XAccessible.hpp> |
| #include <com/sun/star/accessibility/XAccessibleStateSet.hpp> |
| #include <com/sun/star/accessibility/AccessibleRole.hpp> |
| #include <com/sun/star/accessibility/AccessibleEventId.hpp> |
| #include <com/sun/star/accessibility/AccessibleStateType.hpp> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::accessibility; |
| using namespace ::com::sun::star::accessibility::AccessibleStateType; |
| |
| using ::com::sun::star::uno::Any; |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::Sequence; |
| using ::com::sun::star::uno::UNO_QUERY; |
| using ::com::sun::star::lang::IndexOutOfBoundsException; |
| using ::com::sun::star::lang::IllegalArgumentException; |
| using ::com::sun::star::uno::RuntimeException; |
| using ::rtl::OUString; |
| using ::std::for_each; |
| using ::std::vector; |
| |
| // ============================================================================ |
| |
| namespace { |
| |
| class AddRemoveEventListener : public ::std::unary_function<void, Reference<XAccessible> > |
| { |
| public: |
| explicit AddRemoveEventListener(const Reference<XAccessibleEventListener>& rListener, bool bAdd) : |
| mxListener(rListener), mbAdd(bAdd) {} |
| |
| void operator() (const Reference<XAccessible>& xAccessible) const |
| { |
| if (!xAccessible.is()) |
| return; |
| |
| Reference<XAccessibleEventBroadcaster> xBc(xAccessible, UNO_QUERY); |
| if (xBc.is()) |
| { |
| if (mbAdd) |
| xBc->addEventListener(mxListener); |
| else |
| xBc->removeEventListener(mxListener); |
| } |
| } |
| private: |
| Reference<XAccessibleEventListener> mxListener; |
| bool mbAdd; |
| }; |
| |
| } |
| |
| // ============================================================================ |
| |
| ScAccessibleFilterMenu::ScAccessibleFilterMenu(const Reference<XAccessible>& rxParent, ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos, ScDocument* pDoc) : |
| ScAccessibleContextBase(rxParent, AccessibleRole::MENU), |
| mnMenuPos(nMenuPos), |
| mpWindow(pWin), |
| mpDoc(pDoc), |
| mbEnabled(true) |
| { |
| SetName(rName); |
| } |
| |
| ScAccessibleFilterMenu::~ScAccessibleFilterMenu() |
| { |
| } |
| |
| // XAccessibleComponent |
| |
| Reference<XAccessible> ScAccessibleFilterMenu::getAccessibleAtPoint( const ::com::sun::star::awt::Point& /*rPoint*/ ) |
| throw (RuntimeException) |
| { |
| return this; |
| } |
| |
| sal_Bool ScAccessibleFilterMenu::isVisible() throw (RuntimeException) |
| { |
| return mpWindow->IsVisible(); |
| } |
| |
| void ScAccessibleFilterMenu::grabFocus() |
| throw (RuntimeException) |
| { |
| } |
| |
| sal_Int32 ScAccessibleFilterMenu::getForeground() |
| throw (RuntimeException) |
| { |
| return 0; |
| } |
| |
| sal_Int32 ScAccessibleFilterMenu::getBackground() |
| throw (RuntimeException) |
| { |
| return 0; |
| } |
| |
| // XAccessibleContext |
| |
| OUString ScAccessibleFilterMenu::getAccessibleName() throw (RuntimeException) |
| { |
| return ScAccessibleContextBase::getAccessibleName(); |
| } |
| |
| sal_Int32 ScAccessibleFilterMenu::getAccessibleChildCount() |
| throw (RuntimeException) |
| { |
| return getMenuItemCount(); |
| } |
| |
| Reference<XAccessible> ScAccessibleFilterMenu::getAccessibleChild(sal_Int32 nIndex) |
| throw (RuntimeException, IndexOutOfBoundsException) |
| { |
| if (maMenuItems.size() <= static_cast<size_t>(nIndex)) |
| throw IndexOutOfBoundsException(); |
| |
| return maMenuItems[nIndex]; |
| } |
| |
| Reference<XAccessibleStateSet> ScAccessibleFilterMenu::getAccessibleStateSet() |
| throw (RuntimeException) |
| { |
| updateStates(); |
| return mxStateSet; |
| } |
| |
| OUString ScAccessibleFilterMenu::getImplementationName() |
| throw (RuntimeException) |
| { |
| return OUString::createFromAscii("ScAccessibleFilterMenu"); |
| } |
| |
| // XAccessibleEventBroadcaster |
| |
| void ScAccessibleFilterMenu::addEventListener( |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::accessibility::XAccessibleEventListener>& xListener) |
| throw (com::sun::star::uno::RuntimeException) |
| { |
| ScAccessibleContextBase::addEventListener(xListener); |
| for_each(maMenuItems.begin(), maMenuItems.end(), AddRemoveEventListener(xListener, true)); |
| } |
| |
| void ScAccessibleFilterMenu::removeEventListener( |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::accessibility::XAccessibleEventListener>& xListener) |
| throw (com::sun::star::uno::RuntimeException) |
| { |
| ScAccessibleContextBase::removeEventListener(xListener); |
| for_each(maMenuItems.begin(), maMenuItems.end(), AddRemoveEventListener(xListener, false)); |
| } |
| |
| // XAccessibleSelection |
| |
| void ScAccessibleFilterMenu::selectAccessibleChild(sal_Int32 nChildIndex) |
| throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| if (static_cast<size_t>(nChildIndex) >= maMenuItems.size()) |
| throw IndexOutOfBoundsException(); |
| |
| mpWindow->setSelectedMenuItem(nChildIndex, false, true); |
| } |
| |
| sal_Bool ScAccessibleFilterMenu::isAccessibleChildSelected(sal_Int32 nChildIndex) |
| throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| if (static_cast<size_t>(nChildIndex) >= maMenuItems.size()) |
| throw IndexOutOfBoundsException(); |
| |
| return mpWindow->isMenuItemSelected(static_cast<size_t>(nChildIndex)); |
| } |
| |
| void ScAccessibleFilterMenu::clearAccessibleSelection() throw (RuntimeException) |
| { |
| mpWindow->clearSelectedMenuItem(); |
| } |
| |
| void ScAccessibleFilterMenu::selectAllAccessibleChildren() throw (RuntimeException) |
| { |
| // not suported - this is a menu, you can't select all menu items. |
| } |
| |
| sal_Int32 ScAccessibleFilterMenu::getSelectedAccessibleChildCount() throw (RuntimeException) |
| { |
| // Since this is a menu, either one menu item is selected, or none at all. |
| return mpWindow->getSelectedMenuItem() == ScMenuFloatingWindow::MENU_NOT_SELECTED ? 0 : 1; |
| } |
| |
| Reference<XAccessible> ScAccessibleFilterMenu::getSelectedAccessibleChild(sal_Int32 nChildIndex) |
| throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| if (static_cast<size_t>(nChildIndex) >= maMenuItems.size()) |
| throw IndexOutOfBoundsException(); |
| |
| return maMenuItems[nChildIndex]; |
| } |
| |
| void ScAccessibleFilterMenu::deselectAccessibleChild(sal_Int32 nChildIndex) throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| if (static_cast<size_t>(nChildIndex) >= maMenuItems.size()) |
| throw IndexOutOfBoundsException(); |
| |
| mpWindow->selectMenuItem(nChildIndex, false, false); |
| } |
| |
| // XInterface |
| |
| uno::Any SAL_CALL ScAccessibleFilterMenu::queryInterface( uno::Type const & rType ) |
| throw (RuntimeException) |
| { |
| Any any = ScAccessibleContextBase::queryInterface(rType); |
| if (any.hasValue()) |
| return any; |
| |
| return ScAccessibleFilterMenu_BASE::queryInterface(rType); |
| } |
| |
| void SAL_CALL ScAccessibleFilterMenu::acquire() throw () |
| { |
| ScAccessibleContextBase::acquire(); |
| } |
| |
| void SAL_CALL ScAccessibleFilterMenu::release() throw () |
| { |
| ScAccessibleContextBase::release(); |
| } |
| |
| // XTypeProvider |
| |
| Sequence<sal_Int8> ScAccessibleFilterMenu::getImplementationId() |
| throw (RuntimeException) |
| { |
| Sequence<sal_Int8> aId(16); |
| return aId; |
| } |
| |
| Rectangle ScAccessibleFilterMenu::GetBoundingBoxOnScreen() const |
| throw (RuntimeException) |
| { |
| if (mnMenuPos == ScMenuFloatingWindow::MENU_NOT_SELECTED) |
| return Rectangle(); |
| |
| // Menu object's bounding box is the bounding box of the menu item that |
| // launches the menu, which belongs to the parent window. |
| ScMenuFloatingWindow* pParentWin = mpWindow->getParentMenuWindow(); |
| if (!pParentWin) |
| return Rectangle(); |
| |
| if (!pParentWin->IsVisible()) |
| return Rectangle(); |
| |
| Point aPos = pParentWin->OutputToAbsoluteScreenPixel(Point(0,0)); |
| Point aMenuPos; |
| Size aMenuSize; |
| pParentWin->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize); |
| Rectangle aRect(aPos + aMenuPos, aMenuSize); |
| return aRect; |
| } |
| |
| Rectangle ScAccessibleFilterMenu::GetBoundingBox() const |
| throw (RuntimeException) |
| { |
| if (mnMenuPos == ScMenuFloatingWindow::MENU_NOT_SELECTED) |
| return Rectangle(); |
| |
| // Menu object's bounding box is the bounding box of the menu item that |
| // launches the menu, which belongs to the parent window. |
| ScMenuFloatingWindow* pParentWin = mpWindow->getParentMenuWindow(); |
| if (!pParentWin) |
| return Rectangle(); |
| |
| if (!pParentWin->IsVisible()) |
| return Rectangle(); |
| |
| Point aMenuPos; |
| Size aMenuSize; |
| pParentWin->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize); |
| Rectangle aRect(aMenuPos, aMenuSize); |
| return aRect; |
| } |
| |
| void ScAccessibleFilterMenu::appendMenuItem(const OUString& rName, bool bEnabled, size_t nMenuPos) |
| { |
| // Check weather this menu item is a sub menu or a regular menu item. |
| ScMenuFloatingWindow* pSubMenu = mpWindow->getSubMenuWindow(nMenuPos); |
| Reference<XAccessible> xAccessible; |
| if (pSubMenu) |
| { |
| xAccessible = pSubMenu->CreateAccessible(); |
| ScAccessibleFilterMenu* p = |
| static_cast<ScAccessibleFilterMenu*>(xAccessible.get()); |
| p->setEnabled(bEnabled); |
| p->setMenuPos(nMenuPos); |
| } |
| else |
| { |
| xAccessible.set(new ScAccessibleFilterMenuItem(this, mpWindow, rName, nMenuPos)); |
| ScAccessibleFilterMenuItem* p = |
| static_cast<ScAccessibleFilterMenuItem*>(xAccessible.get()); |
| p->setEnabled(bEnabled); |
| } |
| maMenuItems.push_back(xAccessible); |
| } |
| |
| void ScAccessibleFilterMenu::setMenuPos(size_t nMenuPos) |
| { |
| mnMenuPos = nMenuPos; |
| } |
| |
| void ScAccessibleFilterMenu::setEnabled(bool bEnabled) |
| { |
| mbEnabled = bEnabled; |
| } |
| |
| sal_Int32 ScAccessibleFilterMenu::getMenuItemCount() const |
| { |
| return maMenuItems.size(); |
| } |
| |
| bool ScAccessibleFilterMenu::isSelected() const |
| { |
| // Check to see if any of the child menu items is selected. |
| return mpWindow->isMenuItemSelected(mnMenuPos); |
| } |
| |
| bool ScAccessibleFilterMenu::isFocused() const |
| { |
| return isSelected(); |
| } |
| |
| void ScAccessibleFilterMenu::updateStates() |
| { |
| if (!mxStateSet.is()) |
| mxStateSet.set(new ScAccessibleStateSet); |
| |
| ScAccessibleStateSet* p = static_cast<ScAccessibleStateSet*>( |
| mxStateSet.get()); |
| |
| p->clear(); |
| |
| p->insert(ENABLED); |
| p->insert(FOCUSABLE); |
| p->insert(SELECTABLE); |
| p->insert(SENSITIVE); |
| p->insert(OPAQUE); |
| |
| if (isFocused()) |
| p->insert(FOCUSED); |
| |
| if (isSelected()) |
| p->insert(SELECTED); |
| } |