/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using ::utl::AccessibleRelationSetHelper; using ::utl::AccessibleStateSetHelper; using ::accessibility::AccessibleStaticTextBase; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::XInterface; using ::com::sun::star::lang::IndexOutOfBoundsException; using ::com::sun::star::beans::PropertyValue; using namespace ::com::sun::star::accessibility; const sal_Unicode cRulerDot = '.'; const sal_Unicode cRulerLine = '|'; const sal_Int32 CSV_LINE_HEADER = CSV_POS_INVALID; const sal_uInt32 CSV_COLUMN_HEADER = CSV_COLUMN_INVALID; ScAccessibleCsvControl::ScAccessibleCsvControl(ScCsvControl& rControl) : mpControl(&rControl) { } ScAccessibleCsvControl::~ScAccessibleCsvControl() { ensureDisposed(); } void SAL_CALL ScAccessibleCsvControl::disposing() { SolarMutexGuard aGuard; mpControl = nullptr; comphelper::OAccessibleComponentHelper::disposing(); } // XAccessibleComponent ------------------------------------------------------- Reference< XAccessible > SAL_CALL ScAccessibleCsvControl::getAccessibleAtPoint( const css::awt::Point& /* rPoint */ ) { ensureAlive(); return nullptr; } void SAL_CALL ScAccessibleCsvControl::grabFocus() { SolarMutexGuard aGuard; ensureAlive(); implGetControl().GrabFocus(); } // events --------------------------------------------------------------------- void ScAccessibleCsvControl::SendFocusEvent( bool bFocused ) { Any aOldAny, aNewAny; if (bFocused) aNewAny <<= AccessibleStateType::FOCUSED; else aOldAny <<= AccessibleStateType::FOCUSED; NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny); } void ScAccessibleCsvControl::SendCaretEvent() { OSL_FAIL( "ScAccessibleCsvControl::SendCaretEvent - Illegal call" ); } void ScAccessibleCsvControl::SendVisibleEvent() { NotifyAccessibleEvent(AccessibleEventId::VISIBLE_DATA_CHANGED, Any(), Any()); } void ScAccessibleCsvControl::SendSelectionEvent() { NotifyAccessibleEvent(AccessibleEventId::SELECTION_CHANGED, Any(), Any()); } void ScAccessibleCsvControl::SendTableUpdateEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */, bool /* bAllRows */ ) { OSL_FAIL( "ScAccessibleCsvControl::SendTableUpdateEvent - Illegal call" ); } void ScAccessibleCsvControl::SendInsertColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ ) { OSL_FAIL( "ScAccessibleCsvControl::SendInsertColumnEvent - Illegal call" ); } void ScAccessibleCsvControl::SendRemoveColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ ) { OSL_FAIL( "ScAccessibleCsvControl::SendRemoveColumnEvent - Illegal call" ); } // helpers -------------------------------------------------------------------- css::awt::Rectangle ScAccessibleCsvControl::implGetBounds() { SolarMutexGuard aGuard; ensureAlive(); Size aOutSize(implGetControl().GetOutputSizePixel()); return css::awt::Rectangle(0, 0, aOutSize.Width(), aOutSize.Height()); } ScCsvControl& ScAccessibleCsvControl::implGetControl() const { assert(mpControl && "ScAccessibleCsvControl::implGetControl - missing control"); return *mpControl; } rtl::Reference ScAccessibleCsvControl::implCreateStateSet() { SolarMutexGuard aGuard; rtl::Reference pStateSet = new AccessibleStateSetHelper(); if (isAlive()) { const ScCsvControl& rCtrl = implGetControl(); pStateSet->AddState( AccessibleStateType::OPAQUE ); if( rCtrl.IsEnabled() ) pStateSet->AddState( AccessibleStateType::ENABLED ); if( rCtrl.IsReallyVisible() ) pStateSet->AddState( AccessibleStateType::SHOWING ); if( rCtrl.IsVisible() ) pStateSet->AddState( AccessibleStateType::VISIBLE ); } else pStateSet->AddState( AccessibleStateType::DEFUNC ); return pStateSet; } // Ruler ====================================================================== /** Converts a ruler cursor position to API text index. */ static sal_Int32 lcl_GetApiPos( sal_Int32 nRulerPos ) { sal_Int32 nApiPos = nRulerPos; sal_Int32 nStart = (nRulerPos - 1) / 10; sal_Int32 nExp = 1; while( nStart >= nExp ) { nApiPos += nStart - nExp + 1; nExp *= 10; } return ::std::max( nApiPos, static_cast(0) ); } /** Converts an API text index to a ruler cursor position. */ static sal_Int32 lcl_GetRulerPos( sal_Int32 nApiPos ) { sal_Int32 nDiv = 10; sal_Int32 nExp = 10; sal_Int32 nRulerPos = 0; sal_Int32 nApiBase = 0; sal_Int32 nApiLimit = 10; while( nApiPos >= nApiLimit ) { ++nDiv; nRulerPos = nExp; nExp *= 10; nApiBase = nApiLimit; nApiLimit = lcl_GetApiPos( nExp ); } sal_Int32 nRelPos = nApiPos - nApiBase; return nRulerPos + nRelPos / nDiv * 10 + ::std::max( nRelPos % nDiv - nDiv + 10, 0 ); } /** Expands the sequence's size and returns the base index of the new inserted elements. */ static sal_Int32 lcl_ExpandSequence( Sequence< PropertyValue >& rSeq, sal_Int32 nExp ) { OSL_ENSURE( nExp > 0, "lcl_ExpandSequence - invalid value" ); rSeq.realloc( rSeq.getLength() + nExp ); return rSeq.getLength() - nExp; } /** Fills the property value rVal with the specified name and value from the item. */ static void lcl_FillProperty( PropertyValue& rVal, const OUString& rPropName, const SfxPoolItem& rItem, sal_uInt8 nMID ) { rVal.Name = rPropName; rItem.QueryValue( rVal.Value, nMID ); } /** Fills the sequence with all font attributes of rFont. */ static void lcl_FillFontAttributes( Sequence< PropertyValue >& rSeq, const vcl::Font& rFont ) { SvxFontItem aFontItem( rFont.GetFamilyType(), rFont.GetFamilyName(), rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), ATTR_FONT ); SvxFontHeightItem aHeightItem( rFont.GetFontSize().Height(), 100, ATTR_FONT_HEIGHT ); SvxLanguageItem aLangItem( rFont.GetLanguage(), ATTR_FONT_LANGUAGE ); sal_Int32 nIndex = lcl_ExpandSequence( rSeq, 7 ); auto pSeq = rSeq.getArray(); lcl_FillProperty( pSeq[ nIndex++ ], "CharFontName", aFontItem, MID_FONT_FAMILY_NAME ); lcl_FillProperty( pSeq[ nIndex++ ], "CharFontFamily", aFontItem, MID_FONT_FAMILY ); lcl_FillProperty( pSeq[ nIndex++ ], "CharFontStyleName", aFontItem, MID_FONT_STYLE_NAME ); lcl_FillProperty( pSeq[ nIndex++ ], "CharFontCharSet", aFontItem, MID_FONT_PITCH ); lcl_FillProperty( pSeq[ nIndex++ ], "CharFontPitch", aFontItem, MID_FONT_CHAR_SET ); lcl_FillProperty( pSeq[ nIndex++ ], "CharHeight", aHeightItem, MID_FONTHEIGHT ); lcl_FillProperty( pSeq[ nIndex++ ], "CharLocale", aLangItem, MID_LANG_LOCALE ); } ScAccessibleCsvRuler::ScAccessibleCsvRuler(ScCsvRuler& rRuler) : ScAccessibleCsvControl(rRuler) { constructStringBuffer(); } ScAccessibleCsvRuler::~ScAccessibleCsvRuler() { ensureDisposed(); } // XAccessibleComponent ----------------------------------------------------- sal_Int32 SAL_CALL ScAccessibleCsvRuler::getForeground( ) { SolarMutexGuard aGuard; ensureAlive(); return sal_Int32(Application::GetSettings().GetStyleSettings().GetLabelTextColor()); } sal_Int32 SAL_CALL ScAccessibleCsvRuler::getBackground( ) { SolarMutexGuard aGuard; ensureAlive(); return sal_Int32(Application::GetSettings().GetStyleSettings().GetFaceColor()); } // XAccessibleContext --------------------------------------------------------- sal_Int32 SAL_CALL ScAccessibleCsvRuler::getAccessibleChildCount() { ensureAlive(); return 0; } Reference< XAccessible > SAL_CALL ScAccessibleCsvRuler::getAccessibleChild( sal_Int32 /* nIndex */ ) { ensureAlive(); throw IndexOutOfBoundsException(); } Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleRelationSet() { SolarMutexGuard aGuard; ensureAlive(); rtl::Reference pRelationSet = new AccessibleRelationSetHelper(); ScCsvRuler& rRuler = implGetRuler(); ScCsvTableBox* pTableBox = rRuler.GetTableBox(); ScCsvGrid& rGrid = pTableBox->GetGrid(); css::uno::Reference xAccObj(static_cast(rGrid.GetAccessible())); if( xAccObj.is() ) { Sequence< Reference< XInterface > > aSeq{ xAccObj }; pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLER_FOR, aSeq ) ); } return pRelationSet; } Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleStateSet() { SolarMutexGuard aGuard; rtl::Reference pStateSet = implCreateStateSet(); if( isAlive() ) { pStateSet->AddState( AccessibleStateType::FOCUSABLE ); pStateSet->AddState( AccessibleStateType::SINGLE_LINE ); if( implGetRuler().HasFocus() ) pStateSet->AddState( AccessibleStateType::FOCUSED ); } return pStateSet; } // XAccessibleText ------------------------------------------------------------ sal_Int32 SAL_CALL ScAccessibleCsvRuler::getCaretPosition() { SolarMutexGuard aGuard; ensureAlive(); return lcl_GetApiPos( implGetRuler().GetRulerCursorPos() ); } sal_Bool SAL_CALL ScAccessibleCsvRuler::setCaretPosition( sal_Int32 nIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nIndex ); ScCsvRuler& rRuler = implGetRuler(); sal_Int32 nOldCursor = rRuler.GetRulerCursorPos(); rRuler.Execute( CSVCMD_MOVERULERCURSOR, lcl_GetRulerPos( nIndex ) ); return rRuler.GetRulerCursorPos() != nOldCursor; } sal_Unicode SAL_CALL ScAccessibleCsvRuler::getCharacter( sal_Int32 nIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nIndex ); return maBuffer[nIndex]; } Sequence< PropertyValue > SAL_CALL ScAccessibleCsvRuler::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& /* aRequestedAttributes */ ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndexWithEnd( nIndex ); Sequence< PropertyValue > aSeq; lcl_FillFontAttributes( aSeq, implGetRuler().GetDrawingArea()->get_ref_device().GetFont() ); return aSeq; } css::awt::Rectangle SAL_CALL ScAccessibleCsvRuler::getCharacterBounds( sal_Int32 nIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndexWithEnd( nIndex ); ScCsvRuler& rRuler = implGetRuler(); Point aPos( rRuler.GetX( lcl_GetRulerPos( nIndex ) ) - rRuler.GetCharWidth() / 2, 0 ); css::awt::Rectangle aRect( aPos.X(), aPos.Y(), rRuler.GetCharWidth(), rRuler.GetOutputSizePixel().Height() ); // do not return rectangle out of window sal_Int32 nWidth = rRuler.GetOutputSizePixel().Width(); if( aRect.X >= nWidth ) throw IndexOutOfBoundsException(); if( aRect.X + aRect.Width > nWidth ) aRect.Width = nWidth - aRect.X; return aRect; } sal_Int32 SAL_CALL ScAccessibleCsvRuler::getCharacterCount() { SolarMutexGuard aGuard; ensureAlive(); return implGetTextLength(); } sal_Int32 SAL_CALL ScAccessibleCsvRuler::getIndexAtPoint( const css::awt::Point& rPoint ) { SolarMutexGuard aGuard; ensureAlive(); ScCsvRuler& rRuler = implGetRuler(); // use object's coordinate system, convert to API position return lcl_GetApiPos( ::std::clamp( rRuler.GetPosFromX( rPoint.X ), sal_Int32(0), rRuler.GetPosCount() ) ); } OUString SAL_CALL ScAccessibleCsvRuler::getSelectedText() { ensureAlive(); return OUString(); } sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionStart() { ensureAlive(); return -1; } sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionEnd() { ensureAlive(); return -1; } sal_Bool SAL_CALL ScAccessibleCsvRuler::setSelection( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ ) { ensureAlive(); return false; } OUString SAL_CALL ScAccessibleCsvRuler::getText() { SolarMutexGuard aGuard; ensureAlive(); return OUString( maBuffer.getStr(), implGetTextLength() ); } OUString SAL_CALL ScAccessibleCsvRuler::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidRange( nStartIndex, nEndIndex ); return OUString( maBuffer.getStr() + nStartIndex, nEndIndex - nStartIndex ); } TextSegment SAL_CALL ScAccessibleCsvRuler::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) { SolarMutexGuard aGuard; ensureAlive(); TextSegment aResult; aResult.SegmentStart = -1; aResult.SegmentEnd = -1; if( (nIndex == implGetTextLength()) && (nTextType != AccessibleTextType::LINE) ) return aResult; ensureValidIndex( nIndex ); OUStringBuffer aResultText; // will be assigned to aResult.SegmentText below sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex ); switch( nTextType ) { // single character case AccessibleTextType::CHARACTER: { aResult.SegmentStart = nIndex; aResultText.append(maBuffer[nIndex]); } break; // entire number or single dot/line case AccessibleTextType::WORD: case AccessibleTextType::GLYPH: aResult.SegmentStart = nIndex; if( nRulerPos % 10 ) aResultText.append(maBuffer[nIndex]); else aResultText.append( nRulerPos ); // string representation of sal_Int32!!! break; // entire text case AccessibleTextType::SENTENCE: case AccessibleTextType::PARAGRAPH: case AccessibleTextType::LINE: aResult.SegmentStart = 0; aResultText.append( maBuffer.getStr(), implGetTextLength() ); break; // equal-formatted text case AccessibleTextType::ATTRIBUTE_RUN: { sal_Int32 nFirstIndex = implGetFirstEqualFormatted( nIndex ); sal_Int32 nLastIndex = implGetLastEqualFormatted( nIndex ); aResult.SegmentStart = nFirstIndex; aResultText.append( maBuffer.getStr() + nFirstIndex, nLastIndex - nFirstIndex + 1 ); } break; default: throw RuntimeException(); } aResult.SegmentText = aResultText.makeStringAndClear(); aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); return aResult; } TextSegment SAL_CALL ScAccessibleCsvRuler::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndexWithEnd( nIndex ); TextSegment aResult; aResult.SegmentStart = -1; aResult.SegmentEnd = -1; sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex ); switch( nTextType ) { // single character case AccessibleTextType::CHARACTER: if( nIndex > 0 ) aResult = getTextAtIndex( nIndex - 1, nTextType ); // else empty break; // entire number or single dot/line case AccessibleTextType::WORD: case AccessibleTextType::GLYPH: if( nRulerPos > 0 ) aResult = getTextAtIndex( lcl_GetApiPos( nRulerPos - 1 ), nTextType ); // else empty break; // entire text case AccessibleTextType::SENTENCE: case AccessibleTextType::PARAGRAPH: case AccessibleTextType::LINE: // empty break; // equal-formatted text case AccessibleTextType::ATTRIBUTE_RUN: { sal_Int32 nFirstIndex = implGetFirstEqualFormatted( nIndex ); if( nFirstIndex > 0 ) aResult = getTextAtIndex( nFirstIndex - 1, nTextType ); // else empty } break; default: throw RuntimeException(); } return aResult; } TextSegment SAL_CALL ScAccessibleCsvRuler::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndexWithEnd( nIndex ); TextSegment aResult; aResult.SegmentStart = -1; aResult.SegmentEnd = -1; sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex ); sal_Int32 nLastValid = implGetTextLength(); switch( nTextType ) { // single character case AccessibleTextType::CHARACTER: if( nIndex < nLastValid ) aResult = getTextAtIndex( nIndex + 1, nTextType ); // else empty break; // entire number or single dot/line case AccessibleTextType::WORD: case AccessibleTextType::GLYPH: if( nRulerPos < implGetRuler().GetPosCount() ) aResult = getTextAtIndex( lcl_GetApiPos( nRulerPos + 1 ), nTextType ); // else empty break; // entire text case AccessibleTextType::SENTENCE: case AccessibleTextType::PARAGRAPH: case AccessibleTextType::LINE: // empty break; // equal-formatted text case AccessibleTextType::ATTRIBUTE_RUN: { sal_Int32 nLastIndex = implGetLastEqualFormatted( nIndex ); if( nLastIndex < nLastValid ) aResult = getTextAtIndex( nLastIndex + 1, nTextType ); // else empty } break; default: throw RuntimeException(); } return aResult; } sal_Bool SAL_CALL ScAccessibleCsvRuler::copyText( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ ) { ensureAlive(); return false; } sal_Bool SAL_CALL ScAccessibleCsvRuler::scrollSubstringTo( sal_Int32 /* nStartIndex */, sal_Int32/* nEndIndex */, AccessibleScrollType /* aScrollType */ ) { return false; } // XInterface ----------------------------------------------------------------- Any SAL_CALL ScAccessibleCsvRuler::queryInterface( const css::uno::Type& rType ) { Any aAny( ScAccessibleCsvRulerImpl::queryInterface( rType ) ); return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType ); } void SAL_CALL ScAccessibleCsvRuler::acquire() noexcept { ScAccessibleCsvControl::acquire(); } void SAL_CALL ScAccessibleCsvRuler::release() noexcept { ScAccessibleCsvControl::release(); } // XTypeProvider -------------------------------------------------------------- Sequence< css::uno::Type > SAL_CALL ScAccessibleCsvRuler::getTypes() { return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), Sequence { cppu::UnoType::get() }); } Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvRuler::getImplementationId() { return css::uno::Sequence(); } // events --------------------------------------------------------------------- void ScAccessibleCsvRuler::SendCaretEvent() { sal_Int32 nPos = implGetRuler().GetRulerCursorPos(); if (nPos != CSV_POS_INVALID) { Any aOldValue, aNewValue; aNewValue <<= nPos; NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED, aOldValue, aNewValue ); } } // helpers -------------------------------------------------------------------- OUString SAL_CALL ScAccessibleCsvRuler::getAccessibleName() { return ScResId( STR_ACC_CSVRULER_NAME ); } OUString SAL_CALL ScAccessibleCsvRuler::getAccessibleDescription() { return ScResId( STR_ACC_CSVRULER_DESCR ); } void ScAccessibleCsvRuler::ensureValidIndex( sal_Int32 nIndex ) const { if( (nIndex < 0) || (nIndex >= implGetTextLength()) ) throw IndexOutOfBoundsException(); } void ScAccessibleCsvRuler::ensureValidIndexWithEnd( sal_Int32 nIndex ) const { if( (nIndex < 0) || (nIndex > implGetTextLength()) ) throw IndexOutOfBoundsException(); } void ScAccessibleCsvRuler::ensureValidRange( sal_Int32& rnStartIndex, sal_Int32& rnEndIndex ) const { if( rnStartIndex > rnEndIndex ) ::std::swap( rnStartIndex, rnEndIndex ); if( (rnStartIndex < 0) || (rnEndIndex > implGetTextLength()) ) throw IndexOutOfBoundsException(); } ScCsvRuler& ScAccessibleCsvRuler::implGetRuler() const { return static_cast< ScCsvRuler& >( implGetControl() ); } void ScAccessibleCsvRuler::constructStringBuffer() { SolarMutexGuard aGuard; ensureAlive(); // extend existing string buffer to new ruler size sal_Int32 nRulerCount = implGetRuler().GetPosCount(); sal_Int32 nRulerPos = lcl_GetRulerPos( maBuffer.getLength() ); for( ; nRulerPos <= nRulerCount; ++nRulerPos ) // include last position { switch( nRulerPos % 10 ) { case 0: maBuffer.append( nRulerPos ); break; case 5: maBuffer.append( cRulerLine ); break; default: maBuffer.append( cRulerDot ); } } } sal_Int32 ScAccessibleCsvRuler::implGetTextLength() const { return lcl_GetApiPos( implGetRuler().GetPosCount() + 1 ); } bool ScAccessibleCsvRuler::implHasSplit( sal_Int32 nApiPos ) { sal_Int32 nRulerPos = lcl_GetRulerPos( nApiPos ); return implGetRuler().HasSplit( nRulerPos ) && (nApiPos == lcl_GetApiPos( nRulerPos )); } sal_Int32 ScAccessibleCsvRuler::implGetFirstEqualFormatted( sal_Int32 nApiPos ) { bool bSplit = implHasSplit( nApiPos ); while( (nApiPos > 0) && (implHasSplit( nApiPos - 1 ) == bSplit) ) --nApiPos; return nApiPos; } sal_Int32 ScAccessibleCsvRuler::implGetLastEqualFormatted( sal_Int32 nApiPos ) { bool bSplit = implHasSplit( nApiPos ); sal_Int32 nLength = implGetTextLength(); while( (nApiPos < nLength - 1) && (implHasSplit( nApiPos + 1 ) == bSplit) ) ++nApiPos; return nApiPos; } css::uno::Reference SAL_CALL ScAccessibleCsvRuler::getAccessibleParent() { return implGetControl().GetDrawingArea()->get_accessible_parent(); } // Grid ======================================================================= /** Converts a grid columnm index to an API column index. */ static sal_Int32 lcl_GetApiColumn( sal_uInt32 nGridColumn ) { return (nGridColumn != CSV_COLUMN_HEADER) ? static_cast< sal_Int32 >( nGridColumn + 1 ) : 0; } /** Converts an API columnm index to a ScCsvGrid column index. */ static sal_uInt32 lcl_GetGridColumn( sal_Int32 nApiColumn ) { return (nApiColumn > 0) ? static_cast< sal_uInt32 >( nApiColumn - 1 ) : CSV_COLUMN_HEADER; } ScAccessibleCsvGrid::ScAccessibleCsvGrid(ScCsvGrid& rGrid) : ScAccessibleCsvControl(rGrid) { } ScAccessibleCsvGrid::~ScAccessibleCsvGrid() { ensureDisposed(); } void ScAccessibleCsvGrid::disposing() { SolarMutexGuard aGuard; for (auto& rEntry : maAccessibleChildren) rEntry.second->dispose(); maAccessibleChildren.clear(); ScAccessibleCsvControl::disposing(); } // XAccessibleComponent ------------------------------------------------------- Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleAtPoint( const css::awt::Point& rPoint ) { Reference< XAccessible > xRet; if( containsPoint( rPoint ) ) { SolarMutexGuard aGuard; ensureAlive(); const ScCsvGrid& rGrid = implGetGrid(); // #102679#; use <= instead of <, because the offset is the size and not the point sal_Int32 nColumn = ((rGrid.GetFirstX() <= rPoint.X) && (rPoint.X <= rGrid.GetLastX())) ? lcl_GetApiColumn( rGrid.GetColumnFromX( rPoint.X ) ) : 0; sal_Int32 nRow = (rPoint.Y >= rGrid.GetHdrHeight()) ? (rGrid.GetLineFromY( rPoint.Y ) - rGrid.GetFirstVisLine() + 1) : 0; xRet = getAccessibleCell(nRow, nColumn); } return xRet; } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getForeground( ) { SolarMutexGuard aGuard; ensureAlive(); return sal_Int32(Application::GetSettings().GetStyleSettings().GetButtonTextColor()); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getBackground( ) { SolarMutexGuard aGuard; ensureAlive(); return sal_Int32(SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor); } // XAccessibleContext --------------------------------------------------------- sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleChildCount() { SolarMutexGuard aGuard; ensureAlive(); return implGetCellCount(); } Reference ScAccessibleCsvGrid::getAccessibleCell(sal_Int32 nRow, sal_Int32 nColumn) { sal_Int32 nIndex = implGetIndex(nRow, nColumn); XAccessibleSet::iterator aI = maAccessibleChildren.lower_bound(nIndex); if (aI != maAccessibleChildren.end() && !(maAccessibleChildren.key_comp()(nIndex, aI->first))) { // key already exists return aI->second; } // key does not exist rtl::Reference xNew = implCreateCellObj(nRow, nColumn); maAccessibleChildren.insert(aI, XAccessibleSet::value_type(nIndex, xNew)); return xNew; } Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleChild( sal_Int32 nIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nIndex ); return getAccessibleCell(implGetRow(nIndex), implGetColumn(nIndex)); } Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleRelationSet() { SolarMutexGuard aGuard; ensureAlive(); rtl::Reference pRelationSet = new AccessibleRelationSetHelper(); ScCsvGrid& rGrid = implGetGrid(); ScCsvTableBox* pTableBox = rGrid.GetTableBox(); ScCsvRuler& rRuler = pTableBox->GetRuler(); if (rRuler.IsVisible()) { css::uno::Reference xAccObj(static_cast(rRuler.GetAccessible())); if( xAccObj.is() ) { Sequence< Reference< XInterface > > aSeq{ xAccObj }; pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLED_BY, aSeq ) ); } } return pRelationSet; } Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleStateSet() { SolarMutexGuard aGuard; rtl::Reference pStateSet = implCreateStateSet(); if( isAlive() ) { pStateSet->AddState( AccessibleStateType::FOCUSABLE ); pStateSet->AddState( AccessibleStateType::MULTI_SELECTABLE ); pStateSet->AddState( AccessibleStateType::MANAGES_DESCENDANTS ); if( implGetGrid().HasFocus() ) pStateSet->AddState( AccessibleStateType::FOCUSED ); } else pStateSet->AddState( AccessibleStateType::DEFUNC ); return pStateSet; } // XAccessibleTable ----------------------------------------------------------- sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowCount() { SolarMutexGuard aGuard; ensureAlive(); return implGetRowCount(); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnCount() { SolarMutexGuard aGuard; ensureAlive(); return implGetColumnCount(); } OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleRowDescription( sal_Int32 nRow ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidPosition( nRow, 0 ); return implGetCellText( nRow, 0 ); } OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnDescription( sal_Int32 nColumn ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidPosition( 0, nColumn ); return implGetCellText( 0, nColumn ); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) { ensureAlive(); ensureValidPosition( nRow, nColumn ); return 1; } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) { ensureAlive(); ensureValidPosition( nRow, nColumn ); return 1; } Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleRowHeaders() { ensureAlive(); return nullptr; } Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnHeaders() { ensureAlive(); return nullptr; } Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleRows() { ensureAlive(); return Sequence< sal_Int32 >(); } Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleColumns() { SolarMutexGuard aGuard; ensureAlive(); ScCsvGrid& rGrid = implGetGrid(); Sequence< sal_Int32 > aSeq( implGetColumnCount() ); auto pSeq = aSeq.getArray(); sal_Int32 nSeqIx = 0; sal_uInt32 nColIx = rGrid.GetFirstSelected(); for( ; nColIx != CSV_COLUMN_INVALID; ++nSeqIx, nColIx = rGrid.GetNextSelected( nColIx ) ) pSeq[ nSeqIx ] = lcl_GetApiColumn( nColIx ); aSeq.realloc( nSeqIx ); return aSeq; } sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleRowSelected( sal_Int32 /* nRow */ ) { ensureAlive(); return false; } sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleColumnSelected( sal_Int32 nColumn ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nColumn ); return implIsColumnSelected( nColumn ); } Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidPosition( nRow, nColumn ); return getAccessibleCell(nRow, nColumn); } Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCaption() { ensureAlive(); return nullptr; } Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleSummary() { ensureAlive(); return nullptr; } sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleSelected( sal_Int32 /* nRow */, sal_Int32 nColumn ) { return isAccessibleColumnSelected( nColumn ); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidPosition( nRow, nColumn ); return implGetIndex( nRow, nColumn ); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRow( sal_Int32 nChildIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nChildIndex ); return implGetRow( nChildIndex ); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumn( sal_Int32 nChildIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nChildIndex ); return implGetColumn( nChildIndex ); } // XAccessibleSelection ------------------------------------------------------- void SAL_CALL ScAccessibleCsvGrid::selectAccessibleChild( sal_Int32 nChildIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nChildIndex ); sal_Int32 nColumn = implGetColumn( nChildIndex ); if( nChildIndex == 0 ) implGetGrid().SelectAll(); else implSelectColumn( nColumn, true ); } sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleChildSelected( sal_Int32 nChildIndex ) { SolarMutexGuard aGuard; ensureAlive(); ensureValidIndex( nChildIndex ); sal_Int32 nColumn = implGetColumn( nChildIndex ); return implIsColumnSelected( nColumn ); } void SAL_CALL ScAccessibleCsvGrid::clearAccessibleSelection() { SolarMutexGuard aGuard; ensureAlive(); implGetGrid().SelectAll( false ); } void SAL_CALL ScAccessibleCsvGrid::selectAllAccessibleChildren() { selectAccessibleChild( 0 ); } sal_Int32 SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChildCount() { SolarMutexGuard aGuard; ensureAlive(); return implGetRowCount() * implGetSelColumnCount(); } Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) { SolarMutexGuard aGuard; ensureAlive(); sal_Int32 nColumns = implGetSelColumnCount(); if( nColumns == 0 ) throw IndexOutOfBoundsException(); sal_Int32 nRow = nSelectedChildIndex / nColumns; sal_Int32 nColumn = implGetSelColumn( nSelectedChildIndex % nColumns ); return getAccessibleCellAt( nRow, nColumn ); } void SAL_CALL ScAccessibleCsvGrid::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) { SolarMutexGuard aGuard; ensureAlive(); sal_Int32 nColumns = implGetSelColumnCount(); if( nColumns == 0 ) throw IndexOutOfBoundsException(); sal_Int32 nColumn = implGetSelColumn( nSelectedChildIndex % nColumns ); ensureValidPosition( nSelectedChildIndex / nColumns, nColumn ); if( nColumn > 0 ) implSelectColumn( nColumn, false ); } // XInterface ----------------------------------------------------------------- Any SAL_CALL ScAccessibleCsvGrid::queryInterface( const css::uno::Type& rType ) { Any aAny( ScAccessibleCsvGridImpl::queryInterface( rType ) ); return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType ); } void SAL_CALL ScAccessibleCsvGrid::acquire() noexcept { ScAccessibleCsvControl::acquire(); } void SAL_CALL ScAccessibleCsvGrid::release() noexcept { ScAccessibleCsvControl::release(); } // XTypeProvider -------------------------------------------------------------- Sequence< css::uno::Type > SAL_CALL ScAccessibleCsvGrid::getTypes() { return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), Sequence { cppu::UnoType::get(), cppu::UnoType::get() }); } Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvGrid::getImplementationId() { return css::uno::Sequence(); } // events --------------------------------------------------------------------- void ScAccessibleCsvGrid::SendFocusEvent( bool bFocused ) { ScAccessibleCsvControl::SendFocusEvent( bFocused ); Any aOldAny, aNewAny; (bFocused ? aNewAny : aOldAny) <<= getAccessibleCellAt( 0, lcl_GetApiColumn( implGetGrid().GetFocusColumn() ) ); NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny); } void ScAccessibleCsvGrid::SendTableUpdateEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn, bool bAllRows ) { if( nFirstColumn <= nLastColumn ) { AccessibleTableModelChange aModelChange( AccessibleTableModelChangeType::UPDATE, 0, bAllRows ? implGetRowCount() - 1 : 0, lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); Any aOldAny, aNewAny; aNewAny <<= aModelChange; NotifyAccessibleEvent(AccessibleEventId::TABLE_MODEL_CHANGED, aOldAny, aNewAny); } } void ScAccessibleCsvGrid::SendInsertColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn ) { if( nFirstColumn <= nLastColumn ) { AccessibleTableModelChange aModelChange( AccessibleTableModelChangeType::COLUMNS_INSERTED, -1, -1, lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); Any aOldAny, aNewAny; aNewAny <<= aModelChange; NotifyAccessibleEvent(AccessibleEventId::TABLE_MODEL_CHANGED, aOldAny, aNewAny); } } void ScAccessibleCsvGrid::SendRemoveColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn ) { if( nFirstColumn <= nLastColumn ) { AccessibleTableModelChange aModelChange( AccessibleTableModelChangeType::COLUMNS_REMOVED, -1, -1, lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); Any aOldAny, aNewAny; aNewAny <<= aModelChange; NotifyAccessibleEvent(AccessibleEventId::TABLE_MODEL_CHANGED, aOldAny, aNewAny); } } // helpers -------------------------------------------------------------------- OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleName() { return ScResId( STR_ACC_CSVGRID_NAME ); } OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleDescription() { return ScResId( STR_ACC_CSVGRID_DESCR ); } void ScAccessibleCsvGrid::ensureValidIndex( sal_Int32 nIndex ) const { if( (nIndex < 0) || (nIndex >= implGetCellCount()) ) throw IndexOutOfBoundsException(); } void ScAccessibleCsvGrid::ensureValidPosition( sal_Int32 nRow, sal_Int32 nColumn ) const { if( (nRow < 0) || (nRow >= implGetRowCount()) || (nColumn < 0) || (nColumn >= implGetColumnCount()) ) throw IndexOutOfBoundsException(); } ScCsvGrid& ScAccessibleCsvGrid::implGetGrid() const { return static_cast< ScCsvGrid& >( implGetControl() ); } bool ScAccessibleCsvGrid::implIsColumnSelected( sal_Int32 nColumn ) const { return (nColumn > 0) && implGetGrid().IsSelected( lcl_GetGridColumn( nColumn ) ); } void ScAccessibleCsvGrid::implSelectColumn( sal_Int32 nColumn, bool bSelect ) { if( nColumn > 0 ) implGetGrid().Select( lcl_GetGridColumn( nColumn ), bSelect ); } sal_Int32 ScAccessibleCsvGrid::implGetRowCount() const { return static_cast< sal_Int32 >( implGetGrid().GetLastVisLine() - implGetGrid().GetFirstVisLine() + 2 ); } sal_Int32 ScAccessibleCsvGrid::implGetColumnCount() const { return static_cast< sal_Int32 >( implGetGrid().GetColumnCount() + 1 ); } sal_Int32 ScAccessibleCsvGrid::implGetSelColumnCount() const { ScCsvGrid& rGrid = implGetGrid(); sal_Int32 nCount = 0; for( sal_uInt32 nColIx = rGrid.GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = rGrid.GetNextSelected( nColIx ) ) ++nCount; return nCount; } sal_Int32 ScAccessibleCsvGrid::implGetSelColumn( sal_Int32 nSelColumn ) const { ScCsvGrid& rGrid = implGetGrid(); sal_Int32 nColumn = 0; for( sal_uInt32 nColIx = rGrid.GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = rGrid.GetNextSelected( nColIx ) ) { if( nColumn == nSelColumn ) return static_cast< sal_Int32 >( nColIx + 1 ); ++nColumn; } return 0; } OUString ScAccessibleCsvGrid::implGetCellText( sal_Int32 nRow, sal_Int32 nColumn ) const { ScCsvGrid& rGrid = implGetGrid(); sal_Int32 nLine = nRow + rGrid.GetFirstVisLine() - 1; OUString aCellStr; if( (nColumn > 0) && (nRow > 0) ) aCellStr = rGrid.GetCellText( lcl_GetGridColumn( nColumn ), nLine ); else if( nRow > 0 ) aCellStr = OUString::number( nLine + 1 ); else if( nColumn > 0 ) aCellStr = rGrid.GetColumnTypeName( lcl_GetGridColumn( nColumn ) ); return aCellStr; } rtl::Reference ScAccessibleCsvGrid::implCreateCellObj( sal_Int32 nRow, sal_Int32 nColumn ) { return new ScAccessibleCsvCell(implGetGrid(), implGetCellText(nRow, nColumn), nRow, nColumn); } css::uno::Reference SAL_CALL ScAccessibleCsvGrid::getAccessibleParent() { return implGetControl().GetDrawingArea()->get_accessible_parent(); } ScAccessibleCsvCell::ScAccessibleCsvCell( ScCsvGrid& rGrid, const OUString& rCellText, sal_Int32 nRow, sal_Int32 nColumn ) : ScAccessibleCsvControl( rGrid ), AccessibleStaticTextBase( SvxEditSourcePtr() ), maCellText( rCellText ), mnLine( nRow ? (nRow + rGrid.GetFirstVisLine() - 1) : CSV_LINE_HEADER ), mnColumn( lcl_GetGridColumn( nColumn ) ), mnIndex( nRow * (rGrid.GetColumnCount() + 1) + nColumn ) { SetEditSource( implCreateEditSource() ); } ScAccessibleCsvCell::~ScAccessibleCsvCell() { } void SAL_CALL ScAccessibleCsvCell::disposing() { SolarMutexGuard aGuard; SetEditSource( SvxEditSourcePtr() ); ScAccessibleCsvControl::disposing(); } // XAccessibleComponent ------------------------------------------------------- void SAL_CALL ScAccessibleCsvCell::grabFocus() { SolarMutexGuard aGuard; ensureAlive(); ScCsvGrid& rGrid = implGetGrid(); rGrid.Execute( CSVCMD_MOVEGRIDCURSOR, rGrid.GetColumnPos( mnColumn ) ); } sal_Int32 SAL_CALL ScAccessibleCsvCell::getForeground( ) { SolarMutexGuard aGuard; ensureAlive(); return sal_Int32(Application::GetSettings().GetStyleSettings().GetButtonTextColor()); } sal_Int32 SAL_CALL ScAccessibleCsvCell::getBackground( ) { SolarMutexGuard aGuard; ensureAlive(); return sal_Int32(SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor); } // XAccessibleContext ----------------------------------------------------- sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleChildCount() { return AccessibleStaticTextBase::getAccessibleChildCount(); } Reference< XAccessible > SAL_CALL ScAccessibleCsvCell::getAccessibleChild( sal_Int32 nIndex ) { return AccessibleStaticTextBase::getAccessibleChild( nIndex ); } sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleIndexInParent() { SolarMutexGuard aGuard; ensureAlive(); return mnIndex; } Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvCell::getAccessibleRelationSet() { SolarMutexGuard aGuard; ensureAlive(); return new AccessibleRelationSetHelper(); } Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvCell::getAccessibleStateSet() { SolarMutexGuard aGuard; rtl::Reference pStateSet = implCreateStateSet(); if( isAlive() ) { const ScCsvGrid& rGrid = implGetGrid(); pStateSet->AddState( AccessibleStateType::SINGLE_LINE ); if( mnColumn != CSV_COLUMN_HEADER ) pStateSet->AddState( AccessibleStateType::SELECTABLE ); if( rGrid.HasFocus() && (rGrid.GetFocusColumn() == mnColumn) && (mnLine == CSV_LINE_HEADER) ) pStateSet->AddState( AccessibleStateType::ACTIVE ); if( rGrid.IsSelected( mnColumn ) ) pStateSet->AddState( AccessibleStateType::SELECTED ); } return pStateSet; } // XInterface ----------------------------------------------------------------- IMPLEMENT_FORWARD_XINTERFACE2( ScAccessibleCsvCell, ScAccessibleCsvControl, AccessibleStaticTextBase ) // XTypeProvider -------------------------------------------------------------- IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScAccessibleCsvCell, ScAccessibleCsvControl, AccessibleStaticTextBase ) // helpers -------------------------------------------------------------------- OUString SAL_CALL ScAccessibleCsvCell::getAccessibleName() { return maCellText; } OUString SAL_CALL ScAccessibleCsvCell::getAccessibleDescription() { return OUString(); } ScCsvGrid& ScAccessibleCsvCell::implGetGrid() const { return static_cast< ScCsvGrid& >( implGetControl() ); } Point ScAccessibleCsvCell::implGetRealPos() const { ScCsvGrid& rGrid = implGetGrid(); return Point( (mnColumn == CSV_COLUMN_HEADER) ? rGrid.GetHdrX() : rGrid.GetColumnX( mnColumn ), (mnLine == CSV_LINE_HEADER) ? 0 : rGrid.GetY( mnLine ) ); } sal_uInt32 ScAccessibleCsvCell::implCalcPixelWidth(sal_uInt32 nChars) const { ScCsvGrid& rGrid = implGetGrid(); return rGrid.GetCharWidth() * nChars; } Size ScAccessibleCsvCell::implGetRealSize() const { ScCsvGrid& rGrid = implGetGrid(); return Size( (mnColumn == CSV_COLUMN_HEADER) ? rGrid.GetHdrWidth() : implCalcPixelWidth( rGrid.GetColumnWidth( mnColumn ) ), (mnLine == CSV_LINE_HEADER) ? rGrid.GetHdrHeight() : rGrid.GetLineHeight() ); } css::awt::Rectangle ScAccessibleCsvCell::implGetBounds() { ScCsvGrid& rGrid = implGetGrid(); tools::Rectangle aClipRect( Point( 0, 0 ), rGrid.GetOutputSizePixel() ); if( mnColumn != CSV_COLUMN_HEADER ) { aClipRect.SetLeft( rGrid.GetFirstX() ); aClipRect.SetRight( rGrid.GetLastX() ); } if( mnLine != CSV_LINE_HEADER ) aClipRect.SetTop( rGrid.GetHdrHeight() ); tools::Rectangle aRect( implGetRealPos(), implGetRealSize() ); aRect.Intersection( aClipRect ); if( aRect.IsEmpty() ) aRect.SetSize( Size( -1, -1 ) ); return css::awt::Rectangle(aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight()); } ::std::unique_ptr< SvxEditSource > ScAccessibleCsvCell::implCreateEditSource() { ScCsvGrid& rGrid = implGetGrid(); ::std::unique_ptr< SvxEditSource > pEditSource( new ScAccessibilityEditSource( std::make_unique(&rGrid.GetDrawingArea()->get_ref_device(), rGrid.GetEditEngine(), maCellText, implGetRealSize()) ) ); return pEditSource; } css::uno::Reference SAL_CALL ScAccessibleCsvCell::getAccessibleParent() { ScCsvGrid& rGrid = implGetGrid(); ScAccessibleCsvGrid* pAcc = static_cast(rGrid.GetAccessible()); return pAcc; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */