/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include #include #include #include #include #include #include "AccessibleViewForwarder.hxx" #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::WeakReference; using ::com::sun::star::uno::Any; using osl::MutexGuard; namespace chart { AccessibleChartView::AccessibleChartView(SdrView* pView ) : impl::AccessibleChartView_Base( AccessibleElementInfo(), // empty for now true, // has children true // always transparent ), m_pSdrView( pView ) { AddState( AccessibleStateType::OPAQUE ); } AccessibleChartView::~AccessibleChartView() { } awt::Rectangle AccessibleChartView::GetWindowPosSize() const { Reference< awt::XWindow > xWindow( GetInfo().m_xWindow ); if( ! xWindow.is()) return awt::Rectangle(); awt::Rectangle aBBox( xWindow->getPosSize() ); VclPtr pWindow( VCLUnoHelper::GetWindow( GetInfo().m_xWindow )); if( pWindow ) { SolarMutexGuard aSolarGuard; Point aVCLPoint( pWindow->OutputToAbsoluteScreenPixel( Point( 0, 0 ) )); aBBox.X = aVCLPoint.getX(); aBBox.Y = aVCLPoint.getY(); } return aBBox; } awt::Point AccessibleChartView::GetUpperLeftOnScreen() const { awt::Point aParentPosition; awt::Rectangle aBBox( GetWindowPosSize() ); aParentPosition.X = aBBox.X; aParentPosition.Y = aBBox.Y; return aParentPosition; } // ________ XAccessibleContext ________ OUString SAL_CALL AccessibleChartView::getAccessibleName() { return SchResId(STR_OBJECT_DIAGRAM); } OUString SAL_CALL AccessibleChartView::getAccessibleDescription() { return getAccessibleName(); } Reference< XAccessible > SAL_CALL AccessibleChartView::getAccessibleParent() { return Reference< XAccessible >( m_xParent ); } sal_Int32 SAL_CALL AccessibleChartView::getAccessibleIndexInParent() { // the document is always the only child of the window return 0; } sal_Int16 SAL_CALL AccessibleChartView::getAccessibleRole() { return AccessibleRole::DOCUMENT; } // ________ XAccessibleComponent ________ awt::Rectangle SAL_CALL AccessibleChartView::getBounds() { awt::Rectangle aResult( GetWindowPosSize()); Reference< XAccessible > xParent( m_xParent ); if( xParent.is()) { Reference< XAccessibleComponent > xContext( xParent->getAccessibleContext(), uno::UNO_QUERY ); if( xContext.is()) { awt::Point aParentPosition = xContext->getLocationOnScreen(); aResult.X -= aParentPosition.X; aResult.Y -= aParentPosition.Y; } } return aResult; } awt::Point SAL_CALL AccessibleChartView::getLocationOnScreen() { awt::Rectangle aBounds( getBounds()); awt::Point aResult; Reference< XAccessible > xParent( m_xParent ); if( xParent.is()) { Reference< XAccessibleComponent > xAccComp( xParent->getAccessibleContext(), uno::UNO_QUERY ); aResult = xAccComp->getLocationOnScreen(); aResult.X += aBounds.X; aResult.Y += aBounds.Y; } return aResult; } // lang::XInitialization void SAL_CALL AccessibleChartView::initialize( const Sequence< Any >& rArguments ) { //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself //1: frame::XModel representing the chart model - offers access to object data //2: lang::XInterface representing the normal chart view - offers access to some extra object data //all arguments are only valid until next initialization bool bChanged = false; bool bOldInvalid = false; bool bNewInvalid = false; Reference< view::XSelectionSupplier > xSelectionSupplier; Reference< frame::XModel > xChartModel; Reference< uno::XInterface > xChartView; Reference< XAccessible > xParent; Reference< awt::XWindow > xWindow; { MutexGuard aGuard( m_aMutex); xSelectionSupplier.set( m_xSelectionSupplier ); xChartModel.set( m_xChartModel ); xChartView.set( m_xChartView ); xParent.set( m_xParent ); xWindow.set( m_xWindow ); } if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) { bOldInvalid = true; } if( rArguments.getLength() > 1 ) { Reference< frame::XModel > xNewChartModel; rArguments[1] >>= xNewChartModel; if( xNewChartModel != xChartModel ) { xChartModel = xNewChartModel; bChanged = true; } } else if( xChartModel.is() ) { bChanged = true; xChartModel = nullptr; } if( rArguments.getLength() > 2 ) { Reference< uno::XInterface > xNewChartView; rArguments[2] >>= xNewChartView; if( xNewChartView != xChartView ) { xChartView = xNewChartView; bChanged = true; } } else if( xChartView.is() ) { bChanged = true; xChartView = nullptr; } if( rArguments.getLength() > 3 ) { Reference< XAccessible > xNewParent; rArguments[3] >>= xNewParent; if( xNewParent != xParent ) { xParent = xNewParent; bChanged = true; } } if( rArguments.getLength() > 4 ) { Reference< awt::XWindow > xNewWindow; rArguments[4] >>= xNewWindow; if( xNewWindow != xWindow ) { xWindow.set( xNewWindow ); bChanged = true; } } if( rArguments.hasElements() && xChartModel.is() && xChartView.is() ) { Reference< view::XSelectionSupplier > xNewSelectionSupplier; rArguments[0] >>= xNewSelectionSupplier; if(xSelectionSupplier!=xNewSelectionSupplier) { bChanged = true; if(xSelectionSupplier.is()) xSelectionSupplier->removeSelectionChangeListener(this); if(xNewSelectionSupplier.is()) xNewSelectionSupplier->addSelectionChangeListener(this); xSelectionSupplier = xNewSelectionSupplier; } } else if( xSelectionSupplier.is() ) { bChanged = true; xSelectionSupplier->removeSelectionChangeListener(this); xSelectionSupplier = nullptr; } if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) { if(xSelectionSupplier.is()) xSelectionSupplier->removeSelectionChangeListener(this); xSelectionSupplier = nullptr; xChartModel.clear(); xChartView.clear(); xParent.clear(); xWindow.clear(); bNewInvalid = true; } { MutexGuard aGuard( m_aMutex); m_xSelectionSupplier = WeakReference< view::XSelectionSupplier >(xSelectionSupplier); m_xChartModel = WeakReference< frame::XModel >(xChartModel); m_xChartView = WeakReference< uno::XInterface >(xChartView); m_xParent = WeakReference< XAccessible >(xParent); m_xWindow = WeakReference< awt::XWindow >(xWindow); } if( bOldInvalid && bNewInvalid ) bChanged = false; if( !bChanged ) return; { //before notification we prepare for creation of new context //the old context will be deleted after notification than MutexGuard aGuard( m_aMutex); Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); if( xChartDoc.is()) m_spObjectHierarchy = std::make_shared( xChartDoc, comphelper::getFromUnoTunnel(m_xChartView) ); else m_spObjectHierarchy.reset(); } { AccessibleElementInfo aAccInfo; aAccInfo.m_aOID = ObjectIdentifier("ROOT"); aAccInfo.m_xChartDocument = uno::WeakReference< chart2::XChartDocument >( uno::Reference< chart2::XChartDocument >( m_xChartModel.get(), uno::UNO_QUERY )); aAccInfo.m_xSelectionSupplier = m_xSelectionSupplier; aAccInfo.m_xView = m_xChartView; aAccInfo.m_xWindow = m_xWindow; aAccInfo.m_pParent = nullptr; aAccInfo.m_spObjectHierarchy = m_spObjectHierarchy; aAccInfo.m_pSdrView = m_pSdrView; VclPtr pWindow = VCLUnoHelper::GetWindow( m_xWindow ); m_pViewForwarder.reset( new AccessibleViewForwarder( this, pWindow ) ); aAccInfo.m_pViewForwarder = m_pViewForwarder.get(); // broadcasts an INVALIDATE_ALL_CHILDREN event globally SetInfo( aAccInfo ); } } // view::XSelectionChangeListener void SAL_CALL AccessibleChartView::selectionChanged( const lang::EventObject& /*rEvent*/ ) { Reference< view::XSelectionSupplier > xSelectionSupplier; { MutexGuard aGuard( m_aMutex); xSelectionSupplier.set(m_xSelectionSupplier); } if( !xSelectionSupplier.is() ) return; ObjectIdentifier aSelectedOID( xSelectionSupplier->getSelection() ); if ( m_aCurrentSelectionOID.isValid() ) { NotifyEvent( EventType::LOST_SELECTION, m_aCurrentSelectionOID ); } if( aSelectedOID.isValid() ) { NotifyEvent( EventType::GOT_SELECTION, aSelectedOID ); } m_aCurrentSelectionOID = aSelectedOID; } // XEventListener void SAL_CALL AccessibleChartView::disposing( const lang::EventObject& /*Source*/ ) { } } //namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */