blob: fa3af41d42eeec8c591fa3b564f77945f1b6d6b7 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// ============================================================================
#include "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;
}
// ============================================================================