diff options
Diffstat (limited to 'sc/source/ui/Accessibility/AccessibleCsvControl.cxx')
-rw-r--r-- | sc/source/ui/Accessibility/AccessibleCsvControl.cxx | 1680 |
1 files changed, 1680 insertions, 0 deletions
diff --git a/sc/source/ui/Accessibility/AccessibleCsvControl.cxx b/sc/source/ui/Accessibility/AccessibleCsvControl.cxx new file mode 100644 index 000000000000..e99bd1971e4c --- /dev/null +++ b/sc/source/ui/Accessibility/AccessibleCsvControl.cxx @@ -0,0 +1,1680 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// ============================================================================ +#include "AccessibleCsvControl.hxx" +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_ +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +#endif +#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#endif +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp> +#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp> +#include <tools/debug.hxx> +#include <rtl/uuid.h> +#include <toolkit/helper/convert.hxx> +#include <unotools/accessiblerelationsethelper.hxx> +#ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX +#include <unotools/accessiblestatesethelper.hxx> +#endif +#include <comphelper/sequence.hxx> +#include "scitems.hxx" +#include <editeng/fontitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/langitem.hxx> +#include "csvcontrol.hxx" +#include "csvruler.hxx" +#include "csvgrid.hxx" +#include "AccessibleText.hxx" +#include "editsrc.hxx" +#include "unoguard.hxx" +#include "scresid.hxx" +#include "sc.hrc" +#include "scmod.hxx" +#include <svtools/colorcfg.hxx> +// ause +#include "editutil.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +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::DisposedException; +using ::com::sun::star::lang::IndexOutOfBoundsException; +using ::com::sun::star::lang::IllegalArgumentException; +using ::com::sun::star::beans::PropertyValue; +using namespace ::com::sun::star::accessibility; + + +// ---------------------------------------------------------------------------- + +const sal_uInt16 nRulerRole = AccessibleRole::TEXT; +const sal_uInt16 nGridRole = AccessibleRole::TABLE; +const sal_uInt16 nCellRole = AccessibleRole::TEXT; + +#define CREATE_OUSTRING( name ) OUString( RTL_CONSTASCII_USTRINGPARAM( name ) ) + +#define RULER_IMPL_NAME "ScAccessibleCsvRuler" +#define GRID_IMPL_NAME "ScAccessibleCsvGrid" +#define CELL_IMPL_NAME "ScAccessibleCsvCell" + +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; + + +// CSV base control =========================================================== + +DBG_NAME( ScAccessibleCsvControl ) + +ScAccessibleCsvControl::ScAccessibleCsvControl( + const Reference< XAccessible >& rxParent, + ScCsvControl& rControl, + sal_uInt16 nRole ) : + ScAccessibleContextBase( rxParent, nRole ), + mpControl( &rControl ) +{ + DBG_CTOR( ScAccessibleCsvControl, NULL ); +} + +ScAccessibleCsvControl::~ScAccessibleCsvControl() +{ + DBG_DTOR( ScAccessibleCsvControl, NULL ); + implDispose(); +} + +void SAL_CALL ScAccessibleCsvControl::disposing() +{ + ScUnoGuard aGuard; + mpControl = NULL; + ScAccessibleContextBase::disposing(); +} + + +// XAccessibleComponent ------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ScAccessibleCsvControl::getAccessibleAtPoint( const AwtPoint& /* rPoint */ ) + throw( RuntimeException ) +{ + ensureAlive(); + return NULL; +} + +sal_Bool SAL_CALL ScAccessibleCsvControl::isVisible() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetControl().IsVisible(); +} + +void SAL_CALL ScAccessibleCsvControl::grabFocus() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + implGetControl().GrabFocus(); +} + + +// events --------------------------------------------------------------------- + +void ScAccessibleCsvControl::SendFocusEvent( bool bFocused ) +{ + if( bFocused ) + CommitFocusGained(); + else + CommitFocusLost(); +} + +void ScAccessibleCsvControl::SendCaretEvent() +{ + DBG_ERRORFILE( "ScAccessibleCsvControl::SendCaretEvent - Illegal call" ); +} + +void ScAccessibleCsvControl::SendVisibleEvent() +{ + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + CommitChange( aEvent ); +} + +void ScAccessibleCsvControl::SendSelectionEvent() +{ + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + CommitChange( aEvent ); +} + +void ScAccessibleCsvControl::SendTableUpdateEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */, bool /* bAllRows */ ) +{ + DBG_ERRORFILE( "ScAccessibleCsvControl::SendTableUpdateEvent - Illegal call" ); +} + +void ScAccessibleCsvControl::SendInsertColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ ) +{ + DBG_ERRORFILE( "ScAccessibleCsvControl::SendInsertColumnEvent - Illegal call" ); +} + +void ScAccessibleCsvControl::SendRemoveColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ ) +{ + DBG_ERRORFILE( "ScAccessibleCsvControl::SendRemoveColumnEvent - Illegal call" ); +} + + +// helpers -------------------------------------------------------------------- + +Rectangle ScAccessibleCsvControl::GetBoundingBoxOnScreen() const throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetControl().GetWindowExtentsRelative( NULL ); +} + +Rectangle ScAccessibleCsvControl::GetBoundingBox() const throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetControl().GetWindowExtentsRelative( implGetControl().GetAccessibleParentWindow() ); +} + +void ScAccessibleCsvControl::getUuid( Sequence< sal_Int8 >& rSeq ) +{ + ScUnoGuard aGuard; + ensureAlive(); + if( !rSeq.hasElements() ) + { + rSeq.realloc( 16 ); + rtl_createUuid( reinterpret_cast< sal_uInt8* >( rSeq.getArray() ), NULL, sal_True ); + } +} + +void ScAccessibleCsvControl::ensureAlive() const throw( DisposedException ) +{ + if( !implIsAlive() ) + throw DisposedException(); +} + +ScCsvControl& ScAccessibleCsvControl::implGetControl() const +{ + DBG_ASSERT( mpControl, "ScAccessibleCsvControl::implGetControl - missing control" ); + return *mpControl; +} + +Reference< XAccessible > ScAccessibleCsvControl::implGetChildByRole( + const Reference< XAccessible >& rxParentObj, sal_uInt16 nRole ) throw( RuntimeException ) +{ + Reference< XAccessible > xAccObj; + if( rxParentObj.is() ) + { + Reference< XAccessibleContext > xParentCtxt = rxParentObj->getAccessibleContext(); + if( xParentCtxt.is() ) + { + sal_Int32 nCount = xParentCtxt->getAccessibleChildCount(); + sal_Int32 nIndex = 0; + while( !xAccObj.is() && (nIndex < nCount) ) + { + Reference< XAccessible > xCurrObj = xParentCtxt->getAccessibleChild( nIndex ); + if( xCurrObj.is() ) + { + Reference< XAccessibleContext > xCurrCtxt = xCurrObj->getAccessibleContext(); + if( xCurrCtxt.is() && (xCurrCtxt->getAccessibleRole() == nRole) ) + xAccObj = xCurrObj; + } + ++nIndex; + } + } + } + return xAccObj; +} + +AccessibleStateSetHelper* ScAccessibleCsvControl::implCreateStateSet() +{ + ScUnoGuard aGuard; + AccessibleStateSetHelper* pStateSet = new AccessibleStateSetHelper(); + if( implIsAlive() ) + { + const ScCsvControl& rCtrl = implGetControl(); + pStateSet->AddState( AccessibleStateType::OPAQUE ); + if( rCtrl.IsEnabled() ) + pStateSet->AddState( AccessibleStateType::ENABLED ); + if( isShowing() ) + pStateSet->AddState( AccessibleStateType::SHOWING ); + if( isVisible() ) + pStateSet->AddState( AccessibleStateType::VISIBLE ); + } + else + pStateSet->AddState( AccessibleStateType::DEFUNC ); + return pStateSet; +} + +void ScAccessibleCsvControl::implDispose() +{ + if( implIsAlive() ) + { + // prevent multiple call of dtor + osl_incrementInterlockedCount( &m_refCount ); + dispose(); + } +} + +Point ScAccessibleCsvControl::implGetAbsPos( const Point& rPos ) const +{ + return rPos + implGetControl().GetWindowExtentsRelative( NULL ).TopLeft(); +} + + +// Ruler ====================================================================== + +/** Converts a ruler cursor position to API text index. */ +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<sal_Int32>(0) ); +} + +/** Converts an API text index to a ruler cursor position. */ +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 + 10L, 0L ); +} + +/** Expands the sequence's size and returns the base index of the new inserted elements. */ +inline sal_Int32 lcl_ExpandSequence( Sequence< PropertyValue >& rSeq, sal_Int32 nExp ) +{ + DBG_ASSERT( 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. */ +inline 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. */ +void lcl_FillFontAttributes( Sequence< PropertyValue >& rSeq, const Font& rFont ) +{ + SvxFontItem aFontItem( rFont.GetFamily(), rFont.GetName(), rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), ATTR_FONT ); + SvxFontHeightItem aHeightItem( rFont.GetSize().Height(), 100, ATTR_FONT_HEIGHT ); + SvxLanguageItem aLangItem( rFont.GetLanguage(), ATTR_FONT_LANGUAGE ); + + sal_Int32 nIndex = lcl_ExpandSequence( rSeq, 7 ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontName" ), aFontItem, MID_FONT_FAMILY_NAME ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontFamily" ), aFontItem, MID_FONT_FAMILY ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontStyleName" ), aFontItem, MID_FONT_STYLE_NAME ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontCharSet" ), aFontItem, MID_FONT_PITCH ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontPitch" ), aFontItem, MID_FONT_CHAR_SET ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharHeight" ), aHeightItem, MID_FONTHEIGHT ); + lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharLocale" ), aLangItem, MID_LANG_LOCALE ); +} + + + +// ---------------------------------------------------------------------------- + +DBG_NAME( ScAccessibleCsvRuler ) + +ScAccessibleCsvRuler::ScAccessibleCsvRuler( ScCsvRuler& rRuler ) : + ScAccessibleCsvControl( rRuler.GetAccessibleParentWindow()->GetAccessible(), rRuler, nRulerRole ) +{ + DBG_CTOR( ScAccessibleCsvRuler, NULL ); + constructStringBuffer(); +} + +ScAccessibleCsvRuler::~ScAccessibleCsvRuler() +{ + DBG_DTOR( ScAccessibleCsvRuler, NULL ); + implDispose(); +} + +// XAccessibleComponent ----------------------------------------------------- + +sal_Int32 SAL_CALL ScAccessibleCsvRuler::getForeground( ) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetRuler().GetSettings().GetStyleSettings().GetLabelTextColor().GetColor(); +} + +sal_Int32 SAL_CALL ScAccessibleCsvRuler::getBackground( ) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetRuler().GetSettings().GetStyleSettings().GetFaceColor().GetColor(); +} + +// XAccessibleContext --------------------------------------------------------- + +sal_Int32 SAL_CALL ScAccessibleCsvRuler::getAccessibleChildCount() throw( RuntimeException ) +{ + ensureAlive(); + return 0; +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvRuler::getAccessibleChild( sal_Int32 /* nIndex */ ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ensureAlive(); + throw IndexOutOfBoundsException(); +} + +Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleRelationSet() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + AccessibleRelationSetHelper* pRelationSet = new AccessibleRelationSetHelper(); + Reference< XAccessible > xAccObj = implGetChildByRole( getAccessibleParent(), nGridRole ); + if( xAccObj.is() ) + { + Sequence< Reference< XInterface > > aSeq( 1 ); + aSeq[ 0 ] = xAccObj; + pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLER_FOR, aSeq ) ); + } + return pRelationSet; +} + +Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleStateSet() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + AccessibleStateSetHelper* pStateSet = implCreateStateSet(); + if( implIsAlive() ) + { + 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() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return lcl_GetApiPos( implGetRuler().GetRulerCursorPos() ); +} + +sal_Bool SAL_CALL ScAccessibleCsvRuler::setCaretPosition( sal_Int32 nIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard 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 ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndex( nIndex ); + return maBuffer.charAt( nIndex ); +} + +Sequence< PropertyValue > SAL_CALL ScAccessibleCsvRuler::getCharacterAttributes( sal_Int32 nIndex, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& /* aRequestedAttributes */ ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndexWithEnd( nIndex ); + Sequence< PropertyValue > aSeq; + lcl_FillFontAttributes( aSeq, implGetRuler().GetFont() ); +//! TODO split attribute: waiting for #102221# +// if( implHasSplit( nIndex ) ) +// { +// sal_Int32 nIndex = lcl_ExpandSequence( aSeq, 1 ); +// aSeq[ nIndex ].Name = CREATE_OUSTRING( "..." ); +// aSeq[ nIndex ].Value <<= ...; +// } + return aSeq; +} + +ScAccessibleCsvRuler::AwtRectangle SAL_CALL ScAccessibleCsvRuler::getCharacterBounds( sal_Int32 nIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndexWithEnd( nIndex ); + ScCsvRuler& rRuler = implGetRuler(); + Point aPos( rRuler.GetX( lcl_GetRulerPos( nIndex ) ) - rRuler.GetCharWidth() / 2, 0 ); + AwtRectangle aRect( aPos.X(), aPos.Y(), rRuler.GetCharWidth(), rRuler.GetSizePixel().Height() ); + // #107054# 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() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetTextLength(); +} + +sal_Int32 SAL_CALL ScAccessibleCsvRuler::getIndexAtPoint( const AwtPoint& rPoint ) + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ScCsvRuler& rRuler = implGetRuler(); + // #107054# use object's coordinate system, convert to API position + return lcl_GetApiPos( ::std::min( ::std::max( rRuler.GetPosFromX( rPoint.X ), static_cast<sal_Int32>(0) ), rRuler.GetPosCount() ) ); +} + +OUString SAL_CALL ScAccessibleCsvRuler::getSelectedText() throw( RuntimeException ) +{ + ensureAlive(); + return OUString(); +} + +sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionStart() throw( RuntimeException ) +{ + ensureAlive(); + return -1; +} + +sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionEnd() throw( RuntimeException ) +{ + ensureAlive(); + return -1; +} + +sal_Bool SAL_CALL ScAccessibleCsvRuler::setSelection( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ensureAlive(); + return sal_False; +} + +OUString SAL_CALL ScAccessibleCsvRuler::getText() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return OUString( maBuffer.getStr(), implGetTextLength() ); +} + +OUString SAL_CALL ScAccessibleCsvRuler::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidRange( nStartIndex, nEndIndex ); + return OUString( maBuffer.getStr() + nStartIndex, nEndIndex - nStartIndex ); +} + +TextSegment SAL_CALL ScAccessibleCsvRuler::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) + throw( IndexOutOfBoundsException, IllegalArgumentException, RuntimeException ) +{ + ScUnoGuard 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.charAt( nIndex ) ); + } + break; + + // entire number or single dot/line + case AccessibleTextType::WORD: + case AccessibleTextType::GLYPH: + aResult.SegmentStart = nIndex; + if( nRulerPos % 10 ) + aResultText.append( maBuffer.charAt( 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 ) + throw( IndexOutOfBoundsException, IllegalArgumentException, RuntimeException ) +{ + ScUnoGuard 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 ) + throw( IndexOutOfBoundsException, IllegalArgumentException, RuntimeException ) +{ + ScUnoGuard 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 */ ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ensureAlive(); + return sal_False; +} + + +// XInterface ----------------------------------------------------------------- + +Any SAL_CALL ScAccessibleCsvRuler::queryInterface( const ::com::sun::star::uno::Type& rType ) + throw( RuntimeException ) +{ + Any aAny( ScAccessibleCsvRulerImpl::queryInterface( rType ) ); + return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType ); +} + +void SAL_CALL ScAccessibleCsvRuler::acquire() throw () +{ + ScAccessibleCsvControl::acquire(); +} + +void SAL_CALL ScAccessibleCsvRuler::release() throw () +{ + ScAccessibleCsvControl::release(); +} + + +// XServiceInfo --------------------------------------------------------------- + +OUString SAL_CALL ScAccessibleCsvRuler::getImplementationName() throw( RuntimeException ) +{ + return CREATE_OUSTRING( RULER_IMPL_NAME ); +} + + +// XTypeProvider -------------------------------------------------------------- + +Sequence< ::com::sun::star::uno::Type > SAL_CALL ScAccessibleCsvRuler::getTypes() throw( RuntimeException ) +{ + Sequence< ::com::sun::star::uno::Type > aSeq( 1 ); + aSeq[ 0 ] = getCppuType( static_cast< const Reference< XAccessibleText >* >( NULL ) ); + return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), aSeq ); +} + +Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvRuler::getImplementationId() throw( RuntimeException ) +{ + static Sequence< sal_Int8 > aSeq; + getUuid( aSeq ); + return aSeq; +} + + +// events --------------------------------------------------------------------- + +void ScAccessibleCsvRuler::SendCaretEvent() +{ + sal_Int32 nPos = implGetRuler().GetRulerCursorPos(); + if( nPos != CSV_POS_INVALID ) + { + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::CARET_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + aEvent.NewValue <<= nPos; + CommitChange( aEvent ); + } +} + + +// helpers -------------------------------------------------------------------- + +OUString SAL_CALL ScAccessibleCsvRuler::createAccessibleName() throw( RuntimeException ) +{ + return String( ScResId( STR_ACC_CSVRULER_NAME ) ); +} + +OUString SAL_CALL ScAccessibleCsvRuler::createAccessibleDescription() throw( RuntimeException ) +{ + return String( ScResId( STR_ACC_CSVRULER_DESCR ) ); +} + +void ScAccessibleCsvRuler::ensureValidIndex( sal_Int32 nIndex ) const + throw( IndexOutOfBoundsException ) +{ + if( (nIndex < 0) || (nIndex >= implGetTextLength()) ) + throw IndexOutOfBoundsException(); +} + +void ScAccessibleCsvRuler::ensureValidIndexWithEnd( sal_Int32 nIndex ) const + throw( IndexOutOfBoundsException ) +{ + if( (nIndex < 0) || (nIndex > implGetTextLength()) ) + throw IndexOutOfBoundsException(); +} + +void ScAccessibleCsvRuler::ensureValidRange( sal_Int32& rnStartIndex, sal_Int32& rnEndIndex ) const + throw( IndexOutOfBoundsException ) +{ + 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() throw( RuntimeException ) +{ + ScUnoGuard 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; +} + + +// Grid ======================================================================= + +/** Converts a grid columnm index to an API column index. */ +inline 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. */ +inline sal_uInt32 lcl_GetGridColumn( sal_Int32 nApiColumn ) +{ + return (nApiColumn > 0) ? static_cast< sal_uInt32 >( nApiColumn - 1 ) : CSV_COLUMN_HEADER; +} + + +// ---------------------------------------------------------------------------- + +DBG_NAME( ScAccessibleCsvGrid ) + +ScAccessibleCsvGrid::ScAccessibleCsvGrid( ScCsvGrid& rGrid ) : + ScAccessibleCsvControl( rGrid.GetAccessibleParentWindow()->GetAccessible(), rGrid, nGridRole ) +{ + DBG_CTOR( ScAccessibleCsvGrid, NULL ); +} + +ScAccessibleCsvGrid::~ScAccessibleCsvGrid() +{ + DBG_DTOR( ScAccessibleCsvGrid, NULL ); + implDispose(); +} + + +// XAccessibleComponent ------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleAtPoint( const AwtPoint& rPoint ) + throw( RuntimeException ) +{ + Reference< XAccessible > xRet; + if( containsPoint( rPoint ) ) + { + ScUnoGuard 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 = implCreateCellObj( nRow, nColumn ); + } + return xRet; +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getForeground( ) +throw (RuntimeException) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetGrid().GetSettings().GetStyleSettings().GetButtonTextColor().GetColor(); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getBackground( ) +throw (RuntimeException) +{ + ScUnoGuard aGuard; + ensureAlive(); + return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor; +} + +// XAccessibleContext --------------------------------------------------------- + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleChildCount() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetCellCount(); +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleChild( sal_Int32 nIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndex( nIndex ); + return implCreateCellObj( implGetRow( nIndex ), implGetColumn( nIndex ) ); +} + +Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleRelationSet() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + AccessibleRelationSetHelper* pRelationSet = new AccessibleRelationSetHelper(); + Reference< XAccessible > xAccObj = implGetChildByRole( getAccessibleParent(), nRulerRole ); + if( xAccObj.is() ) + { + Sequence< Reference< XInterface > > aSeq( 1 ); + aSeq[ 0 ] = xAccObj; + pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLED_BY, aSeq ) ); + } + return pRelationSet; +} + +Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleStateSet() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + AccessibleStateSetHelper* pStateSet = implCreateStateSet(); + if( implIsAlive() ) + { + 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() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetRowCount(); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnCount() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetColumnCount(); +} + +OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleRowDescription( sal_Int32 nRow ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidPosition( nRow, 0 ); + return implGetCellText( nRow, 0 ); +} + +OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnDescription( sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidPosition( 0, nColumn ); + return implGetCellText( 0, nColumn ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ensureAlive(); + ensureValidPosition( nRow, nColumn ); + return 1; +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ensureAlive(); + ensureValidPosition( nRow, nColumn ); + return 1; +} + +Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleRowHeaders() + throw( RuntimeException ) +{ + ensureAlive(); + return NULL; +} + +Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnHeaders() + throw( RuntimeException ) +{ + ensureAlive(); + return NULL; +} + +Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleRows() + throw( RuntimeException ) +{ + ensureAlive(); + return Sequence< sal_Int32 >(); +} + +Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleColumns() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + + ScCsvGrid& rGrid = implGetGrid(); + Sequence< sal_Int32 > aSeq( implGetColumnCount() ); + + sal_Int32 nSeqIx = 0; + sal_uInt32 nColIx = rGrid.GetFirstSelected(); + for( ; nColIx != CSV_COLUMN_INVALID; ++nSeqIx, nColIx = rGrid.GetNextSelected( nColIx ) ) + aSeq[ nSeqIx ] = lcl_GetApiColumn( nColIx ); + + aSeq.realloc( nSeqIx ); + return aSeq; +} + +sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleRowSelected( sal_Int32 /* nRow */ ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ensureAlive(); + return sal_False; +} + +sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleColumnSelected( sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndex( nColumn ); + return implIsColumnSelected( nColumn ); +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidPosition( nRow, nColumn ); + return implCreateCellObj( nRow, nColumn ); +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCaption() + throw( RuntimeException ) +{ + ensureAlive(); + return NULL; +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleSummary() + throw( RuntimeException ) +{ + ensureAlive(); + return NULL; +} + +sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleSelected( sal_Int32 /* nRow */, sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + return isAccessibleColumnSelected( nColumn ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidPosition( nRow, nColumn ); + return implGetIndex( nRow, nColumn ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRow( sal_Int32 nChildIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndex( nChildIndex ); + return implGetRow( nChildIndex ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumn( sal_Int32 nChildIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndex( nChildIndex ); + return implGetColumn( nChildIndex ); +} + + +// XAccessibleSelection ------------------------------------------------------- + +void SAL_CALL ScAccessibleCsvGrid::selectAccessibleChild( sal_Int32 nChildIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard 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 ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ensureValidIndex( nChildIndex ); + sal_Int32 nColumn = implGetColumn( nChildIndex ); + return implIsColumnSelected( nColumn ); +} + +void SAL_CALL ScAccessibleCsvGrid::clearAccessibleSelection() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + implGetGrid().SelectAll( false ); +} + +void SAL_CALL ScAccessibleCsvGrid::selectAllAccessibleChildren() throw( RuntimeException ) +{ + selectAccessibleChild( 0 ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChildCount() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetRowCount() * implGetSelColumnCount(); +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard 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 ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + ScUnoGuard 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 ::com::sun::star::uno::Type& rType ) + throw( RuntimeException ) +{ + Any aAny( ScAccessibleCsvGridImpl::queryInterface( rType ) ); + return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType ); +} + +void SAL_CALL ScAccessibleCsvGrid::acquire() throw () +{ + ScAccessibleCsvControl::acquire(); +} + +void SAL_CALL ScAccessibleCsvGrid::release() throw () +{ + ScAccessibleCsvControl::release(); +} + + +// XServiceInfo --------------------------------------------------------------- + +OUString SAL_CALL ScAccessibleCsvGrid::getImplementationName() throw( RuntimeException ) +{ + return CREATE_OUSTRING( GRID_IMPL_NAME ); +} + + +// XTypeProvider -------------------------------------------------------------- + +Sequence< ::com::sun::star::uno::Type > SAL_CALL ScAccessibleCsvGrid::getTypes() throw( RuntimeException ) +{ + Sequence< ::com::sun::star::uno::Type > aSeq( 2 ); + aSeq[ 0 ] = getCppuType( static_cast< const Reference< XAccessibleTable >* >( NULL ) ); + aSeq[ 1 ] = getCppuType( static_cast< const Reference< XAccessibleSelection >* >( NULL ) ); + return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), aSeq ); +} + +Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvGrid::getImplementationId() throw( RuntimeException ) +{ + static Sequence< sal_Int8 > aSeq; + getUuid( aSeq ); + return aSeq; +} + + +// events --------------------------------------------------------------------- + +void ScAccessibleCsvGrid::SendFocusEvent( bool bFocused ) +{ + ScAccessibleCsvControl::SendFocusEvent( bFocused ); + + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + (bFocused ? aEvent.NewValue : aEvent.OldValue) <<= + getAccessibleCellAt( 0, lcl_GetApiColumn( implGetGrid().GetFocusColumn() ) ); + CommitChange( aEvent ); +} + +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 ) ); + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + aEvent.NewValue <<= aModelChange; + CommitChange( aEvent ); + } +} + +void ScAccessibleCsvGrid::SendInsertColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn ) +{ + if( nFirstColumn <= nLastColumn ) + { + AccessibleTableModelChange aModelChange( + AccessibleTableModelChangeType::INSERT, 0, implGetRowCount() - 1, + lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + aEvent.NewValue <<= aModelChange; + CommitChange( aEvent ); + } +} + +void ScAccessibleCsvGrid::SendRemoveColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn ) +{ + if( nFirstColumn <= nLastColumn ) + { + AccessibleTableModelChange aModelChange( + AccessibleTableModelChangeType::DELETE, 0, implGetRowCount() - 1, + lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED; + aEvent.Source = Reference< XAccessible >( this ); + aEvent.NewValue <<= aModelChange; + CommitChange( aEvent ); + } +} + + +// helpers -------------------------------------------------------------------- + +OUString SAL_CALL ScAccessibleCsvGrid::createAccessibleName() throw( RuntimeException ) +{ + return String( ScResId( STR_ACC_CSVGRID_NAME ) ); +} + +OUString SAL_CALL ScAccessibleCsvGrid::createAccessibleDescription() throw( RuntimeException ) +{ + return String( ScResId( STR_ACC_CSVGRID_DESCR ) ); +} + +void ScAccessibleCsvGrid::ensureValidIndex( sal_Int32 nIndex ) const + throw( IndexOutOfBoundsException ) +{ + if( (nIndex < 0) || (nIndex >= implGetCellCount()) ) + throw IndexOutOfBoundsException(); +} + +void ScAccessibleCsvGrid::ensureValidPosition( sal_Int32 nRow, sal_Int32 nColumn ) const + throw( IndexOutOfBoundsException ) +{ + 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; +} + +String ScAccessibleCsvGrid::implGetCellText( sal_Int32 nRow, sal_Int32 nColumn ) const +{ + ScCsvGrid& rGrid = implGetGrid(); + sal_Int32 nLine = nRow + rGrid.GetFirstVisLine() - 1; + String aCellStr; + if( (nColumn > 0) && (nRow > 0) ) + aCellStr = rGrid.GetCellText( lcl_GetGridColumn( nColumn ), nLine ); + else if( nRow > 0 ) + aCellStr = String::CreateFromInt32( nLine + 1L ); + else if( nColumn > 0 ) + aCellStr = rGrid.GetColumnTypeName( lcl_GetGridColumn( nColumn ) ); + return aCellStr; +} + + +ScAccessibleCsvControl* ScAccessibleCsvGrid::implCreateCellObj( sal_Int32 nRow, sal_Int32 nColumn ) const +{ + return new ScAccessibleCsvCell( implGetGrid(), implGetCellText( nRow, nColumn ), nRow, nColumn ); +} + + +// ============================================================================ + +DBG_NAME( ScAccessibleCsvCell ) + +ScAccessibleCsvCell::ScAccessibleCsvCell( + ScCsvGrid& rGrid, + const String& rCellText, + sal_Int32 nRow, sal_Int32 nColumn ) : + ScAccessibleCsvControl( rGrid.GetAccessible(), rGrid, nCellRole ), + AccessibleStaticTextBase( SvxEditSourcePtr( NULL ) ), + maCellText( rCellText ), + mnLine( nRow ? (nRow + rGrid.GetFirstVisLine() - 1) : CSV_LINE_HEADER ), + mnColumn( lcl_GetGridColumn( nColumn ) ), + mnIndex( nRow * (rGrid.GetColumnCount() + 1) + nColumn ) +{ + DBG_CTOR( ScAccessibleCsvCell, NULL ); + SetEditSource( implCreateEditSource() ); +} + +ScAccessibleCsvCell::~ScAccessibleCsvCell() +{ + DBG_DTOR( ScAccessibleCsvCell, NULL ); +} + +void SAL_CALL ScAccessibleCsvCell::disposing() +{ + ScUnoGuard aGuard; + SetEditSource( SvxEditSourcePtr( NULL ) ); + ScAccessibleCsvControl::disposing(); +} + + +// XAccessibleComponent ------------------------------------------------------- + +void SAL_CALL ScAccessibleCsvCell::grabFocus() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + ScCsvGrid& rGrid = implGetGrid(); + rGrid.Execute( CSVCMD_MOVEGRIDCURSOR, rGrid.GetColumnPos( mnColumn ) ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvCell::getForeground( ) +throw (RuntimeException) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetGrid().GetSettings().GetStyleSettings().GetButtonTextColor().GetColor(); +} + +sal_Int32 SAL_CALL ScAccessibleCsvCell::getBackground( ) +throw (RuntimeException) +{ + ScUnoGuard aGuard; + ensureAlive(); + return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor; +} + +// XAccessibleContext ----------------------------------------------------- + +sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleChildCount() throw( RuntimeException ) +{ + return AccessibleStaticTextBase::getAccessibleChildCount(); +} + +Reference< XAccessible > SAL_CALL ScAccessibleCsvCell::getAccessibleChild( sal_Int32 nIndex ) + throw( IndexOutOfBoundsException, RuntimeException ) +{ + return AccessibleStaticTextBase::getAccessibleChild( nIndex ); +} + +sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleIndexInParent() throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return mnIndex; +} + +Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvCell::getAccessibleRelationSet() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return new AccessibleRelationSetHelper(); +} + +Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvCell::getAccessibleStateSet() + throw( RuntimeException ) +{ + ScUnoGuard aGuard; + AccessibleStateSetHelper* pStateSet = implCreateStateSet(); + if( implIsAlive() ) + { + 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 ) + +// XServiceInfo --------------------------------------------------------------- + +OUString SAL_CALL ScAccessibleCsvCell::getImplementationName() throw( RuntimeException ) +{ + return CREATE_OUSTRING( CELL_IMPL_NAME ); +} + +// helpers -------------------------------------------------------------------- + +Rectangle ScAccessibleCsvCell::GetBoundingBoxOnScreen() const throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + Rectangle aRect( implGetBoundingBox() ); + aRect.SetPos( implGetAbsPos( aRect.TopLeft() ) ); + return aRect; +} + +Rectangle ScAccessibleCsvCell::GetBoundingBox() const throw( RuntimeException ) +{ + ScUnoGuard aGuard; + ensureAlive(); + return implGetBoundingBox(); +} + +OUString SAL_CALL ScAccessibleCsvCell::createAccessibleName() throw( RuntimeException ) +{ + return maCellText; +} + +OUString SAL_CALL ScAccessibleCsvCell::createAccessibleDescription() throw( RuntimeException ) +{ + 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() ); +} + +Rectangle ScAccessibleCsvCell::implGetBoundingBox() const +{ + ScCsvGrid& rGrid = implGetGrid(); + Rectangle aClipRect( Point( 0, 0 ), rGrid.GetSizePixel() ); + if( mnColumn != CSV_COLUMN_HEADER ) + { + aClipRect.Left() = rGrid.GetFirstX(); + aClipRect.Right() = rGrid.GetLastX(); + } + if( mnLine != CSV_LINE_HEADER ) + aClipRect.Top() = rGrid.GetHdrHeight(); + + Rectangle aRect( implGetRealPos(), implGetRealSize() ); + aRect.Intersection( aClipRect ); + if( (aRect.GetWidth() <= 0) || (aRect.GetHeight() <= 0) ) + aRect.SetSize( Size( -1, -1 ) ); + return aRect; +} + +::std::auto_ptr< SvxEditSource > ScAccessibleCsvCell::implCreateEditSource() +{ + ScCsvGrid& rGrid = implGetGrid(); + Rectangle aBoundRect( implGetBoundingBox() ); + aBoundRect -= implGetRealPos(); + + ::std::auto_ptr< ScAccessibleTextData > pCsvTextData( new ScAccessibleCsvTextData( + &rGrid, rGrid.GetEditEngine(), maCellText, aBoundRect, implGetRealSize() ) ); + + ::std::auto_ptr< SvxEditSource > pEditSource( new ScAccessibilityEditSource( pCsvTextData ) ); + return pEditSource; +} + + +// ============================================================================ + |