summaryrefslogtreecommitdiff
path: root/svtools/source
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source')
-rw-r--r--[-rwxr-xr-x]svtools/source/table/cellvalueconversion.cxx455
-rw-r--r--[-rwxr-xr-x]svtools/source/table/cellvalueconversion.hxx16
-rw-r--r--svtools/source/table/gridtablerenderer.cxx69
-rw-r--r--[-rwxr-xr-x]svtools/source/table/mousefunction.cxx19
-rw-r--r--svtools/source/table/tablecontrol.cxx169
-rw-r--r--[-rwxr-xr-x]svtools/source/table/tablecontrol_impl.cxx822
-rw-r--r--[-rwxr-xr-x]svtools/source/table/tablecontrol_impl.hxx65
-rw-r--r--svtools/source/table/tabledatawindow.cxx13
-rw-r--r--svtools/source/table/tabledatawindow.hxx6
-rw-r--r--svtools/source/toolpanel/drawerlayouter.cxx4
-rw-r--r--svtools/source/uno/svtxgridcontrol.cxx263
-rwxr-xr-xsvtools/source/uno/svtxgridcontrol.hxx43
-rw-r--r--svtools/source/uno/unocontroltablemodel.cxx98
-rw-r--r--svtools/source/uno/unocontroltablemodel.hxx8
14 files changed, 1486 insertions, 564 deletions
diff --git a/svtools/source/table/cellvalueconversion.cxx b/svtools/source/table/cellvalueconversion.cxx
index 286ca505bb30..18e28c2cdc82 100755..100644
--- a/svtools/source/table/cellvalueconversion.cxx
+++ b/svtools/source/table/cellvalueconversion.cxx
@@ -29,8 +29,27 @@
#include "cellvalueconversion.hxx"
/** === begin UNO includes === **/
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
/** === end UNO includes === **/
+#include <comphelper/componentcontext.hxx>
+#include <rtl/math.hxx>
+#include <rtl/strbuf.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/syslocale.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <hash_map>
+
//......................................................................................................................
namespace svt
{
@@ -38,36 +57,432 @@ namespace svt
/** === begin UNO using === **/
using ::com::sun::star::uno::Any;
+ using ::com::sun::star::util::XNumberFormatter;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::util::DateTime;
+ using ::com::sun::star::uno::TypeClass;
+ using ::com::sun::star::util::XNumberFormatTypes;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::TypeClass_BYTE;
+ using ::com::sun::star::uno::TypeClass_SHORT;
+ using ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT;
+ using ::com::sun::star::uno::TypeClass_LONG;
+ using ::com::sun::star::uno::TypeClass_UNSIGNED_LONG;
+ using ::com::sun::star::uno::TypeClass_HYPER;
/** === end UNO using === **/
+ namespace NumberFormat = ::com::sun::star::util::NumberFormat;
+
+ typedef ::com::sun::star::util::Time UnoTime;
+ typedef ::com::sun::star::util::Date UnoDate;
//==================================================================================================================
- //= CellValueConversion
+ //= helper
//==================================================================================================================
- //------------------------------------------------------------------------------------------------------------------
- ::rtl::OUString CellValueConversion::convertToString( const Any& i_value )
+ namespace
{
- ::rtl::OUString sConvertString;
- if ( !i_value.hasValue() )
- return sConvertString;
+ //--------------------------------------------------------------------------------------------------------------
+ double lcl_convertDateToDays( long const i_day, long const i_month, long const i_year )
+ {
+ long const nNullDateDays = ::Date::DateToDays( 1, 1, 1900 );
+ long const nValueDateDays = ::Date::DateToDays( i_day, i_month, i_year );
+
+ return nValueDateDays - nNullDateDays;
+ }
+
+ //--------------------------------------------------------------------------------------------------------------
+ double lcl_convertTimeToDays( long const i_hours, long const i_minutes, long const i_seconds, long const i_100thSeconds )
+ {
+ return Time( i_hours, i_minutes, i_seconds, i_100thSeconds ).GetTimeInDays();
+ }
+ }
+
+ //==================================================================================================================
+ //= IValueNormalization
+ //==================================================================================================================
+ class SAL_NO_VTABLE IValueNormalization
+ {
+ public:
+ virtual ~IValueNormalization() { }
+
+ /** converts the given <code>Any</code> into a <code>double</code> value to be fed into a number formatter
+ */
+ virtual double convertToDouble( Any const & i_value ) const = 0;
+
+ /** returns the format key to be used for formatting values
+ */
+ virtual ::sal_Int32 getFormatKey() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< IValueNormalization > PValueNormalization;
+ typedef ::std::hash_map< ::rtl::OUString, PValueNormalization, ::rtl::OUStringHash > NormalizerCache;
+
+ //==================================================================================================================
+ //= CellValueConversion_Data
+ //==================================================================================================================
+ struct CellValueConversion_Data
+ {
+ ::comphelper::ComponentContext const aContext;
+ Reference< XNumberFormatter > xNumberFormatter;
+ bool bAttemptedFormatterCreation;
+ NormalizerCache aNormalizers;
+
+ CellValueConversion_Data( ::comphelper::ComponentContext const & i_context )
+ :aContext( i_context )
+ ,xNumberFormatter()
+ ,bAttemptedFormatterCreation( false )
+ ,aNormalizers()
+ {
+ }
+ };
+
+ //==================================================================================================================
+ //= StandardFormatNormalizer
+ //==================================================================================================================
+ class StandardFormatNormalizer : public IValueNormalization
+ {
+ protected:
+ StandardFormatNormalizer( Reference< XNumberFormatter > const & i_formatter, ::sal_Int32 const i_numberFormatType )
+ :m_nFormatKey( 0 )
+ {
+ try
+ {
+ ENSURE_OR_THROW( i_formatter.is(), "StandardFormatNormalizer: no formatter!" );
+ Reference< XNumberFormatsSupplier > const xSupplier( i_formatter->getNumberFormatsSupplier(), UNO_SET_THROW );
+ Reference< XNumberFormatTypes > const xTypes( xSupplier->getNumberFormats(), UNO_QUERY_THROW );
+ m_nFormatKey = xTypes->getStandardFormat( i_numberFormatType, SvtSysLocale().GetLocale() );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ virtual ::sal_Int32 getFormatKey() const
+ {
+ return m_nFormatKey;
+ }
+
+ private:
+ ::sal_Int32 m_nFormatKey;
+ };
+
+ //==================================================================================================================
+ //= DoubleNormalization
+ //==================================================================================================================
+ class DoubleNormalization : public StandardFormatNormalizer
+ {
+ public:
+ DoubleNormalization( Reference< XNumberFormatter > const & i_formatter )
+ :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER )
+ {
+ }
+
+ virtual double convertToDouble( Any const & i_value ) const
+ {
+ double returnValue(0);
+ ::rtl::math::setNan( &returnValue );
+ OSL_VERIFY( i_value >>= returnValue );
+ return returnValue;
+ }
+
+ virtual ~DoubleNormalization() { }
+ };
+
+ //==================================================================================================================
+ //= IntegerNormalization
+ //==================================================================================================================
+ class IntegerNormalization : public StandardFormatNormalizer
+ {
+ public:
+ IntegerNormalization( Reference< XNumberFormatter > const & i_formatter )
+ :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER )
+ {
+ }
+
+ virtual ~IntegerNormalization() {}
+
+ virtual double convertToDouble( Any const & i_value ) const
+ {
+ sal_Int64 value( 0 );
+ OSL_VERIFY( i_value >>= value );
+ return value;
+ }
+ };
+
+ //==================================================================================================================
+ //= BooleanNormalization
+ //==================================================================================================================
+ class BooleanNormalization : public StandardFormatNormalizer
+ {
+ public:
+ BooleanNormalization( Reference< XNumberFormatter > const & i_formatter )
+ :StandardFormatNormalizer( i_formatter, NumberFormat::LOGICAL )
+ {
+ }
+
+ virtual ~BooleanNormalization() {}
+
+ virtual double convertToDouble( Any const & i_value ) const
+ {
+ bool value( false );
+ OSL_VERIFY( i_value >>= value );
+ return value ? 1 : 0;
+ }
+ };
+
+ //==================================================================================================================
+ //= DateTimeNormalization
+ //==================================================================================================================
+ class DateTimeNormalization : public StandardFormatNormalizer
+ {
+ public:
+ DateTimeNormalization( Reference< XNumberFormatter > const & i_formatter )
+ :StandardFormatNormalizer( i_formatter, NumberFormat::DATETIME )
+ {
+ }
+
+ virtual ~DateTimeNormalization() {}
+
+ virtual double convertToDouble( Any const & i_value ) const
+ {
+ double returnValue(0);
+ ::rtl::math::setNan( &returnValue );
+ // extract actual UNO value
+ DateTime aDateTimeValue;
+ ENSURE_OR_RETURN( i_value >>= aDateTimeValue, "allowed for DateTime values only", returnValue );
- // TODO: use css.script.XTypeConverter?
+ // date part
+ returnValue = lcl_convertDateToDays( aDateTimeValue.Day, aDateTimeValue.Month, aDateTimeValue.Year );
- sal_Int32 nInt = 0;
- sal_Bool bBool = false;
- double fDouble = 0;
+ // time part
+ returnValue += lcl_convertTimeToDays(
+ aDateTimeValue.Hours, aDateTimeValue.Minutes, aDateTimeValue.Seconds, aDateTimeValue.HundredthSeconds );
+ // done
+ return returnValue;
+ }
+ };
+
+ //==================================================================================================================
+ //= DateNormalization
+ //==================================================================================================================
+ class DateNormalization : public StandardFormatNormalizer
+ {
+ public:
+ DateNormalization( Reference< XNumberFormatter > const & i_formatter )
+ :StandardFormatNormalizer( i_formatter, NumberFormat::DATE )
+ {
+ }
+
+ virtual ~DateNormalization() {}
+
+ virtual double convertToDouble( Any const & i_value ) const
+ {
+ double returnValue(0);
+ ::rtl::math::setNan( &returnValue );
+
+ // extract
+ UnoDate aDateValue;
+ ENSURE_OR_RETURN( i_value >>= aDateValue, "allowed for Date values only", returnValue );
+
+ // convert
+ returnValue = lcl_convertDateToDays( aDateValue.Day, aDateValue.Month, aDateValue.Year );
+
+ // done
+ return returnValue;
+ }
+ };
+
+ //==================================================================================================================
+ //= TimeNormalization
+ //==================================================================================================================
+ class TimeNormalization : public StandardFormatNormalizer
+ {
+ public:
+ TimeNormalization( Reference< XNumberFormatter > const & i_formatter )
+ :StandardFormatNormalizer( i_formatter, NumberFormat::TIME )
+ {
+ }
+
+ virtual ~TimeNormalization() {}
+
+ virtual double convertToDouble( Any const & i_value ) const
+ {
+ double returnValue(0);
+ ::rtl::math::setNan( &returnValue );
+
+ // extract
+ UnoTime aTimeValue;
+ ENSURE_OR_RETURN( i_value >>= aTimeValue, "allowed for Time values only", returnValue );
+
+ // convert
+ returnValue += lcl_convertTimeToDays(
+ aTimeValue.Hours, aTimeValue.Minutes, aTimeValue.Seconds, aTimeValue.HundredthSeconds );
+
+ // done
+ return returnValue;
+ }
+ };
+
+ //==================================================================================================================
+ //= operations
+ //==================================================================================================================
+ namespace
+ {
+ //--------------------------------------------------------------------------------------------------------------
+ bool lcl_ensureNumberFormatter( CellValueConversion_Data & io_data )
+ {
+ if ( io_data.bAttemptedFormatterCreation )
+ return io_data.xNumberFormatter.is();
+ io_data.bAttemptedFormatterCreation = true;
+
+ try
+ {
+ // a number formatter
+ Reference< XNumberFormatter > const xFormatter(
+ io_data.aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW );
+
+ // a supplier of number formats
+ Sequence< Any > aInitArgs(1);
+ aInitArgs[0] <<= SvtSysLocale().GetLocale();
+
+ Reference< XNumberFormatsSupplier > const xSupplier(
+ io_data.aContext.createComponentWithArguments( "com.sun.star.util.NumberFormatsSupplier", aInitArgs ),
+ UNO_QUERY_THROW
+ );
+
+ // ensure a NullDate we will assume later on
+ UnoDate const aNullDate( 1, 1, 1900 );
+ Reference< XPropertySet > const xFormatSettings( xSupplier->getNumberFormatSettings(), UNO_SET_THROW );
+ xFormatSettings->setPropertyValue( ::rtl::OUString::createFromAscii( "NullDate" ), makeAny( aNullDate ) );
+
+ // knit
+ xFormatter->attachNumberFormatsSupplier( xSupplier );
+
+ // done
+ io_data.xNumberFormatter = xFormatter;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return io_data.xNumberFormatter.is();
+ }
+
+ //--------------------------------------------------------------------------------------------------------------
+ bool lcl_getValueNormalizer( CellValueConversion_Data & io_data, Type const & i_valueType,
+ PValueNormalization & o_formatter )
+ {
+ NormalizerCache::const_iterator pos = io_data.aNormalizers.find( i_valueType.getTypeName() );
+ if ( pos == io_data.aNormalizers.end() )
+ {
+ // never encountered this type before
+ o_formatter.reset();
+
+ ::rtl::OUString const sTypeName( i_valueType.getTypeName() );
+ TypeClass const eTypeClass = i_valueType.getTypeClass();
+
+ if ( sTypeName.equals( ::cppu::UnoType< DateTime >::get().getTypeName() ) )
+ {
+ o_formatter.reset( new DateTimeNormalization( io_data.xNumberFormatter ) );
+ }
+ else if ( sTypeName.equals( ::cppu::UnoType< UnoDate >::get().getTypeName() ) )
+ {
+ o_formatter.reset( new DateNormalization( io_data.xNumberFormatter ) );
+ }
+ else if ( sTypeName.equals( ::cppu::UnoType< UnoTime >::get().getTypeName() ) )
+ {
+ o_formatter.reset( new TimeNormalization( io_data.xNumberFormatter ) );
+ }
+ else if ( sTypeName.equals( ::cppu::UnoType< ::sal_Bool >::get().getTypeName() ) )
+ {
+ o_formatter.reset( new BooleanNormalization( io_data.xNumberFormatter ) );
+ }
+ else if ( sTypeName.equals( ::cppu::UnoType< double >::get().getTypeName() )
+ || sTypeName.equals( ::cppu::UnoType< float >::get().getTypeName() )
+ )
+ {
+ o_formatter.reset( new DoubleNormalization( io_data.xNumberFormatter ) );
+ }
+ else if ( ( eTypeClass == TypeClass_BYTE )
+ || ( eTypeClass == TypeClass_SHORT )
+ || ( eTypeClass == TypeClass_UNSIGNED_SHORT )
+ || ( eTypeClass == TypeClass_LONG )
+ || ( eTypeClass == TypeClass_UNSIGNED_LONG )
+ || ( eTypeClass == TypeClass_HYPER )
+ )
+ {
+ o_formatter.reset( new IntegerNormalization( io_data.xNumberFormatter ) );
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 0
+ ::rtl::OStringBuffer message( "lcl_getValueNormalizer: unsupported type '" );
+ message.append( ::rtl::OUStringToOString( sTypeName, RTL_TEXTENCODING_ASCII_US ) );
+ message.append( "'!" );
+ OSL_ENSURE( false, message.makeStringAndClear() );
+#endif
+ }
+ io_data.aNormalizers[ sTypeName ] = o_formatter;
+ }
+ else
+ o_formatter = pos->second;
+
+ return !!o_formatter;
+ }
+ }
+
+ //==================================================================================================================
+ //= CellValueConversion
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ CellValueConversion::CellValueConversion( ::comphelper::ComponentContext const & i_context )
+ :m_pData( new CellValueConversion_Data( i_context ) )
+ {
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ CellValueConversion::~CellValueConversion()
+ {
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString CellValueConversion::convertToString( const Any& i_value )
+ {
::rtl::OUString sStringValue;
- if ( i_value >>= sConvertString )
- sStringValue = sConvertString;
- else if ( i_value >>= nInt )
- sStringValue = sConvertString.valueOf( nInt );
- else if ( i_value >>= bBool )
- sStringValue = sConvertString.valueOf( bBool );
- else if ( i_value >>= fDouble )
- sStringValue = sConvertString.valueOf( fDouble );
- else
- OSL_ENSURE( !i_value.hasValue(), "CellValueConversion::convertToString: cannot handle the given cell content type!" );
+ if ( !i_value.hasValue() )
+ return sStringValue;
+
+ if ( ! ( i_value >>= sStringValue ) )
+ {
+ if ( lcl_ensureNumberFormatter( *m_pData ) )
+ {
+ PValueNormalization pNormalizer;
+ if ( lcl_getValueNormalizer( *m_pData, i_value.getValueType(), pNormalizer ) )
+ {
+ try
+ {
+ double const formatterCompliantValue = pNormalizer->convertToDouble( i_value );
+ sal_Int32 const formatKey = pNormalizer->getFormatKey();
+ sStringValue = m_pData->xNumberFormatter->convertNumberToString(
+ formatKey, formatterCompliantValue );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+ }
return sStringValue;
}
diff --git a/svtools/source/table/cellvalueconversion.hxx b/svtools/source/table/cellvalueconversion.hxx
index 4d6b8c8d6aac..c4d8baa98489 100755..100644
--- a/svtools/source/table/cellvalueconversion.hxx
+++ b/svtools/source/table/cellvalueconversion.hxx
@@ -31,6 +31,13 @@
#include <com/sun/star/uno/Any.hxx>
/** === end UNO includes === **/
+#include <boost/scoped_ptr.hpp>
+
+namespace comphelper
+{
+ class ComponentContext;
+}
+
//......................................................................................................................
namespace svt
{
@@ -39,10 +46,17 @@ namespace svt
//==================================================================================================================
//= CellValueConversion
//==================================================================================================================
+ struct CellValueConversion_Data;
class CellValueConversion
{
public:
- static ::rtl::OUString convertToString( const ::com::sun::star::uno::Any& i_cellValue );
+ CellValueConversion( ::comphelper::ComponentContext const & i_context );
+ ~CellValueConversion();
+
+ ::rtl::OUString convertToString( const ::com::sun::star::uno::Any& i_cellValue );
+
+ private:
+ ::boost::scoped_ptr< CellValueConversion_Data > m_pData;
};
//......................................................................................................................
diff --git a/svtools/source/table/gridtablerenderer.cxx b/svtools/source/table/gridtablerenderer.cxx
index 1e230d372c24..341c398b5bcd 100644
--- a/svtools/source/table/gridtablerenderer.cxx
+++ b/svtools/source/table/gridtablerenderer.cxx
@@ -35,6 +35,8 @@
#include <com/sun/star/graphic/XGraphic.hpp>
/** === end UNO includes === **/
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/processfactory.hxx>
#include <tools/debug.hxx>
#include <tools/diagnose_ex.h>
#include <vcl/window.hxx>
@@ -123,11 +125,14 @@ namespace svt { namespace table
RowPos nCurrentRow;
bool bUseGridLines;
CachedSortIndicator aSortIndicator;
+ CellValueConversion aStringConverter;
GridTableRenderer_Impl( ITableModel& _rModel )
:rModel( _rModel )
,nCurrentRow( ROW_INVALID )
,bUseGridLines( true )
+ ,aSortIndicator( )
+ ,aStringConverter( ::comphelper::ComponentContext( ::comphelper::getProcessServiceFactory() ) )
{
}
};
@@ -168,7 +173,9 @@ namespace svt { namespace table
}
sal_uLong nHorzFlag = TEXT_DRAW_LEFT;
- HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign();
+ HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnCount() > 0
+ ? i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign()
+ : HorizontalAlignment_CENTER;
switch ( eHorzAlign )
{
case HorizontalAlignment_CENTER: nHorzFlag = TEXT_DRAW_CENTER; break;
@@ -324,7 +331,7 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
- void GridTableRenderer::PrepareRow( RowPos _nRow, bool _bActive, bool _bSelected,
+ void GridTableRenderer::PrepareRow( RowPos _nRow, bool i_hasControlFocus, bool _bSelected,
OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle )
{
// remember the row for subsequent calls to the other ->ITableRenderer methods
@@ -334,13 +341,17 @@ namespace svt { namespace table
::Color backgroundColor = _rStyle.GetFieldColor();
- ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
+ ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() );
::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ ::Color const activeSelectionBackColor =
+ lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor );
if ( _bSelected )
{
// selected rows use the background color from the style
- backgroundColor = _rStyle.GetHighlightColor();
+ backgroundColor = i_hasControlFocus
+ ? activeSelectionBackColor
+ : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor );
if ( !aLineColor )
lineColor = backgroundColor;
}
@@ -357,7 +368,7 @@ namespace svt { namespace table
}
else
{
- Color hilightColor = _rStyle.GetHighlightColor();
+ Color hilightColor = activeSelectionBackColor;
hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() );
hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() );
hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() );
@@ -384,13 +395,10 @@ namespace svt { namespace table
_rDevice.DrawRect( _rRowArea );
_rDevice.Pop();
-
- (void)_bActive;
- // row containing the active cell not rendered any special at the moment
}
//------------------------------------------------------------------------------------------------------------------
- void GridTableRenderer::PaintRowHeader( bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea,
+ void GridTableRenderer::PaintRowHeader( bool i_hasControlFocus, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea,
const StyleSettings& _rStyle )
{
_rDevice.Push( PUSH_LINECOLOR | PUSH_TEXTCOLOR );
@@ -401,7 +409,7 @@ namespace svt { namespace table
_rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) );
- ::rtl::OUString const rowTitle( CellValueConversion::convertToString( rowHeading ) );
+ ::rtl::OUString const rowTitle( m_pImpl->aStringConverter.convertToString( rowHeading ) );
if ( rowTitle.getLength() )
{
::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
@@ -413,8 +421,7 @@ namespace svt { namespace table
_rDevice.DrawText( aTextRect, rowTitle, nDrawTextFlags );
}
- // TODO: active? selected?
- (void)_bActive;
+ (void)i_hasControlFocus;
(void)_bSelected;
_rDevice.Pop();
}
@@ -427,26 +434,28 @@ namespace svt { namespace table
StyleSettings const & rStyle;
ColPos const nColumn;
bool const bSelected;
+ bool const bHasControlFocus;
CellRenderContext( OutputDevice& i_device, Rectangle const & i_contentArea,
- StyleSettings const & i_style, ColPos const i_column, bool const i_selected )
+ StyleSettings const & i_style, ColPos const i_column, bool const i_selected, bool const i_hasControlFocus )
:rDevice( i_device )
,aContentArea( i_contentArea )
,rStyle( i_style )
,nColumn( i_column )
,bSelected( i_selected )
+ ,bHasControlFocus( i_hasControlFocus )
{
}
};
//------------------------------------------------------------------------------------------------------------------
- void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool _bActive,
+ void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool i_hasControlFocus,
OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle )
{
_rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
Rectangle const aContentArea( lcl_getContentArea( *m_pImpl, _rArea ) );
- CellRenderContext const aRenderContext( _rDevice, aContentArea, _rStyle, i_column, _bSelected );
+ CellRenderContext const aRenderContext( _rDevice, aContentArea, _rStyle, i_column, _bSelected, i_hasControlFocus );
impl_paintCellContent( aRenderContext );
if ( m_pImpl->bUseGridLines )
@@ -457,7 +466,9 @@ namespace svt { namespace table
if ( _bSelected && !aLineColor )
{
// if no line color is specified by the model, use the usual selection color for lines in selected cells
- lineColor = _rStyle.GetHighlightColor();
+ lineColor = i_hasControlFocus
+ ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor )
+ : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor );
}
_rDevice.SetLineColor( lineColor );
@@ -466,9 +477,6 @@ namespace svt { namespace table
}
_rDevice.Pop();
-
- (void)_bActive;
- // no special painting for the active cell at the moment
}
//------------------------------------------------------------------------------------------------------------------
@@ -537,7 +545,7 @@ namespace svt { namespace table
return;
}
- const ::rtl::OUString sText( CellValueConversion::convertToString( aCellContent ) );
+ const ::rtl::OUString sText( m_pImpl->aStringConverter.convertToString( aCellContent ) );
impl_paintCellText( i_context, sText );
}
@@ -545,7 +553,12 @@ namespace svt { namespace table
void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, ::rtl::OUString const & i_text )
{
if ( i_context.bSelected )
- i_context.rDevice.SetTextColor( i_context.rStyle.GetHighlightTextColor() );
+ {
+ ::Color const textColor = i_context.bHasControlFocus
+ ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetHighlightTextColor )
+ : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetDeactiveTextColor );
+ i_context.rDevice.SetTextColor( textColor );
+ }
else
{
::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor );
@@ -572,7 +585,7 @@ namespace svt { namespace table
//------------------------------------------------------------------------------------------------------------------
bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent, ColPos const i_colPos, RowPos const i_rowPos,
- bool const i_active, bool const i_selected, OutputDevice& i_targetDevice, Rectangle const & i_targetArea )
+ bool const i_active, bool const i_selected, OutputDevice& i_targetDevice, Rectangle const & i_targetArea ) const
{
if ( !i_cellContent.hasValue() )
return true;
@@ -592,7 +605,7 @@ namespace svt { namespace table
return true;
}
- ::rtl::OUString const sText( CellValueConversion::convertToString( i_cellContent ) );
+ ::rtl::OUString const sText( m_pImpl->aStringConverter.convertToString( i_cellContent ) );
if ( sText.getLength() == 0 )
return true;
@@ -613,6 +626,16 @@ namespace svt { namespace table
return true;
}
+ //------------------------------------------------------------------------------------------------------------------
+ bool GridTableRenderer::GetFormattedCellString( Any const & i_cellValue, ColPos const i_colPos, RowPos const i_rowPos, ::rtl::OUString & o_cellString ) const
+ {
+ o_cellString = m_pImpl->aStringConverter.convertToString( i_cellValue );
+
+ OSL_UNUSED( i_colPos );
+ OSL_UNUSED( i_rowPos );
+ return true;
+ }
+
//......................................................................................................................
} } // namespace svt::table
//......................................................................................................................
diff --git a/svtools/source/table/mousefunction.cxx b/svtools/source/table/mousefunction.cxx
index 20d505e911e9..162abc7936c8 100755..100644
--- a/svtools/source/table/mousefunction.cxx
+++ b/svtools/source/table/mousefunction.cxx
@@ -207,27 +207,14 @@ namespace svt { namespace table
TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
if ( tableCell.nRow >= 0 )
{
- bool bSetCursor = false;
if ( i_tableControl.getSelEngine()->GetSelectionMode() == NO_SELECTION )
{
- bSetCursor = true;
+ i_tableControl.activateCell( tableCell.nColumn, tableCell.nRow );
+ handled = true;
}
else
{
- if ( !i_tableControl.isRowSelected( tableCell.nRow ) )
- {
- handled = i_tableControl.getSelEngine()->SelMouseButtonDown( i_event );
- }
- else
- {
- bSetCursor = true;
- }
- }
-
- if ( bSetCursor )
- {
- i_tableControl.activateCell( tableCell.nColumn, tableCell.nRow );
- handled = true;
+ handled = i_tableControl.getSelEngine()->SelMouseButtonDown( i_event );
}
}
diff --git a/svtools/source/table/tablecontrol.cxx b/svtools/source/table/tablecontrol.cxx
index 01a9b667a8f7..d0e726fa5c53 100644
--- a/svtools/source/table/tablecontrol.cxx
+++ b/svtools/source/table/tablecontrol.cxx
@@ -35,6 +35,7 @@
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <tools/diagnose_ex.h>
@@ -49,6 +50,8 @@ namespace svt { namespace table
{
//......................................................................................................................
+ namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
+
//==================================================================================================================
//= TableControl
//==================================================================================================================
@@ -58,14 +61,14 @@ namespace svt { namespace table
,m_pImpl( new TableControl_Impl( *this ) )
{
TableDataWindow& rDataWindow = m_pImpl->getDataWindow();
- rDataWindow.SetMouseButtonDownHdl( LINK( this, TableControl, ImplMouseButtonDownHdl ) );
- rDataWindow.SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) );
rDataWindow.SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) );
// by default, use the background as determined by the style settings
const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() );
SetBackground( Wallpaper( aWindowColor ) );
SetFillColor( aWindowColor );
+
+ SetCompoundControl( true );
}
// -----------------------------------------------------------------------------------------------------------------
@@ -97,6 +100,27 @@ namespace svt { namespace table
{
if ( !m_pImpl->getInputHandler()->KeyInput( *m_pImpl, rKEvt ) )
Control::KeyInput( rKEvt );
+ else
+ {
+ if ( m_pImpl->isAccessibleAlive() )
+ {
+ m_pImpl->commitCellEvent( AccessibleEventId::STATE_CHANGED,
+ makeAny( AccessibleStateType::FOCUSED ),
+ Any()
+ );
+ // Huh? What the heck? Why do we unconditionally notify a STATE_CHANGE/FOCUSED after each and every
+ // (handled) key stroke?
+
+ m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ Any(),
+ Any()
+ );
+ // ditto: Why do we notify this unconditionally? We should find the right place to notify the
+ // ACTIVE_DESCENDANT_CHANGED event.
+ // Also, we should check if STATE_CHANGED/FOCUSED is really necessary: finally, the children are
+ // transient, aren't they?
+ }
+ }
}
@@ -108,6 +132,10 @@ namespace svt { namespace table
// forward certain settings to the data window
switch ( i_nStateChange )
{
+ case STATE_CHANGE_CONTROL_FOCUS:
+ m_pImpl->invalidateSelectedRows();
+ break;
+
case STATE_CHANGE_CONTROLBACKGROUND:
if ( IsControlBackground() )
getDataWindow().SetControlBackground( GetControlBackground() );
@@ -209,7 +237,7 @@ namespace svt { namespace table
void TableControl::SelectRow( RowPos const i_rowIndex, bool const i_select )
{
ENSURE_OR_RETURN_VOID( ( i_rowIndex >= 0 ) && ( i_rowIndex < m_pImpl->getModel()->getRowCount() ),
- "TableControl::SelectRow: no control (anymore)!" );
+ "TableControl::SelectRow: invalid row index!" );
if ( i_select )
{
@@ -291,10 +319,10 @@ namespace svt { namespace table
switch( eObjType )
{
case TCTYPE_GRIDCONTROL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridControl" ) );
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grid control" ) );
break;
case TCTYPE_TABLE:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Table" ) );
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grid conrol" ) );
break;
case TCTYPE_ROWHEADERBAR:
aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowHeaderBar" ) );
@@ -303,7 +331,19 @@ namespace svt { namespace table
aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ColumnHeaderBar" ) );
break;
case TCTYPE_TABLECELL:
- aRetText = GetAccessibleCellText(_nRow, _nCol);
+ //the name of the cell constists of column name and row name if defined
+ //if the name is equal to cell content, it'll be read twice
+ if(GetModel()->hasColumnHeaders())
+ {
+ aRetText = GetColumnName(_nCol);
+ aRetText += rtl::OUString::createFromAscii(" , ");
+ }
+ if(GetModel()->hasRowHeaders())
+ {
+ aRetText += GetRowName(_nRow);
+ aRetText += rtl::OUString::createFromAscii(" , ");
+ }
+ //aRetText = GetAccessibleCellText(_nRow, _nCol);
break;
case TCTYPE_ROWHEADERCELL:
aRetText = GetRowName(_nRow);
@@ -324,7 +364,7 @@ namespace svt { namespace table
switch( eObjType )
{
case TCTYPE_GRIDCONTROL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridControl description" ) );
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grid control description" ) );
break;
case TCTYPE_TABLE:
aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLE description" ) );
@@ -336,7 +376,17 @@ namespace svt { namespace table
aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERBAR description" ) );
break;
case TCTYPE_TABLECELL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLECELL description" ) );
+ // the description of the cell consists of column name and row name if defined
+ // if the name is equal to cell content, it'll be read twice
+ if ( GetModel()->hasColumnHeaders() )
+ {
+ aRetText = GetColumnName( GetCurrentColumn() );
+ aRetText += rtl::OUString::createFromAscii( " , " );
+ }
+ if ( GetModel()->hasRowHeaders() )
+ {
+ aRetText += GetRowName( GetCurrentRow() );
+ }
break;
case TCTYPE_ROWHEADERCELL:
aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERCELL description" ) );
@@ -401,38 +451,60 @@ namespace svt { namespace table
case TCTYPE_TABLE:
rStateSet.AddState( AccessibleStateType::FOCUSABLE );
- rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
- if ( HasFocus() )
+
+ if ( m_pImpl->getSelEngine()->GetSelectionMode() == MULTIPLE_SELECTION )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
+
+ if ( HasChildPathFocus() )
rStateSet.AddState( AccessibleStateType::FOCUSED );
+
if ( IsActive() )
rStateSet.AddState( AccessibleStateType::ACTIVE );
- if ( IsEnabled() )
+
+ if ( m_pImpl->getDataWindow().IsEnabled() )
+ {
rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
if ( IsReallyVisible() )
rStateSet.AddState( AccessibleStateType::VISIBLE );
- rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
+ if ( eObjType == TCTYPE_TABLE )
+ rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
break;
+
case TCTYPE_ROWHEADERBAR:
rStateSet.AddState( AccessibleStateType::VISIBLE );
rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
break;
+
case TCTYPE_COLUMNHEADERBAR:
rStateSet.AddState( AccessibleStateType::VISIBLE );
rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
break;
+
case TCTYPE_TABLECELL:
{
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( HasChildPathFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ rStateSet.AddState( AccessibleStateType::ACTIVE );
rStateSet.AddState( AccessibleStateType::TRANSIENT );
rStateSet.AddState( AccessibleStateType::SELECTABLE);
- if( GetSelectedRowCount()>0)
- rStateSet.AddState( AccessibleStateType::SELECTED);
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+ if ( IsRowSelected( GetCurrentRow() ) )
+ // Hmm? Wouldn't we expect the affected row to be a parameter to this function?
+ rStateSet.AddState( AccessibleStateType::SELECTED );
}
break;
+
case TCTYPE_ROWHEADERCELL:
rStateSet.AddState( AccessibleStateType::VISIBLE );
rStateSet.AddState( AccessibleStateType::TRANSIENT );
break;
+
case TCTYPE_COLUMNHEADERCELL:
rStateSet.AddState( AccessibleStateType::VISIBLE );
break;
@@ -440,6 +512,20 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
+ void TableControl::commitCellEventIfAccessibleAlive( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ if ( m_pImpl->isAccessibleAlive() )
+ m_pImpl->commitCellEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl::commitTableEventIfAccessibleAlive( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ if ( m_pImpl->isAccessibleAlive() )
+ m_pImpl->commitTableEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) const
{
return Control::GetWindowExtentsRelative( pRelativeWindow );
@@ -484,13 +570,12 @@ namespace svt { namespace table
//------------------------------------------------------------------------------------------------------------------
sal_Int32 TableControl::GetAccessibleControlCount() const
{
- sal_Int32 count = 0;
- if(GetRowCount()>0)
- count+=1;
- if(GetModel()->hasRowHeaders())
- count+=1;
- if(GetModel()->hasColumnHeaders())
- count+=1;
+ // TC_TABLE is always defined, no matter whether empty or not
+ sal_Int32 count = 1;
+ if ( GetModel()->hasRowHeaders() )
+ ++count;
+ if ( GetModel()->hasColumnHeaders() )
+ ++count;
return count;
}
@@ -532,10 +617,20 @@ namespace svt { namespace table
//------------------------------------------------------------------------------------------------------------------
void TableControl::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
{
- if ( GetCurrentRow() == _nRow && GetCurrentColumn() == _nColumnPos )
+ if ( IsRowSelected( _nRow ) )
+ _rStateSet.AddState( AccessibleStateType::SELECTED );
+ if ( HasChildPathFocus() )
_rStateSet.AddState( AccessibleStateType::FOCUSED );
else // only transient when column is not focused
_rStateSet.AddState( AccessibleStateType::TRANSIENT );
+
+ _rStateSet.AddState( AccessibleStateType::VISIBLE );
+ _rStateSet.AddState( AccessibleStateType::SHOWING );
+ _rStateSet.AddState( AccessibleStateType::ENABLED );
+ _rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ _rStateSet.AddState( AccessibleStateType::ACTIVE );
+
+ (void)_nColumnPos;
}
//------------------------------------------------------------------------------------------------------------------
@@ -562,30 +657,27 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
- Rectangle TableControl::calcTableRect(sal_Bool _bOnScreen)
+ Rectangle TableControl::calcHeaderCellRect( sal_Bool _bIsColumnBar, sal_Int32 nPos )
{
- (void)_bOnScreen;
- return m_pImpl->calcTableRect();
+ return m_pImpl->calcHeaderCellRect( _bIsColumnBar, nPos );
}
//------------------------------------------------------------------------------------------------------------------
- IMPL_LINK( TableControl, ImplSelectHdl, void*, EMPTYARG )
+ Rectangle TableControl::calcTableRect(sal_Bool _bOnScreen)
{
- Select();
- return 1;
+ (void)_bOnScreen;
+ return m_pImpl->calcTableRect();
}
//------------------------------------------------------------------------------------------------------------------
- IMPL_LINK( TableControl, ImplMouseButtonDownHdl, MouseEvent*, pData )
+ Rectangle TableControl::calcCellRect( sal_Int32 _nRowPos, sal_Int32 _nColPos )
{
- CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, pData );
- return 1;
+ return m_pImpl->calcCellRect( _nRowPos, _nColPos );
}
-
//------------------------------------------------------------------------------------------------------------------
- IMPL_LINK( TableControl, ImplMouseButtonUpHdl, MouseEvent*, pData )
+ IMPL_LINK( TableControl, ImplSelectHdl, void*, EMPTYARG )
{
- CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, pData );
+ Select();
return 1;
}
@@ -593,6 +685,15 @@ namespace svt { namespace table
void TableControl::Select()
{
ImplCallEventListenersAndHandler( VCLEVENT_TABLEROW_SELECT, m_pImpl->getSelectHandler(), this );
+
+ if ( m_pImpl->isAccessibleAlive() )
+ {
+ m_pImpl->commitAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+
+ m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), Any() );
+ // TODO: why do we notify this when the *selection* changed? Shouldn't we find a better place for this,
+ // actually, when the active descendant, i.e. the current cell, *really* changed?
+ }
}
//------------------------------------------------------------------------------------------------------------------
diff --git a/svtools/source/table/tablecontrol_impl.cxx b/svtools/source/table/tablecontrol_impl.cxx
index 8e481d27d993..4ecce7359a15 100755..100644
--- a/svtools/source/table/tablecontrol_impl.cxx
+++ b/svtools/source/table/tablecontrol_impl.cxx
@@ -34,7 +34,6 @@
#include "tabledatawindow.hxx"
#include "tablecontrol_impl.hxx"
#include "tablegeometry.hxx"
-#include "cellvalueconversion.hxx"
/** === begin UNO includes === **/
#include <com/sun/star/accessibility/XAccessible.hpp>
@@ -51,6 +50,7 @@
#include <tools/diagnose_ex.h>
#include <functional>
+#include <numeric>
#define MIN_COLUMN_WIDTH_PIXEL 4
@@ -186,6 +186,22 @@ namespace svt { namespace table
{
return ::boost::optional< ::Color >();
}
+ virtual ::boost::optional< ::Color > getActiveSelectionBackColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getInactiveSelectionBackColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getActiveSelectionTextColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getInactiveSelectionTextColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
virtual ::boost::optional< ::Color > getTextColor() const
{
return ::boost::optional< ::Color >();
@@ -487,7 +503,7 @@ namespace svt { namespace table
// recalc some model-dependent cached info
impl_ni_updateCachedModelValues();
- impl_ni_updateScrollbars();
+ impl_ni_relayout();
// completely invalidate
m_rAntiImpl.Invalidate();
@@ -535,8 +551,8 @@ namespace svt { namespace table
if ( i_first <= m_nCurRow )
goTo( m_nCurColumn, m_nCurRow + insertedRows );
- // adjust scrollbars
- impl_ni_updateScrollbars();
+ // relayout, since the scrollbar need might have changed
+ impl_ni_relayout();
// notify A1YY events
if ( impl_isAccessibleAlive() )
@@ -545,20 +561,6 @@ namespace svt { namespace table
makeAny( AccessibleTableModelChange( AccessibleTableModelChangeType::INSERT, i_first, i_last, 0, m_pModel->getColumnCount() ) ),
Any()
);
- impl_commitAccessibleEvent( AccessibleEventId::CHILD,
- makeAny( m_pAccessibleTable->getTableHeader( TCTYPE_ROWHEADERBAR ) ),
- Any()
- );
-
-// for ( sal_Int32 i = 0 ; i <= m_pModel->getColumnCount(); ++i )
-// {
-// impl_commitAccessibleEvent(
-// CHILD,
-// makeAny( m_pAccessibleTable->getTable() ),
-// Any());
-// }
- // Huh? What's that? We're notifying |columnCount| CHILD events here, claiming the *table* itself
- // has been inserted. Doesn't make much sense, does it?
}
// schedule repaint
@@ -610,13 +612,13 @@ namespace svt { namespace table
m_nCurRow = ROW_INVALID;
}
- // adjust scrollbars
- impl_ni_updateScrollbars();
+ // relayout, since the scrollbar need might have changed
+ impl_ni_relayout();
// notify A11Y events
if ( impl_isAccessibleAlive() )
{
- impl_commitAccessibleEvent(
+ commitTableEvent(
AccessibleEventId::TABLE_MODEL_CHANGED,
makeAny( AccessibleTableModelChange(
AccessibleTableModelChangeType::DELETE,
@@ -641,8 +643,7 @@ namespace svt { namespace table
void TableControl_Impl::columnInserted( ColPos const i_colIndex )
{
m_nColumnCount = m_pModel->getColumnCount();
- impl_ni_updateColumnWidths();
- impl_ni_updateScrollbars();
+ impl_ni_relayout();
m_rAntiImpl.Invalidate();
@@ -653,8 +654,17 @@ namespace svt { namespace table
void TableControl_Impl::columnRemoved( ColPos const i_colIndex )
{
m_nColumnCount = m_pModel->getColumnCount();
- impl_ni_updateColumnWidths();
- impl_ni_updateScrollbars();
+
+ // adjust the current column, if it is larger than the column count now
+ if ( m_nCurColumn >= m_nColumnCount )
+ {
+ if ( m_nColumnCount > 0 )
+ goTo( m_nCurColumn - 1, m_nCurRow );
+ else
+ m_nCurColumn = COL_INVALID;
+ }
+
+ impl_ni_relayout();
m_rAntiImpl.Invalidate();
@@ -665,8 +675,7 @@ namespace svt { namespace table
void TableControl_Impl::allColumnsRemoved()
{
m_nColumnCount = m_pModel->getColumnCount();
- impl_ni_updateColumnWidths();
- impl_ni_updateScrollbars();
+ impl_ni_relayout();
m_rAntiImpl.Invalidate();
}
@@ -683,11 +692,8 @@ namespace svt { namespace table
//------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::tableMetricsChanged()
{
- long const oldRowHeaderWidthPixel = m_nRowHeaderWidthPixel;
impl_ni_updateCachedTableMetrics();
- if ( oldRowHeaderWidthPixel != m_nRowHeaderWidthPixel )
- impl_ni_updateColumnWidths();
- impl_ni_updateScrollbars();
+ impl_ni_relayout();
m_rAntiImpl.Invalidate();
}
@@ -717,9 +723,8 @@ namespace svt { namespace table
{
if ( !m_bUpdatingColWidths )
{
- impl_ni_updateColumnWidths( i_column );
+ impl_ni_relayout( i_column );
invalidate( TableAreaAll );
- impl_ni_updateScrollbars();
}
nGroup &= ~COL_ATTRS_WIDTH;
@@ -795,67 +800,157 @@ namespace svt { namespace table
//------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::impl_ni_updateCachedModelValues()
{
- m_pInputHandler.reset();
- m_nColumnCount = m_nRowCount = 0;
-
- impl_ni_updateCachedTableMetrics();
- impl_ni_updateColumnWidths();
-
m_pInputHandler = m_pModel->getInputHandler();
if ( !m_pInputHandler )
m_pInputHandler.reset( new DefaultInputHandler );
m_nColumnCount = m_pModel->getColumnCount();
+ if ( m_nLeftColumn >= m_nColumnCount )
+ m_nLeftColumn = ( m_nColumnCount > 0 ) ? m_nColumnCount - 1 : 0;
+
m_nRowCount = m_pModel->getRowCount();
+ if ( m_nTopRow >= m_nRowCount )
+ m_nTopRow = ( m_nRowCount > 0 ) ? m_nRowCount - 1 : 0;
+
+ impl_ni_updateCachedTableMetrics();
}
//------------------------------------------------------------------------------------------------------------------
- void TableControl_Impl::impl_ni_updateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding )
+ namespace
{
- ENSURE_OR_RETURN_VOID( !m_bUpdatingColWidths, "TableControl_Impl::impl_ni_updateColumnWidths: recursive call detected!" );
+ //..............................................................................................................
+ /// determines whether a scrollbar is needed for the given values
+ bool lcl_determineScrollbarNeed( long const i_position, ScrollbarVisibility const i_visibility,
+ long const i_availableSpace, long const i_neededSpace )
+ {
+ if ( i_visibility == ScrollbarShowNever )
+ return false;
+ if ( i_visibility == ScrollbarShowAlways )
+ return true;
+ if ( i_position > 0 )
+ return true;
+ if ( i_availableSpace >= i_neededSpace )
+ return false;
+ return true;
+ }
- m_aColumnWidths.resize( 0 );
- if ( !m_pModel )
- return;
+ //..............................................................................................................
+ void lcl_setButtonRepeat( Window& _rWindow, sal_uLong _nDelay )
+ {
+ AllSettings aSettings = _rWindow.GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
- const TableSize colCount = m_pModel->getColumnCount();
- if ( colCount == 0 )
- return;
+ aMouseSettings.SetButtonRepeat( _nDelay );
+ aSettings.SetMouseSettings( aMouseSettings );
- m_bUpdatingColWidths = true;
- const ::comphelper::FlagGuard aWidthUpdateFlag( m_bUpdatingColWidths );
+ _rWindow.SetSettings( aSettings, sal_True );
+ }
- m_aColumnWidths.reserve( colCount );
+ //..............................................................................................................
+ bool lcl_updateScrollbar( Window& _rParent, ScrollBar*& _rpBar,
+ bool const i_needBar, long _nVisibleUnits,
+ long _nPosition, long _nLineSize, long _nRange,
+ bool _bHorizontal, const Link& _rScrollHandler )
+ {
+ // do we currently have the scrollbar?
+ bool bHaveBar = _rpBar != NULL;
+
+ // do we need to correct the scrollbar visibility?
+ if ( bHaveBar && !i_needBar )
+ {
+ if ( _rpBar->IsTracking() )
+ _rpBar->EndTracking();
+ DELETEZ( _rpBar );
+ }
+ else if ( !bHaveBar && i_needBar )
+ {
+ _rpBar = new ScrollBar(
+ &_rParent,
+ WB_DRAG | ( _bHorizontal ? WB_HSCROLL : WB_VSCROLL )
+ );
+ _rpBar->SetScrollHdl( _rScrollHandler );
+ // get some speed into the scrolling ....
+ lcl_setButtonRepeat( *_rpBar, 0 );
+ }
+
+ if ( _rpBar )
+ {
+ _rpBar->SetRange( Range( 0, _nRange ) );
+ _rpBar->SetVisibleSize( _nVisibleUnits );
+ _rpBar->SetPageSize( _nVisibleUnits );
+ _rpBar->SetLineSize( _nLineSize );
+ _rpBar->SetThumbPos( _nPosition );
+ _rpBar->Show();
+ }
+
+ return ( bHaveBar != i_needBar );
+ }
+ //..............................................................................................................
+ /** returns the number of rows fitting into the given range,
+ for the given row height. Partially fitting rows are counted, too, if the
+ respective parameter says so.
+ */
+ TableSize lcl_getRowsFittingInto( long _nOverallHeight, long _nRowHeightPixel, bool _bAcceptPartialRow = false )
+ {
+ return _bAcceptPartialRow
+ ? ( _nOverallHeight + ( _nRowHeightPixel - 1 ) ) / _nRowHeightPixel
+ : _nOverallHeight / _nRowHeightPixel;
+ }
+
+ //..............................................................................................................
+ /** returns the number of columns fitting into the given area,
+ with the first visible column as given. Partially fitting columns are counted, too,
+ if the respective parameter says so.
+ */
+ TableSize lcl_getColumnsVisibleWithin( const Rectangle& _rArea, ColPos _nFirstVisibleColumn,
+ const TableControl_Impl& _rControl, bool _bAcceptPartialRow )
+ {
+ TableSize visibleColumns = 0;
+ TableColumnGeometry aColumn( _rControl, _rArea, _nFirstVisibleColumn );
+ while ( aColumn.isValid() )
+ {
+ if ( !_bAcceptPartialRow )
+ if ( aColumn.getRect().Right() > _rArea.Right() )
+ // this column is only partially visible, and this is not allowed
+ break;
+
+ aColumn.moveRight();
+ ++visibleColumns;
+ }
+ return visibleColumns;
+ }
+
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ long TableControl_Impl::impl_ni_calculateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding,
+ bool const i_assumeVerticalScrollbar, ::std::vector< long >& o_newColWidthsPixel ) const
+ {
// the available horizontal space
long gridWidthPixel = m_rAntiImpl.GetOutputSizePixel().Width();
+ ENSURE_OR_RETURN( !!m_pModel, "TableControl_Impl::impl_ni_calculateColumnWidths: not allowed without a model!", gridWidthPixel );
if ( m_pModel->hasRowHeaders() && ( gridWidthPixel != 0 ) )
{
gridWidthPixel -= m_nRowHeaderWidthPixel;
}
- if ( m_pModel->getVerticalScrollbarVisibility() != ScrollbarShowNever )
+
+ if ( i_assumeVerticalScrollbar && ( m_pModel->getVerticalScrollbarVisibility() != ScrollbarShowNever ) )
{
long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
gridWidthPixel -= nScrollbarMetrics;
}
- // TODO: shouldn't we take the visibility of the vertical scroll bar into account here, too?
- long const gridWidthAppFont = m_rAntiImpl.PixelToLogic( Size( gridWidthPixel, 0 ), MAP_APPFONT ).Width();
-
- // determine the accumulated current width of all columns
- for ( ColPos col = 0; col < colCount; ++col )
- {
- const PColumnModel pColumn = m_pModel->getColumnModel( col );
- ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
-
- }
+ // no need to do anything without columns
+ TableSize const colCount = m_pModel->getColumnCount();
+ if ( colCount == 0 )
+ return gridWidthPixel;
// collect some meta data for our columns:
- // - their current (appt-font) metrics
+ // - their current (pixel) metrics
long accumulatedCurrentWidth = 0;
::std::vector< long > currentColWidths;
currentColWidths.reserve( colCount );
- // - their effective minimal and maximal width (app-font!)
typedef ::std::vector< ::std::pair< long, long > > ColumnLimits;
ColumnLimits effectiveColumnLimits;
effectiveColumnLimits.reserve( colCount );
@@ -865,13 +960,14 @@ namespace svt { namespace table
::std::vector< ::sal_Int32 > columnFlexibilities;
columnFlexibilities.reserve( colCount );
long flexibilityDenominator = 0;
+ size_t flexibleColumnCount = 0;
for ( ColPos col = 0; col < colCount; ++col )
{
PColumnModel const pColumn = m_pModel->getColumnModel( col );
ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
// current width
- TableMetrics const currentWidth = pColumn->getWidth();
+ long const currentWidth = appFontWidthToPixel( pColumn->getWidth() );
currentColWidths.push_back( currentWidth );
// accumulated width
@@ -879,7 +975,7 @@ namespace svt { namespace table
// flexibility
::sal_Int32 flexibility = pColumn->getFlexibility();
- OSL_ENSURE( flexibility >= 0, "TableControl_Impl::impl_ni_updateColumnWidths: a column's flexibility should be non-negative." );
+ OSL_ENSURE( flexibility >= 0, "TableControl_Impl::impl_ni_calculateColumnWidths: a column's flexibility should be non-negative." );
if ( ( flexibility < 0 ) // normalization
|| ( !pColumn->isResizable() ) // column not resizeable => no auto-resize
|| ( col <= i_assumeInflexibleColumnsUpToIncluding ) // column shall be treated as inflexible => respec this
@@ -891,18 +987,18 @@ namespace svt { namespace table
// if the column is not flexible, it will not be asked for min/max, but we assume the current width as limit then
if ( flexibility > 0 )
{
- long const minWidth = pColumn->getMinWidth();
+ long const minWidth = appFontWidthToPixel( pColumn->getMinWidth() );
if ( minWidth > 0 )
effectiveMin = minWidth;
else
effectiveMin = MIN_COLUMN_WIDTH_PIXEL;
- long const maxWidth = pColumn->getMaxWidth();
- OSL_ENSURE( minWidth <= maxWidth, "TableControl_Impl::impl_ni_updateColumnWidths: pretty undecided 'bout its width limits, this column!" );
+ long const maxWidth = appFontWidthToPixel( pColumn->getMaxWidth() );
+ OSL_ENSURE( minWidth <= maxWidth, "TableControl_Impl::impl_ni_calculateColumnWidths: pretty undecided 'bout its width limits, this column!" );
if ( ( maxWidth > 0 ) && ( maxWidth >= minWidth ) )
effectiveMax = maxWidth;
else
- effectiveMax = gridWidthAppFont; // TODO: any better guess here?
+ effectiveMax = gridWidthPixel; // TODO: any better guess here?
if ( effectiveMin == effectiveMax )
// if the min and the max are identical, this implies no flexibility at all
@@ -911,27 +1007,29 @@ namespace svt { namespace table
columnFlexibilities.push_back( flexibility );
flexibilityDenominator += flexibility;
+ if ( flexibility > 0 )
+ ++flexibleColumnCount;
effectiveColumnLimits.push_back( ::std::pair< long, long >( effectiveMin, effectiveMax ) );
accumulatedMinWidth += effectiveMin;
accumulatedMaxWidth += effectiveMax;
}
- ::std::vector< long > newWidths( currentColWidths );
+ o_newColWidthsPixel = currentColWidths;
if ( flexibilityDenominator == 0 )
{
// no column is flexible => don't adjust anything
}
- else if ( gridWidthAppFont > accumulatedCurrentWidth )
+ else if ( gridWidthPixel > accumulatedCurrentWidth )
{ // we have space to give away ...
- long distributeAppFontUnits = gridWidthAppFont - accumulatedCurrentWidth;
- if ( gridWidthAppFont > accumulatedMaxWidth )
+ long distributePixel = gridWidthPixel - accumulatedCurrentWidth;
+ if ( gridWidthPixel > accumulatedMaxWidth )
{
// ... but the column's maximal widths are still less than we have
// => set them all to max
for ( size_t i = 0; i < size_t( colCount ); ++i )
{
- newWidths[i] = effectiveColumnLimits[i].second;
+ o_newColWidthsPixel[i] = effectiveColumnLimits[i].second;
}
}
else
@@ -941,13 +1039,13 @@ namespace svt { namespace table
{
startOver = false;
// distribute the remaining space amongst all columns with a positive flexibility
- for ( size_t i=0; i<newWidths.size() && !startOver; ++i )
+ for ( size_t i=0; i<o_newColWidthsPixel.size() && !startOver; ++i )
{
long const columnFlexibility = columnFlexibilities[i];
if ( columnFlexibility == 0 )
continue;
- long newColWidth = currentColWidths[i] + columnFlexibility * distributeAppFontUnits / flexibilityDenominator;
+ long newColWidth = currentColWidths[i] + columnFlexibility * distributePixel / flexibilityDenominator;
if ( newColWidth > effectiveColumnLimits[i].second )
{ // that was too much, we hit the col's maximum
@@ -956,9 +1054,10 @@ namespace svt { namespace table
// adjust the flexibility denominator ...
flexibilityDenominator -= columnFlexibility;
columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
// ... and the remaining width ...
long const difference = newColWidth - currentColWidths[i];
- distributeAppFontUnits -= difference;
+ distributePixel -= difference;
// ... this way, we ensure that the width not taken up by this column is consumed by the other
// flexible ones (if there are some)
@@ -967,22 +1066,47 @@ namespace svt { namespace table
startOver = true;
}
- newWidths[i] = newColWidth;
+ o_newColWidthsPixel[i] = newColWidth;
}
}
while ( startOver );
+
+ // are there pixels left (might be caused by rounding errors)?
+ distributePixel = gridWidthPixel - ::std::accumulate( o_newColWidthsPixel.begin(), o_newColWidthsPixel.end(), 0 );
+ while ( ( distributePixel > 0 ) && ( flexibleColumnCount > 0 ) )
+ {
+ // yes => ignore relative flexibilities, and subsequently distribute single pixels to all flexible
+ // columns which did not yet reach their maximum.
+ for ( size_t i=0; ( i < o_newColWidthsPixel.size() ) && ( distributePixel > 0 ); ++i )
+ {
+ if ( columnFlexibilities[i] == 0 )
+ continue;
+
+ OSL_ENSURE( o_newColWidthsPixel[i] <= effectiveColumnLimits[i].second,
+ "TableControl_Impl::impl_ni_calculateColumnWidths: inconsitency!" );
+ if ( o_newColWidthsPixel[i] >= effectiveColumnLimits[i].first )
+ {
+ columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
+ continue;
+ }
+
+ ++o_newColWidthsPixel[i];
+ --distributePixel;
+ }
+ }
}
}
- else if ( gridWidthAppFont < accumulatedCurrentWidth )
+ else if ( gridWidthPixel < accumulatedCurrentWidth )
{ // we need to take away some space from the columns which allow it ...
- long takeAwayAppFontUnits = accumulatedCurrentWidth - gridWidthAppFont;
- if ( gridWidthAppFont < accumulatedMinWidth )
+ long takeAwayPixel = accumulatedCurrentWidth - gridWidthPixel;
+ if ( gridWidthPixel < accumulatedMinWidth )
{
// ... but the column's minimal widths are still more than we have
// => set them all to min
for ( size_t i = 0; i < size_t( colCount ); ++i )
{
- newWidths[i] = effectiveColumnLimits[i].first;
+ o_newColWidthsPixel[i] = effectiveColumnLimits[i].first;
}
}
else
@@ -992,13 +1116,13 @@ namespace svt { namespace table
{
startOver = false;
// take away the space we need from the columns with a positive flexibility
- for ( size_t i=0; i<newWidths.size() && !startOver; ++i )
+ for ( size_t i=0; i<o_newColWidthsPixel.size() && !startOver; ++i )
{
long const columnFlexibility = columnFlexibilities[i];
if ( columnFlexibility == 0 )
continue;
- long newColWidth = currentColWidths[i] - columnFlexibility * takeAwayAppFontUnits / flexibilityDenominator;
+ long newColWidth = currentColWidths[i] - columnFlexibility * takeAwayPixel / flexibilityDenominator;
if ( newColWidth < effectiveColumnLimits[i].first )
{ // that was too much, we hit the col's minimum
@@ -1007,172 +1131,79 @@ namespace svt { namespace table
// adjust the flexibility denominator ...
flexibilityDenominator -= columnFlexibility;
columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
// ... and the remaining width ...
long const difference = currentColWidths[i] - newColWidth;
- takeAwayAppFontUnits -= difference;
+ takeAwayPixel -= difference;
// and start over with the first column, since there might be earlier columns which need
// to be recalculated now
startOver = true;
}
- newWidths[i] = newColWidth;
+ o_newColWidthsPixel[i] = newColWidth;
}
}
while ( startOver );
- }
- }
- // now that we have calculated the app-font widths, get the actual pixels
- long accumulatedWidthPixel = m_nRowHeaderWidthPixel;
- for ( ColPos col = 0; col < colCount; ++col )
- {
- long const colWidth = m_rAntiImpl.LogicToPixel( Size( newWidths[col], 0 ), MAP_APPFONT ).Width();
- const long columnStart = accumulatedWidthPixel;
- const long columnEnd = columnStart + colWidth;
- m_aColumnWidths.push_back( MutableColumnMetrics( columnStart, columnEnd ) );
- accumulatedWidthPixel = columnEnd;
-
- // and don't forget to forward this to the column models
- PColumnModel const pColumn = m_pModel->getColumnModel( col );
- ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
- pColumn->setWidth( newWidths[col] );
- }
+ // are there pixels left (might be caused by rounding errors)?
+ takeAwayPixel = ::std::accumulate( o_newColWidthsPixel.begin(), o_newColWidthsPixel.end(), 0 ) - gridWidthPixel;
+ while ( ( takeAwayPixel > 0 ) && ( flexibleColumnCount > 0 ) )
+ {
+ // yes => ignore relative flexibilities, and subsequently take away pixels from all flexible
+ // columns which did not yet reach their minimum.
+ for ( size_t i=0; ( i < o_newColWidthsPixel.size() ) && ( takeAwayPixel > 0 ); ++i )
+ {
+ if ( columnFlexibilities[i] == 0 )
+ continue;
- // if the column resizing happened to leave some space at the right, but there are columns
- // scrolled out to the left, scroll them in
- while ( ( m_nLeftColumn > 0 )
- && ( accumulatedWidthPixel - m_aColumnWidths[ m_nLeftColumn - 1 ].getStart() <= gridWidthPixel )
- )
- {
- --m_nLeftColumn;
- }
+ OSL_ENSURE( o_newColWidthsPixel[i] >= effectiveColumnLimits[i].first,
+ "TableControl_Impl::impl_ni_calculateColumnWidths: inconsitency!" );
+ if ( o_newColWidthsPixel[i] <= effectiveColumnLimits[i].first )
+ {
+ columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
+ continue;
+ }
- // now adjust the column metrics, since they currently ignore the horizontal scroll position
- if ( m_nLeftColumn > 0 )
- {
- const long offsetPixel = m_aColumnWidths[ 0 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getStart();
- for ( ColumnPositions::iterator colPos = m_aColumnWidths.begin();
- colPos != m_aColumnWidths.end();
- ++colPos
- )
- {
- colPos->move( offsetPixel );
+ --o_newColWidthsPixel[i];
+ --takeAwayPixel;
+ }
+ }
}
}
+
+ return gridWidthPixel;
}
//------------------------------------------------------------------------------------------------------------------
- namespace
+ void TableControl_Impl::impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding )
{
- //..............................................................................................................
- /// determines whether a scrollbar is needed for the given values
- bool lcl_determineScrollbarNeed( long const i_position, ScrollbarVisibility const i_visibility,
- long const i_availableSpace, long const i_neededSpace )
- {
- if ( i_visibility == ScrollbarShowNever )
- return false;
- if ( i_visibility == ScrollbarShowAlways )
- return true;
- if ( i_position > 0 )
- return true;
- if ( i_availableSpace >= i_neededSpace )
- return false;
- return true;
- }
-
- //..............................................................................................................
- void lcl_setButtonRepeat( Window& _rWindow, sal_uLong _nDelay )
- {
- AllSettings aSettings = _rWindow.GetSettings();
- MouseSettings aMouseSettings = aSettings.GetMouseSettings();
-
- aMouseSettings.SetButtonRepeat( _nDelay );
- aSettings.SetMouseSettings( aMouseSettings );
-
- _rWindow.SetSettings( aSettings, sal_True );
- }
-
- //..............................................................................................................
- void lcl_updateScrollbar( Window& _rParent, ScrollBar*& _rpBar,
- bool const i_needBar, long _nVisibleUnits,
- long _nPosition, long _nLineSize, long _nRange,
- bool _bHorizontal, const Link& _rScrollHandler )
- {
- // do we currently have the scrollbar?
- bool bHaveBar = _rpBar != NULL;
-
- // do we need to correct the scrollbar visibility?
- if ( bHaveBar && !i_needBar )
- {
- if ( _rpBar->IsTracking() )
- _rpBar->EndTracking();
- DELETEZ( _rpBar );
- }
- else if ( !bHaveBar && i_needBar )
- {
- _rpBar = new ScrollBar(
- &_rParent,
- WB_DRAG | ( _bHorizontal ? WB_HSCROLL : WB_VSCROLL )
- );
- _rpBar->SetScrollHdl( _rScrollHandler );
- // get some speed into the scrolling ....
- lcl_setButtonRepeat( *_rpBar, 0 );
- }
-
- if ( _rpBar )
- {
- _rpBar->SetRange( Range( 0, _nRange ) );
- _rpBar->SetVisibleSize( _nVisibleUnits );
- _rpBar->SetPageSize( _nVisibleUnits );
- _rpBar->SetLineSize( _nLineSize );
- _rpBar->SetThumbPos( _nPosition );
- _rpBar->Show();
- }
- }
-
- //..............................................................................................................
- /** returns the number of rows fitting into the given range,
- for the given row height. Partially fitting rows are counted, too, if the
- respective parameter says so.
- */
- TableSize lcl_getRowsFittingInto( long _nOverallHeight, long _nRowHeightPixel, bool _bAcceptPartialRow = false )
- {
- return _bAcceptPartialRow
- ? ( _nOverallHeight + ( _nRowHeightPixel - 1 ) ) / _nRowHeightPixel
- : _nOverallHeight / _nRowHeightPixel;
- }
-
- //..............................................................................................................
- /** returns the number of columns fitting into the given area,
- with the first visible column as given. Partially fitting columns are counted, too,
- if the respective parameter says so.
- */
- TableSize lcl_getColumnsVisibleWithin( const Rectangle& _rArea, ColPos _nFirstVisibleColumn,
- const TableControl_Impl& _rControl, bool _bAcceptPartialRow )
- {
- TableSize visibleColumns = 0;
- TableColumnGeometry aColumn( _rControl, _rArea, _nFirstVisibleColumn );
- while ( aColumn.isValid() )
- {
- if ( !_bAcceptPartialRow )
- if ( aColumn.getRect().Right() > _rArea.Right() )
- // this column is only partially visible, and this is not allowed
- break;
+ ENSURE_OR_RETURN_VOID( !m_bUpdatingColWidths, "TableControl_Impl::impl_ni_relayout: recursive call detected!" );
- aColumn.moveRight();
- ++visibleColumns;
- }
- return visibleColumns;
- }
-
- }
+ m_aColumnWidths.resize( 0 );
+ if ( !m_pModel )
+ return;
- //------------------------------------------------------------------------------------------------------------------
- void TableControl_Impl::impl_ni_updateScrollbars()
- {
+ ::comphelper::FlagRestorationGuard const aWidthUpdateFlag( m_bUpdatingColWidths, true );
SuppressCursor aHideCursor( *this );
+ // layouting steps:
+ //
+ // 1. adjust column widths, leaving space for a vertical scrollbar
+ // 2. determine need for a vertical scrollbar
+ // - V-YES: all fine, result from 1. is still valid
+ // - V-NO: result from 1. is still under consideration
+ //
+ // 3. determine need for a horizontal scrollbar
+ // - H-NO: all fine, result from 2. is still valid
+ // - H-YES: reconsider need for a vertical scrollbar, if result of 2. was V-NO
+ // - V-YES: all fine, result from 1. is still valid
+ // - V-NO: redistribute the remaining space (if any) amongst all columns which allow it
+
+ ::std::vector< long > newWidthsPixel;
+ long gridWidthPixel = impl_ni_calculateColumnWidths( i_assumeInflexibleColumnsUpToIncluding, true, newWidthsPixel );
+
// the width/height of a scrollbar, needed several times below
long const nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
@@ -1181,18 +1212,13 @@ namespace svt { namespace table
Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() );
aDataCellPlayground.Left() = m_nRowHeaderWidthPixel;
aDataCellPlayground.Top() = m_nColHeaderHeightPixel;
- m_nRowCount = m_pModel->getRowCount();
- m_nColumnCount = m_pModel->getColumnCount();
- if ( m_aColumnWidths.empty() )
- impl_ni_updateColumnWidths();
- OSL_ENSURE( m_aColumnWidths.size() == size_t( m_nColumnCount ), "TableControl_Impl::impl_ni_updateScrollbars: inconsistency!" );
- const long nAllColumnsWidth = m_aColumnWidths.empty()
- ? 0
- : m_aColumnWidths[ m_nColumnCount - 1 ].getEnd() - m_aColumnWidths[ 0 ].getStart();
+ OSL_ENSURE( ( m_nRowCount == m_pModel->getRowCount() ) && ( m_nColumnCount == m_pModel->getColumnCount() ),
+ "TableControl_Impl::impl_ni_relayout: how is this expected to work with invalid data?" );
+ long const nAllColumnsWidth = ::std::accumulate( newWidthsPixel.begin(), newWidthsPixel.end(), 0 );
- const ScrollbarVisibility eVertScrollbar = m_pModel->getVerticalScrollbarVisibility();
- const ScrollbarVisibility eHorzScrollbar = m_pModel->getHorizontalScrollbarVisibility();
+ ScrollbarVisibility const eVertScrollbar = m_pModel->getVerticalScrollbarVisibility();
+ ScrollbarVisibility const eHorzScrollbar = m_pModel->getHorizontalScrollbarVisibility();
// do we need a vertical scrollbar?
bool bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
@@ -1203,8 +1229,10 @@ namespace svt { namespace table
aDataCellPlayground.Right() -= nScrollbarMetrics;
bFirstRoundVScrollNeed = true;
}
+
// do we need a horizontal scrollbar?
- const bool bNeedHorizontalScrollbar = lcl_determineScrollbarNeed( m_nLeftColumn, eHorzScrollbar, aDataCellPlayground.GetWidth(), nAllColumnsWidth );
+ bool const bNeedHorizontalScrollbar = lcl_determineScrollbarNeed(
+ m_nLeftColumn, eHorzScrollbar, aDataCellPlayground.GetWidth(), nAllColumnsWidth );
if ( bNeedHorizontalScrollbar )
{
aDataCellPlayground.Bottom() -= nScrollbarMetrics;
@@ -1223,12 +1251,77 @@ namespace svt { namespace table
}
}
}
+
+ // the initial call to impl_ni_calculateColumnWidths assumed that we need a vertical scrollbar. If, by now,
+ // we know that this is not the case, re-calculate the column widths.
+ if ( !bNeedVerticalScrollbar )
+ gridWidthPixel = impl_ni_calculateColumnWidths( i_assumeInflexibleColumnsUpToIncluding, false, newWidthsPixel );
+
+ // update the column objects with the new widths we finally calculated
+ TableSize const colCount = m_pModel->getColumnCount();
+ m_aColumnWidths.reserve( colCount );
+ long accumulatedWidthPixel = m_nRowHeaderWidthPixel;
+ bool anyColumnWidthChanged = false;
+ for ( ColPos col = 0; col < colCount; ++col )
+ {
+ const long columnStart = accumulatedWidthPixel;
+ const long columnEnd = columnStart + newWidthsPixel[col];
+ m_aColumnWidths.push_back( MutableColumnMetrics( columnStart, columnEnd ) );
+ accumulatedWidthPixel = columnEnd;
+
+ // and don't forget to forward this to the column models
+ PColumnModel const pColumn = m_pModel->getColumnModel( col );
+ ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
+
+ long const oldColumnWidthAppFont = pColumn->getWidth();
+ long const newColumnWidthAppFont = pixelWidthToAppFont( newWidthsPixel[col] );
+ pColumn->setWidth( newColumnWidthAppFont );
+
+ anyColumnWidthChanged |= ( oldColumnWidthAppFont != newColumnWidthAppFont );
+ }
+
+ // if the column widths changed, ensure everything is repainted
+ if ( anyColumnWidthChanged )
+ invalidate( TableAreaAll );
+
+ // if the column resizing happened to leave some space at the right, but there are columns
+ // scrolled out to the left, scroll them in
+ while ( ( m_nLeftColumn > 0 )
+ && ( accumulatedWidthPixel - m_aColumnWidths[ m_nLeftColumn - 1 ].getStart() <= gridWidthPixel )
+ )
+ {
+ --m_nLeftColumn;
+ }
+
+ // now adjust the column metrics, since they currently ignore the horizontal scroll position
+ if ( m_nLeftColumn > 0 )
+ {
+ const long offsetPixel = m_aColumnWidths[ 0 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getStart();
+ for ( ColumnPositions::iterator colPos = m_aColumnWidths.begin();
+ colPos != m_aColumnWidths.end();
+ ++colPos
+ )
+ {
+ colPos->move( offsetPixel );
+ }
+ }
+
+ // show or hide the scrollbars as needed, and position the data window
+ impl_ni_positionChildWindows( aDataCellPlayground, bNeedVerticalScrollbar, bNeedHorizontalScrollbar );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::impl_ni_positionChildWindows( Rectangle const & i_dataCellPlayground,
+ bool const i_verticalScrollbar, bool const i_horizontalScrollbar )
+ {
+ long const nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
+
// create or destroy the vertical scrollbar, as needed
lcl_updateScrollbar(
m_rAntiImpl,
m_pVScroll,
- bNeedVerticalScrollbar,
- lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ),
+ i_verticalScrollbar,
+ lcl_getRowsFittingInto( i_dataCellPlayground.GetHeight(), m_nRowHeightPixel ),
// visible units
m_nTopRow, // current position
1, // line size
@@ -1236,12 +1329,13 @@ namespace svt { namespace table
false, // vertical
LINK( this, TableControl_Impl, OnScroll ) // scroll handler
);
+
// position it
if ( m_pVScroll )
{
Rectangle aScrollbarArea(
- Point( aDataCellPlayground.Right() + 1, 0 ),
- Size( nScrollbarMetrics, aDataCellPlayground.Bottom() + 1 )
+ Point( i_dataCellPlayground.Right() + 1, 0 ),
+ Size( nScrollbarMetrics, i_dataCellPlayground.Bottom() + 1 )
);
m_pVScroll->SetPosSizePixel(
aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() );
@@ -1251,8 +1345,8 @@ namespace svt { namespace table
lcl_updateScrollbar(
m_rAntiImpl,
m_pHScroll,
- bNeedHorizontalScrollbar,
- lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false ),
+ i_horizontalScrollbar,
+ lcl_getColumnsVisibleWithin( i_dataCellPlayground, m_nLeftColumn, *this, false ),
// visible units
m_nLeftColumn, // current position
1, // line size
@@ -1260,22 +1354,23 @@ namespace svt { namespace table
true, // horizontal
LINK( this, TableControl_Impl, OnScroll ) // scroll handler
);
+
// position it
if ( m_pHScroll )
{
- TableSize const nVisibleUnits = lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false );
+ TableSize const nVisibleUnits = lcl_getColumnsVisibleWithin( i_dataCellPlayground, m_nLeftColumn, *this, false );
TableMetrics const nRange = m_nColumnCount;
if( m_nLeftColumn + nVisibleUnits == nRange - 1 )
{
- if ( m_aColumnWidths[ nRange - 1 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getEnd() + m_aColumnWidths[ nRange-1 ].getWidth() > aDataCellPlayground.GetWidth() )
+ if ( m_aColumnWidths[ nRange - 1 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getEnd() + m_aColumnWidths[ nRange-1 ].getWidth() > i_dataCellPlayground.GetWidth() )
{
m_pHScroll->SetVisibleSize( nVisibleUnits -1 );
m_pHScroll->SetPageSize( nVisibleUnits - 1 );
}
}
Rectangle aScrollbarArea(
- Point( 0, aDataCellPlayground.Bottom() + 1 ),
- Size( aDataCellPlayground.Right() + 1, nScrollbarMetrics )
+ Point( 0, i_dataCellPlayground.Bottom() + 1 ),
+ Size( i_dataCellPlayground.Right() + 1, nScrollbarMetrics )
);
m_pHScroll->SetPosSizePixel(
aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() );
@@ -1292,19 +1387,19 @@ namespace svt { namespace table
{
m_pScrollCorner = new ScrollBarBox( &m_rAntiImpl );
m_pScrollCorner->SetSizePixel( Size( nScrollbarMetrics, nScrollbarMetrics ) );
- m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) );
+ m_pScrollCorner->SetPosPixel( Point( i_dataCellPlayground.Right() + 1, i_dataCellPlayground.Bottom() + 1 ) );
m_pScrollCorner->Show();
}
else if(bHaveScrollCorner && bNeedScrollCorner)
{
- m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) );
+ m_pScrollCorner->SetPosPixel( Point( i_dataCellPlayground.Right() + 1, i_dataCellPlayground.Bottom() + 1 ) );
m_pScrollCorner->Show();
}
// resize the data window
m_pDataWindow->SetSizePixel( Size(
- aDataCellPlayground.GetWidth() + m_nRowHeaderWidthPixel,
- aDataCellPlayground.GetHeight() + m_nColHeaderHeightPixel
+ i_dataCellPlayground.GetWidth() + m_nRowHeaderWidthPixel,
+ i_dataCellPlayground.GetHeight() + m_nColHeaderHeightPixel
) );
}
@@ -1313,8 +1408,7 @@ namespace svt { namespace table
{
DBG_CHECK_ME();
- impl_ni_updateColumnWidths();
- impl_ni_updateScrollbars();
+ impl_ni_relayout();
checkCursorPosition();
}
@@ -1408,14 +1502,14 @@ namespace svt { namespace table
if ( _rUpdateRect.GetIntersection( aRowIterator.getRect() ).IsEmpty() )
continue;
- bool const isActiveRow = ( aRowIterator.getRow() == getCurrentRow() );
+ bool const isControlFocused = m_rAntiImpl.HasControlFocus();
bool const isSelectedRow = isRowSelected( aRowIterator.getRow() );
Rectangle const aRect = aRowIterator.getRect().GetIntersection( aAllDataCellsArea );
// give the redenderer a chance to prepare the row
pRenderer->PrepareRow(
- aRowIterator.getRow(), isActiveRow, isSelectedRow,
+ aRowIterator.getRow(), isControlFocused, isSelectedRow,
*m_pDataWindow, aRect, rStyle
);
@@ -1423,7 +1517,7 @@ namespace svt { namespace table
if ( m_pModel->hasRowHeaders() )
{
const Rectangle aCurrentRowHeader( aRowHeaderArea.GetIntersection( aRowIterator.getRect() ) );
- pRenderer->PaintRowHeader( isActiveRow, isSelectedRow, *m_pDataWindow, aCurrentRowHeader,
+ pRenderer->PaintRowHeader( isControlFocused, isSelectedRow, *m_pDataWindow, aCurrentRowHeader,
rStyle );
}
@@ -1437,7 +1531,7 @@ namespace svt { namespace table
)
{
bool isSelectedColumn = false;
- pRenderer->PaintCell( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow,
+ pRenderer->PaintCell( aCell.getColumn(), isSelectedRow || isSelectedColumn, isControlFocused,
*m_pDataWindow, aCell.getRect(), rStyle );
}
}
@@ -1469,30 +1563,25 @@ namespace svt { namespace table
bool bSuccess = false;
bool selectionChanged = false;
- Rectangle rCells;
switch ( _eAction )
{
case cursorDown:
- if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
+ if ( m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION )
{
//if other rows already selected, deselect them
- if(m_aSelectedRows.size()>0)
+ if ( m_aSelectedRows.size()>0 )
{
- for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
- it!=m_aSelectedRows.end();++it)
- {
- invalidateSelectedRegion(*it, *it, rCells);
- }
+ invalidateSelectedRows();
m_aSelectedRows.clear();
}
- if(m_nCurRow < m_nRowCount-1)
+ if ( m_nCurRow < m_nRowCount-1 )
{
++m_nCurRow;
m_aSelectedRows.push_back(m_nCurRow);
}
else
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
ensureVisible(m_nCurColumn,m_nCurRow,false);
selectionChanged = true;
bSuccess = true;
@@ -1509,23 +1598,19 @@ namespace svt { namespace table
{
if(m_aSelectedRows.size()>0)
{
- for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
- it!=m_aSelectedRows.end();++it)
- {
- invalidateSelectedRegion(*it, *it, rCells);
- }
+ invalidateSelectedRows();
m_aSelectedRows.clear();
}
if(m_nCurRow>0)
{
--m_nCurRow;
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
else
{
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
ensureVisible(m_nCurColumn,m_nCurRow,false);
selectionChanged = true;
@@ -1607,7 +1692,7 @@ namespace svt { namespace table
//else select the row->put it in the vector
else
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
selectionChanged = true;
bSuccess = true;
}
@@ -1630,14 +1715,10 @@ namespace svt { namespace table
//and select the current row
if(m_nAnchor==-1)
{
- for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
- it!=m_aSelectedRows.end();++it)
- {
- invalidateSelectedRegion(*it, *it, rCells);
- }
+ invalidateSelectedRows();
m_aSelectedRows.clear();
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
else
{
@@ -1655,12 +1736,12 @@ namespace svt { namespace table
if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
{
m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
- invalidateSelectedRegion(m_nCurRow+1, m_nCurRow+1, rCells);
+ invalidateRow( m_nCurRow + 1 );
}
else
{
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
}
else
@@ -1670,7 +1751,7 @@ namespace svt { namespace table
m_aSelectedRows.push_back(m_nCurRow);
m_nCurRow--;
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
+ invalidateSelectedRegion( m_nCurRow+1, m_nCurRow );
}
}
}
@@ -1685,12 +1766,12 @@ namespace svt { namespace table
m_aSelectedRows.push_back(m_nCurRow);
m_nCurRow--;
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
+ invalidateSelectedRegion( m_nCurRow+1, m_nCurRow );
}
else
{
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
}
m_pSelEngine->SetAnchor(sal_True);
@@ -1717,14 +1798,10 @@ namespace svt { namespace table
//and select the current row
if(m_nAnchor==-1)
{
- for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
- it!=m_aSelectedRows.end();++it)
- {
- invalidateSelectedRegion(*it, *it, rCells);
- }
+ invalidateSelectedRows();
m_aSelectedRows.clear();
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
else
{
@@ -1742,12 +1819,12 @@ namespace svt { namespace table
if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
{
m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
- invalidateSelectedRegion(m_nCurRow-1, m_nCurRow-1, rCells);
+ invalidateRow( m_nCurRow - 1 );
}
else
{
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
}
else
@@ -1757,7 +1834,7 @@ namespace svt { namespace table
m_aSelectedRows.push_back(m_nCurRow);
m_nCurRow++;
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
+ invalidateSelectedRegion( m_nCurRow-1, m_nCurRow );
}
}
}
@@ -1770,12 +1847,12 @@ namespace svt { namespace table
m_aSelectedRows.push_back(m_nCurRow);
m_nCurRow++;
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
+ invalidateSelectedRegion( m_nCurRow-1, m_nCurRow );
}
else
{
m_aSelectedRows.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ invalidateRow( m_nCurRow );
}
}
m_pSelEngine->SetAnchor(sal_True);
@@ -1797,7 +1874,7 @@ namespace svt { namespace table
{
//select the region between the current and the upper row
RowPos iter = m_nCurRow;
- invalidateSelectedRegion(m_nCurRow, 0, rCells);
+ invalidateSelectedRegion( m_nCurRow, 0 );
//put the rows in vector
while(iter>=0)
{
@@ -1823,7 +1900,7 @@ namespace svt { namespace table
return bSuccess = false;
//select the region between the current and the last row
RowPos iter = m_nCurRow;
- invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells);
+ invalidateSelectedRegion( m_nCurRow, m_nRowCount-1 );
//put the rows in the vector
while(iter<=m_nRowCount)
{
@@ -2001,6 +2078,12 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
+ long TableControl_Impl::appFontWidthToPixel( long const i_appFontUnits ) const
+ {
+ return m_pDataWindow->LogicToPixel( Size( i_appFontUnits, 0 ), MAP_APPFONT ).Width();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::hideTracking()
{
m_pDataWindow->HideTracking();
@@ -2020,48 +2103,59 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
- void TableControl_Impl::invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect)
+ void TableControl_Impl::invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow )
{
DBG_CHECK_ME();
- //get the visible area of the table control and set the Left and right border of the region to be repainted
+ // get the visible area of the table control and set the Left and right border of the region to be repainted
Rectangle const aAllCells( impl_getAllVisibleCellsArea() );
- _rCellRect.Left() = aAllCells.Left();
- _rCellRect.Right() = aAllCells.Right();
- //if only one row is selected
- if(_nPrevRow == _nCurRow)
+
+ Rectangle aInvalidateRect;
+ aInvalidateRect.Left() = aAllCells.Left();
+ aInvalidateRect.Right() = aAllCells.Right();
+ // if only one row is selected
+ if ( _nPrevRow == _nCurRow )
{
Rectangle aCellRect;
impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
- _rCellRect.Top() = aCellRect.Top();
- _rCellRect.Bottom() = aCellRect.Bottom();
+ aInvalidateRect.Top() = aCellRect.Top();
+ aInvalidateRect.Bottom() = aCellRect.Bottom();
}
//if the region is above the current row
else if(_nPrevRow < _nCurRow )
{
Rectangle aCellRect;
impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
- _rCellRect.Top() = aCellRect.Top();
+ aInvalidateRect.Top() = aCellRect.Top();
impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
- _rCellRect.Bottom() = aCellRect.Bottom();
+ aInvalidateRect.Bottom() = aCellRect.Bottom();
}
//if the region is beneath the current row
else
{
Rectangle aCellRect;
impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
- _rCellRect.Top() = aCellRect.Top();
+ aInvalidateRect.Top() = aCellRect.Top();
impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
- _rCellRect.Bottom() = aCellRect.Bottom();
+ aInvalidateRect.Bottom() = aCellRect.Bottom();
}
- m_pDataWindow->Invalidate(_rCellRect);
+ m_pDataWindow->Invalidate( aInvalidateRect );
}
+
//------------------------------------------------------------------------------------------------------------------
- void TableControl_Impl::invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow )
+ void TableControl_Impl::invalidateSelectedRows()
{
- if ( m_nCursorHidden == 2 )
- // WTF? what kind of hack is this?
- --m_nCursorHidden;
+ for ( ::std::vector< RowPos >::iterator selRow = m_aSelectedRows.begin();
+ selRow != m_aSelectedRows.end();
+ ++selRow
+ )
+ {
+ invalidateRow( *selRow );
+ }
+ }
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow )
+ {
RowPos const firstRow = i_firstRow < m_nTopRow ? m_nTopRow : i_firstRow;
RowPos const lastVisibleRow = m_nTopRow + impl_getVisibleRows( true ) - 1;
RowPos const lastRow = ( ( i_lastRow == ROW_INVALID ) || ( i_lastRow > lastVisibleRow ) ) ? lastVisibleRow : i_lastRow;
@@ -2203,9 +2297,13 @@ namespace svt { namespace table
//--------------------------------------------------------------------
::rtl::OUString TableControl_Impl::getCellContentAsString( RowPos const i_row, ColPos const i_col )
{
- ::com::sun::star::uno::Any content;
- m_pModel->getCellContent( i_col, i_row, content );
- return CellValueConversion::convertToString( content );
+ Any aCellValue;
+ m_pModel->getCellContent( i_col, i_row, aCellValue );
+
+ ::rtl::OUString sCellStringContent;
+ m_pModel->getRenderer()->GetFormattedCellString( aCellValue, i_col, i_row, sCellStringContent );
+
+ return sCellStringContent;
}
//--------------------------------------------------------------------
@@ -2245,12 +2343,19 @@ namespace svt { namespace table
m_pDataWindow->Invalidate( INVALIDATE_UPDATE );
// update the position at the vertical scrollbar
- m_pVScroll->SetThumbPos( m_nTopRow );
- }
-
- // The scroll bar availaility might change when we scrolled. This is because we do not hide
- // the scrollbar when it is, in theory, unnecessary, but currently at a position > 0. In this case, it will
- // be auto-hidden when it's scrolled back to pos 0.
+ if ( m_pVScroll != NULL )
+ m_pVScroll->SetThumbPos( m_nTopRow );
+ }
+
+ // The scroll bar availaility might change when we scrolled.
+ // For instance, imagine a view with 10 rows, if which 5 fit into the window, numbered 1 to 10.
+ // Now let
+ // - the user scroll to row number 6, so the last 5 rows are visible
+ // - somebody remove the last 4 rows
+ // - the user scroll to row number 5 being the top row, so the last two rows are visible
+ // - somebody remove row number 6
+ // - the user scroll to row number 1
+ // => in this case, the need for the scrollbar vanishes immediately.
if ( m_nTopRow == 0 )
m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
@@ -2315,7 +2420,8 @@ namespace svt { namespace table
m_pDataWindow->Invalidate( INVALIDATE_UPDATE );
// update the position at the horizontal scrollbar
- m_pHScroll->SetThumbPos( m_nLeftColumn );
+ if ( m_pHScroll != NULL )
+ m_pHScroll->SetThumbPos( m_nLeftColumn );
}
// The scroll bar availaility might change when we scrolled. This is because we do not hide
@@ -2388,18 +2494,16 @@ namespace svt { namespace table
if ( i_ordinate < m_nRowHeaderWidthPixel )
return COL_ROW_HEADERS;
- long const ordinate = i_ordinate - m_nRowHeaderWidthPixel;
-
ColumnPositions::const_iterator lowerBound = ::std::lower_bound(
m_aColumnWidths.begin(),
m_aColumnWidths.end(),
- ordinate + 1,
+ i_ordinate + 1,
ColumnInfoPositionLess()
);
if ( lowerBound == m_aColumnWidths.end() )
{
// point is *behind* the start of the last column ...
- if ( ordinate < m_aColumnWidths.rbegin()->getEnd() )
+ if ( i_ordinate < m_aColumnWidths.rbegin()->getEnd() )
// ... but still before its end
return m_nColumnCount - 1;
return COL_INVALID;
@@ -2506,6 +2610,28 @@ namespace svt { namespace table
}
//--------------------------------------------------------------------
+ void TableControl_Impl::commitAccessibleEvent( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ impl_commitAccessibleEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ //--------------------------------------------------------------------
+ void TableControl_Impl::commitCellEvent( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ DBG_CHECK_ME();
+ if ( impl_isAccessibleAlive() )
+ m_pAccessibleTable->commitCellEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ //--------------------------------------------------------------------
+ void TableControl_Impl::commitTableEvent( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ DBG_CHECK_ME();
+ if ( impl_isAccessibleAlive() )
+ m_pAccessibleTable->commitTableEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ //--------------------------------------------------------------------
Rectangle TableControl_Impl::calcHeaderRect(bool bColHeader)
{
Rectangle const aRectTableWithHeaders( impl_getAllVisibleCellsArea() );
@@ -2517,16 +2643,38 @@ namespace svt { namespace table
}
//--------------------------------------------------------------------
+ Rectangle TableControl_Impl::calcHeaderCellRect( bool bColHeader, sal_Int32 nPos )
+ {
+ Rectangle const aHeaderRect = calcHeaderRect( bColHeader );
+ TableCellGeometry const aGeometry(
+ *this, aHeaderRect,
+ bColHeader ? nPos : COL_ROW_HEADERS,
+ bColHeader ? ROW_COL_HEADERS : nPos
+ );
+ return aGeometry.getRect();
+ }
+
+ //--------------------------------------------------------------------
Rectangle TableControl_Impl::calcTableRect()
{
return impl_getAllVisibleDataCellArea();
}
//--------------------------------------------------------------------
+ Rectangle TableControl_Impl::calcCellRect( sal_Int32 nRow, sal_Int32 nCol )
+ {
+ Rectangle aCellRect;
+ impl_getCellRect( nRow, nCol, aCellRect );
+ return aCellRect;
+ }
+
+ //--------------------------------------------------------------------
IMPL_LINK( TableControl_Impl, OnUpdateScrollbars, void*, /**/ )
{
DBG_CHECK_ME();
- impl_ni_updateScrollbars();
+ // TODO: can't we simply use lcl_updateScrollbar here, so the scrollbars ranges are updated, instead of
+ // doing a complete re-layout?
+ impl_ni_relayout();
return 1L;
}
@@ -2666,8 +2814,7 @@ namespace svt { namespace table
}
m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
}
- Rectangle aCellRect;
- m_pTableControl->invalidateSelectedRegion( m_pTableControl->getCurRow(), newRow, aCellRect );
+ m_pTableControl->invalidateSelectedRegion( m_pTableControl->getCurRow(), newRow );
bHandled = sal_True;
}
//no region selected
@@ -2690,8 +2837,7 @@ namespace svt { namespace table
if ( m_pTableControl->getSelectedRowCount() > 1 && m_pTableControl->getSelEngine()->GetSelectionMode() != SINGLE_SELECTION )
m_pTableControl->getSelEngine()->AddAlways(sal_True);
- Rectangle aCellRect;
- m_pTableControl->invalidateSelectedRegion( newRow, newRow, aCellRect );
+ m_pTableControl->invalidateRow( newRow );
bHandled = sal_True;
}
m_pTableControl->goTo( newCol, newRow );
@@ -2716,8 +2862,7 @@ namespace svt { namespace table
void TableFunctionSet::DeselectAtPoint( const Point& rPoint )
{
(void)rPoint;
- Rectangle aCellRange;
- m_pTableControl->invalidateSelectedRegion( m_nCurrentRow, m_nCurrentRow, aCellRange );
+ m_pTableControl->invalidateRow( m_nCurrentRow );
m_pTableControl->markRowAsDeselected( m_nCurrentRow );
}
@@ -2726,11 +2871,10 @@ namespace svt { namespace table
{
if ( m_pTableControl->hasRowSelection() )
{
- Rectangle aCellRange;
for ( size_t i=0; i<m_pTableControl->getSelectedRowCount(); ++i )
{
RowPos const rowIndex = m_pTableControl->getSelectedRowIndex(i);
- m_pTableControl->invalidateSelectedRegion( rowIndex, rowIndex, aCellRange );
+ m_pTableControl->invalidateRow( rowIndex );
}
m_pTableControl->markAllRowsAsDeselected();
diff --git a/svtools/source/table/tablecontrol_impl.hxx b/svtools/source/table/tablecontrol_impl.hxx
index bc1ac55fbe51..4f3d18aa84fd 100755..100644
--- a/svtools/source/table/tablecontrol_impl.hxx
+++ b/svtools/source/table/tablecontrol_impl.hxx
@@ -226,10 +226,10 @@ namespace svt { namespace table
/** returns the position of the current row in the selection vector */
int getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current);
- /** _rCellRect contains the region, which should be invalidate after some action e.g. selecting row*/
- void invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect );
+ /** ??? */
+ void invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow );
- /** invalidates the part of the data window which is covered by the given row
+ /** invalidates the part of the data window which is covered by the given rows
@param i_firstRow
the index of the first row to include in the invalidation
@param i_lastRow
@@ -238,6 +238,14 @@ namespace svt { namespace table
*/
void invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow );
+ /** invalidates the part of the data window which is covered by the given row
+ */
+ void invalidateRow( RowPos const i_row ) { invalidateRowRange( i_row, i_row ); }
+
+ /** invalidates all selected rows
+ */
+ void invalidateSelectedRows();
+
void checkCursorPosition();
bool hasRowSelection() const { return !m_aSelectedRows.empty(); }
@@ -272,6 +280,10 @@ namespace svt { namespace table
void setSelectHandler( Link const & i_selectHandler ) { m_aSelectHdl = i_selectHandler; }
Link const& getSelectHandler() const { return m_aSelectHdl; }
+ void commitAccessibleEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue );
+ void commitCellEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue );
+ void commitTableEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue );
+
// ITableControl
virtual void hideCursor();
virtual void showCursor();
@@ -296,19 +308,25 @@ namespace svt { namespace table
virtual bool isRowSelected( RowPos i_row ) const;
+ long appFontWidthToPixel( long const i_appFontUnits ) const;
+
TableDataWindow& getDataWindow() { return *m_pDataWindow; }
const TableDataWindow& getDataWindow() const { return *m_pDataWindow; }
ScrollBar* getHorzScrollbar();
ScrollBar* getVertScrollbar();
- Rectangle calcHeaderRect(bool bColHeader);
+ Rectangle calcHeaderRect( bool bColHeader );
+ Rectangle calcHeaderCellRect( bool bColHeader, sal_Int32 nPos );
Rectangle calcTableRect();
+ Rectangle calcCellRect( sal_Int32 nRow, sal_Int32 nCol );
// A11Y
::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
getAccessible( Window& i_parentWindow );
void disposeAccessible();
+ inline bool isAccessibleAlive() const { return impl_isAccessibleAlive(); }
+
// ITableModelListener
virtual void rowsInserted( RowPos first, RowPos last );
virtual void rowsRemoved( RowPos first, RowPos last );
@@ -371,26 +389,45 @@ namespace svt { namespace table
*/
void impl_ni_updateCachedTableMetrics();
- /** updates ->m_aColumnWidthsPixel with the current pixel widths of all model columns
+ /** does a relayout of the table control
- The method is not bound to the classes public invariants, as it's used in
- situations where the they must not necessarily be fullfilled.
+ Column widths, and consequently the availability of the vertical and horizontal scrollbar, are updated
+ with a call to this method.
@param i_assumeInflexibleColumnsUpToIncluding
the index of a column up to which all columns should be considered as inflexible, or
<code>COL_INVALID</code>.
*/
- void impl_ni_updateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID );
+ void impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID );
- /** updates the scrollbars of the control
+ /** calculates the new width of our columns, taking into account their min and max widths, and their relative
+ flexibility.
- The method is not bound to the classes public invariants, as it's used in
- situations where the they must not necessarily be fullfilled.
+ @param i_assumeInflexibleColumnsUpToIncluding
+ the index of a column up to which all columns should be considered as inflexible, or
+ <code>COL_INVALID</code>.
+
+ @param i_assumeVerticalScrollbar
+ controls whether or not we should assume the presence of a vertical scrollbar. If <true/>, and
+ if the model has a VerticalScrollbarVisibility != ScrollbarShowNever, the method will leave
+ space for a vertical scrollbar.
+
+ @return
+ the overall width of the grid, which is available for columns
+ */
+ long impl_ni_calculateColumnWidths(
+ ColPos const i_assumeInflexibleColumnsUpToIncluding,
+ bool const i_assumeVerticalScrollbar,
+ ::std::vector< long >& o_newColWidthsPixel
+ ) const;
- This includes both the existence of the scrollbars, and their
- state.
+ /** positions all child windows, e.g. the both scrollbars, the corner window, and the data window
*/
- void impl_ni_updateScrollbars();
+ void impl_ni_positionChildWindows(
+ Rectangle const & i_dataCellPlayground,
+ bool const i_verticalScrollbar,
+ bool const i_horizontalScrollbar
+ );
/** scrolls the view by the given number of rows
diff --git a/svtools/source/table/tabledatawindow.cxx b/svtools/source/table/tabledatawindow.cxx
index 11605e36c8b2..ccdd826686f6 100644
--- a/svtools/source/table/tabledatawindow.cxx
+++ b/svtools/source/table/tabledatawindow.cxx
@@ -32,7 +32,6 @@
#include "tabledatawindow.hxx"
#include "tablecontrol_impl.hxx"
#include "tablegeometry.hxx"
-#include "cellvalueconversion.hxx"
#include <vcl/help.hxx>
@@ -140,7 +139,7 @@ namespace svt { namespace table
aCellToolTip.clear();
}
- sHelpText = CellValueConversion::convertToString( aCellToolTip );
+ pTableModel->getRenderer()->GetFormattedCellString( aCellToolTip, hitCol, hitRow, sHelpText );
if ( sHelpText.indexOf( '\n' ) >= 0 )
nHelpStyle = QUICKHELP_TIP_STYLE_BALLOON;
@@ -149,18 +148,26 @@ namespace svt { namespace table
if ( sHelpText.getLength() )
{
+ // hide the standard (singleton) help window, so we do not have two help windows open at the same time
+ Help::HideBalloonAndQuickHelp();
+
Rectangle const aControlScreenRect(
OutputToScreenPixel( Point( 0, 0 ) ),
GetOutputSizePixel()
);
if ( m_nTipWindowHandle )
+ {
Help::UpdateTip( m_nTipWindowHandle, this, aControlScreenRect, sHelpText );
+ }
else
m_nTipWindowHandle = Help::ShowTip( this, aControlScreenRect, sHelpText, nHelpStyle );
}
else
+ {
impl_hideTipWindow();
+ Window::RequestHelp( rHEvt );
+ }
}
//------------------------------------------------------------------------------------------------------------------
@@ -204,7 +211,6 @@ namespace svt { namespace table
{
m_aSelectHdl.Call( NULL );
}
- m_aMouseButtonDownHdl.Call((MouseEvent*) &rMEvt);
}
//------------------------------------------------------------------------------------------------------------------
@@ -213,7 +219,6 @@ namespace svt { namespace table
if ( !m_rTableControl.getInputHandler()->MouseButtonUp( m_rTableControl, rMEvt ) )
Window::MouseButtonUp( rMEvt );
- m_aMouseButtonUpHdl.Call((MouseEvent*) &rMEvt);
m_rTableControl.getAntiImpl().GrabFocus();
}
diff --git a/svtools/source/table/tabledatawindow.hxx b/svtools/source/table/tabledatawindow.hxx
index 6f78ac49c44d..645c37641870 100644
--- a/svtools/source/table/tabledatawindow.hxx
+++ b/svtools/source/table/tabledatawindow.hxx
@@ -52,8 +52,6 @@ namespace svt { namespace table
friend class TableFunctionSet;
private:
TableControl_Impl& m_rTableControl;
- Link m_aMouseButtonDownHdl;
- Link m_aMouseButtonUpHdl;
Link m_aSelectHdl;
sal_uLong m_nTipWindowHandle;
@@ -61,10 +59,6 @@ namespace svt { namespace table
TableDataWindow( TableControl_Impl& _rTableControl );
~TableDataWindow();
- inline void SetMouseButtonDownHdl( const Link& rLink ) { m_aMouseButtonDownHdl = rLink; }
- inline const Link& GetMouseButtonDownHdl() const { return m_aMouseButtonDownHdl; }
- inline void SetMouseButtonUpHdl( const Link& rLink ) { m_aMouseButtonUpHdl = rLink; }
- inline const Link& GetMouseButtonUpHdl() const { return m_aMouseButtonUpHdl; }
inline void SetSelectHdl( const Link& rLink ) { m_aSelectHdl = rLink; }
inline const Link& GetSelectHdl() const { return m_aSelectHdl; }
diff --git a/svtools/source/toolpanel/drawerlayouter.cxx b/svtools/source/toolpanel/drawerlayouter.cxx
index 4de76107fd20..ecb808395c35 100644
--- a/svtools/source/toolpanel/drawerlayouter.cxx
+++ b/svtools/source/toolpanel/drawerlayouter.cxx
@@ -87,7 +87,7 @@ namespace svt
const size_t nUpperBound = !!aActivePanel ? *aActivePanel : nPanelCount - 1;
for ( size_t i=0; i<=nUpperBound; ++i )
{
- sal_uInt32 nDrawerHeight = m_aDrawers[i]->GetPreferredHeightPixel();
+ long const nDrawerHeight = m_aDrawers[i]->GetPreferredHeightPixel();
m_aDrawers[i]->SetPosSizePixel(
aUpperDrawerPos, Size( nWidth, nDrawerHeight ) );
aUpperDrawerPos.Move( 0, nDrawerHeight );
@@ -97,7 +97,7 @@ namespace svt
Point aLowerDrawerPos( i_rDeckPlayground.BottomLeft() );
for ( size_t j = nPanelCount - 1; j > nUpperBound; --j )
{
- sal_uInt32 nDrawerHeight = m_aDrawers[j]->GetPreferredHeightPixel();
+ long const nDrawerHeight = m_aDrawers[j]->GetPreferredHeightPixel();
m_aDrawers[j]->SetPosSizePixel(
Point( aLowerDrawerPos.X(), aLowerDrawerPos.Y() - nDrawerHeight + 1 ),
Size( nWidth, nDrawerHeight )
diff --git a/svtools/source/uno/svtxgridcontrol.cxx b/svtools/source/uno/svtxgridcontrol.cxx
index 0e826ef6bff3..64b8f9241ae0 100644
--- a/svtools/source/uno/svtxgridcontrol.cxx
+++ b/svtools/source/uno/svtxgridcontrol.cxx
@@ -43,24 +43,52 @@
#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/awt/grid/GridInvalidDataException.hpp>
#include <com/sun/star/awt/grid/GridInvalidModelException.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/util/Color.hpp>
#include <com/sun/star/awt/FontDescriptor.hpp>
+/** === begin UNO using === **/
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::makeAny;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::awt::grid::XGridSelectionListener;
+using ::com::sun::star::style::VerticalAlignment;
+using ::com::sun::star::style::VerticalAlignment_TOP;
+using ::com::sun::star::view::SelectionType;
+using ::com::sun::star::view::SelectionType_NONE;
+using ::com::sun::star::view::SelectionType_RANGE;
+using ::com::sun::star::view::SelectionType_SINGLE;
+using ::com::sun::star::view::SelectionType_MULTI;
+using ::com::sun::star::awt::grid::XGridDataModel;
+using ::com::sun::star::awt::grid::GridInvalidDataException;
+using ::com::sun::star::lang::EventObject;
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+using ::com::sun::star::awt::grid::XGridColumnModel;
+using ::com::sun::star::awt::grid::GridSelectionEvent;
+using ::com::sun::star::awt::grid::XGridColumn;
+using ::com::sun::star::container::ContainerEvent;
+using ::com::sun::star::awt::grid::GridDataEvent;
+using ::com::sun::star::awt::grid::GridInvalidModelException;
+using ::com::sun::star::util::VetoException;
+/** === end UNO using === **/
+
+namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
+namespace AccessibleStateType = ::com::sun::star::accessibility::AccessibleStateType;
+
using namespace ::svt::table;
-using namespace ::com::sun::star::uno;
-using namespace ::com::sun::star::awt::grid;
-using namespace ::com::sun::star::view;
-using namespace ::com::sun::star::style;
-using namespace ::com::sun::star::container;
-using namespace ::com::sun::star::accessibility;
+typedef ::com::sun::star::util::Color UnoColor;
+// ---------------------------------------------------------------------------------------------------------------------
SVTXGridControl::SVTXGridControl()
:m_pTableModel( new UnoControlTableModel() )
- ,m_bHasColumnHeaders( false )
- ,m_bHasRowHeaders( false )
,m_bTableModelInitCompleted( false )
- ,m_nSelectedRowCount( 0 )
,m_aSelectionListeners( *this )
{
}
@@ -78,7 +106,21 @@ void SVTXGridControl::SetWindow( Window* pWindow )
}
// ---------------------------------------------------------------------------------------------------------------------
-sal_Int32 SAL_CALL SVTXGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException)
+void SVTXGridControl::impl_checkColumnIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_columnIndex ) const
+{
+ if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= i_table.GetColumnCount() ) )
+ throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< SVTXGridControl* >( this ) );
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+void SVTXGridControl::impl_checkRowIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_rowIndex ) const
+{
+ if ( ( i_rowIndex < 0 ) || ( i_rowIndex >= i_table.GetRowCount() ) )
+ throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< SVTXGridControl* >( this ) );
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+sal_Int32 SAL_CALL SVTXGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
@@ -90,7 +132,7 @@ sal_Int32 SAL_CALL SVTXGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
}
// ---------------------------------------------------------------------------------------------------------------------
-sal_Int32 SAL_CALL SVTXGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException)
+sal_Int32 SAL_CALL SVTXGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
@@ -125,14 +167,28 @@ sal_Int32 SAL_CALL SVTXGridControl::getCurrentRow( ) throw (RuntimeException)
return ( nRow >= 0 ) ? nRow : -1;
}
+//----------------------------------------------------------------------------------------------------------------------
+void SAL_CALL SVTXGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException, VetoException)
+{
+ ::vos::OGuard aGuard( GetMutex() );
+
+ TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
+ ENSURE_OR_RETURN_VOID( pTable != NULL, "SVTXGridControl::getCurrentRow: no control (anymore)!" );
+
+ impl_checkColumnIndex_throw( *pTable, i_columnIndex );
+ impl_checkRowIndex_throw( *pTable, i_rowIndex );
+
+ pTable->GoTo( i_columnIndex, i_rowIndex );
+}
+
// ---------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::addSelectionListener(const Reference< XGridSelectionListener > & listener) throw (RuntimeException)
{
m_aSelectionListeners.addInterface(listener);
}
// ---------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::removeSelectionListener(const Reference< XGridSelectionListener > & listener) throw (RuntimeException)
{
m_aSelectionListeners.removeInterface(listener);
}
@@ -284,6 +340,27 @@ void SVTXGridControl::setProperty( const ::rtl::OUString& PropertyName, const An
pTable->Invalidate();
break;
+ case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
+ m_pTableModel->setActiveSelectionBackColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
+ m_pTableModel->setInactiveSelectionBackColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
+ m_pTableModel->setActiveSelectionTextColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
+ m_pTableModel->setInactiveSelectionTextColor( aValue );
+ pTable->Invalidate();
+ break;
+
+
case BASEPROPERTY_TEXTCOLOR:
m_pTableModel->setTextColor( aValue );
pTable->Invalidate();
@@ -455,7 +532,7 @@ Any SVTXGridControl::getProperty( const ::rtl::OUString& PropertyName ) throw(Ru
aPropertyValue.clear();
else
{
- Sequence< ::com::sun::star::util::Color > aAPIColors( aColors->size() );
+ Sequence< UnoColor > aAPIColors( aColors->size() );
for ( size_t i=0; i<aColors->size(); ++i )
{
aAPIColors[i] = aColors->at(i).GetColor();
@@ -477,6 +554,22 @@ Any SVTXGridControl::getProperty( const ::rtl::OUString& PropertyName ) throw(Ru
lcl_convertColor( m_pTableModel->getHeaderTextColor(), aPropertyValue );
break;
+ case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
+ lcl_convertColor( m_pTableModel->getActiveSelectionBackColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
+ lcl_convertColor( m_pTableModel->getInactiveSelectionBackColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
+ lcl_convertColor( m_pTableModel->getActiveSelectionTextColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
+ lcl_convertColor( m_pTableModel->getInactiveSelectionTextColor(), aPropertyValue );
+ break;
+
case BASEPROPERTY_TEXTCOLOR:
lcl_convertColor( m_pTableModel->getTextColor(), aPropertyValue );
break;
@@ -505,6 +598,10 @@ void SVTXGridControl::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
BASEPROPERTY_GRID_HEADER_TEXT_COLOR,
BASEPROPERTY_GRID_LINE_COLOR,
BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS,
+ BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR,
+ BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR,
+ BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR,
+ BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR,
0
);
VCLXWindow::ImplGetPropertyIds( rIds, true );
@@ -585,24 +682,26 @@ void SAL_CALL SVTXGridControl::elementReplaced( const ContainerEvent& i_event )
//----------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::disposing( const EventObject& Source ) throw(RuntimeException)
{
VCLXWindow::disposing( Source );
}
//----------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::selectRow( ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::selectRow( ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException )
{
::vos::OGuard aGuard( GetMutex() );
TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectRow: no control (anymore)!" );
+ impl_checkRowIndex_throw( *pTable, i_rowIndex );
+
pTable->SelectRow( i_rowIndex, true );
}
//----------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::selectAllRows() throw (::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::selectAllRows() throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
@@ -613,18 +712,20 @@ void SAL_CALL SVTXGridControl::selectAllRows() throw (::com::sun::star::uno::Run
}
//----------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::deselectRow( ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::deselectRow( ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException )
{
::vos::OGuard aGuard( GetMutex() );
TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectRow: no control (anymore)!" );
+ impl_checkRowIndex_throw( *pTable, i_rowIndex );
+
pTable->SelectRow( i_rowIndex, false );
}
//----------------------------------------------------------------------------------------------------------------------
-void SAL_CALL SVTXGridControl::deselectAllRows() throw (::com::sun::star::uno::RuntimeException)
+void SAL_CALL SVTXGridControl::deselectAllRows() throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
@@ -635,12 +736,12 @@ void SAL_CALL SVTXGridControl::deselectAllRows() throw (::com::sun::star::uno::R
}
//----------------------------------------------------------------------------------------------------------------------
-::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL SVTXGridControl::getSelection() throw (::com::sun::star::uno::RuntimeException)
+Sequence< ::sal_Int32 > SAL_CALL SVTXGridControl::getSelectedRows() throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
- ENSURE_OR_RETURN( pTable, "SVTXGridControl::getSelection: no control (anymore)!", Sequence< sal_Int32 >() );
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getSelectedRows: no control (anymore)!", Sequence< sal_Int32 >() );
sal_Int32 selectionCount = pTable->GetSelectedRowCount();
Sequence< sal_Int32 > selectedRows( selectionCount );
@@ -650,31 +751,31 @@ void SAL_CALL SVTXGridControl::deselectAllRows() throw (::com::sun::star::uno::R
}
//----------------------------------------------------------------------------------------------------------------------
-::sal_Bool SAL_CALL SVTXGridControl::isSelectionEmpty() throw (::com::sun::star::uno::RuntimeException)
+::sal_Bool SAL_CALL SVTXGridControl::hasSelectedRows() throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
- ENSURE_OR_RETURN( pTable, "SVTXGridControl::getSelection: no control (anymore)!", sal_True );
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::hasSelectedRows: no control (anymore)!", sal_True );
return pTable->GetSelectedRowCount() > 0;
}
//----------------------------------------------------------------------------------------------------------------------
-::sal_Bool SAL_CALL SVTXGridControl::isSelectedIndex( ::sal_Int32 index ) throw (::com::sun::star::uno::RuntimeException)
+::sal_Bool SAL_CALL SVTXGridControl::isRowSelected( ::sal_Int32 index ) throw (RuntimeException)
{
::vos::OGuard aGuard( GetMutex() );
TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
- ENSURE_OR_RETURN( pTable, "SVTXGridControl::isSelectedIndex: no control (anymore)!", sal_False );
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::isRowSelected: no control (anymore)!", sal_False );
return pTable->IsRowSelected( index );
}
//----------------------------------------------------------------------------------------------------------------------
-void SVTXGridControl::dispose() throw(::com::sun::star::uno::RuntimeException)
+void SVTXGridControl::dispose() throw(RuntimeException)
{
- ::com::sun::star::lang::EventObject aObj;
+ EventObject aObj;
aObj.Source = (::cppu::OWeakObject*)this;
m_aSelectionListeners.disposeAndClear( aObj );
VCLXWindow::dispose();
@@ -685,22 +786,76 @@ void SVTXGridControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent
{
::vos::OGuard aGuard( GetMutex() );
- ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > xKeepAlive( this );
+ Reference< XWindow > xKeepAlive( this );
+
+ TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ProcessWindowEvent: no control (anymore)!" );
+
+ bool handled = false;
switch ( rVclWindowEvent.GetId() )
{
case VCLEVENT_TABLEROW_SELECT:
{
- TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
- ENSURE_OR_BREAK( pTable, "SVTXGridControl::ProcessWindowEvent: no control (anymore)!" );
if ( m_aSelectionListeners.getLength() )
ImplCallItemListeners();
+ handled = true;
}
break;
- default:
- VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
- break;
+ case VCLEVENT_CONTROL_GETFOCUS:
+ {
+ // TODO: this doesn't belong here. It belongs into the TableControl/_Impl, so A11Y also
+ // works when the control is used outside the UNO context
+ if ( pTable->GetRowCount()>0 )
+ {
+ pTable->commitCellEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ makeAny( AccessibleStateType::FOCUSED ),
+ Any()
+ );
+ pTable->commitTableEventIfAccessibleAlive(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ Any(),
+ Any()
+ );
+ }
+ else
+ {
+ pTable->commitTableEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ makeAny( AccessibleStateType::FOCUSED ),
+ Any()
+ );
+ }
+ }
+ break;
+
+ case VCLEVENT_CONTROL_LOSEFOCUS:
+ {
+ // TODO: this doesn't belong here. It belongs into the TableControl/_Impl, so A11Y also
+ // works when the control is used outside the UNO context
+ if ( pTable->GetRowCount()>0 )
+ {
+ pTable->commitCellEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ Any(),
+ makeAny( AccessibleStateType::FOCUSED )
+ );
+ }
+ else
+ {
+ pTable->commitTableEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ Any(),
+ makeAny( AccessibleStateType::FOCUSED )
+ );
+ }
+ }
+ break;
}
+
+ if ( !handled )
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
}
//----------------------------------------------------------------------------------------------------------------------
@@ -711,42 +866,13 @@ void SVTXGridControl::ImplCallItemListeners()
if ( m_aSelectionListeners.getLength() )
{
- sal_Int32 const actSelRowCount = pTable->GetSelectedRowCount();
- ::com::sun::star::awt::grid::GridSelectionEvent aEvent;
+ GridSelectionEvent aEvent;
aEvent.Source = (::cppu::OWeakObject*)this;
- aEvent.Column = 0;
- sal_Int32 diff = actSelRowCount - m_nSelectedRowCount;
- //row added to selection
- if(diff >= 1)
- {
- aEvent.Action = com::sun::star::awt::grid::SelectionEventType(0);
- aEvent.Row = pTable->GetSelectedRowIndex( actSelRowCount - 1 );
- aEvent.Range = diff;
- }
- //selected row changed
- else if(diff == 0 && actSelRowCount != 0)
- {
- aEvent.Row = pTable->GetSelectedRowIndex( actSelRowCount - 1 );
- aEvent.Action = com::sun::star::awt::grid::SelectionEventType(2);
- aEvent.Range = 0;
- }
- else
- {
- //selection changed: multiple row deselected, only 1 row is selected
- if(actSelRowCount == 1)
- {
- aEvent.Row = pTable->GetSelectedRowIndex( actSelRowCount - 1 );
- aEvent.Action = com::sun::star::awt::grid::SelectionEventType(2);
- }
- //row is deselected
- else
- {
- aEvent.Row = pTable->GetCurrentRow();
- aEvent.Action = com::sun::star::awt::grid::SelectionEventType(1);
- }
- aEvent.Range = 0;
- }
- m_nSelectedRowCount=actSelRowCount;
+
+ sal_Int32 const nSelectedRowCount( pTable->GetSelectedRowCount() );
+ aEvent.SelectedRowIndexes.realloc( nSelectedRowCount );
+ for ( sal_Int32 i=0; i<nSelectedRowCount; ++i )
+ aEvent.SelectedRowIndexes[i] = pTable->GetSelectedRowIndex( i );
m_aSelectionListeners.selectionChanged( aEvent );
}
}
@@ -777,4 +903,3 @@ void SVTXGridControl::impl_updateColumnsFromModel_nothrow()
DBG_UNHANDLED_EXCEPTION();
}
}
-
diff --git a/svtools/source/uno/svtxgridcontrol.hxx b/svtools/source/uno/svtxgridcontrol.hxx
index 525327b3c760..ebde9b76c078 100755
--- a/svtools/source/uno/svtxgridcontrol.hxx
+++ b/svtools/source/uno/svtxgridcontrol.hxx
@@ -31,6 +31,7 @@
#include <unocontroltablemodel.hxx>
#include <svtools/table/tablecontrol.hxx>
#include <com/sun/star/awt/grid/XGridControl.hpp>
+#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
#include <com/sun/star/awt/grid/XGridDataListener.hpp>
#include <com/sun/star/awt/grid/GridDataEvent.hpp>
#include <com/sun/star/awt/grid/GridColumnEvent.hpp>
@@ -45,22 +46,22 @@
#include <toolkit/helper/listenermultiplexer.hxx>
-using namespace ::svt::table;
+namespace svt { namespace table {
+ class TableControl;
+} }
-typedef ::cppu::ImplInheritanceHelper3 < VCLXWindow
+typedef ::cppu::ImplInheritanceHelper4 < VCLXWindow
, ::com::sun::star::awt::grid::XGridControl
+ , ::com::sun::star::awt::grid::XGridRowSelection
, ::com::sun::star::awt::grid::XGridDataListener
, ::com::sun::star::container::XContainerListener
> SVTXGridControl_Base;
class SVTXGridControl : public SVTXGridControl_Base
{
private:
- ::boost::shared_ptr< UnoControlTableModel > m_pTableModel;
- bool m_bHasColumnHeaders;
- bool m_bHasRowHeaders;
- bool m_bTableModelInitCompleted;
- sal_Int32 m_nSelectedRowCount;
- SelectionListenerMultiplexer m_aSelectionListeners;
+ ::boost::shared_ptr< ::svt::table::UnoControlTableModel > m_pTableModel;
+ bool m_bTableModelInitCompleted;
+ SelectionListenerMultiplexer m_aSelectionListeners;
protected:
virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent );
@@ -84,22 +85,23 @@ public:
// XEventListener
virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException);
- // XGridSelection
- virtual void SAL_CALL selectRow( ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException);
- virtual void SAL_CALL selectAllRows() throw (::com::sun::star::uno::RuntimeException);
- virtual void SAL_CALL deselectRow( ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException);
- virtual void SAL_CALL deselectAllRows() throw (::com::sun::star::uno::RuntimeException);
- virtual ::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL getSelection() throw (::com::sun::star::uno::RuntimeException);
- virtual ::sal_Bool SAL_CALL isSelectionEmpty() throw (::com::sun::star::uno::RuntimeException);
- virtual ::sal_Bool SAL_CALL isSelectedIndex(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException);
- virtual void SAL_CALL addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException);
- virtual void SAL_CALL removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException);
-
// XGridControl
virtual ::sal_Int32 SAL_CALL getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException);
virtual ::sal_Int32 SAL_CALL getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException);
virtual ::sal_Int32 SAL_CALL getCurrentColumn( ) throw (::com::sun::star::uno::RuntimeException);
virtual ::sal_Int32 SAL_CALL getCurrentRow( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::util::VetoException);
+
+ // XGridRowSelection
+ virtual void SAL_CALL selectRow( ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IndexOutOfBoundsException );
+ virtual void SAL_CALL selectAllRows() throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL deselectRow( ::sal_Int32 i_rowIndex ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IndexOutOfBoundsException );
+ virtual void SAL_CALL deselectAllRows() throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL getSelectedRows() throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL hasSelectedRows() throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL isRowSelected(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException);
void SAL_CALL setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value ) throw(::com::sun::star::uno::RuntimeException);
::com::sun::star::uno::Any SAL_CALL getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException);
@@ -115,5 +117,8 @@ protected:
private:
void impl_updateColumnsFromModel_nothrow();
void impl_checkTableModelInit();
+
+ void impl_checkColumnIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_columnIndex ) const;
+ void impl_checkRowIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_rowIndex ) const;
};
#endif // _SVT_GRIDCONTROL_HXX_
diff --git a/svtools/source/uno/unocontroltablemodel.cxx b/svtools/source/uno/unocontroltablemodel.cxx
index 933363115810..b4c1bed746fa 100644
--- a/svtools/source/uno/unocontroltablemodel.cxx
+++ b/svtools/source/uno/unocontroltablemodel.cxx
@@ -98,6 +98,10 @@ namespace svt { namespace table
::boost::optional< ::Color > m_aGridLineColor;
::boost::optional< ::Color > m_aHeaderBackgroundColor;
::boost::optional< ::Color > m_aHeaderTextColor;
+ ::boost::optional< ::Color > m_aActiveSelectionBackColor;
+ ::boost::optional< ::Color > m_aInactiveSelectionBackColor;
+ ::boost::optional< ::Color > m_aActiveSelectionTextColor;
+ ::boost::optional< ::Color > m_aInactiveSelectionTextColor;
::boost::optional< ::Color > m_aTextColor;
::boost::optional< ::Color > m_aTextLineColor;
::boost::optional< ::std::vector< ::Color > > m_aRowColors;
@@ -107,23 +111,27 @@ namespace svt { namespace table
WeakReference< XGridColumnModel > m_aColumnModel;
UnoControlTableModel_Impl()
- :aColumns ( )
- ,bHasColumnHeaders ( true )
- ,bHasRowHeaders ( false )
- ,eVScrollMode ( ScrollbarShowNever )
- ,eHScrollMode ( ScrollbarShowNever )
- ,pRenderer ( )
- ,pInputHandler ( )
- ,nRowHeight ( 10 )
- ,nColumnHeaderHeight ( 10 )
- ,nRowHeaderWidth ( 10 )
- ,m_aGridLineColor ( )
- ,m_aHeaderBackgroundColor ( )
- ,m_aHeaderTextColor ( )
- ,m_aTextColor ( )
- ,m_aTextLineColor ( )
- ,m_aRowColors ( )
- ,m_eVerticalAlign ( VerticalAlignment_TOP )
+ :aColumns ( )
+ ,bHasColumnHeaders ( true )
+ ,bHasRowHeaders ( false )
+ ,eVScrollMode ( ScrollbarShowNever )
+ ,eHScrollMode ( ScrollbarShowNever )
+ ,pRenderer ( )
+ ,pInputHandler ( )
+ ,nRowHeight ( 10 )
+ ,nColumnHeaderHeight ( 10 )
+ ,nRowHeaderWidth ( 10 )
+ ,m_aGridLineColor ( )
+ ,m_aHeaderBackgroundColor ( )
+ ,m_aHeaderTextColor ( )
+ ,m_aActiveSelectionBackColor ( )
+ ,m_aInactiveSelectionBackColor ( )
+ ,m_aActiveSelectionTextColor ( )
+ ,m_aInactiveSelectionTextColor ( )
+ ,m_aTextColor ( )
+ ,m_aTextLineColor ( )
+ ,m_aRowColors ( )
+ ,m_eVerticalAlign ( VerticalAlignment_TOP )
{
}
};
@@ -654,6 +662,34 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
+ ::boost::optional< ::Color > UnoControlTableModel::getActiveSelectionBackColor() const
+ {
+ DBG_CHECK_ME();
+ return m_pImpl->m_aActiveSelectionBackColor;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::boost::optional< ::Color > UnoControlTableModel::getInactiveSelectionBackColor() const
+ {
+ DBG_CHECK_ME();
+ return m_pImpl->m_aInactiveSelectionBackColor;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::boost::optional< ::Color > UnoControlTableModel::getActiveSelectionTextColor() const
+ {
+ DBG_CHECK_ME();
+ return m_pImpl->m_aActiveSelectionTextColor;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::boost::optional< ::Color > UnoControlTableModel::getInactiveSelectionTextColor() const
+ {
+ DBG_CHECK_ME();
+ return m_pImpl->m_aInactiveSelectionTextColor;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
void UnoControlTableModel::setHeaderTextColor( Any const & i_color )
{
DBG_CHECK_ME();
@@ -661,6 +697,34 @@ namespace svt { namespace table
}
//------------------------------------------------------------------------------------------------------------------
+ void UnoControlTableModel::setActiveSelectionBackColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_pImpl->m_aActiveSelectionBackColor );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UnoControlTableModel::setInactiveSelectionBackColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_pImpl->m_aInactiveSelectionBackColor );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UnoControlTableModel::setActiveSelectionTextColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_pImpl->m_aActiveSelectionTextColor );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UnoControlTableModel::setInactiveSelectionTextColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_pImpl->m_aInactiveSelectionTextColor );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
::boost::optional< ::Color > UnoControlTableModel::getTextColor() const
{
DBG_CHECK_ME();
diff --git a/svtools/source/uno/unocontroltablemodel.hxx b/svtools/source/uno/unocontroltablemodel.hxx
index 537c3d9a5249..3c5f52748eee 100644
--- a/svtools/source/uno/unocontroltablemodel.hxx
+++ b/svtools/source/uno/unocontroltablemodel.hxx
@@ -89,6 +89,10 @@ namespace svt { namespace table
virtual ::boost::optional< ::Color > getLineColor() const;
virtual ::boost::optional< ::Color > getHeaderBackgroundColor() const;
virtual ::boost::optional< ::Color > getHeaderTextColor() const;
+ virtual ::boost::optional< ::Color > getActiveSelectionBackColor() const;
+ virtual ::boost::optional< ::Color > getInactiveSelectionBackColor() const;
+ virtual ::boost::optional< ::Color > getActiveSelectionTextColor() const;
+ virtual ::boost::optional< ::Color > getInactiveSelectionTextColor() const;
virtual ::boost::optional< ::Color > getTextColor() const;
virtual ::boost::optional< ::Color > getTextLineColor() const;
virtual ::boost::optional< ::std::vector< ::Color > >
@@ -130,6 +134,10 @@ namespace svt { namespace table
void setLineColor( ::com::sun::star::uno::Any const & i_color );
void setHeaderBackgroundColor( ::com::sun::star::uno::Any const & i_color );
void setHeaderTextColor( ::com::sun::star::uno::Any const & i_color );
+ void setActiveSelectionBackColor( ::com::sun::star::uno::Any const & i_color );
+ void setInactiveSelectionBackColor( ::com::sun::star::uno::Any const & i_color );
+ void setActiveSelectionTextColor( ::com::sun::star::uno::Any const & i_color );
+ void setInactiveSelectionTextColor( ::com::sun::star::uno::Any const & i_color );
void setTextColor( ::com::sun::star::uno::Any const & i_color );
void setTextLineColor( ::com::sun::star::uno::Any const & i_color );
void setRowBackgroundColors( ::com::sun::star::uno::Any const & i_APIValue );