summaryrefslogtreecommitdiff
path: root/svtools/source/table
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/table')
-rwxr-xr-xsvtools/source/table/cellvalueconversion.cxx77
-rwxr-xr-xsvtools/source/table/cellvalueconversion.hxx52
-rw-r--r--svtools/source/table/defaultinputhandler.cxx203
-rw-r--r--svtools/source/table/gridtablerenderer.cxx663
-rw-r--r--svtools/source/table/makefile.mk51
-rwxr-xr-xsvtools/source/table/mousefunction.cxx320
-rwxr-xr-xsvtools/source/table/mousefunction.hxx161
-rw-r--r--svtools/source/table/tablecontrol.cxx785
-rwxr-xr-x[-rw-r--r--]svtools/source/table/tablecontrol_impl.cxx2606
-rwxr-xr-x[-rw-r--r--]svtools/source/table/tablecontrol_impl.hxx315
-rw-r--r--svtools/source/table/tabledatawindow.cxx199
-rw-r--r--svtools/source/table/tabledatawindow.hxx92
-rw-r--r--svtools/source/table/tablegeometry.cxx132
-rw-r--r--svtools/source/table/tablegeometry.hxx40
14 files changed, 3603 insertions, 2093 deletions
diff --git a/svtools/source/table/cellvalueconversion.cxx b/svtools/source/table/cellvalueconversion.cxx
new file mode 100755
index 000000000000..286ca505bb30
--- /dev/null
+++ b/svtools/source/table/cellvalueconversion.cxx
@@ -0,0 +1,77 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_svtools.hxx"
+
+#include "cellvalueconversion.hxx"
+
+/** === begin UNO includes === **/
+/** === end UNO includes === **/
+
+//......................................................................................................................
+namespace svt
+{
+//......................................................................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Any;
+ /** === end UNO using === **/
+
+ //==================================================================================================================
+ //= CellValueConversion
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString CellValueConversion::convertToString( const Any& i_value )
+ {
+ ::rtl::OUString sConvertString;
+ if ( !i_value.hasValue() )
+ return sConvertString;
+
+
+ // TODO: use css.script.XTypeConverter?
+
+ sal_Int32 nInt = 0;
+ sal_Bool bBool = false;
+ double fDouble = 0;
+
+ ::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!" );
+
+ return sStringValue;
+ }
+
+//......................................................................................................................
+} // namespace svt
+//......................................................................................................................
diff --git a/svtools/source/table/cellvalueconversion.hxx b/svtools/source/table/cellvalueconversion.hxx
new file mode 100755
index 000000000000..4d6b8c8d6aac
--- /dev/null
+++ b/svtools/source/table/cellvalueconversion.hxx
@@ -0,0 +1,52 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SVTOOLS_CELLVALUECONVERSION_HXX
+#define SVTOOLS_CELLVALUECONVERSION_HXX
+
+/** === begin UNO includes === **/
+#include <com/sun/star/uno/Any.hxx>
+/** === end UNO includes === **/
+
+//......................................................................................................................
+namespace svt
+{
+//......................................................................................................................
+
+ //==================================================================================================================
+ //= CellValueConversion
+ //==================================================================================================================
+ class CellValueConversion
+ {
+ public:
+ static ::rtl::OUString convertToString( const ::com::sun::star::uno::Any& i_cellValue );
+ };
+
+//......................................................................................................................
+} // namespace svt
+//......................................................................................................................
+
+#endif // SVTOOLS_CELLVALUECONVERSION_HXX
diff --git a/svtools/source/table/defaultinputhandler.cxx b/svtools/source/table/defaultinputhandler.cxx
index b0c4a8c1bf9b..d0ecdb546837 100644
--- a/svtools/source/table/defaultinputhandler.cxx
+++ b/svtools/source/table/defaultinputhandler.cxx
@@ -29,121 +29,133 @@
#include "precompiled_svtools.hxx"
#include "svtools/table/defaultinputhandler.hxx"
-#include "svtools/table/abstracttablecontrol.hxx"
+#include "svtools/table/tablecontrolinterface.hxx"
+
+#include "tabledatawindow.hxx"
+#include "mousefunction.hxx"
#include <tools/debug.hxx>
#include <vcl/event.hxx>
#include <vcl/cursor.hxx>
-#include "svtools/table/tabledatawindow.hxx"
-//........................................................................
+//......................................................................................................................
namespace svt { namespace table
{
-//.......................................................................
+//......................................................................................................................
+ typedef ::rtl::Reference< IMouseFunction > PMouseFunction;
+ typedef ::std::vector< PMouseFunction > MouseFunctions;
struct DefaultInputHandler_Impl
{
+ PMouseFunction pActiveFunction;
+ MouseFunctions aMouseFunctions;
};
- //====================================================================
+ //==================================================================================================================
//= DefaultInputHandler
- //====================================================================
- //--------------------------------------------------------------------
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
DefaultInputHandler::DefaultInputHandler()
:m_pImpl( new DefaultInputHandler_Impl )
- ,m_bResize(false)
{
+ m_pImpl->aMouseFunctions.push_back( new ColumnResize );
+ m_pImpl->aMouseFunctions.push_back( new RowSelection );
+ m_pImpl->aMouseFunctions.push_back( new ColumnSortHandler );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
DefaultInputHandler::~DefaultInputHandler()
{
- DELETEZ( m_pImpl );
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::MouseMove( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt )
+ //------------------------------------------------------------------------------------------------------------------
+ namespace
{
- Point aPoint = _rMEvt.GetPosPixel();
- if(m_bResize)
+ bool lcl_delegateMouseEvent( DefaultInputHandler_Impl& i_impl, ITableControl& i_control, const MouseEvent& i_event,
+ FunctionResult ( IMouseFunction::*i_handlerMethod )( ITableControl&, const MouseEvent& ) )
{
- _rControl.resizeColumn(aPoint);
- return true;
- }
- return false;
- }
-
- //--------------------------------------------------------------------
- bool DefaultInputHandler::MouseButtonDown( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt )
- {
- bool bHandled = false;
- Point aPoint = _rMEvt.GetPosPixel();
- RowPos nRow = _rControl.getCurrentRow(aPoint);
- if(nRow == -1)
- {
- m_bResize = _rControl.startResizeColumn(aPoint);
- bHandled = true;
- }
- else if(nRow >= 0)
- {
- if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION)
+ if ( i_impl.pActiveFunction.is() )
{
- _rControl.setCursorAtCurrentCell(aPoint);
- bHandled = true;
+ bool furtherHandler = false;
+ switch ( (i_impl.pActiveFunction.get()->*i_handlerMethod)( i_control, i_event ) )
+ {
+ case ActivateFunction:
+ OSL_ENSURE( false, "lcl_delegateMouseEvent: unexpected - function already *is* active!" );
+ break;
+ case ContinueFunction:
+ break;
+ case DeactivateFunction:
+ i_impl.pActiveFunction.clear();
+ break;
+ case SkipFunction:
+ furtherHandler = true;
+ break;
+ }
+ if ( !furtherHandler )
+ // handled the event
+ return true;
}
- else
+
+ // ask all other handlers
+ bool handled = false;
+ for ( MouseFunctions::iterator handler = i_impl.aMouseFunctions.begin();
+ ( handler != i_impl.aMouseFunctions.end() ) && !handled;
+ ++handler
+ )
{
- if(!_rControl.isRowSelected(nRow))
- bHandled = _rControl.getSelEngine()->SelMouseButtonDown(_rMEvt);
- else
- bHandled = true;
+ if ( *handler == i_impl.pActiveFunction )
+ // we already invoked this function
+ continue;
+
+ switch ( (handler->get()->*i_handlerMethod)( i_control, i_event ) )
+ {
+ case ActivateFunction:
+ i_impl.pActiveFunction = *handler;
+ handled = true;
+ break;
+ case ContinueFunction:
+ case DeactivateFunction:
+ OSL_ENSURE( false, "lcl_delegateMouseEvent: unexpected: inactivate handler cannot be continued or deactivated!" );
+ break;
+ case SkipFunction:
+ handled = false;
+ break;
+ }
}
+ return handled;
}
- return bHandled;
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::MouseButtonUp( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt )
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::MouseMove( ITableControl& i_tableControl, const MouseEvent& i_event )
{
- bool bHandled = false;
- Point aPoint = _rMEvt.GetPosPixel();
- if(_rControl.getCurrentRow(aPoint) >= 0)
- {
- if(m_bResize)
- {
- m_bResize = _rControl.endResizeColumn(aPoint);
- bHandled = true;
- }
- else if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION)
- {
- bHandled = true;
- }
- else
- {
- bHandled = _rControl.getSelEngine()->SelMouseButtonUp(_rMEvt);
- }
- }
- else
- {
- if(m_bResize)
- {
- m_bResize = _rControl.endResizeColumn(aPoint);
- bHandled = true;
- }
- }
- return bHandled;
+ return lcl_delegateMouseEvent( *m_pImpl, i_tableControl, i_event, &IMouseFunction::handleMouseMove );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::MouseButtonDown( ITableControl& i_tableControl, const MouseEvent& i_event )
+ {
+ return lcl_delegateMouseEvent( *m_pImpl, i_tableControl, i_event, &IMouseFunction::handleMouseDown );
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::KeyInput( IAbstractTableControl& _rControl, const KeyEvent& rKEvt )
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::MouseButtonUp( ITableControl& i_tableControl, const MouseEvent& i_event )
+ {
+ return lcl_delegateMouseEvent( *m_pImpl, i_tableControl, i_event, &IMouseFunction::handleMouseUp );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::KeyInput( ITableControl& _rControl, const KeyEvent& rKEvt )
{
bool bHandled = false;
const KeyCode& rKeyCode = rKEvt.GetKeyCode();
- USHORT nKeyCode = rKeyCode.GetCode();
+ sal_uInt16 nKeyCode = rKeyCode.GetCode();
struct _ActionMapEntry
{
- USHORT nKeyCode;
- USHORT nKeyModifier;
+ sal_uInt16 nKeyCode;
+ sal_uInt16 nKeyModifier;
TableControlAction eAction;
}
static aKnownActions[] = {
@@ -159,11 +171,11 @@ namespace svt { namespace table
{ KEY_PAGEDOWN, KEY_MOD1, cursorToLastLine },
{ KEY_HOME, KEY_MOD1, cursorTopLeft },
{ KEY_END, KEY_MOD1, cursorBottomRight },
- { KEY_SPACE, KEY_MOD1, cursorSelectRow },
- { KEY_UP, KEY_SHIFT, cursorSelectRowUp },
- { KEY_DOWN, KEY_SHIFT, cursorSelectRowDown },
- { KEY_END, KEY_SHIFT, cursorSelectRowAreaBottom },
- { KEY_HOME, KEY_SHIFT, cursorSelectRowAreaTop },
+ { KEY_SPACE, KEY_MOD1, cursorSelectRow },
+ { KEY_UP, KEY_SHIFT, cursorSelectRowUp },
+ { KEY_DOWN, KEY_SHIFT, cursorSelectRowDown },
+ { KEY_END, KEY_SHIFT, cursorSelectRowAreaBottom },
+ { KEY_HOME, KEY_SHIFT, cursorSelectRowAreaTop },
{ 0, 0, invalidTableControlAction }
};
@@ -174,7 +186,6 @@ namespace svt { namespace table
if ( ( pActions->nKeyCode == nKeyCode ) && ( pActions->nKeyModifier == rKeyCode.GetAllModifier() ) )
{
bHandled = _rControl.dispatchAction( pActions->eAction );
- bHandled = true; // always handled issue #i114340
break;
}
}
@@ -182,22 +193,22 @@ namespace svt { namespace table
return bHandled;
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::GetFocus( IAbstractTableControl& _rControl )
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::GetFocus( ITableControl& _rControl )
{
_rControl.showCursor();
return false; // continue processing
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::LoseFocus( IAbstractTableControl& _rControl )
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::LoseFocus( ITableControl& _rControl )
{
_rControl.hideCursor();
return false; // continue processing
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::RequestHelp( IAbstractTableControl& _rControl, const HelpEvent& _rHEvt )
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::RequestHelp( ITableControl& _rControl, const HelpEvent& _rHEvt )
{
(void)_rControl;
(void)_rHEvt;
@@ -205,8 +216,8 @@ namespace svt { namespace table
return false;
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::Command( IAbstractTableControl& _rControl, const CommandEvent& _rCEvt )
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::Command( ITableControl& _rControl, const CommandEvent& _rCEvt )
{
(void)_rControl;
(void)_rCEvt;
@@ -214,8 +225,8 @@ namespace svt { namespace table
return false;
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::PreNotify( IAbstractTableControl& _rControl, NotifyEvent& _rNEvt )
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::PreNotify( ITableControl& _rControl, NotifyEvent& _rNEvt )
{
(void)_rControl;
(void)_rNEvt;
@@ -223,16 +234,16 @@ namespace svt { namespace table
return false;
}
- //--------------------------------------------------------------------
- bool DefaultInputHandler::Notify( IAbstractTableControl& _rControl, NotifyEvent& _rNEvt )
+ //------------------------------------------------------------------------------------------------------------------
+ bool DefaultInputHandler::Notify( ITableControl& _rControl, NotifyEvent& _rNEvt )
{
(void)_rControl;
(void)_rNEvt;
// TODO
return false;
}
-//........................................................................
+//......................................................................................................................
} } // namespace svt::table
-//........................................................................
+//......................................................................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/gridtablerenderer.cxx b/svtools/source/table/gridtablerenderer.cxx
index 1be46204a9d3..e69ad5589087 100644
--- a/svtools/source/table/gridtablerenderer.cxx
+++ b/svtools/source/table/gridtablerenderer.cxx
@@ -28,51 +28,209 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
+#include "cellvalueconversion.hxx"
#include "svtools/table/gridtablerenderer.hxx"
+#include "svtools/colorcfg.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/graphic/XGraphic.hpp>
+/** === end UNO includes === **/
#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
#include <vcl/window.hxx>
#include <vcl/image.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/decoview.hxx>
-//........................................................................
+//......................................................................................................................
namespace svt { namespace table
{
-//........................................................................
+//......................................................................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::TypeClass_INTERFACE;
+ using ::com::sun::star::graphic::XGraphic;
+ using ::com::sun::star::style::HorizontalAlignment;
+ using ::com::sun::star::style::HorizontalAlignment_LEFT;
+ using ::com::sun::star::style::HorizontalAlignment_CENTER;
+ using ::com::sun::star::style::HorizontalAlignment_RIGHT;
+ using ::com::sun::star::style::VerticalAlignment;
+ using ::com::sun::star::style::VerticalAlignment_TOP;
+ using ::com::sun::star::style::VerticalAlignment_MIDDLE;
+ using ::com::sun::star::style::VerticalAlignment_BOTTOM;
+ /** === end UNO using === **/
+
+ //==================================================================================================================
+ //= CachedSortIndicator
+ //==================================================================================================================
+ class CachedSortIndicator
+ {
+ public:
+ CachedSortIndicator()
+ :m_lastHeaderHeight( 0 )
+ ,m_lastArrowColor( COL_TRANSPARENT )
+ {
+ }
+
+ BitmapEx const & getBitmapFor( OutputDevice const & i_device, long const i_headerHeight, StyleSettings const & i_style, bool const i_sortAscending );
+
+ private:
+ long m_lastHeaderHeight;
+ Color m_lastArrowColor;
+ BitmapEx m_sortAscending;
+ BitmapEx m_sortDescending;
+ };
+
+ //------------------------------------------------------------------------------------------------------------------
+ BitmapEx const & CachedSortIndicator::getBitmapFor( OutputDevice const & i_device, long const i_headerHeight,
+ StyleSettings const & i_style, bool const i_sortAscending )
+ {
+ BitmapEx & rBitmap( i_sortAscending ? m_sortAscending : m_sortDescending );
+ if ( !rBitmap || ( i_headerHeight != m_lastHeaderHeight ) || ( i_style.GetActiveColor() != m_lastArrowColor ) )
+ {
+ long const nSortIndicatorWidth = 2 * i_headerHeight / 3;
+ long const nSortIndicatorHeight = 2 * nSortIndicatorWidth / 3;
+
+ Point const aBitmapPos( 0, 0 );
+ Size const aBitmapSize( nSortIndicatorWidth, nSortIndicatorHeight );
+ VirtualDevice aDevice( i_device, 0, 0 );
+ aDevice.SetOutputSizePixel( aBitmapSize );
+
+ DecorationView aDecoView( &aDevice );
+ aDecoView.DrawSymbol(
+ Rectangle( aBitmapPos, aBitmapSize ),
+ i_sortAscending ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN,
+ i_style.GetActiveColor()
+ );
+
+ rBitmap = aDevice.GetBitmapEx( aBitmapPos, aBitmapSize );
+ m_lastHeaderHeight = i_headerHeight;
+ m_lastArrowColor = i_style.GetActiveColor();
+ }
+ return rBitmap;
+ }
+ //==================================================================================================================
+ //= GridTableRenderer_Impl
+ //==================================================================================================================
struct GridTableRenderer_Impl
{
- ITableModel& rModel;
- RowPos nCurrentRow;
+ ITableModel& rModel;
+ RowPos nCurrentRow;
+ bool bUseGridLines;
+ CachedSortIndicator aSortIndicator;
GridTableRenderer_Impl( ITableModel& _rModel )
:rModel( _rModel )
,nCurrentRow( ROW_INVALID )
+ ,bUseGridLines( true )
{
}
};
- //====================================================================
+ //==================================================================================================================
+ //= helper
+ //==================================================================================================================
+ namespace
+ {
+ static Rectangle lcl_getContentArea( GridTableRenderer_Impl const & i_impl, Rectangle const & i_cellArea )
+ {
+ Rectangle aContentArea( i_cellArea );
+ if ( i_impl.bUseGridLines )
+ {
+ --aContentArea.Right();
+ --aContentArea.Bottom();
+ }
+ return aContentArea;
+ }
+ static Rectangle lcl_getTextRenderingArea( Rectangle const & i_contentArea )
+ {
+ Rectangle aTextArea( i_contentArea );
+ aTextArea.Left() += 2; aTextArea.Right() -= 2;
+ ++aTextArea.Top(); --aTextArea.Bottom();
+ return aTextArea;
+ }
+
+ static sal_uLong lcl_getAlignmentTextDrawFlags( GridTableRenderer_Impl const & i_impl, ColPos const i_columnPos )
+ {
+ sal_uLong nVertFlag = TEXT_DRAW_TOP;
+ VerticalAlignment const eVertAlign = i_impl.rModel.getVerticalAlign();
+ switch ( eVertAlign )
+ {
+ case VerticalAlignment_MIDDLE: nVertFlag = TEXT_DRAW_VCENTER; break;
+ case VerticalAlignment_BOTTOM: nVertFlag = TEXT_DRAW_BOTTOM; break;
+ default:
+ break;
+ }
+
+ sal_uLong nHorzFlag = TEXT_DRAW_LEFT;
+ HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign();
+ switch ( eHorzAlign )
+ {
+ case HorizontalAlignment_CENTER: nHorzFlag = TEXT_DRAW_CENTER; break;
+ case HorizontalAlignment_RIGHT: nHorzFlag = TEXT_DRAW_RIGHT; break;
+ default:
+ break;
+ }
+
+ return nVertFlag | nHorzFlag;
+ }
+
+ }
+
+ //==================================================================================================================
//= GridTableRenderer
- //====================================================================
- //--------------------------------------------------------------------
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
GridTableRenderer::GridTableRenderer( ITableModel& _rModel )
:m_pImpl( new GridTableRenderer_Impl( _rModel ) )
{
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
GridTableRenderer::~GridTableRenderer()
{
- DELETEZ( m_pImpl );
}
- //--------------------------------------------------------------------
- RowPos GridTableRenderer::getCurrentRow()
+ //------------------------------------------------------------------------------------------------------------------
+ RowPos GridTableRenderer::getCurrentRow() const
{
return m_pImpl->nCurrentRow;
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
+ bool GridTableRenderer::useGridLines() const
+ {
+ return m_pImpl->bUseGridLines;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void GridTableRenderer::useGridLines( bool const i_use )
+ {
+ m_pImpl->bUseGridLines = i_use;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ namespace
+ {
+ Color lcl_getEffectiveColor(
+ ::boost::optional< ::Color > const & i_modelColor,
+ StyleSettings const & i_styleSettings,
+ ::Color const & ( StyleSettings::*i_getDefaultColor ) () const
+ )
+ {
+ if ( !!i_modelColor )
+ return *i_modelColor;
+ return ( i_styleSettings.*i_getDefaultColor )();
+ }
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
void GridTableRenderer::PaintHeaderArea(
OutputDevice& _rDevice, const Rectangle& _rArea, bool _bIsColHeaderArea, bool _bIsRowHeaderArea,
const StyleSettings& _rStyle )
@@ -80,15 +238,18 @@ namespace svt { namespace table
OSL_PRECOND( _bIsColHeaderArea || _bIsRowHeaderArea,
"GridTableRenderer::PaintHeaderArea: invalid area flags!" );
- _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR);
- Color background = m_pImpl->rModel.getHeaderBackgroundColor();
- if( background != 0xFFFFFF)
- _rDevice.SetFillColor(background);
- else
- _rDevice.SetFillColor(_rStyle.GetDialogColor());
- _rDevice.SetLineColor(_rStyle.GetSeparatorColor());
+ _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
+
+ Color const background = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderBackgroundColor(), _rStyle, &StyleSettings::GetDialogColor );
+ _rDevice.SetFillColor( background );
+
+ _rDevice.SetLineColor();
_rDevice.DrawRect( _rArea );
+
// delimiter lines at bottom/right
+ ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
+ ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ _rDevice.SetLineColor( lineColor );
_rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
_rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
@@ -97,48 +258,73 @@ namespace svt { namespace table
(void)_bIsRowHeaderArea;
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void GridTableRenderer::PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected,
OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle )
{
_rDevice.Push( PUSH_LINECOLOR);
- _rDevice.SetLineColor(_rStyle.GetSeparatorColor());
- _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight());
String sHeaderText;
- PColumnModel pColumn = m_pImpl->rModel.getColumnModel( _nCol );
+ PColumnModel const pColumn = m_pImpl->rModel.getColumnModel( _nCol );
DBG_ASSERT( !!pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" );
if ( !!pColumn )
sHeaderText = pColumn->getName();
- if(m_pImpl->rModel.getTextColor() != 0x000000)
- _rDevice.SetTextColor(m_pImpl->rModel.getTextColor());
- else
- _rDevice.SetTextColor(_rStyle.GetFieldTextColor());
- ULONG nHorFlag = TEXT_DRAW_LEFT;
- ULONG nVerFlag = TEXT_DRAW_TOP;
- if(m_pImpl->rModel.getVerticalAlign() == 1)
- nVerFlag = TEXT_DRAW_VCENTER;
- else if(m_pImpl->rModel.getVerticalAlign() == 2)
- nVerFlag = TEXT_DRAW_BOTTOM;
- if(m_pImpl->rModel.getColumnModel(_nCol)->getHorizontalAlign() == 1)
- nHorFlag = TEXT_DRAW_CENTER;
- else if(m_pImpl->rModel.getColumnModel(_nCol)->getHorizontalAlign() == 2)
- nHorFlag = TEXT_DRAW_RIGHT;
- Rectangle aRect(_rArea);
- aRect.Left()+=4; aRect.Right()-=4;
- aRect.Bottom()-=2;
- _rDevice.DrawText( aRect, sHeaderText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP);
+
+ ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
+ _rDevice.SetTextColor( textColor );
+
+ Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) );
+ sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | TEXT_DRAW_CLIP;
+ _rDevice.DrawText( aTextRect, sHeaderText, nDrawTextFlags );
+
+ ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() );
+ ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ _rDevice.SetLineColor( lineColor );
+ _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight());
_rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
+
+ // draw sort indicator if the model data is sorted by the given column
+ ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter();
+ ColumnSort aCurrentSortOrder;
+ if ( pSortAdapter != NULL )
+ aCurrentSortOrder = pSortAdapter->getCurrentSortOrder();
+ if ( aCurrentSortOrder.nColumnPos == _nCol )
+ {
+ long const nHeaderHeight( _rArea.GetHeight() );
+ BitmapEx const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor( _rDevice, nHeaderHeight, _rStyle,
+ aCurrentSortOrder.eSortDirection == ColumnSortAscending );
+ Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() );
+ long const nSortIndicatorPaddingX = 2;
+ long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2;
+
+ if ( ( nDrawTextFlags & TEXT_DRAW_RIGHT ) != 0 )
+ {
+ // text is right aligned => draw the sort indicator at the left hand side
+ _rDevice.DrawBitmapEx(
+ Point( _rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY ),
+ aIndicatorBitmap
+ );
+ }
+ else
+ {
+ // text is left-aligned or centered => draw the sort indicator at the right hand side
+ _rDevice.DrawBitmapEx(
+ Point( _rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY ),
+ aIndicatorBitmap
+ );
+ }
+ }
+
_rDevice.Pop();
(void)_bActive;
// no special painting for the active column at the moment
(void)_bSelected;
- //selection for column header not yet implemented
+ // selection for column header not yet implemented
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void GridTableRenderer::PrepareRow( RowPos _nRow, bool _bActive, bool _bSelected,
OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle )
{
@@ -147,238 +333,289 @@ namespace svt { namespace table
_rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR);
- Color aRowBackground = m_pImpl->rModel.getOddRowBackgroundColor();
- Color line = m_pImpl->rModel.getLineColor();
- Color aRowBackground2 = m_pImpl->rModel.getEvenRowBackgroundColor();
- Color fieldColor = _rStyle.GetFieldColor();
- if(aRowBackground == 0xFFFFFF)
- aRowBackground = fieldColor;
- if(aRowBackground2 == 0xFFFFFF)
- aRowBackground2 = fieldColor;
- //if row is selected background color becomes blue, and lines should be also blue
- //if they aren't user defined
- if(_bSelected)
+ ::Color backgroundColor = _rStyle.GetFieldColor();
+
+ ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
+ ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+
+ if ( _bSelected )
{
- Color aSelected(_rStyle.GetHighlightColor());
- aRowBackground = aSelected;
- if(line == 0xFFFFFF)
- _rDevice.SetLineColor(aRowBackground);
- else
- _rDevice.SetLineColor(line);
+ // selected rows use the background color from the style
+ backgroundColor = _rStyle.GetHighlightColor();
+ if ( !aLineColor )
+ lineColor = backgroundColor;
}
- //if row not selected, check the cases whether user defined backgrounds are set
- //and set line color to be the same
else
{
- if(aRowBackground2 != fieldColor && _nRow%2)
+ ::boost::optional< ::std::vector< ::Color > > aRowColors = m_pImpl->rModel.getRowBackgroundColors();
+ if ( !aRowColors )
{
- aRowBackground = aRowBackground2;
- if(line == 0xFFFFFF)
- _rDevice.SetLineColor(aRowBackground);
+ // use alternating default colors
+ Color const fieldColor = _rStyle.GetFieldColor();
+ if ( _rStyle.GetHighContrastMode() || ( ( m_pImpl->nCurrentRow % 2 ) == 0 ) )
+ {
+ backgroundColor = fieldColor;
+ }
else
- _rDevice.SetLineColor(line);
+ {
+ Color hilightColor = _rStyle.GetHighlightColor();
+ 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() );
+ backgroundColor = hilightColor;
+ }
}
- //fill the rows with alternating background colors if second background color is specified
- else if(aRowBackground != fieldColor && line == 0xFFFFFF)
- _rDevice.SetLineColor(aRowBackground);
else
{
- //if Line color is set, then it was user defined and should be visible
- //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible
- _rDevice.SetLineColor(line);
+ if ( aRowColors->empty() )
+ {
+ // all colors have the same background color
+ backgroundColor = _rStyle.GetFieldColor();
+ }
+ else
+ {
+ backgroundColor = aRowColors->at( m_pImpl->nCurrentRow % aRowColors->size() );
+ }
}
}
- _rDevice.SetFillColor( aRowBackground );
- _rDevice.DrawRect( _rRowArea );
- // TODO: active?
+ //m_pImpl->bUseGridLines ? _rDevice.SetLineColor( lineColor ) : _rDevice.SetLineColor();
+ _rDevice.SetLineColor();
+ _rDevice.SetFillColor( backgroundColor );
+ _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,
- const StyleSettings& _rStyle, rtl::OUString& _rText )
+ const StyleSettings& _rStyle )
{
- _rDevice.Push( PUSH_LINECOLOR);
- _rDevice.SetLineColor(_rStyle.GetSeparatorColor());
+ _rDevice.Push( PUSH_LINECOLOR | PUSH_TEXTCOLOR );
+
+ ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() );
+ ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ _rDevice.SetLineColor( lineColor );
_rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
- if(m_pImpl->rModel.getTextColor() != 0x000000)
- _rDevice.SetTextColor(m_pImpl->rModel.getTextColor());
- else
- _rDevice.SetTextColor(_rStyle.GetFieldTextColor());
- ULONG nHorFlag = TEXT_DRAW_LEFT;
- ULONG nVerFlag = TEXT_DRAW_TOP;
- if(m_pImpl->rModel.getVerticalAlign() == 1)
- nVerFlag = TEXT_DRAW_VCENTER;
- else if(m_pImpl->rModel.getVerticalAlign() == 2)
- nVerFlag = TEXT_DRAW_BOTTOM;
- if(m_pImpl->rModel.getColumnModel(0)->getHorizontalAlign() == 1)
- nHorFlag = TEXT_DRAW_CENTER;
- else if(m_pImpl->rModel.getColumnModel(0)->getHorizontalAlign() == 2)
- nHorFlag = TEXT_DRAW_RIGHT;
- Rectangle aRect(_rArea);
- aRect.Left()+=4; aRect.Right()-=4;
- aRect.Bottom()-=2;
- _rDevice.DrawText( aRect, _rText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP);
+
+ Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) );
+ ::rtl::OUString const rowTitle( CellValueConversion::convertToString( rowHeading ) );
+ if ( rowTitle.getLength() )
+ {
+ ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
+ _rDevice.SetTextColor( textColor );
+
+ Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) );
+ sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, 0 ) | TEXT_DRAW_CLIP;
+ // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitray ..
+ _rDevice.DrawText( aTextRect, rowTitle, nDrawTextFlags );
+ }
+
// TODO: active? selected?
(void)_bActive;
(void)_bSelected;
- //at the moment no special paint for selected row header
_rDevice.Pop();
}
- //--------------------------------------------------------------------
- void GridTableRenderer::PaintCellImage( ColPos _nColumn, bool _bSelected, bool _bActive,
- OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, Image* _pCellData )
- {
- _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR);
- Color background1 = m_pImpl->rModel.getOddRowBackgroundColor();
- Color background2 = m_pImpl->rModel.getEvenRowBackgroundColor();
- Color line = m_pImpl->rModel.getLineColor();
- //if row is selected and line color isn't user specified, set it blue
- if(_bSelected)
+ //------------------------------------------------------------------------------------------------------------------
+ struct GridTableRenderer::CellRenderContext
+ {
+ OutputDevice& rDevice;
+ Rectangle const aContentArea;
+ StyleSettings const & rStyle;
+ ColPos const nColumn;
+ bool const bSelected;
+
+ CellRenderContext( OutputDevice& i_device, Rectangle const & i_contentArea,
+ StyleSettings const & i_style, ColPos const i_column, bool const i_selected )
+ :rDevice( i_device )
+ ,aContentArea( i_contentArea )
+ ,rStyle( i_style )
+ ,nColumn( i_column )
+ ,bSelected( i_selected )
{
- if(line == 0xFFFFFF)
- _rDevice.SetLineColor(_rStyle.GetHighlightColor());
- else
- _rDevice.SetLineColor(line);
}
- //else set line color to the color of row background
- else
+ };
+
+ //------------------------------------------------------------------------------------------------------------------
+ void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool _bActive,
+ 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 );
+ impl_paintCellContent( aRenderContext );
+
+ if ( m_pImpl->bUseGridLines )
{
- if(background2 != 0xFFFFFF && m_pImpl->nCurrentRow%2)
- {
- if(line == 0xFFFFFF)
- _rDevice.SetLineColor(background2);
- else
- _rDevice.SetLineColor(line);
- }
- else if(background1 != 0xFFFFFF && line == 0xFFFFFF)
- _rDevice.SetLineColor(background1);
- else
+ ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
+ ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+
+ if ( _bSelected && !aLineColor )
{
- //if line color is set, then it was user defined and should be visible
- //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible
- _rDevice.SetLineColor(line);
+ // if no line color is specified by the model, use the usual selection color for lines in selected cells
+ lineColor = _rStyle.GetHighlightColor();
}
- }
- _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
- Rectangle aRect( _rArea );
- ++aRect.Left(); --aRect.Right();
- aRect.Top(); aRect.Bottom();
- Point imagePos(Point(aRect.Left(), aRect.Top()));
- Size imageSize = _pCellData->GetSizePixel();
- if(aRect.GetWidth() > imageSize.Width())
- {
- if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 1)
- imagePos.X() = aRect.Left()+((double)(aRect.GetWidth() - imageSize.Width()))/2;
- else if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 2)
- imagePos.X() = aRect.Right() - imageSize.Width();
- }
- else
- imageSize.Width() = aRect.GetWidth();
- if(aRect.GetHeight() > imageSize.Height())
- {
- if(m_pImpl->rModel.getVerticalAlign() == 1)
- imagePos.Y() = aRect.Top()+((double)(aRect.GetHeight() - imageSize.Height()))/2;
- else if(m_pImpl->rModel.getVerticalAlign() == 2)
- imagePos.Y() = aRect.Bottom() - imageSize.Height();
+ _rDevice.SetLineColor( lineColor );
+ _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
+ _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
}
- else
- imageSize.Height() = aRect.GetHeight()-1;
- Image& image (*_pCellData);
- _rDevice.DrawImage(imagePos, imageSize, image, 0);
+
_rDevice.Pop();
(void)_bActive;
// no special painting for the active cell at the moment
}
- //--------------------------------------------------------------------
- void GridTableRenderer::PaintCellString( ColPos _nColumn, bool _bSelected, bool _bActive,
- OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, rtl::OUString& _rText )
- {
- _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
- Color background1 = m_pImpl->rModel.getOddRowBackgroundColor();
- Color background2 = m_pImpl->rModel.getEvenRowBackgroundColor();
- Color line = m_pImpl->rModel.getLineColor();
- //if row is selected and line color isn't user specified, set it blue
- if(_bSelected)
+ //------------------------------------------------------------------------------------------------------------------
+ void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image )
+ {
+ Point imagePos( Point( i_context.aContentArea.Left(), i_context.aContentArea.Top() ) );
+ Size imageSize = i_image.GetSizePixel();
+ if ( i_context.aContentArea.GetWidth() > imageSize.Width() )
{
- if(line == 0xFFFFFF)
- _rDevice.SetLineColor(_rStyle.GetHighlightColor());
- else
- _rDevice.SetLineColor(line);
+ const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign();
+ switch ( eHorzAlign )
+ {
+ case HorizontalAlignment_CENTER:
+ imagePos.X() += ( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2;
+ break;
+ case HorizontalAlignment_RIGHT:
+ imagePos.X() = i_context.aContentArea.Right() - imageSize.Width();
+ break;
+ default:
+ break;
+ }
+
}
- //else set line color to the color of row background
else
+ imageSize.Width() = i_context.aContentArea.GetWidth();
+
+ if ( i_context.aContentArea.GetHeight() > imageSize.Height() )
{
- if(background2 != 0xFFFFFF && m_pImpl->nCurrentRow%2)
+ const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign();
+ switch ( eVertAlign )
{
- if(line == 0xFFFFFF)
- _rDevice.SetLineColor(background2);
- else
- _rDevice.SetLineColor(line);
- }
- else if(background1 != 0xFFFFFF && line == 0xFFFFFF)
- _rDevice.SetLineColor(background1);
- else
- {
- //if Line color is set, then it was user defined and should be visible
- //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible
- _rDevice.SetLineColor(line);
+ case VerticalAlignment_MIDDLE:
+ imagePos.Y() += ( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2;
+ break;
+ case VerticalAlignment_BOTTOM:
+ imagePos.Y() = i_context.aContentArea.Bottom() - imageSize.Height();
+ break;
+ default:
+ break;
}
}
- _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
+ else
+ imageSize.Height() = i_context.aContentArea.GetHeight() - 1;
+
+ i_context.rDevice.DrawImage( imagePos, imageSize, i_image, 0 );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context )
+ {
+ Any aCellContent;
+ m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent );
+
+ if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY );
+ if ( !xContentInterface.is() )
+ // allowed. kind of.
+ return;
- Rectangle aRect( _rArea );
- ++aRect.Left(); --aRect.Right();
- aRect.Top(); aRect.Bottom();
- if(_bSelected)
- _rDevice.SetTextColor(_rStyle.GetHighlightTextColor());
- else if(m_pImpl->rModel.getTextColor() != 0x000000)
- _rDevice.SetTextColor(m_pImpl->rModel.getTextColor());
+ Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY );
+ ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." );
+
+ const Image aImage( xGraphic );
+ impl_paintCellImage( i_context, aImage );
+ return;
+ }
+
+ const ::rtl::OUString sText( CellValueConversion::convertToString( aCellContent ) );
+ impl_paintCellText( i_context, sText );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ 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() );
else
- _rDevice.SetTextColor(_rStyle.GetFieldTextColor());
- ULONG nHorFlag = TEXT_DRAW_LEFT;
- ULONG nVerFlag = TEXT_DRAW_TOP;
- if(m_pImpl->rModel.getVerticalAlign() == 1)
- nVerFlag = TEXT_DRAW_VCENTER;
- else if(m_pImpl->rModel.getVerticalAlign() == 2)
- nVerFlag = TEXT_DRAW_BOTTOM;
- if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 1)
- nHorFlag = TEXT_DRAW_CENTER;
- else if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 2)
- nHorFlag = TEXT_DRAW_RIGHT;
- Rectangle textRect(_rArea);
- textRect.Left()+=4; textRect.Right()-=4;
- textRect.Bottom()-=2;
- _rDevice.DrawText( textRect, _rText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP);
+ {
+ ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor );
+ i_context.rDevice.SetTextColor( textColor );
+ }
- _rDevice.Pop();
- (void)_bActive;
- // no special painting for the active cell at the moment
+ Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) );
+ sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | TEXT_DRAW_CLIP;
+ i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void GridTableRenderer::ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect)
{
_rView.ShowFocus( _rCursorRect );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect)
{
- (void)_rCursorRect;
+ (void)_rCursorRect;
_rView.HideFocus();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ 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 )
+ {
+ if ( !i_cellContent.hasValue() )
+ return true;
+
+ if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY );
+ if ( !xContentInterface.is() )
+ return true;
+
+ Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY );
+ if ( xGraphic.is() )
+ // for the moment, assume it fits. We can always scale it down during painting ...
+ return true;
+
+ OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." );
+ return true;
+ }
+
+ ::rtl::OUString const sText( CellValueConversion::convertToString( i_cellContent ) );
+ if ( sText.getLength() == 0 )
+ return true;
+
+ Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) );
+
+ long const nTextHeight = i_targetDevice.GetTextHeight();
+ if ( nTextHeight > aTargetArea.GetHeight() )
+ return false;
+
+ long const nTextWidth = i_targetDevice.GetTextWidth( sText );
+ if ( nTextWidth > aTargetArea.GetWidth() )
+ return false;
+ OSL_UNUSED( i_active );
+ OSL_UNUSED( i_selected );
+ OSL_UNUSED( i_rowPos );
+ OSL_UNUSED( i_colPos );
+ return true;
}
-//........................................................................
+//......................................................................................................................
} } // namespace svt::table
-//........................................................................
+//......................................................................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/makefile.mk b/svtools/source/table/makefile.mk
deleted file mode 100644
index 78c50f9eca4a..000000000000
--- a/svtools/source/table/makefile.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-#*************************************************************************
-#
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# Copyright 2000, 2010 Oracle and/or its affiliates.
-#
-# OpenOffice.org - a multi-platform office productivity suite
-#
-# This file is part of OpenOffice.org.
-#
-# OpenOffice.org is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3
-# only, as published by the Free Software Foundation.
-#
-# OpenOffice.org is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License version 3 for more details
-# (a copy is included in the LICENSE file that accompanied this code).
-#
-# You should have received a copy of the GNU Lesser General Public License
-# version 3 along with OpenOffice.org. If not, see
-# <http://www.openoffice.org/license.html>
-# for a copy of the LGPLv3 License.
-#
-#*************************************************************************
-
-PRJ=..$/..
-
-ENABLE_EXCEPTIONS=TRUE
-PRJNAME=svtools
-TARGET=table
-
-# --- Settings -----------------------------------------------------
-
-.INCLUDE : settings.mk
-.INCLUDE : $(PRJ)$/util$/svt.pmk
-
-# --- Files --------------------------------------------------------
-
-SLOFILES=\
- $(SLO)$/tablecontrol.obj \
- $(SLO)$/tablecontrol_impl.obj \
- $(SLO)$/gridtablerenderer.obj \
- $(SLO)$/tablegeometry.obj \
- $(SLO)$/defaultinputhandler.obj \
- $(SLO)$/tabledatawindow.obj
-
-# --- Targets ------------------------------------------------------
-
-.INCLUDE : target.mk
diff --git a/svtools/source/table/mousefunction.cxx b/svtools/source/table/mousefunction.cxx
new file mode 100755
index 000000000000..20d505e911e9
--- /dev/null
+++ b/svtools/source/table/mousefunction.cxx
@@ -0,0 +1,320 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_svtools.hxx"
+
+#include "mousefunction.hxx"
+#include "svtools/table/tablecontrolinterface.hxx"
+
+#include <tools/diagnose_ex.h>
+#include <vcl/window.hxx>
+
+//......................................................................................................................
+namespace svt { namespace table
+{
+//......................................................................................................................
+
+ //==================================================================================================================
+ //= MouseFunction
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ oslInterlockedCount MouseFunction::acquire()
+ {
+ return osl_incrementInterlockedCount( &m_refCount );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ oslInterlockedCount MouseFunction::release()
+ {
+ oslInterlockedCount newCount = osl_decrementInterlockedCount( &m_refCount );
+ if ( newCount == 0 )
+ {
+ delete this;
+ return 0;
+ }
+ return newCount;
+ }
+
+ //==================================================================================================================
+ //= ColumnResize
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult ColumnResize::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ Point const aPoint = i_event.GetPosPixel();
+
+ if ( m_nResizingColumn == COL_INVALID )
+ {
+ // if we hit a column divider, change the mosue pointer accordingly
+ Pointer aNewPointer( POINTER_ARROW );
+ TableCell const tableCell = i_tableControl.hitTest( aPoint );
+ if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.eArea == ColumnDivider ) )
+ {
+ aNewPointer = Pointer( POINTER_HSPLIT );
+ }
+ i_tableControl.setPointer( aNewPointer );
+
+ return SkipFunction; // TODO: is this correct?
+ }
+
+ ::Size const tableSize = i_tableControl.getTableSizePixel();
+
+ // set proper pointer
+ Pointer aNewPointer( POINTER_ARROW );
+ ColumnMetrics const & columnMetrics( i_tableControl.getColumnMetrics( m_nResizingColumn ) );
+ if ( ( aPoint.X() > tableSize.Width() )
+ || ( aPoint.X() < columnMetrics.nStartPixel )
+ )
+ {
+ aNewPointer = Pointer( POINTER_NOTALLOWED );
+ }
+ else
+ {
+ aNewPointer = Pointer( POINTER_HSPLIT );
+ }
+ i_tableControl.setPointer( aNewPointer );
+
+ // show tracking line
+ i_tableControl.hideTracking();
+ i_tableControl.showTracking(
+ Rectangle(
+ Point( aPoint.X(), 0 ),
+ Size( 1, tableSize.Height() )
+ ),
+ SHOWTRACK_SPLIT | SHOWTRACK_WINDOW
+ );
+
+ (void)i_event;
+ return ContinueFunction;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult ColumnResize::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nResizingColumn != COL_INVALID )
+ {
+ OSL_ENSURE( false, "ColumnResize::handleMouseDown: suspicious: MouseButtonDown while still tracking?" );
+ return ContinueFunction;
+ }
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( tableCell.nRow == ROW_COL_HEADERS )
+ {
+ if ( ( tableCell.nColumn != COL_INVALID )
+ && ( tableCell.eArea == ColumnDivider )
+ )
+ {
+ m_nResizingColumn = tableCell.nColumn;
+ i_tableControl.captureMouse();
+ return ActivateFunction;
+ }
+ }
+
+ return SkipFunction;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult ColumnResize::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nResizingColumn == COL_INVALID )
+ return SkipFunction;
+
+ Point const aPoint = i_event.GetPosPixel();
+
+ i_tableControl.hideTracking();
+ PColumnModel const pColumn = i_tableControl.getModel()->getColumnModel( m_nResizingColumn );
+ long const maxWidthLogical = pColumn->getMaxWidth();
+ long const minWidthLogical = pColumn->getMinWidth();
+
+ // new position of mouse
+ long const requestedEnd = aPoint.X();
+
+ // old position of right border
+ long const oldEnd = i_tableControl.getColumnMetrics( m_nResizingColumn ).nEndPixel;
+
+ // position of left border if cursor in the to-be-resized column
+ long const columnStart = i_tableControl.getColumnMetrics( m_nResizingColumn ).nStartPixel;
+ long const requestedWidth = requestedEnd - columnStart;
+ // TODO: this is not correct, strictly: It assumes that the mouse was pressed exactly on the "end" pos,
+ // but for a while now, we have relaxed this, and allow clicking a few pixels aside, too
+
+ if ( requestedEnd >= columnStart )
+ {
+ long requestedWidthLogical = i_tableControl.pixelWidthToAppFont( requestedWidth );
+ // respect column width limits
+ if ( oldEnd > requestedEnd )
+ {
+ // column has become smaller, check against minimum width
+ if ( ( minWidthLogical != 0 ) && ( requestedWidthLogical < minWidthLogical ) )
+ requestedWidthLogical = minWidthLogical;
+ }
+ else if ( oldEnd < requestedEnd )
+ {
+ // column has become larger, check against max width
+ if ( ( maxWidthLogical != 0 ) && ( requestedWidthLogical >= maxWidthLogical ) )
+ requestedWidthLogical = maxWidthLogical;
+ }
+ pColumn->setWidth( requestedWidthLogical );
+ i_tableControl.invalidate( TableAreaAll );
+ }
+
+ i_tableControl.setPointer( Pointer() );
+ i_tableControl.releaseMouse();
+
+ m_nResizingColumn = COL_INVALID;
+ return DeactivateFunction;
+ }
+
+ //==================================================================================================================
+ //= RowSelection
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult RowSelection::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ OSL_UNUSED( i_tableControl );
+ OSL_UNUSED( i_event );
+ return SkipFunction;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult RowSelection::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ bool handled = false;
+
+ 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;
+ }
+ 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;
+ }
+ }
+
+ if ( handled )
+ m_bActive = true;
+ return handled ? ActivateFunction : SkipFunction;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult RowSelection::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ TableCell const tableCell = i_tableControl.hitTest( i_event.GetPosPixel() );
+ if ( tableCell.nRow >= 0 )
+ {
+ if ( i_tableControl.getSelEngine()->GetSelectionMode() != NO_SELECTION )
+ {
+ i_tableControl.getSelEngine()->SelMouseButtonUp( i_event );
+ }
+ }
+ if ( m_bActive )
+ {
+ m_bActive = false;
+ return DeactivateFunction;
+ }
+ return SkipFunction;
+ }
+
+ //==================================================================================================================
+ //= ColumnSortHandler
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult ColumnSortHandler::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ OSL_UNUSED( i_tableControl );
+ OSL_UNUSED( i_event );
+ return SkipFunction;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult ColumnSortHandler::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nActiveColumn != COL_INVALID )
+ {
+ OSL_ENSURE( false, "ColumnSortHandler::handleMouseDown: called while already active - suspicious!" );
+ return ContinueFunction;
+ }
+
+ if ( i_tableControl.getModel()->getSortAdapter() == NULL )
+ // no sorting support at the model
+ return SkipFunction;
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( ( tableCell.nRow != ROW_COL_HEADERS ) || ( tableCell.nColumn < 0 ) )
+ return SkipFunction;
+
+ // TODO: ensure the column header is rendered in some special way, indicating its current state
+
+ m_nActiveColumn = tableCell.nColumn;
+ return ActivateFunction;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ FunctionResult ColumnSortHandler::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nActiveColumn == COL_INVALID )
+ return SkipFunction;
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.nColumn == m_nActiveColumn ) )
+ {
+ ITableDataSort* pSort = i_tableControl.getModel()->getSortAdapter();
+ ENSURE_OR_RETURN( pSort != NULL, "ColumnSortHandler::handleMouseUp: somebody is mocking with us!", DeactivateFunction );
+ // in handleMousButtonDown, the model claimed to have sort support ...
+
+ ColumnSortDirection eSortDirection = ColumnSortAscending;
+ ColumnSort const aCurrentSort = pSort->getCurrentSortOrder();
+ if ( aCurrentSort.nColumnPos == m_nActiveColumn )
+ // invert existing sort order
+ eSortDirection = ( aCurrentSort.eSortDirection == ColumnSortAscending ) ? ColumnSortDescending : ColumnSortAscending;
+
+ pSort->sortByColumn( m_nActiveColumn, eSortDirection );
+ }
+
+ m_nActiveColumn = COL_INVALID;
+ return DeactivateFunction;
+ }
+
+//......................................................................................................................
+} } // namespace svt::table
+//......................................................................................................................
diff --git a/svtools/source/table/mousefunction.hxx b/svtools/source/table/mousefunction.hxx
new file mode 100755
index 000000000000..2149026a0923
--- /dev/null
+++ b/svtools/source/table/mousefunction.hxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SVTOOLS_MOUSEFUNCTION_HXX
+#define SVTOOLS_MOUSEFUNCTION_HXX
+
+#include "svtools/table/tabletypes.hxx"
+
+#include <rtl/ref.hxx>
+
+#include <boost/noncopyable.hpp>
+
+class MouseEvent;
+
+//......................................................................................................................
+namespace svt { namespace table
+{
+//......................................................................................................................
+
+ class ITableControl;
+
+ //==================================================================================================================
+ //= FunctionResult
+ //==================================================================================================================
+ enum FunctionResult
+ {
+ ActivateFunction,
+ ContinueFunction,
+ DeactivateFunction,
+
+ SkipFunction
+ };
+
+ //==================================================================================================================
+ //= IMouseFunction
+ //==================================================================================================================
+ class IMouseFunction : public ::rtl::IReference, public ::boost::noncopyable
+ {
+ public:
+ virtual FunctionResult handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) = 0;
+ virtual FunctionResult handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) = 0;
+ virtual FunctionResult handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) = 0;
+
+ protected:
+ virtual ~IMouseFunction() { }
+ };
+
+ //==================================================================================================================
+ //= MouseFunction
+ //==================================================================================================================
+ class MouseFunction : public IMouseFunction
+ {
+ public:
+ MouseFunction()
+ :m_refCount( 0 )
+ {
+ }
+ protected:
+ ~MouseFunction()
+ {
+ }
+
+ public:
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+ private:
+ oslInterlockedCount m_refCount;
+ };
+
+ //==================================================================================================================
+ //= ColumnResize
+ //==================================================================================================================
+ class ColumnResize : public MouseFunction
+ {
+ public:
+ ColumnResize()
+ :m_nResizingColumn( COL_INVALID )
+ {
+ }
+
+ public:
+ // IMouseFunction
+ virtual FunctionResult handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event );
+ virtual FunctionResult handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event );
+ virtual FunctionResult handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event );
+
+ private:
+ ColPos m_nResizingColumn;
+ };
+
+ //==================================================================================================================
+ //= RowSelection
+ //==================================================================================================================
+ class RowSelection : public MouseFunction
+ {
+ public:
+ RowSelection()
+ :m_bActive( false )
+ {
+ }
+
+ public:
+ // IMouseFunction
+ virtual FunctionResult handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event );
+ virtual FunctionResult handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event );
+ virtual FunctionResult handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event );
+
+ private:
+ bool m_bActive;
+ };
+
+ //==================================================================================================================
+ //= ColumnSortHandler
+ //==================================================================================================================
+ class ColumnSortHandler : public MouseFunction
+ {
+ public:
+ ColumnSortHandler()
+ :m_nActiveColumn( COL_INVALID )
+ {
+ }
+
+ public:
+ // IMouseFunction
+ virtual FunctionResult handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event );
+ virtual FunctionResult handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event );
+ virtual FunctionResult handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event );
+
+ private:
+ ColPos m_nActiveColumn;
+ };
+
+//......................................................................................................................
+} } // namespace svt::table
+//......................................................................................................................
+
+#endif // SVTOOLS_MOUSEFUNCTION_HXX
diff --git a/svtools/source/table/tablecontrol.cxx b/svtools/source/table/tablecontrol.cxx
index 1ed3894ef883..1aec8d4b27a4 100644
--- a/svtools/source/table/tablecontrol.cxx
+++ b/svtools/source/table/tablecontrol.cxx
@@ -29,54 +29,38 @@
#include "precompiled_svtools.hxx"
#include "svtools/table/tablecontrol.hxx"
+
#include "tablegeometry.hxx"
#include "tablecontrol_impl.hxx"
-#include "accessibletableimp.hxx"
-#include "svtools/table/tabledatawindow.hxx"
+#include "tabledatawindow.hxx"
+
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <tools/diagnose_ex.h>
+
using namespace ::com::sun::star::uno;
using ::com::sun::star::accessibility::XAccessible;
using namespace ::com::sun::star::accessibility;
using namespace ::com::sun::star::lang;
using namespace utl;
-//........................................................................
+//......................................................................................................................
namespace svt { namespace table
{
- //====================================================================
- //= AccessibleTableControl_Impl
- //====================================================================
- // ----------------------------------------------------------------------------
- Reference< XAccessible > AccessibleTableControl_Impl::getAccessibleTableHeader( AccessibleTableControlObjType _eObjType )
- {
- if ( m_pAccessible && m_pAccessible->isAlive() )
- return m_pAccessible->getTableHeader( _eObjType );
- return NULL;
- }
- // ----------------------------------------------------------------------------
- Reference< XAccessible > AccessibleTableControl_Impl::getAccessibleTable( )
- {
- if ( m_pAccessible && m_pAccessible->isAlive() )
- return m_pAccessible->getTable( );
- return NULL;
- }
+//......................................................................................................................
- //====================================================================
+ //==================================================================================================================
//= TableControl
- //====================================================================
- //--------------------------------------------------------------------
+ //==================================================================================================================
+ // -----------------------------------------------------------------------------------------------------------------
TableControl::TableControl( Window* _pParent, WinBits _nStyle )
:Control( _pParent, _nStyle )
,m_pImpl( new TableControl_Impl( *this ) )
- ,m_bSelectionChanged(false)
- ,m_bTooltip(false)
{
- TableDataWindow* aTableData = m_pImpl->getDataWindow();
- aTableData->SetMouseButtonDownHdl( LINK( this, TableControl, ImplMouseButtonDownHdl ) );
- aTableData->SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) );
- aTableData->SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) );
- m_pAccessTable.reset(new ::svt::table::AccessibleTableControl_Impl());
+ 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() );
@@ -84,51 +68,39 @@ namespace svt { namespace table
SetFillColor( aWindowColor );
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
TableControl::~TableControl()
{
ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
- DELETEZ( m_pImpl );
- if ( m_pAccessTable->m_pAccessible )
- {
- m_pAccessTable->m_pAccessible->dispose();
- }
+
+ m_pImpl->setModel( PTableModel() );
+ m_pImpl->disposeAccessible();
+ m_pImpl.reset();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::GetFocus()
{
if ( !m_pImpl->getInputHandler()->GetFocus( *m_pImpl ) )
- {
Control::GetFocus();
- Control::GrabFocus();
- }
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::LoseFocus()
{
if ( !m_pImpl->getInputHandler()->LoseFocus( *m_pImpl ) )
Control::LoseFocus();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::KeyInput( const KeyEvent& rKEvt )
{
if ( !m_pImpl->getInputHandler()->KeyInput( *m_pImpl, rKEvt ) )
Control::KeyInput( rKEvt );
- else
- {
- if(m_bSelectionChanged)
- {
- Select();
- m_bSelectionChanged = false;
- }
- }
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::StateChanged( StateChangedType i_nStateChange )
{
Control::StateChanged( i_nStateChange );
@@ -138,156 +110,180 @@ namespace svt { namespace table
{
case STATE_CHANGE_CONTROLBACKGROUND:
if ( IsControlBackground() )
- getDataWindow()->SetControlBackground( GetControlBackground() );
+ getDataWindow().SetControlBackground( GetControlBackground() );
else
- getDataWindow()->SetControlBackground();
+ getDataWindow().SetControlBackground();
break;
case STATE_CHANGE_CONTROLFOREGROUND:
if ( IsControlForeground() )
- getDataWindow()->SetControlForeground( GetControlForeground() );
+ getDataWindow().SetControlForeground( GetControlForeground() );
else
- getDataWindow()->SetControlForeground();
+ getDataWindow().SetControlForeground();
break;
case STATE_CHANGE_CONTROLFONT:
if ( IsControlFont() )
- getDataWindow()->SetControlFont( GetControlFont() );
+ getDataWindow().SetControlFont( GetControlFont() );
else
- getDataWindow()->SetControlFont();
+ getDataWindow().SetControlFont();
break;
}
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::Resize()
{
Control::Resize();
m_pImpl->onResize();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::SetModel( PTableModel _pModel )
{
m_pImpl->setModel( _pModel );
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
PTableModel TableControl::GetModel() const
{
return m_pImpl->getModel();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
RowPos TableControl::GetTopRow() const
{
return m_pImpl->getTopRow();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
void TableControl::SetTopRow( RowPos _nRow )
{
- // TODO
- (void)_nRow;
+ OSL_ENSURE( false, "TableControl::SetTopRow: not implemented!" );
+ OSL_UNUSED( _nRow );
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
sal_Int32 TableControl::GetCurrentRow() const
{
- return m_pImpl->getCurRow();
+ return m_pImpl->getCurrentRow();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
sal_Int32 TableControl::GetCurrentColumn() const
{
- return m_pImpl->getCurColumn();
+ return m_pImpl->getCurrentColumn();
}
- //--------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
bool TableControl::GoTo( ColPos _nColumn, RowPos _nRow )
{
return m_pImpl->goTo( _nColumn, _nRow );
}
- //--------------------------------------------------------------------
+
+ // -----------------------------------------------------------------------------------------------------------------
sal_Bool TableControl::GoToCell(sal_Int32 _nColPos, sal_Int32 _nRowPos)
{
return m_pImpl->goTo( _nColPos, _nRowPos );
}
- //--------------------------------------------------------------------
- void TableControl::clearSelection()
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Int32 TableControl::GetSelectedRowCount() const
+ {
+ return sal_Int32( m_pImpl->getSelectedRowCount() );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Int32 TableControl::GetSelectedRowIndex( sal_Int32 const i_selectionIndex ) const
{
- m_pImpl->clearSelection();
+ return sal_Int32( m_pImpl->getSelectedRowIndex( i_selectionIndex ) );
}
- //--------------------------------------------------------------------
- void TableControl::InvalidateDataWindow(RowPos _nRowStart, RowPos _nRowEnd, bool _bRemoved)
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableControl::IsRowSelected( sal_Int32 const i_rowIndex ) const
{
- Rectangle _rRect;
- if(_bRemoved)
- m_pImpl->invalidateRows();
+ return m_pImpl->isRowSelected( i_rowIndex );
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ 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)!" );
+
+ if ( i_select )
+ {
+ if ( !m_pImpl->markRowAsSelected( i_rowIndex ) )
+ // nothing to do
+ return;
+ }
else
{
- if(m_bSelectionChanged)
- {
- m_pImpl->invalidateSelectedRegion(_nRowStart, _nRowEnd, _rRect);
- m_bSelectionChanged = false;
- }
- else
- m_pImpl->invalidateRow(_nRowStart, _rRect);
+ m_pImpl->markRowAsDeselected( i_rowIndex );
}
+
+ m_pImpl->invalidateRowRange( i_rowIndex, i_rowIndex );
+ Select();
}
- //--------------------------------------------------------------------
- std::vector<sal_Int32>& TableControl::GetSelectedRows()
- {
- return m_pImpl->getSelectedRows();
- }
- //--------------------------------------------------------------------
- void TableControl::RemoveSelectedRow(RowPos _nRowPos)
+
+ // -----------------------------------------------------------------------------------------------------------------
+ void TableControl::SelectAllRows( bool const i_select )
{
- m_pImpl->removeSelectedRow(_nRowPos);
+ if ( i_select )
+ {
+ if ( !m_pImpl->markAllRowsAsSelected() )
+ // nothing to do
+ return;
+ }
+ else
+ {
+ if ( !m_pImpl->markAllRowsAsDeselected() )
+ // nothing to do
+ return;
+ }
+
+
+ Invalidate();
+ // TODO: can't we do better than this, and invalidate only the rows which changed?
+ Select();
}
- //--------------------------------------------------------------------
- RowPos TableControl::GetCurrentRow(const Point& rPoint)
+ // -----------------------------------------------------------------------------------------------------------------
+ ITableControl& TableControl::getTableControlInterface()
{
- return m_pImpl->getCurrentRow( rPoint );
+ return *m_pImpl;
}
+ // -----------------------------------------------------------------------------------------------------------------
SelectionEngine* TableControl::getSelEngine()
{
return m_pImpl->getSelEngine();
}
- TableDataWindow* TableControl::getDataWindow()
+ // -----------------------------------------------------------------------------------------------------------------
+ Window& TableControl::getDataWindow()
{
return m_pImpl->getDataWindow();
}
+ // -----------------------------------------------------------------------------------------------------------------
Reference< XAccessible > TableControl::CreateAccessible()
{
Window* pParent = GetAccessibleParentWindow();
- DBG_ASSERT( pParent, "TableControl::CreateAccessible - parent not found" );
+ ENSURE_OR_RETURN( pParent, "TableControl::CreateAccessible - parent not found", NULL );
- if( pParent && !m_pAccessTable->m_pAccessible)
- {
- Reference< XAccessible > xAccParent = pParent->GetAccessible();
- if( xAccParent.is() )
- {
- m_pAccessTable->m_pAccessible = getAccessibleFactory().createAccessibleTableControl(
- xAccParent, *this
- );
- }
- }
- Reference< XAccessible > xAccessible;
- if ( m_pAccessTable->m_pAccessible )
- xAccessible = m_pAccessTable->m_pAccessible->getMyself();
- return xAccessible;
+ return m_pImpl->getAccessible( *pParent );
}
+
+ // -----------------------------------------------------------------------------------------------------------------
Reference<XAccessible> TableControl::CreateAccessibleControl( sal_Int32 _nIndex )
{
(void)_nIndex;
- DBG_ASSERT( FALSE, "TableControl::CreateAccessibleControl: to be overwritten!" );
+ DBG_ASSERT( sal_False, "TableControl::CreateAccessibleControl: to be overwritten!" );
return NULL;
}
+
+ // -----------------------------------------------------------------------------------------------------------------
::rtl::OUString TableControl::GetAccessibleObjectName( AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const
{
::rtl::OUString aRetText;
@@ -320,311 +316,298 @@ namespace svt { namespace table
}
return aRetText;
}
-// -----------------------------------------------------------------------------
-::rtl::OUString TableControl::GetAccessibleObjectDescription( AccessibleTableControlObjType eObjType, sal_Int32 ) const
-{
- ::rtl::OUString aRetText;
- switch( eObjType )
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString TableControl::GetAccessibleObjectDescription( AccessibleTableControlObjType eObjType, sal_Int32 ) const
{
- case TCTYPE_GRIDCONTROL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridControl description" ) );
- break;
- case TCTYPE_TABLE:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLE description" ) );
- break;
- case TCTYPE_ROWHEADERBAR:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERBAR description" ) );
- break;
- case TCTYPE_COLUMNHEADERBAR:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERBAR description" ) );
- break;
- case TCTYPE_TABLECELL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLECELL description" ) );
- break;
- case TCTYPE_ROWHEADERCELL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERCELL description" ) );
- break;
- case TCTYPE_COLUMNHEADERCELL:
- aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERCELL description" ) );
- break;
+ ::rtl::OUString aRetText;
+ switch( eObjType )
+ {
+ case TCTYPE_GRIDCONTROL:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridControl description" ) );
+ break;
+ case TCTYPE_TABLE:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLE description" ) );
+ break;
+ case TCTYPE_ROWHEADERBAR:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERBAR description" ) );
+ break;
+ case TCTYPE_COLUMNHEADERBAR:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERBAR description" ) );
+ break;
+ case TCTYPE_TABLECELL:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLECELL description" ) );
+ break;
+ case TCTYPE_ROWHEADERCELL:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERCELL description" ) );
+ break;
+ case TCTYPE_COLUMNHEADERCELL:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERCELL description" ) );
+ break;
+ }
+ return aRetText;
}
- return aRetText;
-}
-// -----------------------------------------------------------------------------
-::rtl::OUString TableControl::GetRowDescription( sal_Int32 _nRow) const
-{
- (void)_nRow;
- return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "row description" ) );
-}
-// -----------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString TableControl::GetRowDescription( sal_Int32 _nRow) const
+ {
+ (void)_nRow;
+ return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "row description" ) );
+ }
-::rtl::OUString TableControl::GetRowName( sal_Int32 _nIndex) const
-{
- return GetModel()->getRowHeaderName()[_nIndex];
-}
-// -----------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString TableControl::GetRowName( sal_Int32 _nIndex) const
+ {
+ ::rtl::OUString sRowName;
+ GetModel()->getRowHeading( _nIndex ) >>= sRowName;
+ return sRowName;
+ }
-::rtl::OUString TableControl::GetColumnDescription( sal_uInt16 _nColumn) const
-{
- (void)_nColumn;
- return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "col description" ) );
-}
-// -----------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString TableControl::GetColumnDescription( sal_uInt16 _nColumn) const
+ {
+ (void)_nColumn;
+ return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "col description" ) );
+ }
-::rtl::OUString TableControl::GetColumnName( sal_Int32 _nIndex) const
-{
- return GetModel()->getColumnModel(_nIndex)->getName();
-}
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString TableControl::GetColumnName( sal_Int32 _nIndex) const
+ {
+ return GetModel()->getColumnModel(_nIndex)->getName();
+ }
-// -----------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
+ ::com::sun::star::uno::Any TableControl::GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos ) const
+ {
+ Any aCellContent;
+ GetModel()->getCellContent( _nColPos, _nRowPos, aCellContent );
+ return aCellContent;
+ }
-::com::sun::star::uno::Any TableControl::GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos) const
-{
- ::com::sun::star::uno::Any cellContent(::com::sun::star::uno::Any(::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("")) ));
- std::vector<std::vector< ::com::sun::star::uno::Any > >& aTableContent = GetModel()->getCellContent();
- if(&aTableContent)
- cellContent = aTableContent[_nRowPos][_nColPos];
- return cellContent;
-}
-// -----------------------------------------------------------------------------
-
-::rtl::OUString TableControl::GetAccessibleCellText( sal_Int32 _nRowPos, sal_Int32 _nColPos) const
-{
- const ::com::sun::star::uno::Any cellContent = GetCellContent(_nRowPos, _nColPos);
- return m_pImpl->convertToString(cellContent);
-}
-// -----------------------------------------------------------------------------
-
-void TableControl::FillAccessibleStateSet(
- ::utl::AccessibleStateSetHelper& rStateSet,
- AccessibleTableControlObjType eObjType ) const
-{
- switch( eObjType )
- {
- case TCTYPE_GRIDCONTROL:
- case TCTYPE_TABLE:
-
- rStateSet.AddState( AccessibleStateType::FOCUSABLE );
- rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
- if ( HasFocus() )
- rStateSet.AddState( AccessibleStateType::FOCUSED );
- if ( IsActive() )
- rStateSet.AddState( AccessibleStateType::ACTIVE );
- if ( IsEnabled() )
- rStateSet.AddState( AccessibleStateType::ENABLED );
- if ( IsReallyVisible() )
- rStateSet.AddState( AccessibleStateType::VISIBLE );
- rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString TableControl::GetAccessibleCellText( sal_Int32 _nRowPos, sal_Int32 _nColPos) const
+ {
+ return m_pImpl->getCellContentAsString( _nRowPos, _nColPos );
+ }
- 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:
- {
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl::FillAccessibleStateSet(
+ ::utl::AccessibleStateSetHelper& rStateSet,
+ AccessibleTableControlObjType eObjType ) const
+ {
+ switch( eObjType )
+ {
+ case TCTYPE_GRIDCONTROL:
+ case TCTYPE_TABLE:
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
+ if ( HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ if ( IsActive() )
+ rStateSet.AddState( AccessibleStateType::ACTIVE );
+ if ( IsEnabled() )
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ if ( IsReallyVisible() )
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ 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::TRANSIENT );
+ rStateSet.AddState( AccessibleStateType::SELECTABLE);
+ if( GetSelectedRowCount()>0)
+ rStateSet.AddState( AccessibleStateType::SELECTED);
+ }
+ break;
+ case TCTYPE_ROWHEADERCELL:
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
rStateSet.AddState( AccessibleStateType::TRANSIENT );
- rStateSet.AddState( AccessibleStateType::SELECTABLE);
- if( GetSelectedRowCount()>0)
- 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;
+ break;
+ case TCTYPE_COLUMNHEADERCELL:
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ break;
+ }
}
-}
-Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) const
-{
- return Control::GetWindowExtentsRelative( pRelativeWindow );
-}
-//-----------------------------------------------------------------------------
-void TableControl::GrabFocus()
-{
- Control::GrabFocus();
-}
-// -----------------------------------------------------------------------------
-Reference< XAccessible > TableControl::GetAccessible( BOOL bCreate )
-{
- return Control::GetAccessible( bCreate );
-}
-// -----------------------------------------------------------------------------
-Window* TableControl::GetAccessibleParentWindow() const
-{
- return Control::GetAccessibleParentWindow();
-}
-// -----------------------------------------------------------------------------
-Window* TableControl::GetWindowInstance()
-{
- return this;
-}
+ //------------------------------------------------------------------------------------------------------------------
+ Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) const
+ {
+ return Control::GetWindowExtentsRelative( pRelativeWindow );
+ }
-sal_Bool TableControl::HasRowHeader()
-{
- return GetModel()->hasRowHeaders();
-}
-//--------------------------------------------------------------------------------
-sal_Bool TableControl::HasColHeader()
-{
- return GetModel()->hasColumnHeaders();
-}
-//--------------------------------------------------------------------------------
-sal_Int32 TableControl::GetAccessibleControlCount() const
-{
- sal_Int32 count = 0;
- if(GetRowCount()>0)
- count+=1;
- if(GetModel()->hasRowHeaders())
- count+=1;
- if(GetModel()->hasColumnHeaders())
- count+=1;
- return count;
-}
-sal_Bool TableControl::ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint )
-{
- sal_Int32 nRow = m_pImpl->getCurrentRow(_rPoint);
- sal_Int32 nCol = GetCurrentColumn();
- _rnIndex = nRow * GetColumnCount() + nCol;
- return nRow>=0 ? sal_True : sal_False;
-}
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl::GrabFocus()
+ {
+ Control::GrabFocus();
+ }
-long TableControl::GetRowCount() const
-{
- return m_pImpl->getRowCount();
-}
-long TableControl::GetColumnCount() const
-{
- return m_pImpl->getColumnCount();
-}
-sal_Bool TableControl::HasRowHeader() const
-{
- PTableModel pModel = GetModel();
- return pModel->hasRowHeaders();
-}
-sal_Int32 TableControl::GetSelectedRowCount() const
-{
- return m_pImpl->getSelectedRows().size();
-}
-bool TableControl::IsRowSelected( long _nRow ) const
-{
- return m_pImpl->isRowSelected(m_pImpl->getSelectedRows(), _nRow);
-}
-sal_Bool TableControl::ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint )
-{
- _rnRow = m_pImpl->getCurrentRow(_rPoint);
- _rnColPos = GetCurrentColumn();
- return _rnRow>=0 ? sal_True : sal_False;
-}
-void TableControl::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
-{
- if ( GetCurrentRow() == _nRow && GetCurrentColumn() == _nColumnPos )
- _rStateSet.AddState( AccessibleStateType::FOCUSED );
- else // only transient when column is not focused
- _rStateSet.AddState( AccessibleStateType::TRANSIENT );
-}
-Rectangle TableControl::GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex)
-{
- (void)_nRow;
- (void)_nColumnPos;
- return GetCharacterBounds(nIndex);
-}
-sal_Int32 TableControl::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
-{
- (void)_nRow;
- (void)_nColumnPos;
- return GetIndexForPoint(_rPoint);
-;
-}
- // -----------------------------------------------------------------------------
-sal_Bool TableControl::isAccessibleAlive( ) const
-{
- return ( NULL != m_pAccessTable->m_pAccessible ) && m_pAccessTable->m_pAccessible->isAlive();
-}
+ //------------------------------------------------------------------------------------------------------------------
+ Reference< XAccessible > TableControl::GetAccessible( sal_Bool bCreate )
+ {
+ return Control::GetAccessible( bCreate );
+ }
-// -----------------------------------------------------------------------------
-::svt::IAccessibleFactory& TableControl::getAccessibleFactory()
-{
- return m_pAccessTable->m_aFactoryAccess.getFactory();
-}
-// -----------------------------------------------------------------------------
-void TableControl::commitGridControlEvent( sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
-{
- if ( isAccessibleAlive() )
- m_pAccessTable->m_pAccessible->commitEvent( _nEventId, _rNewValue, _rOldValue);
-}
-// -----------------------------------------------------------------------------
-Rectangle TableControl::calcHeaderRect(sal_Bool _bIsColumnBar,BOOL _bOnScreen)
-{
- (void)_bOnScreen;
- return m_pImpl->calcHeaderRect(_bIsColumnBar);
-}
-// -----------------------------------------------------------------------------
-Rectangle TableControl::calcTableRect(BOOL _bOnScreen)
-{
- (void)_bOnScreen;
- return m_pImpl->calcTableRect();
-}
-//--------------------------------------------------------------------
-::com::sun::star::uno::Sequence< sal_Int32 >& TableControl::getColumnsForTooltip()
-{
- return m_nCols;
-}
-//--------------------------------------------------------------------
-::com::sun::star::uno::Sequence< ::rtl::OUString >& TableControl::getTextForTooltip()
-{
- return m_aText;
-}
-//--------------------------------------------------------------------
-void TableControl::setTooltip(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aText, const ::com::sun::star::uno::Sequence< sal_Int32 >& nCols )
-{
- m_aText = aText;
- m_nCols = nCols;
- m_bTooltip = true;
-}
-// -----------------------------------------------------------------------
-void TableControl::selectionChanged(bool _bChanged)
-{
- m_bSelectionChanged = _bChanged;
-}
-// -----------------------------------------------------------------------
-bool TableControl::isTooltip()
-{
- return m_bTooltip;
-}
-// -----------------------------------------------------------------------
-IMPL_LINK( TableControl, ImplSelectHdl, void*, EMPTYARG )
-{
- Select();
- return 1;
-}
-IMPL_LINK( TableControl, ImplMouseButtonDownHdl, MouseEvent*, pData )
-{
- CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, pData );
- return 1;
-}
-IMPL_LINK( TableControl, ImplMouseButtonUpHdl, MouseEvent*, pData )
-{
- CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, pData );
- return 1;
-}
-// -----------------------------------------------------------------------
-void TableControl::Select()
-{
- ImplCallEventListenersAndHandler( VCLEVENT_TABLEROW_SELECT, m_aSelectHdl, this );
-}
-//........................................................................
+ //------------------------------------------------------------------------------------------------------------------
+ Window* TableControl::GetAccessibleParentWindow() const
+ {
+ return Control::GetAccessibleParentWindow();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Window* TableControl::GetWindowInstance()
+ {
+ return this;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableControl::HasRowHeader()
+ {
+ return GetModel()->hasRowHeaders();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableControl::HasColHeader()
+ {
+ return GetModel()->hasColumnHeaders();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Int32 TableControl::GetAccessibleControlCount() const
+ {
+ sal_Int32 count = 0;
+ if(GetRowCount()>0)
+ count+=1;
+ if(GetModel()->hasRowHeaders())
+ count+=1;
+ if(GetModel()->hasColumnHeaders())
+ count+=1;
+ return count;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableControl::ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint )
+ {
+ sal_Int32 nRow = m_pImpl->getRowAtPoint( _rPoint );
+ sal_Int32 nCol = m_pImpl->getColAtPoint( _rPoint );
+ _rnIndex = nRow * GetColumnCount() + nCol;
+ return nRow >= 0 ? sal_True : sal_False;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ long TableControl::GetRowCount() const
+ {
+ return GetModel()->getRowCount();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ long TableControl::GetColumnCount() const
+ {
+ return GetModel()->getColumnCount();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableControl::HasRowHeader() const
+ {
+ return GetModel()->hasRowHeaders();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableControl::ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint )
+ {
+ _rnRow = m_pImpl->getRowAtPoint( _rPoint );
+ _rnColPos = m_pImpl->getColAtPoint( _rPoint );
+ return _rnRow >= 0 ? sal_True : sal_False;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
+ {
+ if ( GetCurrentRow() == _nRow && GetCurrentColumn() == _nColumnPos )
+ _rStateSet.AddState( AccessibleStateType::FOCUSED );
+ else // only transient when column is not focused
+ _rStateSet.AddState( AccessibleStateType::TRANSIENT );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Rectangle TableControl::GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex)
+ {
+ (void)_nRow;
+ (void)_nColumnPos;
+ return GetCharacterBounds(nIndex);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Int32 TableControl::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
+ {
+ (void)_nRow;
+ (void)_nColumnPos;
+ return GetIndexForPoint(_rPoint);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Rectangle TableControl::calcHeaderRect(sal_Bool _bIsColumnBar,sal_Bool _bOnScreen)
+ {
+ (void)_bOnScreen;
+ return m_pImpl->calcHeaderRect( _bIsColumnBar ? false : true );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Rectangle TableControl::calcTableRect(sal_Bool _bOnScreen)
+ {
+ (void)_bOnScreen;
+ return m_pImpl->calcTableRect();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ IMPL_LINK( TableControl, ImplSelectHdl, void*, EMPTYARG )
+ {
+ Select();
+ return 1;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ IMPL_LINK( TableControl, ImplMouseButtonDownHdl, MouseEvent*, pData )
+ {
+ CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, pData );
+ return 1;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ IMPL_LINK( TableControl, ImplMouseButtonUpHdl, MouseEvent*, pData )
+ {
+ CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, pData );
+ return 1;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl::Select()
+ {
+ ImplCallEventListenersAndHandler( VCLEVENT_TABLEROW_SELECT, m_pImpl->getSelectHandler(), this );
+ }
}} // namespace svt::table
//........................................................................
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl::SetSelectHdl( const Link& i_selectHandler )
+ {
+ m_pImpl->setSelectHandler( i_selectHandler );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ const Link& TableControl::GetSelectHdl() const
+ {
+ return m_pImpl->getSelectHandler();
+ }
+
+//......................................................................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/tablecontrol_impl.cxx b/svtools/source/table/tablecontrol_impl.cxx
index a02dd9a2a50d..bbcdbfaddeb6 100644..100755
--- a/svtools/source/table/tablecontrol_impl.cxx
+++ b/svtools/source/table/tablecontrol_impl.cxx
@@ -31,40 +31,60 @@
#include "svtools/table/tablecontrol.hxx"
#include "svtools/table/defaultinputhandler.hxx"
#include "svtools/table/tablemodel.hxx"
+
+#include "tabledatawindow.hxx"
#include "tablecontrol_impl.hxx"
#include "tablegeometry.hxx"
-#include "svtools/table/tabledatawindow.hxx"
-#include <com/sun/star/awt/XControl.hpp>
+#include "cellvalueconversion.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/flagguard.hxx>
#include <vcl/scrbar.hxx>
#include <vcl/seleng.hxx>
#include <rtl/ref.hxx>
-#include <toolkit/awt/vclxwindow.hxx>
#include <vcl/image.hxx>
-#include <com/sun/star/graphic/XGraphic.hpp>
+#include <tools/diagnose_ex.h>
#include <functional>
-#include <stdlib.h>
-//........................................................................
+#define MIN_COLUMN_WIDTH_PIXEL 4
+
+//......................................................................................................................
namespace svt { namespace table
{
-//........................................................................
-
- //====================================================================
- //= TempHideCursor
- //====================================================================
- class TempHideCursor
+//......................................................................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::accessibility::AccessibleTableModelChange;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::accessibility::XAccessible;
+ using ::com::sun::star::uno::Reference;
+ /** === end UNO using === **/
+ namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
+ namespace AccessibleTableModelChangeType = ::com::sun::star::accessibility::AccessibleTableModelChangeType;
+
+ //==================================================================================================================
+ //= SuppressCursor
+ //==================================================================================================================
+ class SuppressCursor
{
private:
- IAbstractTableControl& m_rTable;
+ ITableControl& m_rTable;
public:
- TempHideCursor( IAbstractTableControl& _rTable )
+ SuppressCursor( ITableControl& _rTable )
:m_rTable( _rTable )
{
m_rTable.hideCursor();
}
- ~TempHideCursor()
+ ~SuppressCursor()
{
m_rTable.showCursor();
}
@@ -103,50 +123,18 @@ namespace svt { namespace table
{
return false;
}
- virtual void setRowHeaders(bool _bRowHeaders)
- {
- (void)_bRowHeaders;
- }
- virtual void setColumnHeaders(bool _bColumnHeaders)
- {
- (void)_bColumnHeaders;
- }
- void setColumnCount(TableSize _nColCount)
- {
- (void) _nColCount;
- }
- void setRowCount(TableSize _nRowCount)
- {
- (void)_nRowCount;
- }
virtual bool isCellEditable( ColPos col, RowPos row ) const
{
(void)col;
(void)row;
return false;
}
- virtual void addTableModelListener( const PTableModelListener& listener )
- {
- (void)listener;
- // ignore
- }
- virtual void removeTableModelListener( const PTableModelListener& listener )
- {
- (void)listener;
- // ignore
- }
virtual PColumnModel getColumnModel( ColPos column )
{
OSL_FAIL( "EmptyTableModel::getColumnModel: invalid call!" );
(void)column;
return PColumnModel();
}
- virtual PColumnModel getColumnModelByID( ColumnID id )
- {
- OSL_FAIL( "EmptyTableModel::getColumnModel: invalid call!" );
- (void)id;
- return PColumnModel();
- }
virtual PTableRenderer getRenderer() const
{
return PTableRenderer();
@@ -171,83 +159,68 @@ namespace svt { namespace table
{
return 0;
}
- virtual ScrollbarVisibility getVerticalScrollbarVisibility(int , int ) const
+ virtual ScrollbarVisibility getVerticalScrollbarVisibility() const
{
- return ScrollbarShowNever;
+ return ScrollbarShowNever;
}
- virtual ScrollbarVisibility getHorizontalScrollbarVisibility(int , int ) const
+ virtual ScrollbarVisibility getHorizontalScrollbarVisibility() const
{
- return ScrollbarShowNever;
+ return ScrollbarShowNever;
+ }
+ virtual void addTableModelListener( const PTableModelListener& i_listener )
+ {
+ (void)i_listener;
+ }
+ virtual void removeTableModelListener( const PTableModelListener& i_listener )
+ {
+ (void)i_listener;
+ }
+ virtual ::boost::optional< ::Color > getLineColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getHeaderBackgroundColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getHeaderTextColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getTextColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::Color > getTextLineColor() const
+ {
+ return ::boost::optional< ::Color >();
+ }
+ virtual ::boost::optional< ::std::vector< ::Color > > getRowBackgroundColors() const
+ {
+ return ::boost::optional< ::std::vector< ::Color > >();
+ }
+ virtual ::com::sun::star::style::VerticalAlignment getVerticalAlign() const
+ {
+ return com::sun::star::style::VerticalAlignment(0);
+ }
+ virtual ITableDataSort* getSortAdapter()
+ {
+ return NULL;
+ }
+ virtual void getCellContent( ColPos const i_col, RowPos const i_row, ::com::sun::star::uno::Any& o_cellContent )
+ {
+ (void)i_row;
+ (void)i_col;
+ o_cellContent.clear();
+ }
+ virtual void getCellToolTip( ColPos const, RowPos const, ::com::sun::star::uno::Any& )
+ {
+ }
+ virtual Any getRowHeading( RowPos const i_rowPos ) const
+ {
+ (void)i_rowPos;
+ return Any();
}
- virtual bool hasVerticalScrollbar()
- {
- return false;
- }
- virtual bool hasHorizontalScrollbar()
- {
- return false;
- }
- virtual void setCellContent(const std::vector<std::vector< ::com::sun::star::uno::Any > >& )
- {
- }
- virtual ::com::sun::star::util::Color getLineColor()
- {
- return 0;
- }
- virtual void setLineColor(::com::sun::star::util::Color )
- {
- }
- virtual ::com::sun::star::util::Color getHeaderBackgroundColor()
- {
- return -1;
- }
- virtual void setHeaderBackgroundColor(::com::sun::star::util::Color )
- {
- }
- virtual ::com::sun::star::util::Color getTextColor()
- {
- return 0;
- }
- virtual void setTextColor(::com::sun::star::util::Color )
- {
- }
- virtual ::com::sun::star::util::Color getOddRowBackgroundColor()
- {
- return -1;
- }
- virtual void setOddRowBackgroundColor(::com::sun::star::util::Color )
- {
- }
- virtual ::com::sun::star::style::VerticalAlignment getVerticalAlign()
- {
- return com::sun::star::style::VerticalAlignment(0);
- }
- virtual void setVerticalAlign(com::sun::star::style::VerticalAlignment )
- {
- }
- virtual ::com::sun::star::util::Color getEvenRowBackgroundColor()
- {
- return -1;
- }
- virtual void setEvenRowBackgroundColor(::com::sun::star::util::Color )
- {
- }
- virtual std::vector<std::vector< ::com::sun::star::uno::Any > >& getCellContent()
- {
- return m_aCellContent;
- }
- virtual void setRowHeaderName(const std::vector<rtl::OUString>& )
- {
- }
- virtual std::vector<rtl::OUString>& getRowHeaderName()
- {
- aRowHeaderNames.clear();
- aRowHeaderNames.push_back( rtl::OUString() );
- return aRowHeaderNames;
- }
- private:
- std::vector<rtl::OUString> aRowHeaderNames;
- std::vector<std::vector< ::com::sun::star::uno::Any > > m_aCellContent;
};
@@ -313,7 +286,7 @@ namespace svt { namespace table
}
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
const sal_Char* TableControl_Impl::impl_checkInvariants() const
{
if ( !m_pModel )
@@ -328,12 +301,9 @@ namespace svt { namespace table
if ( m_pModel->getRowCount() != m_nRowCount )
return "row counts are inconsistent!";
- if ( ( ( m_nCurColumn != COL_INVALID ) && !m_aColumnWidthsPixel.empty() && ( m_nCurColumn < 0 ) ) || ( m_nCurColumn >= (ColPos)m_aColumnWidthsPixel.size() ) )
+ if ( ( ( m_nCurColumn != COL_INVALID ) && !m_aColumnWidths.empty() && ( m_nCurColumn < 0 ) ) || ( m_nCurColumn >= (ColPos)m_aColumnWidths.size() ) )
return "current column is invalid!";
- if ( m_aColumnWidthsPixel.size() != m_aAccColumnWidthsPixel.size() )
- return "columnd width caches are inconsistent!";
-
if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nTopRow, (RowPos)-1, m_nRowCount, getModel(), (RowPos)0 ) )
return "invalid top row value!";
@@ -349,6 +319,20 @@ namespace svt { namespace table
if ( m_pInputHandler != m_pModel->getInputHandler() )
return "input handler is not the model-provided one!";
+ // m_aSelectedRows should have reasonable content
+ {
+ if ( m_aSelectedRows.size() > size_t( m_pModel->getRowCount() ) )
+ return "there are more rows selected than actually exist";
+ for ( ::std::vector< RowPos >::const_iterator selRow = m_aSelectedRows.begin();
+ selRow != m_aSelectedRows.end();
+ ++selRow
+ )
+ {
+ if ( ( *selRow < 0 ) || ( *selRow >= m_pModel->getRowCount() ) )
+ return "a non-existent row is selected";
+ }
+ }
+
// m_nColHeaderHeightPixel consistent with the model's value?
{
TableMetrics nHeaderHeight = m_pModel->hasColumnHeaders() ? m_pModel->getColumnHeaderHeight() : 0;
@@ -374,7 +358,28 @@ namespace svt { namespace table
return "row header widths are inconsistent!";
}
- // TODO: check m_aColumnWidthsPixel and m_aAccColumnWidthsPixel
+ // m_aColumnWidths consistency
+ if ( size_t( m_nColumnCount ) != m_aColumnWidths.size() )
+ return "wrong number of cached column widths";
+
+ for ( ColumnPositions::const_iterator col = m_aColumnWidths.begin();
+ col != m_aColumnWidths.end();
+ )
+ {
+ if ( col->getEnd() < col->getStart() )
+ return "column widths: 'end' is expected to not be smaller than start";
+
+ ColumnPositions::const_iterator nextCol = col + 1;
+ if ( nextCol != m_aColumnWidths.end() )
+ if ( col->getEnd() != nextCol->getStart() )
+ return "column widths: one column's end should be the next column's start";
+ col = nextCol;
+ }
+
+ if ( m_nLeftColumn < m_nColumnCount )
+ if ( m_aColumnWidths[ m_nLeftColumn ].getStart() != m_nRowHeaderWidthPixel )
+ return "the left-most column should start immediately after the row header";
+
if ( m_nCursorHidden < 0 )
return "invalid hidden count for the cursor!";
@@ -383,6 +388,8 @@ namespace svt { namespace table
DBG_SUSPEND_INV( INV_SCROLL_POSITION );
// prevent infinite recursion
+ if ( m_nLeftColumn < 0 )
+ return "invalid left-most column index";
if ( m_pVScroll->GetThumbPos() != m_nTopRow )
return "vertical scroll bar |position| is incorrect!";
if ( m_pVScroll->GetRange().Max() != m_nRowCount )
@@ -411,44 +418,44 @@ namespace svt { namespace table
#define DBG_CHECK_ME() \
DBG_CHKTHIS( TableControl_Impl, TableControl_Impl_checkInvariants )
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
TableControl_Impl::TableControl_Impl( TableControl& _rAntiImpl )
:m_rAntiImpl ( _rAntiImpl )
,m_pModel ( new EmptyTableModel )
,m_pInputHandler ( )
,m_nRowHeightPixel ( 15 )
- ,m_nColHeaderHeightPixel( 0 )
+ ,m_nColHeaderHeightPixel( 0 )
,m_nRowHeaderWidthPixel ( 0 )
,m_nColumnCount ( 0 )
,m_nRowCount ( 0 )
+ ,m_bColumnsFit ( true )
,m_nCurColumn ( COL_INVALID )
,m_nCurRow ( ROW_INVALID )
,m_nLeftColumn ( 0 )
- ,m_nTopRow ( 0 )
+ ,m_nTopRow ( 0 )
,m_nCursorHidden ( 1 )
,m_pDataWindow ( new TableDataWindow( *this ) )
- ,m_pVScroll ( NULL )
+ ,m_pVScroll ( NULL )
,m_pHScroll ( NULL )
,m_pScrollCorner ( NULL )
- ,m_pSelEngine ( )
- ,m_nRowSelected ( )
- ,m_pTableFunctionSet ( new TableFunctionSet(this ) )
- ,m_nAnchor (-1 )
- ,m_bResizing ( false )
- ,m_nResizingColumn ( 0 )
- ,m_bResizingGrid ( false )
+ ,m_pSelEngine ( )
+ ,m_aSelectedRows ( )
+ ,m_pTableFunctionSet ( new TableFunctionSet( this ) )
+ ,m_nAnchor ( -1 )
+ ,m_bUpdatingColWidths ( false )
+ ,m_pAccessibleTable ( NULL )
#if DBG_UTIL
,m_nRequiredInvariants ( INV_SCROLL_POSITION )
#endif
{
DBG_CTOR( TableControl_Impl, TableControl_Impl_checkInvariants );
- m_pSelEngine = new SelectionEngine(m_pDataWindow, m_pTableFunctionSet);
- m_pSelEngine->SetSelectionMode(SINGLE_SELECTION);
+ m_pSelEngine = new SelectionEngine( m_pDataWindow.get(), m_pTableFunctionSet );
+ m_pSelEngine->SetSelectionMode(SINGLE_SELECTION);
m_pDataWindow->SetPosPixel( Point( 0, 0 ) );
m_pDataWindow->Show();
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
TableControl_Impl::~TableControl_Impl()
{
DBG_DTOR( TableControl_Impl, TableControl_Impl_checkInvariants );
@@ -458,35 +465,30 @@ namespace svt { namespace table
DELETEZ( m_pScrollCorner );
DELETEZ( m_pTableFunctionSet );
DELETEZ( m_pSelEngine );
- DELETEZ( m_pDataWindow );
}
- //--------------------------------------------------------------------
- PTableModel TableControl_Impl::getModel() const
- {
- if ( dynamic_cast< const EmptyTableModel* >( m_pModel.get() ) != NULL )
- // if it's an EmptyTableModel, pretend that there is no model
- return PTableModel();
-
- return m_pModel;
- }
-
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::setModel( PTableModel _pModel )
{
DBG_CHECK_ME();
- TempHideCursor aHideCursor( *this );
+ SuppressCursor aHideCursor( *this );
+
+ if ( !!m_pModel )
+ m_pModel->removeTableModelListener( shared_from_this() );
m_pModel = _pModel;
if ( !m_pModel)
m_pModel.reset( new EmptyTableModel );
+ m_pModel->addTableModelListener( shared_from_this() );
+
m_nCurRow = ROW_INVALID;
m_nCurColumn = COL_INVALID;
// recalc some model-dependent cached info
impl_ni_updateCachedModelValues();
+ impl_ni_updateScrollbars();
// completely invalidate
m_rAntiImpl.Invalidate();
@@ -496,67 +498,308 @@ namespace svt { namespace table
if ( m_nColumnCount ) m_nCurColumn = 0;
}
- //--------------------------------------------------------------------
- void TableControl_Impl::impl_getAllVisibleCellsArea( Rectangle& _rCellArea ) const
+ //------------------------------------------------------------------------------------------------------------------
+ namespace
+ {
+ bool lcl_adjustSelectedRows( ::std::vector< RowPos >& io_selectionIndexes, RowPos const i_firstAffectedRowIndex, TableSize const i_offset )
+ {
+ bool didChanges = false;
+ for ( ::std::vector< RowPos >::iterator selPos = io_selectionIndexes.begin();
+ selPos != io_selectionIndexes.end();
+ ++selPos
+ )
+ {
+ if ( *selPos < i_firstAffectedRowIndex )
+ continue;
+ *selPos += i_offset;
+ didChanges = true;
+ }
+ return didChanges;
+ }
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::rowsInserted( RowPos i_first, RowPos i_last )
{
DBG_CHECK_ME();
+ OSL_PRECOND( i_last >= i_first, "TableControl_Impl::rowsInserted: invalid row indexes!" );
+
+ TableSize const insertedRows = i_last - i_first + 1;
+
+ // adjust selection, if necessary
+ bool const selectionChanged = lcl_adjustSelectedRows( m_aSelectedRows, i_first, insertedRows );
+
+ // adjust our cached row count
+ m_nRowCount = m_pModel->getRowCount();
+
+ // if the rows have been inserted before the current row, adjust this
+ if ( i_first <= m_nCurRow )
+ goTo( m_nCurColumn, m_nCurRow + insertedRows );
+
+ // adjust scrollbars
+ impl_ni_updateScrollbars();
+
+ // notify A1YY events
+ if ( impl_isAccessibleAlive() )
+ {
+ impl_commitAccessibleEvent( AccessibleEventId::TABLE_MODEL_CHANGED,
+ 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
+ invalidateRowRange( i_first, ROW_INVALID );
+
+ // call selection handlers, if necessary
+ if ( selectionChanged )
+ m_rAntiImpl.Select();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::rowsRemoved( RowPos i_first, RowPos i_last )
+ {
+ sal_Int32 firstRemovedRow = i_first;
+ sal_Int32 lastRemovedRow = i_last;
+
+ // adjust selection, if necessary
+ bool selectionChanged = false;
+ if ( i_first == -1 )
+ {
+ selectionChanged = markAllRowsAsDeselected();
+
+ firstRemovedRow = 0;
+ lastRemovedRow = m_nRowCount - 1;
+ }
+ else
+ {
+ ENSURE_OR_RETURN_VOID( i_last >= i_first, "TableControl_Impl::rowsRemoved: illegal indexes!" );
+
+ for ( sal_Int32 row = i_first; row <= i_last; ++row )
+ {
+ if ( markRowAsDeselected( row ) )
+ selectionChanged = true;
+ }
+
+ if ( lcl_adjustSelectedRows( m_aSelectedRows, i_last + 1, i_first - i_last - 1 ) )
+ selectionChanged = true;
+ }
+
+ // adjust cached row count
+ m_nRowCount = m_pModel->getRowCount();
+
+ // adjust the current row, if it is larger than the row count now
+ if ( m_nCurRow >= m_nRowCount )
+ {
+ if ( m_nRowCount > 0 )
+ goTo( m_nCurColumn, m_nRowCount - 1 );
+ else
+ m_nCurRow = ROW_INVALID;
+ }
+
+ // adjust scrollbars
+ impl_ni_updateScrollbars();
+
+ // notify A11Y events
+ if ( impl_isAccessibleAlive() )
+ {
+ impl_commitAccessibleEvent(
+ AccessibleEventId::TABLE_MODEL_CHANGED,
+ makeAny( AccessibleTableModelChange(
+ AccessibleTableModelChangeType::DELETE,
+ firstRemovedRow,
+ lastRemovedRow,
+ 0,
+ m_pModel->getColumnCount()
+ ) ),
+ Any()
+ );
+ }
+
+ // schedule a repaint
+ invalidateRowRange( firstRemovedRow, ROW_INVALID );
- _rCellArea.Left() = 0;
- _rCellArea.Top() = 0;
+ // call selection handlers, if necessary
+ if ( selectionChanged )
+ m_rAntiImpl.Select();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::columnInserted( ColPos const i_colIndex )
+ {
+ m_nColumnCount = m_pModel->getColumnCount();
+ impl_ni_updateColumnWidths();
+ impl_ni_updateScrollbars();
+
+ m_rAntiImpl.Invalidate();
+
+ OSL_UNUSED( i_colIndex );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::columnRemoved( ColPos const i_colIndex )
+ {
+ m_nColumnCount = m_pModel->getColumnCount();
+ impl_ni_updateColumnWidths();
+ impl_ni_updateScrollbars();
+
+ m_rAntiImpl.Invalidate();
+
+ OSL_UNUSED( i_colIndex );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::allColumnsRemoved()
+ {
+ m_nColumnCount = m_pModel->getColumnCount();
+ impl_ni_updateColumnWidths();
+ impl_ni_updateScrollbars();
+
+ m_rAntiImpl.Invalidate();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::cellsUpdated( ColPos const i_firstCol, ColPos i_lastCol, RowPos const i_firstRow, RowPos const i_lastRow )
+ {
+ invalidateRowRange( i_firstRow, i_lastRow );
+
+ OSL_UNUSED( i_firstCol );
+ OSL_UNUSED( i_lastCol );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::tableMetricsChanged()
+ {
+ long const oldRowHeaderWidthPixel = m_nRowHeaderWidthPixel;
+ impl_ni_updateCachedTableMetrics();
+ if ( oldRowHeaderWidthPixel != m_nRowHeaderWidthPixel )
+ impl_ni_updateColumnWidths();
+ impl_ni_updateScrollbars();
+ m_rAntiImpl.Invalidate();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::impl_invalidateColumn( ColPos const i_column )
+ {
+ DBG_CHECK_ME();
+
+ Rectangle const aAllCellsArea( impl_getAllVisibleCellsArea() );
+
+ const TableColumnGeometry aColumn( *this, aAllCellsArea, i_column );
+ if ( aColumn.isValid() )
+ m_rAntiImpl.Invalidate( aColumn.getRect() );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup )
+ {
+ ColumnAttributeGroup nGroup( i_attributeGroup );
+ if ( nGroup & COL_ATTRS_APPEARANCE )
+ {
+ impl_invalidateColumn( i_column );
+ nGroup &= ~COL_ATTRS_APPEARANCE;
+ }
+
+ if ( nGroup & COL_ATTRS_WIDTH )
+ {
+ if ( !m_bUpdatingColWidths )
+ {
+ impl_ni_updateColumnWidths( i_column );
+ invalidate( TableAreaAll );
+ impl_ni_updateScrollbars();
+ }
+
+ nGroup &= ~COL_ATTRS_WIDTH;
+ }
+
+ OSL_ENSURE( ( nGroup == COL_ATTRS_NONE ) || ( i_attributeGroup == COL_ATTRS_ALL ),
+ "TableControl_Impl::columnChanged: don't know how to handle this change!" );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Rectangle TableControl_Impl::impl_getAllVisibleCellsArea() const
+ {
+ DBG_CHECK_ME();
+
+ Rectangle aArea( Point( 0, 0 ), Size( 0, 0 ) );
// determine the right-most border of the last column which is
// at least partially visible
- _rCellArea.Right() = m_nRowHeaderWidthPixel;
- if ( !m_aAccColumnWidthsPixel.empty() )
+ aArea.Right() = m_nRowHeaderWidthPixel;
+ if ( !m_aColumnWidths.empty() )
{
- // the number of pixels which are scroll out of the left hand
+ // the number of pixels which are scrolled out of the left hand
// side of the window
- long nScrolledOutLeft = m_nLeftColumn == 0 ? 0 : m_aAccColumnWidthsPixel[ m_nLeftColumn - 1 ];
+ const long nScrolledOutLeft = m_nLeftColumn == 0 ? 0 : m_aColumnWidths[ m_nLeftColumn - 1 ].getEnd();
- ArrayOfLong::const_reverse_iterator loop = m_aAccColumnWidthsPixel.rbegin();
+ ColumnPositions::const_reverse_iterator loop = m_aColumnWidths.rbegin();
do
{
- _rCellArea.Right() = *loop++ - nScrolledOutLeft + m_nRowHeaderWidthPixel;
+ aArea.Right() = loop->getEnd() - nScrolledOutLeft + m_nRowHeaderWidthPixel;
+ ++loop;
}
- while ( ( loop != m_aAccColumnWidthsPixel.rend() )
- && ( *loop - nScrolledOutLeft >= _rCellArea.Right() )
+ while ( ( loop != m_aColumnWidths.rend() )
+ && ( loop->getEnd() - nScrolledOutLeft >= aArea.Right() )
);
}
- // so far, _rCellArea.Right() denotes the first pixel *after* the cell area
- --_rCellArea.Right();
+ // so far, aArea.Right() denotes the first pixel *after* the cell area
+ --aArea.Right();
// determine the last row which is at least partially visible
- _rCellArea.Bottom() =
+ aArea.Bottom() =
m_nColHeaderHeightPixel
+ impl_getVisibleRows( true ) * m_nRowHeightPixel
- 1;
+
+ return aArea;
}
- //--------------------------------------------------------------------
- void TableControl_Impl::impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const
+ //------------------------------------------------------------------------------------------------------------------
+ Rectangle TableControl_Impl::impl_getAllVisibleDataCellArea() const
{
DBG_CHECK_ME();
- impl_getAllVisibleCellsArea( _rCellArea );
- _rCellArea.Left() = m_nRowHeaderWidthPixel;
- _rCellArea.Top() = m_nColHeaderHeightPixel;
+ Rectangle aArea( impl_getAllVisibleCellsArea() );
+ aArea.Left() = m_nRowHeaderWidthPixel;
+ aArea.Top() = m_nColHeaderHeightPixel;
+ return aArea;
}
- //--------------------------------------------------------------------
- void TableControl_Impl::impl_ni_updateCachedModelValues()
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::impl_ni_updateCachedTableMetrics()
{
- m_nRowHeightPixel = 15;
- m_nColHeaderHeightPixel = 0;
- m_nRowHeaderWidthPixel = 0;
- m_pInputHandler.reset();
- m_nColumnCount = m_nRowCount = 0;
+ m_nRowHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getRowHeight() ), MAP_APPFONT ).Height();
- m_nRowHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getRowHeight() ), MAP_APPFONT ).Height();
- if ( m_pModel->hasColumnHeaders() )
+ m_nColHeaderHeightPixel = 0;
+ if ( m_pModel->hasColumnHeaders() )
m_nColHeaderHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getColumnHeaderHeight() ), MAP_APPFONT ).Height();
+
+ m_nRowHeaderWidthPixel = 0;
if ( m_pModel->hasRowHeaders() )
m_nRowHeaderWidthPixel = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT).Width();
+ }
+ //------------------------------------------------------------------------------------------------------------------
+ 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();
@@ -567,145 +810,280 @@ namespace svt { namespace table
m_nRowCount = m_pModel->getRowCount();
}
- //--------------------------------------------------------------------
- void TableControl_Impl::impl_ni_updateColumnWidths()
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::impl_ni_updateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding )
{
- m_aColumnWidthsPixel.resize( 0 );
- m_aAccColumnWidthsPixel.resize( 0 );
+ ENSURE_OR_RETURN_VOID( !m_bUpdatingColWidths, "TableControl_Impl::impl_ni_updateColumnWidths: recursive call detected!" );
+
+ m_aColumnWidths.resize( 0 );
if ( !m_pModel )
return;
- TableSize colCount = m_pModel->getColumnCount();
+ const TableSize colCount = m_pModel->getColumnCount();
+ if ( colCount == 0 )
+ return;
+
+ m_bUpdatingColWidths = true;
+ const ::comphelper::FlagGuard aWidthUpdateFlag( m_bUpdatingColWidths );
+
+ m_aColumnWidths.reserve( colCount );
- m_aColumnWidthsPixel.reserve( colCount );
- m_aAccColumnWidthsPixel.reserve( colCount );
- if(colCount>0)
+ // the available horizontal space
+ long gridWidthPixel = m_rAntiImpl.GetOutputSizePixel().Width();
+ if ( m_pModel->hasRowHeaders() && ( gridWidthPixel != 0 ) )
{
- std::vector<sal_Int32> aPrePixelWidths(0);
- long accumulatedPixelWidth = 0;
- int lastResizableCol = -1;
- double gridWidth = m_rAntiImpl.GetOutputSizePixel().Width();
- if(m_pModel->hasRowHeaders())
- {
- TableMetrics rowHeaderWidth = m_pModel->getRowHeaderWidth();
- gridWidth-= m_rAntiImpl.LogicToPixel( Size( rowHeaderWidth, 0 ), MAP_APPFONT ).Width();
- }
- if(m_pModel->hasVerticalScrollbar())
+ gridWidthPixel -= m_nRowHeaderWidthPixel;
+ }
+ if ( 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!" );
+
+ }
+
+ // collect some meta data for our columns:
+ // - their current (appt-font) 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 );
+ long accumulatedMinWidth = 0;
+ long accumulatedMaxWidth = 0;
+ // - their relative flexibility
+ ::std::vector< ::sal_Int32 > columnFlexibilities;
+ columnFlexibilities.reserve( colCount );
+ long flexibilityDenominator = 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();
+ currentColWidths.push_back( currentWidth );
+
+ // accumulated width
+ accumulatedCurrentWidth += currentWidth;
+
+ // flexibility
+ ::sal_Int32 flexibility = pColumn->getFlexibility();
+ OSL_ENSURE( flexibility >= 0, "TableControl_Impl::impl_ni_updateColumnWidths: 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
+ )
+ flexibility = 0;
+
+ // min/max width
+ long effectiveMin = currentWidth, effectiveMax = currentWidth;
+ // 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 )
{
- sal_Int32 scrollbarWidth = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
- gridWidth-=scrollbarWidth;
+ long const minWidth = 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!" );
+ if ( ( maxWidth > 0 ) && ( maxWidth >= minWidth ) )
+ effectiveMax = maxWidth;
+ else
+ effectiveMax = gridWidthAppFont; // TODO: any better guess here?
+
+ if ( effectiveMin == effectiveMax )
+ // if the min and the max are identical, this implies no flexibility at all
+ flexibility = 0;
}
- double colWidthsSum = 0.0;
- double colWithoutFixedWidthsSum = 0.0;
- double minColWithoutFixedSum = 0.0;
- for ( ColPos col = 0; col < colCount; ++col )
+
+ columnFlexibilities.push_back( flexibility );
+ flexibilityDenominator += flexibility;
+
+ effectiveColumnLimits.push_back( ::std::pair< long, long >( effectiveMin, effectiveMax ) );
+ accumulatedMinWidth += effectiveMin;
+ accumulatedMaxWidth += effectiveMax;
+ }
+
+ ::std::vector< long > newWidths( currentColWidths );
+ if ( flexibilityDenominator == 0 )
+ {
+ // no column is flexible => don't adjust anything
+ }
+ else if ( gridWidthAppFont > accumulatedCurrentWidth )
+ { // we have space to give away ...
+ long distributeAppFontUnits = gridWidthAppFont - accumulatedCurrentWidth;
+ if ( gridWidthAppFont > accumulatedMaxWidth )
{
- PColumnModel pColumn = m_pModel->getColumnModel( col );
- DBG_ASSERT( !!pColumn, "TableControl_Impl::impl_ni_updateColumnWidths: invalid column returned by the model!" );
- if ( !pColumn )
- continue;
- TableMetrics colWidth = 0;
- TableMetrics colPrefWidth = pColumn->getPreferredWidth();
- bool bResizable = pColumn->isResizable();
- if(pColumn->getMinWidth() == 0 && bResizable)
+ // ... 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 )
{
- pColumn->setMinWidth(1);
- minColWithoutFixedSum+=m_rAntiImpl.PixelToLogic( Size( 1, 0 ), MAP_APPFONT ).Width();
- }
- if(pColumn->getMaxWidth() == 0 && bResizable)
- pColumn->setMaxWidth(m_rAntiImpl.PixelToLogic( Size( (int)gridWidth, 0 ), MAP_APPFONT ).Width());
- if( colPrefWidth != 0)
- {
- if(m_bResizingGrid)
- {
- colWidth = pColumn->getWidth();
- pColumn->setPreferredWidth(0);
- }
- else
- {
- colWidth = colPrefWidth;
- pColumn->setWidth(colPrefWidth);
- }
+ newWidths[i] = effectiveColumnLimits[i].second;
}
- else
- colWidth = pColumn->getWidth();
- long pixelWidth = m_rAntiImpl.LogicToPixel( Size( colWidth, 0 ), MAP_APPFONT ).Width();
- if(bResizable && colPrefWidth == 0)
- {
- colWithoutFixedWidthsSum+=pixelWidth;
- lastResizableCol = col;
- }
- colWidthsSum+=pixelWidth;
- aPrePixelWidths.push_back(pixelWidth);
- }
- double gridWidthWithoutFixed = gridWidth - colWidthsSum + colWithoutFixedWidthsSum;
- double scalingFactor = 1.0;
- if(m_bResizingGrid)
- {
- if(gridWidthWithoutFixed > (minColWithoutFixedSum+colWidthsSum - colWithoutFixedWidthsSum))
- scalingFactor = gridWidthWithoutFixed/colWithoutFixedWidthsSum;
}
else
{
- if(colWidthsSum < gridWidthWithoutFixed)
+ bool startOver = false;
+ do
{
- if(colWithoutFixedWidthsSum>0)
- scalingFactor = gridWidthWithoutFixed/colWithoutFixedWidthsSum;
+ startOver = false;
+ // distribute the remaining space amongst all columns with a positive flexibility
+ for ( size_t i=0; i<newWidths.size() && !startOver; ++i )
+ {
+ long const columnFlexibility = columnFlexibilities[i];
+ if ( columnFlexibility == 0 )
+ continue;
+
+ long newColWidth = currentColWidths[i] + columnFlexibility * distributeAppFontUnits / flexibilityDenominator;
+
+ if ( newColWidth > effectiveColumnLimits[i].second )
+ { // that was too much, we hit the col's maximum
+ // set the new width to exactly this maximum
+ newColWidth = effectiveColumnLimits[i].second;
+ // adjust the flexibility denominator ...
+ flexibilityDenominator -= columnFlexibility;
+ columnFlexibilities[i] = 0;
+ // ... and the remaining width ...
+ long const difference = newColWidth - currentColWidths[i];
+ distributeAppFontUnits -= 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)
+
+ // and start over with the first column, since there might be earlier columns which need
+ // to be recalculated now
+ startOver = true;
+ }
+
+ newWidths[i] = newColWidth;
+ }
}
+ while ( startOver );
}
- for ( ColPos i = 0; i < colCount; ++i )
+ }
+ else if ( gridWidthAppFont < accumulatedCurrentWidth )
+ { // we need to take away some space from the columns which allow it ...
+ long takeAwayAppFontUnits = accumulatedCurrentWidth - gridWidthAppFont;
+ if ( gridWidthAppFont < accumulatedMinWidth )
{
- PColumnModel pColumn = m_pModel->getColumnModel( i );
- DBG_ASSERT( !!pColumn, "TableControl_Impl::impl_ni_updateColumnWidths: invalid column returned by the model!" );
- if ( !pColumn )
- continue;
- if(pColumn->isResizable() && pColumn->getPreferredWidth() == 0)
+ // ... 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 )
{
- aPrePixelWidths[i]*=scalingFactor;
- TableMetrics logicColWidth = m_rAntiImpl.PixelToLogic( Size( aPrePixelWidths[i], 0 ), MAP_APPFONT ).Width();
- pColumn->setWidth(logicColWidth);
+ newWidths[i] = effectiveColumnLimits[i].first;
}
- m_aColumnWidthsPixel.push_back( aPrePixelWidths[i] );
- m_aAccColumnWidthsPixel.push_back( accumulatedPixelWidth += aPrePixelWidths[i] );
}
- if(gridWidth > m_aAccColumnWidthsPixel[colCount-1])
+ else
{
- if(lastResizableCol >= 0)
+ bool startOver = false;
+ do
{
- PColumnModel pColumn = m_pModel->getColumnModel(lastResizableCol);
- m_aColumnWidthsPixel[lastResizableCol]+=gridWidth-m_aAccColumnWidthsPixel[colCount-1];
- TableMetrics logicColWidth1 = m_rAntiImpl.PixelToLogic( Size( m_aColumnWidthsPixel[lastResizableCol], 0 ), MAP_APPFONT ).Width();
- pColumn->setWidth(logicColWidth1);
- while(lastResizableCol < colCount)
+ 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 )
{
- if(lastResizableCol == 0)
- m_aAccColumnWidthsPixel[0] = m_aColumnWidthsPixel[lastResizableCol];
- else
- m_aAccColumnWidthsPixel[lastResizableCol]=m_aAccColumnWidthsPixel[lastResizableCol-1]+m_aColumnWidthsPixel[lastResizableCol];
- ++lastResizableCol;
+ long const columnFlexibility = columnFlexibilities[i];
+ if ( columnFlexibility == 0 )
+ continue;
+
+ long newColWidth = currentColWidths[i] - columnFlexibility * takeAwayAppFontUnits / flexibilityDenominator;
+
+ if ( newColWidth < effectiveColumnLimits[i].first )
+ { // that was too much, we hit the col's minimum
+ // set the new width to exactly this minimum
+ newColWidth = effectiveColumnLimits[i].first;
+ // adjust the flexibility denominator ...
+ flexibilityDenominator -= columnFlexibility;
+ columnFlexibilities[i] = 0;
+ // ... and the remaining width ...
+ long const difference = currentColWidths[i] - newColWidth;
+ takeAwayAppFontUnits -= 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;
}
}
+ 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] );
+ }
+
+ // 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 );
}
}
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
namespace
{
- //................................................................
+ //..............................................................................................................
/// determines whether a scrollbar is needed for the given values
- bool lcl_determineScrollbarNeed( ScrollbarVisibility _eVisibility,
- long _nVisibleUnits, long _nRange )
+ bool lcl_determineScrollbarNeed( long const i_position, ScrollbarVisibility const i_visibility,
+ long const i_availableSpace, long const i_neededSpace )
{
- if ( _eVisibility == ScrollbarShowNever )
+ if ( i_visibility == ScrollbarShowNever )
return false;
- if ( _eVisibility == ScrollbarShowAlways )
+ if ( i_visibility == ScrollbarShowAlways )
+ return true;
+ if ( i_position > 0 )
return true;
- return _nVisibleUnits > _nRange;
+ if ( i_availableSpace >= i_neededSpace )
+ return false;
+ return true;
}
- //................................................................
- void lcl_setButtonRepeat( Window& _rWindow, ULONG _nDelay )
+ //..............................................................................................................
+ void lcl_setButtonRepeat( Window& _rWindow, sal_uLong _nDelay )
{
AllSettings aSettings = _rWindow.GetSettings();
MouseSettings aMouseSettings = aSettings.GetMouseSettings();
@@ -713,27 +1091,26 @@ namespace svt { namespace table
aMouseSettings.SetButtonRepeat( _nDelay );
aSettings.SetMouseSettings( aMouseSettings );
- _rWindow.SetSettings( aSettings, TRUE );
+ _rWindow.SetSettings( aSettings, sal_True );
}
- //................................................................
+ //..............................................................................................................
void lcl_updateScrollbar( Window& _rParent, ScrollBar*& _rpBar,
- ScrollbarVisibility _eVisibility, long _nVisibleUnits,
+ bool const i_needBar, long _nVisibleUnits,
long _nPosition, long _nLineSize, long _nRange,
bool _bHorizontal, const Link& _rScrollHandler )
{
- // do we need the scrollbar?
- bool bNeedBar = lcl_determineScrollbarNeed( _eVisibility, _nVisibleUnits, _nRange );
-
// do we currently have the scrollbar?
bool bHaveBar = _rpBar != NULL;
// do we need to correct the scrollbar visibility?
- if ( bHaveBar && !bNeedBar )
+ if ( bHaveBar && !i_needBar )
{
+ if ( _rpBar->IsTracking() )
+ _rpBar->EndTracking();
DELETEZ( _rpBar );
}
- else if ( !bHaveBar && bNeedBar )
+ else if ( !bHaveBar && i_needBar )
{
_rpBar = new ScrollBar(
&_rParent,
@@ -755,7 +1132,7 @@ namespace svt { namespace table
}
}
- //................................................................
+ //..............................................................................................................
/** 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.
@@ -767,7 +1144,7 @@ namespace svt { namespace table
: _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.
@@ -792,15 +1169,13 @@ namespace svt { namespace table
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::impl_ni_updateScrollbars()
{
- TempHideCursor aHideCursor( *this );
+ SuppressCursor aHideCursor( *this );
// the width/height of a scrollbar, needed several times below
- long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
- if ( m_rAntiImpl.IsZoom() )
- nScrollbarMetrics = (long)( nScrollbarMetrics * (double)m_rAntiImpl.GetZoom() );
+ long const nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
// determine the playground for the data cells (excluding headers)
// TODO: what if the control is smaller than needed for the headers/scrollbars?
@@ -810,26 +1185,28 @@ namespace svt { namespace table
m_nRowCount = m_pModel->getRowCount();
m_nColumnCount = m_pModel->getColumnCount();
- if(m_aAccColumnWidthsPixel.empty())
- {
+ 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();
+
+ const ScrollbarVisibility eVertScrollbar = m_pModel->getVerticalScrollbarVisibility();
+ const ScrollbarVisibility eHorzScrollbar = m_pModel->getHorizontalScrollbarVisibility();
// do we need a vertical scrollbar?
+ bool bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
+ m_nTopRow, eVertScrollbar, aDataCellPlayground.GetHeight(), m_nRowHeightPixel * m_nRowCount );
bool bFirstRoundVScrollNeed = false;
- if ( lcl_determineScrollbarNeed(
- m_pModel->getVerticalScrollbarVisibility(aDataCellPlayground.GetHeight(), m_nRowHeightPixel*m_nRowCount),
- lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ),
- m_nRowCount ) )
+ if ( bNeedVerticalScrollbar )
{
aDataCellPlayground.Right() -= nScrollbarMetrics;
bFirstRoundVScrollNeed = true;
}
// do we need a horizontal scrollbar?
- if ( lcl_determineScrollbarNeed(
- m_pModel->getHorizontalScrollbarVisibility(aDataCellPlayground.GetWidth(), m_aAccColumnWidthsPixel[m_nColumnCount-1]),
- lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false ),
- m_nColumnCount ) )
+ const bool bNeedHorizontalScrollbar = lcl_determineScrollbarNeed( m_nLeftColumn, eHorzScrollbar, aDataCellPlayground.GetWidth(), nAllColumnsWidth );
+ if ( bNeedHorizontalScrollbar )
{
aDataCellPlayground.Bottom() -= nScrollbarMetrics;
@@ -837,19 +1214,21 @@ namespace svt { namespace table
// the need for a vertical one may have changed, since the horizontal
// SB might just occupy enough space so that not all rows do fit
// anymore
- if ( !bFirstRoundVScrollNeed && lcl_determineScrollbarNeed(
- m_pModel->getVerticalScrollbarVisibility(aDataCellPlayground.GetHeight(),m_nRowHeightPixel*m_nRowCount),
- lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ),
- m_nRowCount ) )
+ if ( !bFirstRoundVScrollNeed )
{
- aDataCellPlayground.Right() -= nScrollbarMetrics;
+ bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
+ m_nTopRow, eVertScrollbar, aDataCellPlayground.GetHeight(), m_nRowHeightPixel * m_nRowCount );
+ if ( bNeedVerticalScrollbar )
+ {
+ aDataCellPlayground.Right() -= nScrollbarMetrics;
+ }
}
}
// create or destroy the vertical scrollbar, as needed
lcl_updateScrollbar(
m_rAntiImpl,
m_pVScroll,
- m_pModel->getVerticalScrollbarVisibility(aDataCellPlayground.GetHeight(),m_nRowHeightPixel*m_nRowCount),
+ bNeedVerticalScrollbar,
lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ),
// visible units
m_nTopRow, // current position
@@ -873,7 +1252,7 @@ namespace svt { namespace table
lcl_updateScrollbar(
m_rAntiImpl,
m_pHScroll,
- m_pModel->getHorizontalScrollbarVisibility(aDataCellPlayground.GetWidth(), m_aAccColumnWidthsPixel[m_nColumnCount-1]),
+ bNeedHorizontalScrollbar,
lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false ),
// visible units
m_nLeftColumn, // current position
@@ -885,14 +1264,14 @@ namespace svt { namespace table
// position it
if ( m_pHScroll )
{
- TableSize nVisibleUnits = lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false );
- int nRange = m_nColumnCount;
- if( m_nLeftColumn + nVisibleUnits == nRange-1)
+ TableSize const nVisibleUnits = lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false );
+ TableMetrics const nRange = m_nColumnCount;
+ if( m_nLeftColumn + nVisibleUnits == nRange - 1 )
{
- if(m_aAccColumnWidthsPixel[nRange-2] - m_aAccColumnWidthsPixel[m_nLeftColumn] + m_aColumnWidthsPixel[nRange-1]>aDataCellPlayground.GetWidth())
+ if ( m_aColumnWidths[ nRange - 1 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getEnd() + m_aColumnWidths[ nRange-1 ].getWidth() > aDataCellPlayground.GetWidth() )
{
m_pHScroll->SetVisibleSize( nVisibleUnits -1 );
- m_pHScroll->SetPageSize(nVisibleUnits -1);
+ m_pHScroll->SetPageSize( nVisibleUnits - 1 );
}
}
Rectangle aScrollbarArea(
@@ -930,33 +1309,17 @@ namespace svt { namespace table
) );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::onResize()
{
DBG_CHECK_ME();
- if(m_nRowCount != 0)
- {
- if(m_nColumnCount != 0)
- {
- if(m_bResizingGrid)
- impl_ni_updateColumnWidths();
- invalidateRows();
- m_bResizingGrid = true;
- }
- }
- else
- {
- //In the case that column headers are defined but data hasn't yet been set,
- //only column headers will be shown
- if(m_pModel->hasColumnHeaders())
- if(m_nColHeaderHeightPixel>1)
- m_pDataWindow->SetSizePixel( m_rAntiImpl.GetOutputSizePixel());
- if(m_nColumnCount != 0)
- impl_ni_updateScrollbars();
- }
+
+ impl_ni_updateColumnWidths();
+ impl_ni_updateScrollbars();
+ checkCursorPosition();
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::doPaintContent( const Rectangle& _rUpdateRect )
{
DBG_CHECK_ME();
@@ -964,32 +1327,24 @@ namespace svt { namespace table
if ( !getModel() )
return;
PTableRenderer pRenderer = getModel()->getRenderer();
- DBG_ASSERT( !!pRenderer, "TableDataWindow::Paint: invalid renderer!" );
+ DBG_ASSERT( !!pRenderer, "TableDataWindow::doPaintContent: invalid renderer!" );
if ( !pRenderer )
return;
// our current style settings, to be passed to the renderer
const StyleSettings& rStyle = m_rAntiImpl.GetSettings().GetStyleSettings();
m_nRowCount = m_pModel->getRowCount();
- TableSize nVisibleRows = impl_getVisibleRows(true);
- TableSize nActualRows = m_nRowCount;
- if(m_nRowCount>nVisibleRows)
- nActualRows = nVisibleRows;
// the area occupied by all (at least partially) visible cells, including
// headers
- Rectangle aAllCellsWithHeaders;
- impl_getAllVisibleCellsArea( aAllCellsWithHeaders );
+ Rectangle const aAllCellsWithHeaders( impl_getAllVisibleCellsArea() );
// ............................
// draw the header column area
if ( m_pModel->hasColumnHeaders() )
{
- TableRowGeometry aHeaderRow( *this, Rectangle( Point( 0, 0 ),
+ TableRowGeometry const aHeaderRow( *this, Rectangle( Point( 0, 0 ),
aAllCellsWithHeaders.BottomRight() ), ROW_COL_HEADERS );
- Rectangle aColRect(aHeaderRow.getRect());
- //to avoid double lines when scrolling horizontally
- if(m_nLeftColumn != 0)
- --aColRect.Left();
+ Rectangle const aColRect(aHeaderRow.getRect());
pRenderer->PaintHeaderArea(
*m_pDataWindow, aColRect, true, false, rStyle
);
@@ -1005,7 +1360,7 @@ namespace svt { namespace table
if ( _rUpdateRect.GetIntersection( aCell.getRect() ).IsEmpty() )
continue;
- bool isActiveColumn = ( aCell.getColumn() == getCurColumn() );
+ bool isActiveColumn = ( aCell.getColumn() == getCurrentColumn() );
bool isSelectedColumn = false;
pRenderer->PaintColumnHeader( aCell.getColumn(), isActiveColumn, isSelectedColumn,
*m_pDataWindow, aCell.getRect(), rStyle );
@@ -1017,31 +1372,23 @@ namespace svt { namespace table
{
aRowHeaderArea = aAllCellsWithHeaders;
aRowHeaderArea.Right() = m_nRowHeaderWidthPixel - 1;
- if(m_nTopRow+nActualRows>m_nRowCount)
- aRowHeaderArea.Bottom() = m_nRowHeightPixel * (nActualRows -1)+ m_nColHeaderHeightPixel - 1;
- else
- aRowHeaderArea.Bottom() = m_nRowHeightPixel * nActualRows + m_nColHeaderHeightPixel - 1;
- //to avoid double lines when scrolling vertically
- if(m_nTopRow != 0)
- --aRowHeaderArea.Top();
- --aRowHeaderArea.Right();
- pRenderer->PaintHeaderArea(*m_pDataWindow, aRowHeaderArea, false, true, rStyle);
+
+ TableSize const nVisibleRows = impl_getVisibleRows( true );
+ TableSize nActualRows = nVisibleRows;
+ if ( m_nTopRow + nActualRows > m_nRowCount )
+ nActualRows = m_nRowCount - m_nTopRow;
+ aRowHeaderArea.Bottom() = m_nColHeaderHeightPixel + m_nRowHeightPixel * nActualRows - 1;
+
+ pRenderer->PaintHeaderArea( *m_pDataWindow, aRowHeaderArea, false, true, rStyle );
// Note that strictly, aRowHeaderArea also contains the intersection between column
// and row header area. However, below we go to paint this intersection, again,
// so this hopefully doesn't hurt if we already paint it here.
if ( m_pModel->hasColumnHeaders() )
{
- TableCellGeometry aIntersection( *this, Rectangle( Point( 0, 0 ),
+ TableCellGeometry const aIntersection( *this, Rectangle( Point( 0, 0 ),
aAllCellsWithHeaders.BottomRight() ), COL_ROW_HEADERS, ROW_COL_HEADERS );
- Rectangle aInters(aIntersection.getRect());
- //to avoid double line when scrolling vertically
- if( m_nTopRow != 0 )
- {
- --aInters.Top();
- --aInters.Bottom();
- }
- --aInters.Right();
+ Rectangle const aInters( aIntersection.getRect() );
pRenderer->PaintHeaderArea(
*m_pDataWindow, aInters, true, true, rStyle
);
@@ -1054,51 +1401,36 @@ namespace svt { namespace table
TableSize colCount = getModel()->getColumnCount();
// paint all rows
- Rectangle aAllDataCellsArea;
- impl_getAllVisibleDataCellArea( aAllDataCellsArea );
- ::std::vector< std::vector< ::com::sun::star::uno::Any > >& aCellContent = m_pModel->getCellContent();
+ Rectangle const aAllDataCellsArea( impl_getAllVisibleDataCellArea() );
for ( TableRowGeometry aRowIterator( *this, aAllCellsWithHeaders, getTopRow() );
aRowIterator.isValid();
aRowIterator.moveDown() )
{
if ( _rUpdateRect.GetIntersection( aRowIterator.getRect() ).IsEmpty() )
continue;
- bool isActiveRow = ( aRowIterator.getRow() == getCurRow() );
- bool isSelectedRow = false;
- if(!m_nRowSelected.empty())
- {
- for(std::vector<RowPos>::iterator itSel=m_nRowSelected.begin();
- itSel!=m_nRowSelected.end();++itSel)
- {
- if(*itSel == aRowIterator.getRow())
- isSelectedRow = true;
- }
- }
- Rectangle aRect = aRowIterator.getRect().GetIntersection( aAllDataCellsArea );
- //to avoid double lines
- if( aRowIterator.getRow() != 0 )
- --aRect.Top();
- if(m_nLeftColumn != 0)
- --aRect.Left();
- else
- {
- if(m_pModel->hasRowHeaders())
- --aRect.Left();
- }
+
+ bool const isActiveRow = ( aRowIterator.getRow() == getCurrentRow() );
+ 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,
- *m_pDataWindow, aRect, rStyle );
+ pRenderer->PrepareRow(
+ aRowIterator.getRow(), isActiveRow, isSelectedRow,
+ *m_pDataWindow, aRect, rStyle
+ );
// paint the row header
if ( m_pModel->hasRowHeaders() )
{
- Rectangle aCurrentRowHeader( aRowHeaderArea.GetIntersection( aRowIterator.getRect() ) );
- rtl::OUString rowHeaderName = m_pModel->getRowHeaderName()[aRowIterator.getRow()];
+ const Rectangle aCurrentRowHeader( aRowHeaderArea.GetIntersection( aRowIterator.getRect() ) );
pRenderer->PaintRowHeader( isActiveRow, isSelectedRow, *m_pDataWindow, aCurrentRowHeader,
- rStyle, rowHeaderName );
+ rStyle );
}
+
if ( !colCount )
continue;
+
// paint all cells in this row
for ( TableCellGeometry aCell( aRowIterator, m_nLeftColumn );
aCell.isValid();
@@ -1106,25 +1438,12 @@ namespace svt { namespace table
)
{
bool isSelectedColumn = false;
- ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >xGraphic;
- ::com::sun::star::uno::Any rCellData = aCellContent[aRowIterator.getRow()][aCell.getColumn()];
- if(rCellData>>=xGraphic)
- {
- Image* pImage = new Image(xGraphic);
- if(pImage!=NULL)
- pRenderer->PaintCellImage( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow,
- *m_pDataWindow, aCell.getRect(), rStyle, pImage );
- }
- else
- {
- ::rtl::OUString sContent = convertToString(rCellData);
- pRenderer->PaintCellString( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow,
- *m_pDataWindow, aCell.getRect(), rStyle, sContent );
- }
+ pRenderer->PaintCell( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow,
+ *m_pDataWindow, aCell.getRect(), rStyle );
}
}
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::hideCursor()
{
DBG_CHECK_ME();
@@ -1133,7 +1452,7 @@ namespace svt { namespace table
impl_ni_doSwitchCursor( false );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::showCursor()
{
DBG_CHECK_ME();
@@ -1143,12 +1462,14 @@ namespace svt { namespace table
impl_ni_doSwitchCursor( true );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
bool TableControl_Impl::dispatchAction( TableControlAction _eAction )
{
DBG_CHECK_ME();
bool bSuccess = false;
+ bool selectionChanged = false;
+
Rectangle rCells;
switch ( _eAction )
{
@@ -1156,25 +1477,25 @@ namespace svt { namespace table
if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
{
//if other rows already selected, deselect them
- if(m_nRowSelected.size()>0)
+ if(m_aSelectedRows.size()>0)
{
- for(std::vector<RowPos>::iterator it=m_nRowSelected.begin();
- it!=m_nRowSelected.end();++it)
+ for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
+ it!=m_aSelectedRows.end();++it)
{
invalidateSelectedRegion(*it, *it, rCells);
}
- m_nRowSelected.clear();
+ m_aSelectedRows.clear();
}
if(m_nCurRow < m_nRowCount-1)
{
++m_nCurRow;
- m_nRowSelected.push_back(m_nCurRow);
+ m_aSelectedRows.push_back(m_nCurRow);
}
else
- m_nRowSelected.push_back(m_nCurRow);
+ m_aSelectedRows.push_back(m_nCurRow);
invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
ensureVisible(m_nCurColumn,m_nCurRow,false);
- m_rAntiImpl.selectionChanged(true);
+ selectionChanged = true;
bSuccess = true;
}
else
@@ -1187,28 +1508,28 @@ namespace svt { namespace table
case cursorUp:
if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
{
- if(m_nRowSelected.size()>0)
+ if(m_aSelectedRows.size()>0)
{
- for(std::vector<RowPos>::iterator it=m_nRowSelected.begin();
- it!=m_nRowSelected.end();++it)
+ for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
+ it!=m_aSelectedRows.end();++it)
{
invalidateSelectedRegion(*it, *it, rCells);
}
- m_nRowSelected.clear();
+ m_aSelectedRows.clear();
}
if(m_nCurRow>0)
{
--m_nCurRow;
- m_nRowSelected.push_back(m_nCurRow);
+ m_aSelectedRows.push_back(m_nCurRow);
invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
}
else
{
- m_nRowSelected.push_back(m_nCurRow);
+ m_aSelectedRows.push_back(m_nCurRow);
invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
}
ensureVisible(m_nCurColumn,m_nCurRow,false);
- m_rAntiImpl.selectionChanged(true);
+ selectionChanged = true;
bSuccess = true;
}
else
@@ -1270,259 +1591,269 @@ namespace svt { namespace table
case cursorBottomRight:
bSuccess = goTo( m_nColumnCount - 1, m_nRowCount - 1 );
break;
- case cursorSelectRow:
- {
- if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
- return bSuccess = false;
- //pos is the position of the current row in the vector of selected rows, if current row is selected
- int pos = getRowSelectedNumber(m_nRowSelected, m_nCurRow);
- //if current row is selected, it should be deselected, when ALT+SPACE are pressed
- if(pos>-1)
- {
- m_nRowSelected.erase(m_nRowSelected.begin()+pos);
- if(m_nRowSelected.empty() && m_nAnchor != -1)
- m_nAnchor = -1;
- }
- //else select the row->put it in the vector
- else
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
- m_rAntiImpl.selectionChanged(true);
- bSuccess = true;
- }
- break;
- case cursorSelectRowUp:
- {
- if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
- return bSuccess = false;
- else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
+
+ case cursorSelectRow:
{
- //if there are other selected rows, deselect them
- return false;
+ if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
+ return bSuccess = false;
+ //pos is the position of the current row in the vector of selected rows, if current row is selected
+ int pos = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
+ //if current row is selected, it should be deselected, when ALT+SPACE are pressed
+ if(pos>-1)
+ {
+ m_aSelectedRows.erase(m_aSelectedRows.begin()+pos);
+ if(m_aSelectedRows.empty() && m_nAnchor != -1)
+ m_nAnchor = -1;
+ }
+ //else select the row->put it in the vector
+ else
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ selectionChanged = true;
+ bSuccess = true;
}
- else
+ break;
+ case cursorSelectRowUp:
{
- //there are other selected rows
- if(m_nRowSelected.size()>0)
+ if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
+ return bSuccess = false;
+ else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
+ {
+ //if there are other selected rows, deselect them
+ return false;
+ }
+ else
{
- //the anchor wasn't set -> a region is not selected, that's why clear all selection
- //and select the current row
- if(m_nAnchor==-1)
+ //there are other selected rows
+ if(m_aSelectedRows.size()>0)
{
- for(std::vector<RowPos>::iterator it=m_nRowSelected.begin();
- it!=m_nRowSelected.end();++it)
+ //the anchor wasn't set -> a region is not selected, that's why clear all selection
+ //and select the current row
+ if(m_nAnchor==-1)
{
- invalidateSelectedRegion(*it, *it, rCells);
- }
- m_nRowSelected.clear();
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
- }
- else
- {
- //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected
- int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow);
- int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow-1);
- if(prevRow>-1)
- {
- //if m_nCurRow isn't the upper one, can move up, otherwise not
- if(m_nCurRow>0)
- m_nCurRow--;
- else
- return bSuccess = true;
- //if nextRow already selected, deselect it, otherwise select it
- if(nextRow>-1 && m_nRowSelected[nextRow] == m_nCurRow)
- {
- m_nRowSelected.erase(m_nRowSelected.begin()+prevRow);
- invalidateSelectedRegion(m_nCurRow+1, m_nCurRow+1, rCells);
- }
- else
+ for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
+ it!=m_aSelectedRows.end();++it)
{
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
- }
- }
+ invalidateSelectedRegion(*it, *it, rCells);
+ }
+ m_aSelectedRows.clear();
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ }
else
{
- if(m_nCurRow>0)
+ //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected
+ int prevRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
+ int nextRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow-1);
+ if(prevRow>-1)
+ {
+ //if m_nCurRow isn't the upper one, can move up, otherwise not
+ if(m_nCurRow>0)
+ m_nCurRow--;
+ else
+ return bSuccess = true;
+ //if nextRow already selected, deselect it, otherwise select it
+ if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
+ {
+ m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
+ invalidateSelectedRegion(m_nCurRow+1, m_nCurRow+1, rCells);
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ }
+ }
+ else
{
- m_nRowSelected.push_back(m_nCurRow);
- m_nCurRow--;
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
+ if(m_nCurRow>0)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow--;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
+ }
}
}
}
- }
- else
- {
- //if nothing is selected and the current row isn't the upper one
- //select the current and one row above
- //otherwise select only the upper row
- if(m_nCurRow>0)
- {
- m_nRowSelected.push_back(m_nCurRow);
- m_nCurRow--;
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
- }
else
{
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ //if nothing is selected and the current row isn't the upper one
+ //select the current and one row above
+ //otherwise select only the upper row
+ if(m_nCurRow>0)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow--;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ }
}
+ m_pSelEngine->SetAnchor(sal_True);
+ m_nAnchor = m_nCurRow;
+ ensureVisible(m_nCurColumn, m_nCurRow, false);
+ selectionChanged = true;
+ bSuccess = true;
}
- m_pSelEngine->SetAnchor(TRUE);
- m_nAnchor = m_nCurRow;
- ensureVisible(m_nCurColumn, m_nCurRow, false);
- m_rAntiImpl.selectionChanged(true);
- bSuccess = true;
- }
- }
- break;
- case cursorSelectRowDown:
- {
- if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
- bSuccess = false;
- else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
- {
- bSuccess = false;
}
- else
+ break;
+ case cursorSelectRowDown:
{
- if(m_nRowSelected.size()>0)
+ if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
+ bSuccess = false;
+ else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
+ {
+ bSuccess = false;
+ }
+ else
{
- //the anchor wasn't set -> a region is not selected, that's why clear all selection
- //and select the current row
- if(m_nAnchor==-1)
+ if(m_aSelectedRows.size()>0)
{
- for(std::vector<RowPos>::iterator it=m_nRowSelected.begin();
- it!=m_nRowSelected.end();++it)
+ //the anchor wasn't set -> a region is not selected, that's why clear all selection
+ //and select the current row
+ if(m_nAnchor==-1)
{
- invalidateSelectedRegion(*it, *it, rCells);
- }
- m_nRowSelected.clear();
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
+ it!=m_aSelectedRows.end();++it)
+ {
+ invalidateSelectedRegion(*it, *it, rCells);
+ }
+ m_aSelectedRows.clear();
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ }
+ else
+ {
+ //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected
+ int prevRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
+ int nextRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow+1);
+ if(prevRow>-1)
+ {
+ //if m_nCurRow isn't the last one, can move down, otherwise not
+ if(m_nCurRow<m_nRowCount-1)
+ m_nCurRow++;
+ else
+ return bSuccess = true;
+ //if next row already selected, deselect it, otherwise select it
+ if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
+ {
+ m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
+ invalidateSelectedRegion(m_nCurRow-1, m_nCurRow-1, rCells);
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ }
+ }
+ else
+ {
+ if(m_nCurRow<m_nRowCount-1)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow++;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
+ }
+ }
}
+ }
else
{
- //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected
- int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow);
- int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow+1);
- if(prevRow>-1)
- {
- //if m_nCurRow isn't the last one, can move down, otherwise not
- if(m_nCurRow<m_nRowCount-1)
- m_nCurRow++;
- else
- return bSuccess = true;
- //if next row already selected, deselect it, otherwise select it
- if(nextRow>-1 && m_nRowSelected[nextRow] == m_nCurRow)
- {
- m_nRowSelected.erase(m_nRowSelected.begin()+prevRow);
- invalidateSelectedRegion(m_nCurRow-1, m_nCurRow-1, rCells);
- }
- else
- {
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
- }
+ //there wasn't any selection, select current and row beneath, otherwise only row beneath
+ if(m_nCurRow<m_nRowCount-1)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow++;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
}
else
{
- if(m_nCurRow<m_nRowCount-1)
- {
- m_nRowSelected.push_back(m_nCurRow);
- m_nCurRow++;
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
- }
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
}
}
+ m_pSelEngine->SetAnchor(sal_True);
+ m_nAnchor = m_nCurRow;
+ ensureVisible(m_nCurColumn, m_nCurRow, false);
+ selectionChanged = true;
+ bSuccess = true;
}
+ }
+ break;
+
+ case cursorSelectRowAreaTop:
+ {
+ if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
+ bSuccess = false;
+ else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
+ bSuccess = false;
else
{
- //there wasn't any selection, select current and row beneath, otherwise only row beneath
- if(m_nCurRow<m_nRowCount-1)
- {
- m_nRowSelected.push_back(m_nCurRow);
- m_nCurRow++;
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
- }
- else
+ //select the region between the current and the upper row
+ RowPos iter = m_nCurRow;
+ invalidateSelectedRegion(m_nCurRow, 0, rCells);
+ //put the rows in vector
+ while(iter>=0)
{
- m_nRowSelected.push_back(m_nCurRow);
- invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
+ if ( !isRowSelected( iter ) )
+ m_aSelectedRows.push_back(iter);
+ --iter;
}
+ m_nCurRow = 0;
+ m_nAnchor = m_nCurRow;
+ m_pSelEngine->SetAnchor(sal_True);
+ ensureVisible(m_nCurColumn, 0, false);
+ selectionChanged = true;
+ bSuccess = true;
}
- m_pSelEngine->SetAnchor(TRUE);
- m_nAnchor = m_nCurRow;
- ensureVisible(m_nCurColumn, m_nCurRow, false);
- m_rAntiImpl.selectionChanged(true);
- bSuccess = true;
}
- }
break;
- case cursorSelectRowAreaTop:
- {
- if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
- bSuccess = false;
- else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
- bSuccess = false;
- else
+
+ case cursorSelectRowAreaBottom:
{
- //select the region between the current and the upper row
+ if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
+ return bSuccess = false;
+ else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
+ return bSuccess = false;
+ //select the region between the current and the last row
RowPos iter = m_nCurRow;
- invalidateSelectedRegion(m_nCurRow, 0, rCells);
- //put the rows in vector
- while(iter>=0)
+ invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells);
+ //put the rows in the vector
+ while(iter<=m_nRowCount)
{
- if(!isRowSelected(m_nRowSelected, iter))
- m_nRowSelected.push_back(iter);
- --iter;
+ if ( !isRowSelected( iter ) )
+ m_aSelectedRows.push_back(iter);
+ ++iter;
}
- m_nCurRow = 0;
+ m_nCurRow = m_nRowCount-1;
m_nAnchor = m_nCurRow;
- m_pSelEngine->SetAnchor(TRUE);
- ensureVisible(m_nCurColumn, 0, false);
- m_rAntiImpl.selectionChanged(true);
+ m_pSelEngine->SetAnchor(sal_True);
+ ensureVisible(m_nCurColumn, m_nRowCount-1, false);
+ selectionChanged = true;
bSuccess = true;
}
- }
- break;
- case cursorSelectRowAreaBottom:
- {
- if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
- return bSuccess = false;
- else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
- return bSuccess = false;
- //select the region between the current and the last row
- RowPos iter = m_nCurRow;
- invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells);
- //put the rows in the vector
- while(iter<=m_nRowCount)
- {
- if(!isRowSelected(m_nRowSelected, iter))
- m_nRowSelected.push_back(iter);
- ++iter;
- }
- m_nCurRow = m_nRowCount-1;
- m_nAnchor = m_nCurRow;
- m_pSelEngine->SetAnchor(TRUE);
- ensureVisible(m_nCurColumn, m_nRowCount-1, false);
- m_rAntiImpl.selectionChanged(true);
- bSuccess = true;
- }
break;
default:
OSL_FAIL( "TableControl_Impl::dispatchAction: unsupported action!" );
+ break;
}
+
+ if ( bSuccess && selectionChanged )
+ {
+ m_rAntiImpl.Select();
+ }
+
return bSuccess;
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::impl_ni_doSwitchCursor( bool _bShow )
{
PTableRenderer pRenderer = !!m_pModel ? m_pModel->getRenderer() : PTableRenderer();
@@ -1530,16 +1861,14 @@ namespace svt { namespace table
{
Rectangle aCellRect;
impl_getCellRect( m_nCurColumn, m_nCurRow, aCellRect );
- if(!m_pModel->hasRowHeaders() && m_nCurColumn == 0)
- aCellRect.Left()++;
if ( _bShow )
- pRenderer->ShowCellCursor( *m_pDataWindow, aCellRect);
+ pRenderer->ShowCellCursor( *m_pDataWindow, aCellRect );
else
- pRenderer->HideCellCursor( *m_pDataWindow, aCellRect);
+ pRenderer->HideCellCursor( *m_pDataWindow, aCellRect );
}
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const
{
DBG_CHECK_ME();
@@ -1553,164 +1882,236 @@ namespace svt { namespace table
return;
}
- Rectangle aAllCells;
- impl_getAllVisibleCellsArea( aAllCells );
-
- TableCellGeometry aCell( *this, aAllCells, _nColumn, _nRow );
+ TableCellGeometry aCell( *this, impl_getAllVisibleCellsArea(), _nColumn, _nRow );
_rCellRect = aCell.getRect();
- _rCellRect.Top()--;_rCellRect.Left()--;
}
- //-------------------------------------------------------------------------------
- RowPos TableControl_Impl::getCurrentRow(const Point& rPoint)
+
+ //------------------------------------------------------------------------------------------------------------------
+ RowPos TableControl_Impl::getRowAtPoint( const Point& rPoint ) const
+ {
+ DBG_CHECK_ME();
+ return impl_getRowForAbscissa( rPoint.Y() );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ColPos TableControl_Impl::getColAtPoint( const Point& rPoint ) const
{
DBG_CHECK_ME();
- Rectangle rCellRect;
- RowPos newRowPos = -2;//-1 is HeaderRow
- ColPos newColPos = 0;
- for(int i=-1;i<m_nRowCount;i++)
+ return impl_getColumnForOrdinate( rPoint.X() );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ TableCell TableControl_Impl::hitTest( Point const & i_point ) const
+ {
+ TableCell aCell( getColAtPoint( i_point ), getRowAtPoint( i_point ) );
+ if ( aCell.nColumn > COL_ROW_HEADERS )
{
- for(int j=-1;j<m_nColumnCount;j++)
+ PColumnModel const pColumn = m_pModel->getColumnModel( aCell.nColumn );
+ MutableColumnMetrics const & rColInfo( m_aColumnWidths[ aCell.nColumn ] );
+ if ( ( rColInfo.getEnd() - 3 <= i_point.X() )
+ && ( rColInfo.getEnd() >= i_point.X() )
+ && pColumn->isResizable()
+ )
{
- impl_getCellRect(j,i,rCellRect);
- if((rPoint.X() >= rCellRect.Left() && rPoint.X() <= rCellRect.Right()) && rPoint.Y() >= rCellRect.Top() && rPoint.Y() <= rCellRect.Bottom())
- {
- newRowPos = i;
- newColPos = j;
- if(newColPos != -1)
- m_nCurColumn = newColPos;
- return newRowPos;
- }
+ aCell.eArea = ColumnDivider;
}
}
- return newRowPos;
+ return aCell;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ColumnMetrics TableControl_Impl::getColumnMetrics( ColPos const i_column ) const
+ {
+ DBG_CHECK_ME();
+
+ ENSURE_OR_RETURN( ( i_column >= 0 ) && ( i_column < m_pModel->getColumnCount() ),
+ "TableControl_Impl::getColumnMetrics: illegal column index!", ColumnMetrics() );
+ return (ColumnMetrics const &)m_aColumnWidths[ i_column ];
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ PTableModel TableControl_Impl::getModel() const
+ {
+ return m_pModel;
}
- //-------------------------------------------------------------------------------
- void TableControl_Impl::setCursorAtCurrentCell(const Point& rPoint)
+
+ //------------------------------------------------------------------------------------------------------------------
+ RowPos TableControl_Impl::getCurrentColumn() const
+ {
+ return m_nCurColumn;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ RowPos TableControl_Impl::getCurrentRow() const
+ {
+ return m_nCurRow;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::Size TableControl_Impl::getTableSizePixel() const
+ {
+ return m_pDataWindow->GetOutputSizePixel();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::setPointer( Pointer const & i_pointer )
{
DBG_CHECK_ME();
- hideCursor();
- Rectangle rCellRect;
- RowPos newRowPos = -2;//-1 is HeaderRow
- ColPos newColPos = 0;
- for(int i=0;i<m_nRowCount;i++)
+ m_pDataWindow->SetPointer( i_pointer );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::captureMouse()
+ {
+ m_pDataWindow->CaptureMouse();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::releaseMouse()
+ {
+ m_pDataWindow->ReleaseMouse();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::invalidate( TableArea const i_what )
+ {
+ switch ( i_what )
{
- for(int j=-1;j<m_nColumnCount;j++)
- {
- impl_getCellRect(j,i,rCellRect);
- if((rPoint.X() >= rCellRect.Left() && rPoint.X() <= rCellRect.Right()) && rPoint.Y() >= rCellRect.Top() && rPoint.Y() <= rCellRect.Bottom())
- {
- newRowPos = i;
- m_nCurRow = newRowPos;
- newColPos = j;
- if(newColPos == -1)
- m_nCurColumn = 0;
- else
- m_nCurColumn = newColPos;
- }
- }
+ case TableAreaColumnHeaders:
+ m_pDataWindow->Invalidate( calcHeaderRect( true ) );
+ break;
+
+ case TableAreaRowHeaders:
+ m_pDataWindow->Invalidate( calcHeaderRect( false ) );
+ break;
+
+ case TableAreaDataArea:
+ m_pDataWindow->Invalidate( impl_getAllVisibleDataCellArea() );
+ break;
+
+ case TableAreaAll:
+ m_pDataWindow->Invalidate();
+ break;
}
- showCursor();
}
- //-------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
+ long TableControl_Impl::pixelWidthToAppFont( long const i_pixels ) const
+ {
+ return m_pDataWindow->PixelToLogic( Size( i_pixels, 0 ), MAP_APPFONT ).Width();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::hideTracking()
+ {
+ m_pDataWindow->HideTracking();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::showTracking( Rectangle const & i_location, sal_uInt16 const i_flags )
+ {
+ m_pDataWindow->ShowTracking( i_location, i_flags );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableControl_Impl::activateCell( ColPos const i_col, RowPos const i_row )
+ {
+ DBG_CHECK_ME();
+ return goTo( i_col, i_row );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
void TableControl_Impl::invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect)
{
DBG_CHECK_ME();
- Rectangle aAllCells;
//get the visible area of the table control and set the Left and right border of the region to be repainted
- impl_getAllVisibleCellsArea( aAllCells );
+ Rectangle const aAllCells( impl_getAllVisibleCellsArea() );
_rCellRect.Left() = aAllCells.Left();
_rCellRect.Right() = aAllCells.Right();
- Rectangle rCells;
//if only one row is selected
if(_nPrevRow == _nCurRow)
{
- impl_getCellRect(m_nCurColumn,_nCurRow,rCells);
- _rCellRect.Top()=--rCells.Top();
- _rCellRect.Bottom()=rCells.Bottom();
+ Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
+ _rCellRect.Top() = aCellRect.Top();
+ _rCellRect.Bottom() = aCellRect.Bottom();
}
//if the region is above the current row
else if(_nPrevRow < _nCurRow )
{
- impl_getCellRect(m_nCurColumn,_nPrevRow,rCells);
- _rCellRect.Top()= --rCells.Top();
- impl_getCellRect(m_nCurColumn,_nCurRow,rCells);
- _rCellRect.Bottom()=rCells.Bottom();
+ Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
+ _rCellRect.Top() = aCellRect.Top();
+ impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
+ _rCellRect.Bottom() = aCellRect.Bottom();
}
//if the region is beneath the current row
else
{
- impl_getCellRect(m_nCurColumn,_nCurRow,rCells);
- _rCellRect.Top()= --rCells.Top();
- impl_getCellRect(m_nCurColumn,_nPrevRow,rCells);
- _rCellRect.Bottom()=rCells.Bottom();
+ Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
+ _rCellRect.Top() = aCellRect.Top();
+ impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
+ _rCellRect.Bottom() = aCellRect.Bottom();
}
m_pDataWindow->Invalidate(_rCellRect);
}
- //-------------------------------------------------------------------------------
- //this method is to be called, when a new row is added
- void TableControl_Impl::invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect)
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow )
{
- if(m_nCurRow < 0)
- m_nCurRow = 0;
- if(m_nCursorHidden == 2)
+ if ( m_nCursorHidden == 2 )
+ // WTF? what kind of hack is this?
--m_nCursorHidden;
- impl_getAllVisibleCellsArea( _rCellRect );
- TableRowGeometry _rRow( *this, _rCellRect, _nRowPos);
- impl_ni_updateScrollbars();
- m_pDataWindow->Invalidate(_rRow.getRect());
- }
- //-------------------------------------------------------------------------------
- std::vector<RowPos>& TableControl_Impl::getSelectedRows()
- {
- return m_nRowSelected;
- }
- //--------------------------------------------------------------------
- void TableControl_Impl::clearSelection()
- {
- m_nRowSelected.clear();
- }
- //--------------------------------------------------------------------
- //-------------------------------------------------------------------------------
- void TableControl_Impl::removeSelectedRow(RowPos _nRowPos)
- {
- int i =0;
- //if the row is selected, remove it from the selection vector
- if(isRowSelected(m_nRowSelected, _nRowPos))
+
+ 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;
+
+ Rectangle aInvalidateRect;
+
+ Rectangle const aVisibleCellsArea( impl_getAllVisibleCellsArea() );
+ TableRowGeometry aRow( *this, aVisibleCellsArea, firstRow, true );
+ while ( aRow.isValid() && ( aRow.getRow() <= lastRow ) )
{
- if(m_nRowSelected.size()>1)
- m_nRowSelected.erase(m_nRowSelected.begin()+_nRowPos);
- else
- m_nRowSelected.clear();
+ aInvalidateRect.Union( aRow.getRect() );
+ aRow.moveDown();
}
- //after removing a row, row positions must be updated, so selected rows could stay selected
- if(m_nRowSelected.size()>1)
- {
- for(std::vector<RowPos>::iterator it=m_nRowSelected.begin();it!=m_nRowSelected.end();++it)
- {
- if(*it > _nRowPos)
- m_nRowSelected[i]=*it-1;
- ++i;
- }
- }
- if(_nRowPos == 0)
- m_nCurRow = 0;
- else
- m_nCurRow = _nRowPos-1;
+
+ if ( i_lastRow == ROW_INVALID )
+ aInvalidateRect.Bottom() = m_pDataWindow->GetOutputSizePixel().Height();
+
+ m_pDataWindow->Invalidate( aInvalidateRect );
}
+
//------------------------------------------------------------------------------
- void TableControl_Impl::invalidateRows()
+ void TableControl_Impl::checkCursorPosition()
{
- impl_ni_updateScrollbars();
+ DBG_CHECK_ME();
+
TableSize nVisibleRows = impl_getVisibleRows(true);
TableSize nVisibleCols = impl_getVisibleColumns(true);
- if(m_nTopRow+nVisibleRows>m_nRowCount && m_nRowCount>=nVisibleRows)
- m_nTopRow--;
+ if ( ( m_nTopRow + nVisibleRows > m_nRowCount )
+ && ( m_nRowCount >= nVisibleRows )
+ )
+ {
+ --m_nTopRow;
+ }
else
+ {
m_nTopRow = 0;
- if(m_nLeftColumn+nVisibleCols>m_nColumnCount && m_nColumnCount>=nVisibleCols)
- m_nLeftColumn--;
+ }
+
+ if ( ( m_nLeftColumn + nVisibleCols > m_nColumnCount )
+ && ( m_nColumnCount >= nVisibleCols )
+ )
+ {
+ --m_nLeftColumn;
+ }
else
+ {
m_nLeftColumn = 0;
+ }
+
m_pDataWindow->Invalidate();
}
@@ -1729,7 +2130,7 @@ namespace svt { namespace table
}
//--------------------------------------------------------------------
- TableSize TableControl_Impl::impl_getVisibleColumns( bool _bAcceptPartialRow ) const
+ TableSize TableControl_Impl::impl_getVisibleColumns( bool _bAcceptPartialCol ) const
{
DBG_CHECK_ME();
@@ -1739,7 +2140,7 @@ namespace svt { namespace table
Rectangle( Point( 0, 0 ), m_pDataWindow->GetOutputSizePixel() ),
m_nLeftColumn,
*this,
- _bAcceptPartialRow
+ _bAcceptPartialCol
);
}
@@ -1750,12 +2151,15 @@ namespace svt { namespace table
// TODO: give veto listeners a chance
- if ( ( _nColumn < -1 ) || ( _nColumn >= m_nColumnCount )
- || ( _nRow < -1 ) || ( _nRow >= m_nRowCount )
+ if ( ( _nColumn < 0 ) || ( _nColumn >= m_nColumnCount )
+ || ( _nRow < 0 ) || ( _nRow >= m_nRowCount )
)
+ {
+ OSL_ENSURE( false, "TableControl_Impl::goTo: invalid row or column index!" );
return false;
+ }
- TempHideCursor aHideCursor( *this );
+ SuppressCursor aHideCursor( *this );
m_nCurColumn = _nColumn;
m_nCurRow = _nRow;
@@ -1772,32 +2176,40 @@ namespace svt { namespace table
&& ( _nRow >= 0 ) && ( _nRow < m_nRowCount ),
"TableControl_Impl::ensureVisible: invalid coordinates!" );
- TempHideCursor aHideCursor( *this );
+ SuppressCursor aHideCursor( *this );
if ( _nColumn < m_nLeftColumn )
- impl_ni_ScrollColumns( _nColumn - m_nLeftColumn );
+ impl_scrollColumns( _nColumn - m_nLeftColumn );
else
{
TableSize nVisibleColumns = impl_getVisibleColumns( _bAcceptPartialVisibility );
if ( _nColumn > m_nLeftColumn + nVisibleColumns - 1 )
{
- impl_ni_ScrollColumns( _nColumn - ( m_nLeftColumn + nVisibleColumns - 1 ) );
+ impl_scrollColumns( _nColumn - ( m_nLeftColumn + nVisibleColumns - 1 ) );
// TODO: since not all columns have the same width, this might in theory result
// in the column still not being visible.
}
}
if ( _nRow < m_nTopRow )
- impl_ni_ScrollRows( _nRow - m_nTopRow );
+ impl_scrollRows( _nRow - m_nTopRow );
else
{
TableSize nVisibleRows = impl_getVisibleRows( _bAcceptPartialVisibility );
if ( _nRow > m_nTopRow + nVisibleRows - 1 )
- impl_ni_ScrollRows( _nRow - ( m_nTopRow + nVisibleRows - 1 ) );
+ impl_scrollRows( _nRow - ( m_nTopRow + nVisibleRows - 1 ) );
}
}
//--------------------------------------------------------------------
+ ::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 );
+ }
+
+ //--------------------------------------------------------------------
TableSize TableControl_Impl::impl_ni_ScrollRows( TableSize _nRowDelta )
{
// compute new top row
@@ -1811,10 +2223,10 @@ namespace svt { namespace table
m_nTopRow = nNewTopRow;
// if updates are enabled currently, scroll the viewport
- if ( m_rAntiImpl.IsUpdateMode() && ( m_nTopRow != nOldTopRow ) )
+ if ( m_nTopRow != nOldTopRow )
{
DBG_SUSPEND_INV( INV_SCROLL_POSITION );
- TempHideCursor aHideCursor( *this );
+ SuppressCursor aHideCursor( *this );
// TODO: call a onStartScroll at our listener (or better an own onStartScroll,
// which hides the cursor and then calls the listener)
// Same for onEndScroll
@@ -1837,43 +2249,68 @@ namespace svt { namespace table
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_nTopRow == 0 )
+ m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
+
return (TableSize)( m_nTopRow - nOldTopRow );
}
//--------------------------------------------------------------------
+ TableSize TableControl_Impl::impl_scrollRows( TableSize const i_rowDelta )
+ {
+ DBG_CHECK_ME();
+ return impl_ni_ScrollRows( i_rowDelta );
+ }
+
+ //--------------------------------------------------------------------
TableSize TableControl_Impl::impl_ni_ScrollColumns( TableSize _nColumnDelta )
{
// compute new left column
- ColPos nNewLeftColumn =
+ const ColPos nNewLeftColumn =
::std::max(
::std::min( (ColPos)( m_nLeftColumn + _nColumnDelta ), (ColPos)( m_nColumnCount - 1 ) ),
(ColPos)0
);
- ColPos nOldLeftColumn = m_nLeftColumn;
+ const ColPos nOldLeftColumn = m_nLeftColumn;
m_nLeftColumn = nNewLeftColumn;
// if updates are enabled currently, scroll the viewport
- if ( m_rAntiImpl.IsUpdateMode() && ( m_nLeftColumn != nOldLeftColumn ) )
+ if ( m_nLeftColumn != nOldLeftColumn )
{
DBG_SUSPEND_INV( INV_SCROLL_POSITION );
- TempHideCursor aHideCursor( *this );
+ SuppressCursor aHideCursor( *this );
// TODO: call a onStartScroll at our listener (or better an own onStartScroll,
// which hides the cursor and then calls the listener)
// Same for onEndScroll
// scroll the view port, if possible
- Rectangle aDataArea( Point( m_nRowHeaderWidthPixel, 0 ), m_pDataWindow->GetOutputSizePixel() );
+ const Rectangle aDataArea( Point( m_nRowHeaderWidthPixel, 0 ), m_pDataWindow->GetOutputSizePixel() );
long nPixelDelta =
- ( m_nLeftColumn > 0 ? m_aAccColumnWidthsPixel[ m_nLeftColumn - 1 ] : 0 )
- - ( nOldLeftColumn > 0 ? m_aAccColumnWidthsPixel[ nOldLeftColumn - 1 ] : 0 );
+ m_aColumnWidths[ nOldLeftColumn ].getStart()
+ - m_aColumnWidths[ m_nLeftColumn ].getStart();
+
+ // update our column positions
+ // Do this *before* scrolling, as SCROLL_UPDATE will trigger a paint, which already needs the correct
+ // information in m_aColumnWidths
+ for ( ColumnPositions::iterator colPos = m_aColumnWidths.begin();
+ colPos != m_aColumnWidths.end();
+ ++colPos
+ )
+ {
+ colPos->move( nPixelDelta );
+ }
+ // scroll the window content (if supported and possible), or invalidate the complete window
if ( m_pDataWindow->GetBackground().IsScrollable()
&& abs( nPixelDelta ) < aDataArea.GetWidth()
)
{
- m_pDataWindow->Scroll( (long)-nPixelDelta, 0, aDataArea, SCROLL_CLIP | SCROLL_UPDATE );
+ m_pDataWindow->Scroll( nPixelDelta, 0, aDataArea, SCROLL_CLIP | SCROLL_UPDATE );
}
else
m_pDataWindow->Invalidate( INVALIDATE_UPDATE );
@@ -1882,39 +2319,55 @@ namespace svt { namespace table
m_pHScroll->SetThumbPos( m_nLeftColumn );
}
+ // 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_nLeftColumn == 0 )
+ m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
+
return (TableSize)( m_nLeftColumn - nOldLeftColumn );
}
- //-------------------------------------------------------------------------------
- SelectionEngine* TableControl_Impl::getSelEngine()
+
+ //------------------------------------------------------------------------------------------------------------------
+ TableSize TableControl_Impl::impl_scrollColumns( TableSize const i_columnDelta )
{
- return m_pSelEngine;
+ DBG_CHECK_ME();
+ return impl_ni_ScrollColumns( i_columnDelta );
}
- //-------------------------------------------------------------------------------
- TableDataWindow* TableControl_Impl::getDataWindow()
+
+ //------------------------------------------------------------------------------------------------------------------
+ SelectionEngine* TableControl_Impl::getSelEngine()
{
- return m_pDataWindow;
+ return m_pSelEngine;
}
- //-------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
ScrollBar* TableControl_Impl::getHorzScrollbar()
{
return m_pHScroll;
}
- //-------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
ScrollBar* TableControl_Impl::getVertScrollbar()
{
return m_pVScroll;
}
- //-------------------------------------------------------------------------------
- BOOL TableControl_Impl::isRowSelected(const ::std::vector<RowPos>& selectedRows, RowPos current)
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableControl_Impl::isRowSelected( RowPos i_row ) const
{
- return ::std::find(selectedRows.begin(),selectedRows.end(),current) != selectedRows.end();
+ return ::std::find( m_aSelectedRows.begin(), m_aSelectedRows.end(), i_row ) != m_aSelectedRows.end();
}
- //-------------------------------------------------------------------------------
- bool TableControl_Impl::isRowSelected(RowPos current)
+
+ //------------------------------------------------------------------------------------------------------------------
+ RowPos TableControl_Impl::getSelectedRowIndex( size_t const i_selectionIndex ) const
{
- return ::std::find(m_nRowSelected.begin(),m_nRowSelected.end(),current) != m_nRowSelected.end();
+ if ( i_selectionIndex < m_aSelectedRows.size() )
+ return m_aSelectedRows[ i_selectionIndex ];
+ return ROW_INVALID;
}
- //-------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
int TableControl_Impl::getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current)
{
std::vector<RowPos>::const_iterator it = ::std::find(selectedRows.begin(),selectedRows.end(),current);
@@ -1924,272 +2377,158 @@ namespace svt { namespace table
}
return -1;
}
- //-------------------------------------------------------------------------------
- bool TableControl_Impl::isTooltipActive()
- {
- return m_rAntiImpl.isTooltip();
- }
- //-------------------------------------------------------------------------------
- ::rtl::OUString& TableControl_Impl::setTooltip(const Point& rPoint )
+
+ //--------------------------------------------------------------------
+ ColPos TableControl_Impl::impl_getColumnForOrdinate( long const i_ordinate ) const
{
- ::rtl::OUString aTooltipText;
- RowPos current = getCurrentRow(rPoint);
- com::sun::star::uno::Sequence< sal_Int32 > cols = m_rAntiImpl.getColumnsForTooltip();
- com::sun::star::uno::Sequence< ::rtl::OUString > text = m_rAntiImpl.getTextForTooltip();
- if(text.getLength()==0 && cols.getLength()==0)
- {
- ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][m_nCurColumn];
- aTooltipText = convertToString(content);
- }
- else if(text.getLength() == 0)
- {
- for(int i=0; i<cols.getLength(); i++)
- {
- if(i==0)
- {
- ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]];
- aTooltipText = convertToString(content);
- }
- else
- {
- aTooltipText+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
- ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]];
- aTooltipText += convertToString(content);
- }
- }
- }
- else if(cols.getLength() == 0)
- {
- for(int i=0; i<text.getLength(); i++)
- {
- if(i==0)
- aTooltipText = text[i];
- else
- {
- aTooltipText+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
- aTooltipText+= text[i];
- }
- }
- }
- else
+ DBG_CHECK_ME();
+
+ if ( ( m_aColumnWidths.empty() ) || ( i_ordinate < 0 ) )
+ return COL_INVALID;
+
+ 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,
+ ColumnInfoPositionLess()
+ );
+ if ( lowerBound == m_aColumnWidths.end() )
{
- int nCols = cols.getLength();
- int mText = text.getLength();
- if(nCols < mText )
- cols.realloc(mText);
- else if(mText < nCols)
- text.realloc(nCols);
- for(int i=0; i<cols.getLength(); i++)
- {
- if(i==0)
- {
- ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]];
- aTooltipText = text[i] + convertToString(content);
- }
- else
- {
- aTooltipText+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
- aTooltipText+= text[i];
- if(nCols > i)
- {
- ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]];
- ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >xGraphic;
- aTooltipText += convertToString(content);
- }
- }
- }
+ // point is *behind* the start of the last column ...
+ if ( ordinate < m_aColumnWidths.rbegin()->getEnd() )
+ // ... but still before its end
+ return m_nColumnCount - 1;
+ return COL_INVALID;
}
- return m_aTooltipText = aTooltipText;
+ return lowerBound - m_aColumnWidths.begin();
}
+
//--------------------------------------------------------------------
- void TableControl_Impl::resizeColumn(const Point& rPoint)
- {
- Pointer aNewPointer(POINTER_ARROW);
- int resizingColumn=m_nCurColumn-m_nLeftColumn;
- PColumnModel pColumn = m_pModel->getColumnModel(m_nCurColumn);
- impl_ni_getAccVisibleColWidths();
- int newColWidth = m_aColumnWidthsPixel[m_nCurColumn];
- //subtract 1 from m_aAccColumnWidthPixel because right border should be part of the current cell
- if(m_aVisibleColumnWidthsPixel[resizingColumn]-1 == rPoint.X() && pColumn->isResizable())
- aNewPointer = Pointer( POINTER_HSPLIT );
- //MouseButton was pressed but not yet released, mouse is moving
- if(m_bResizing)
- {
- if(rPoint.X() > m_pDataWindow->GetOutputSizePixel().Width() || rPoint.X() < m_aVisibleColumnWidthsPixel[resizingColumn]-newColWidth)
- aNewPointer = Pointer( POINTER_NOTALLOWED);
- else
- aNewPointer = Pointer( POINTER_HSPLIT );
- m_pDataWindow->HideTracking();
- int lineHeight = 0;
- if(m_pModel->hasColumnHeaders())
- lineHeight+= m_nColHeaderHeightPixel;
- lineHeight+=m_nRowHeightPixel*m_nRowCount;
- int gridHeight = m_pDataWindow->GetOutputSizePixel().Height();
- if(lineHeight >= gridHeight)
- lineHeight = gridHeight;
- m_pDataWindow->ShowTracking(Rectangle(Point(rPoint.X(),0), Size(1, lineHeight )),
- SHOWTRACK_SPLIT | SHOWTRACK_WINDOW);
- }
- m_pDataWindow->SetPointer(aNewPointer);
+ RowPos TableControl_Impl::impl_getRowForAbscissa( long const i_abscissa ) const
+ {
+ DBG_CHECK_ME();
+
+ if ( i_abscissa < 0 )
+ return ROW_INVALID;
+
+ if ( i_abscissa < m_nColHeaderHeightPixel )
+ return ROW_COL_HEADERS;
+
+ long const abscissa = i_abscissa - m_nColHeaderHeightPixel;
+ long const row = m_nTopRow + abscissa / m_nRowHeightPixel;
+ return row < m_pModel->getRowCount() ? row : ROW_INVALID;
}
+
//--------------------------------------------------------------------
- bool TableControl_Impl::startResizeColumn(const Point& rPoint)
+ bool TableControl_Impl::markRowAsDeselected( RowPos const i_rowIndex )
{
- m_bResizingGrid = false;
- m_nResizingColumn = m_nCurColumn;
- PColumnModel pColumn = m_pModel->getColumnModel(m_nResizingColumn);
- if(m_aVisibleColumnWidthsPixel[m_nResizingColumn-m_nLeftColumn]-1 == rPoint.X() && pColumn->isResizable())
- {
- m_pDataWindow->CaptureMouse();
- m_bResizing = true;
- }
- return m_bResizing;
+ DBG_CHECK_ME();
+
+ ::std::vector< RowPos >::iterator selPos = ::std::find( m_aSelectedRows.begin(), m_aSelectedRows.end(), i_rowIndex );
+ if ( selPos == m_aSelectedRows.end() )
+ return false;
+
+ m_aSelectedRows.erase( selPos );
+ return true;
}
+
//--------------------------------------------------------------------
- bool TableControl_Impl::endResizeColumn(const Point& rPoint)
- {
- if(m_bResizing)
- {
- m_pDataWindow->HideTracking();
- PColumnModel pColumn = m_pModel->getColumnModel(m_nResizingColumn);
- int maxWidth = m_rAntiImpl.LogicToPixel( Size( pColumn->getMaxWidth(), 0 ), MAP_APPFONT ).Width();
- int minWidth = m_rAntiImpl.LogicToPixel( Size( pColumn->getMinWidth(), 0 ), MAP_APPFONT ).Width();
- int resizeCol = m_nResizingColumn-m_nLeftColumn;
- //new position of mouse
- int actX = rPoint.X();
- //old position of right border
- int oldX = m_aVisibleColumnWidthsPixel[resizeCol];
- //position of left border if cursor in the first cell
- int leftX = 0;
- if(m_nResizingColumn > m_nLeftColumn)
- leftX = m_aVisibleColumnWidthsPixel[resizeCol-1];
- else if(m_nResizingColumn == m_nLeftColumn && m_pModel->hasRowHeaders())
- leftX = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width();
- int actWidth = actX - leftX;
- int newActWidth = 0;
- //minimize the column width
- if(oldX > actX && actX >= leftX)
+ bool TableControl_Impl::markRowAsSelected( RowPos const i_rowIndex )
+ {
+ DBG_CHECK_ME();
+
+ if ( isRowSelected( i_rowIndex ) )
+ return false;
+
+ SelectionMode const eSelMode = getSelEngine()->GetSelectionMode();
+ switch ( eSelMode )
+ {
+ case SINGLE_SELECTION:
+ if ( !m_aSelectedRows.empty() )
{
- if(minWidth < actWidth)
- {
- newActWidth = m_rAntiImpl.PixelToLogic( Size( actWidth, 0 ), MAP_APPFONT ).Width();
- pColumn->setPreferredWidth(newActWidth);
- }
- else
- pColumn->setPreferredWidth(pColumn->getMinWidth());
- if(m_nLeftColumn != 0)
- impl_updateLeftColumn();
+ OSL_ENSURE( m_aSelectedRows.size() == 1, "TableControl::markRowAsSelected: SingleSelection with more than one selected element?" );
+ m_aSelectedRows[0] = i_rowIndex;
+ break;
+ }
+ // fall through
+
+ case MULTIPLE_SELECTION:
+ m_aSelectedRows.push_back( i_rowIndex );
+ break;
+
+ default:
+ OSL_ENSURE( false, "TableControl_Impl::markRowAsSelected: unsupported selection mode!" );
+ return false;
}
- else if(oldX < actX)
+
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ bool TableControl_Impl::markAllRowsAsDeselected()
+ {
+ if ( m_aSelectedRows.empty() )
+ return false;
+
+ m_aSelectedRows.clear();
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ bool TableControl_Impl::markAllRowsAsSelected()
+ {
+ DBG_CHECK_ME();
+
+ SelectionMode const eSelMode = getSelEngine()->GetSelectionMode();
+ ENSURE_OR_RETURN_FALSE( eSelMode == MULTIPLE_SELECTION, "TableControl_Impl::markAllRowsAsSelected: unsupported selection mode!" );
+
+ if ( m_aSelectedRows.size() == size_t( m_pModel->getRowCount() ) )
{
- if(actWidth < maxWidth)
+ #if OSL_DEBUG_LEVEL > 0
+ for ( TableSize row = 0; row < m_pModel->getRowCount(); ++row )
{
- newActWidth = m_rAntiImpl.PixelToLogic( Size( actWidth, 0 ), MAP_APPFONT ).Width();
- pColumn->setPreferredWidth(newActWidth);
+ OSL_ENSURE( isRowSelected( row ), "TableControl_Impl::markAllRowsAsSelected: inconsistency in the selected rows!" );
}
- else
- pColumn->setPreferredWidth(pColumn->getMaxWidth());
+ #endif
+ // already all rows marked as selected
+ return false;
}
- m_nCurColumn = m_nResizingColumn;
- impl_ni_updateColumnWidths();
- impl_ni_updateScrollbars();
- m_pDataWindow->Invalidate(INVALIDATE_UPDATE);
- m_pDataWindow->SetPointer(Pointer());
- m_bResizing = false;
- m_bResizingGrid = true;
- }
- m_pDataWindow->ReleaseMouse();
- return m_bResizing;
- }
- //-------------------------------------------------------------------------------
- void TableControl_Impl::impl_ni_getAccVisibleColWidths()
- {
- TableSize nVisCols = impl_getVisibleColumns(true);
- int widthsPixel = 0;
- m_aVisibleColumnWidthsPixel.resize(0);
- m_aVisibleColumnWidthsPixel.reserve(nVisCols);
- int headerRowWidth = 0;
- if(m_pModel->hasRowHeaders())
- {
- headerRowWidth = m_rAntiImpl.LogicToPixel( Size(m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width();
- widthsPixel+=headerRowWidth;
- }
- int col = m_nLeftColumn;
- while(nVisCols)
- {
- m_aVisibleColumnWidthsPixel.push_back(widthsPixel+=m_aColumnWidthsPixel[col]);
- col++;
- nVisCols--;
- }
- }
- //-------------------------------------------------------------------------------
- void TableControl_Impl::impl_updateLeftColumn()
- {
- int nVisCols = m_aVisibleColumnWidthsPixel.size();
- int headerRowWidth = 0;
- //sum of currently visible columns
- int widthsPixel = 0;
- //header pixel should be added, because header doesn't vanish when scrolling
- if(m_pModel->hasRowHeaders())
- {
- headerRowWidth = m_rAntiImpl.LogicToPixel( Size(m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width();
- widthsPixel+=headerRowWidth;
- }
- int col = m_nLeftColumn;
- //add column width of the neighbour of the left column
- widthsPixel+=m_aColumnWidthsPixel[col-1];
- //compute the sum of the new column widths
- while(nVisCols)
- {
- PColumnModel pColumn = m_pModel->getColumnModel(col);
- int colWidth = pColumn->getWidth();
- int colPrefWidth = pColumn->getPreferredWidth();
- if(colPrefWidth!=0)
- colWidth = colPrefWidth;
- widthsPixel += m_rAntiImpl.LogicToPixel( Size( colWidth, 0 ), MAP_APPFONT ).Width();
- col++;
- nVisCols--;
- }
- //when the sum of all visible columns and the next to the left column is smaller than
- //window width, then update m_nLeftColumn
- if(widthsPixel<m_pDataWindow->GetOutputSizePixel().Width())
- m_nLeftColumn--;
+
+ m_aSelectedRows.clear();
+ for ( RowPos i=0; i < m_pModel->getRowCount(); ++i )
+ m_aSelectedRows.push_back(i);
+
+ return true;
}
+
//--------------------------------------------------------------------
- rtl::OUString TableControl_Impl::convertToString(const ::com::sun::star::uno::Any& value)
- {
- sal_Int32 nInt = 0;
- sal_Bool bBool = false;
- double fDouble = 0;
- ::rtl::OUString sNewString;
- ::rtl::OUString sConvertString;
- if(value >>= sConvertString)
- sNewString = sConvertString;
- else if(value >>= nInt)
- sNewString = sConvertString.valueOf(nInt);
- else if(value >>= bBool)
- sNewString = sConvertString.valueOf(bBool);
- else if(value >>= fDouble)
- sNewString = sConvertString.valueOf(fDouble);
- return sNewString;
- }
Rectangle TableControl_Impl::calcHeaderRect(bool bColHeader)
{
- Rectangle aRectTable, aRectTableWithHeaders;
- impl_getAllVisibleDataCellArea(aRectTable);
- impl_getAllVisibleCellsArea(aRectTableWithHeaders);
- Size aSizeTable(aRectTable.GetSize());
- Size aSizeTableWithHeaders(aRectTableWithHeaders.GetSize());
- if(bColHeader)
- return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width()-aSizeTable.Width(), aSizeTableWithHeaders.Height()));
+ Rectangle const aRectTableWithHeaders( impl_getAllVisibleCellsArea() );
+ Size const aSizeTableWithHeaders( aRectTableWithHeaders.GetSize() );
+ if ( bColHeader )
+ return Rectangle( aRectTableWithHeaders.TopLeft(), Size( aSizeTableWithHeaders.Width(), m_nColHeaderHeightPixel ) );
else
- return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width(), aSizeTableWithHeaders.Height()-aSizeTable.Height()));
+ return Rectangle( aRectTableWithHeaders.TopLeft(), Size( m_nRowHeaderWidthPixel, aSizeTableWithHeaders.Height() ) );
}
+
+ //--------------------------------------------------------------------
Rectangle TableControl_Impl::calcTableRect()
{
- Rectangle aRect;
- impl_getAllVisibleDataCellArea(aRect);
- return aRect;
+ return impl_getAllVisibleDataCellArea();
+ }
+
+ //--------------------------------------------------------------------
+ IMPL_LINK( TableControl_Impl, OnUpdateScrollbars, void*, /**/ )
+ {
+ DBG_CHECK_ME();
+ impl_ni_updateScrollbars();
+ return 1L;
}
//--------------------------------------------------------------------
@@ -2205,159 +2544,202 @@ namespace svt { namespace table
return 0L;
}
- //---------------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
+ Reference< XAccessible > TableControl_Impl::getAccessible( Window& i_parentWindow )
+ {
+ DBG_TESTSOLARMUTEX();
+ if ( m_pAccessibleTable == NULL )
+ {
+ Reference< XAccessible > const xAccParent = i_parentWindow.GetAccessible();
+ if ( xAccParent.is() )
+ {
+ m_pAccessibleTable = m_aFactoryAccess.getFactory().createAccessibleTableControl(
+ xAccParent, m_rAntiImpl
+ );
+ }
+ }
+
+ Reference< XAccessible > xAccessible;
+ if ( m_pAccessibleTable )
+ xAccessible = m_pAccessibleTable->getMyself();
+ return xAccessible;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::disposeAccessible()
+ {
+ if ( m_pAccessibleTable )
+ m_pAccessibleTable->dispose();
+ m_pAccessibleTable = NULL;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableControl_Impl::impl_isAccessibleAlive() const
+ {
+ DBG_CHECK_ME();
+ return ( NULL != m_pAccessibleTable ) && m_pAccessibleTable->isAlive();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableControl_Impl::impl_commitAccessibleEvent( sal_Int16 const i_eventID, Any const & i_newValue, Any const & i_oldValue )
+ {
+ DBG_CHECK_ME();
+ if ( impl_isAccessibleAlive() )
+ m_pAccessibleTable->commitEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ //==================================================================================================================
+ //= TableFunctionSet
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
TableFunctionSet::TableFunctionSet(TableControl_Impl* _pTableControl)
:m_pTableControl( _pTableControl)
- ,m_nCurrentRow (-2)
+ ,m_nCurrentRow( ROW_INVALID )
{
}
- //-------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
TableFunctionSet::~TableFunctionSet()
{
}
- //-------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableFunctionSet::BeginDrag()
{
}
- //-------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableFunctionSet::CreateAnchor()
{
- m_pTableControl->m_nAnchor = m_pTableControl->m_nCurRow;
+ m_pTableControl->setAnchor( m_pTableControl->getCurRow() );
}
- //-------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
void TableFunctionSet::DestroyAnchor()
{
- m_pTableControl->m_nAnchor = -1;
+ m_pTableControl->setAnchor( ROW_INVALID );
}
- //-------------------------------------------------------------------------------
- BOOL TableFunctionSet::SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor)
+
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableFunctionSet::SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor)
{
- BOOL bHandled = FALSE;
- Rectangle rCells;
- //curRow is the row where the mouse click happened, m_nCurRow is the last selected row, before the mouse click
- RowPos curRow = m_pTableControl->getCurrentRow(rPoint);
- if(curRow == -2)
- return FALSE;
- if( bDontSelectAtCursor )
+ sal_Bool bHandled = sal_False;
+ // newRow is the row which includes the point, getCurRow() is the last selected row, before the mouse click
+ RowPos newRow = m_pTableControl->getRowAtPoint( rPoint );
+ if ( newRow == ROW_COL_HEADERS )
+ newRow = m_pTableControl->getTopRow();
+
+ ColPos newCol = m_pTableControl->getColAtPoint( rPoint );
+ if ( newCol == COL_ROW_HEADERS )
+ newCol = m_pTableControl->getLeftColumn();
+
+ if ( ( newRow == ROW_INVALID ) || ( newCol == COL_INVALID ) )
+ return sal_False;
+
+ if ( bDontSelectAtCursor )
{
- if(m_pTableControl->m_nRowSelected.size()>1)
- m_pTableControl->m_pSelEngine->AddAlways(TRUE);
- bHandled = TRUE;
+ if ( m_pTableControl->getSelectedRowCount() > 1 )
+ m_pTableControl->getSelEngine()->AddAlways(sal_True);
+ bHandled = sal_True;
}
- else if(m_pTableControl->m_nAnchor == m_pTableControl->m_nCurRow)
+ else if ( m_pTableControl->getAnchor() == m_pTableControl->getCurRow() )
{
//selecting region,
- int diff = m_pTableControl->m_nCurRow - curRow;
+ int diff = m_pTableControl->getCurRow() - newRow;
//selected region lies above the last selection
if( diff >= 0)
{
//put selected rows in vector
- while(m_pTableControl->m_nAnchor>=curRow)
+ while ( m_pTableControl->getAnchor() >= newRow )
{
- bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, m_pTableControl->m_nAnchor);
- //if row isn't selected, put it in vector, otherwise don't put it there, because it will be twice there
- if(!isAlreadySelected)
- m_pTableControl->m_nRowSelected.push_back(m_pTableControl->m_nAnchor);
- m_pTableControl->m_nAnchor--;
+ m_pTableControl->markRowAsSelected( m_pTableControl->getAnchor() );
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
diff--;
}
- m_pTableControl->m_nAnchor++;
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() + 1 );
}
//selected region lies beneath the last selected row
else
{
- while(m_pTableControl->m_nAnchor<=curRow)
+ while ( m_pTableControl->getAnchor() <= newRow )
{
- bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, m_pTableControl->m_nAnchor);
- if(!isAlreadySelected)
- m_pTableControl->m_nRowSelected.push_back(m_pTableControl->m_nAnchor);
- m_pTableControl->m_nAnchor++;
+ m_pTableControl->markRowAsSelected( m_pTableControl->getAnchor() );
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() + 1 );
diff++;
}
- m_pTableControl->m_nAnchor--;
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
}
- m_pTableControl->invalidateSelectedRegion(m_pTableControl->m_nCurRow, curRow, rCells);
- bHandled = TRUE;
+ Rectangle aCellRect;
+ m_pTableControl->invalidateSelectedRegion( m_pTableControl->getCurRow(), newRow, aCellRect );
+ bHandled = sal_True;
}
//no region selected
else
{
- if(m_pTableControl->m_nRowSelected.empty())
- m_pTableControl->m_nRowSelected.push_back(curRow);
+ if ( !m_pTableControl->hasRowSelection() )
+ m_pTableControl->markRowAsSelected( newRow );
else
{
- if(m_pTableControl->m_pSelEngine->GetSelectionMode()==SINGLE_SELECTION)
+ if ( m_pTableControl->getSelEngine()->GetSelectionMode() == SINGLE_SELECTION )
{
DeselectAll();
- m_pTableControl->m_nRowSelected.push_back(curRow);
+ m_pTableControl->markRowAsSelected( newRow );
}
else
{
- bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, curRow);
- if(!isAlreadySelected)
- m_pTableControl->m_nRowSelected.push_back(curRow);
+ m_pTableControl->markRowAsSelected( newRow );
}
}
- if(m_pTableControl->m_nRowSelected.size()>1 && m_pTableControl->m_pSelEngine->GetSelectionMode()!=SINGLE_SELECTION)
- m_pTableControl->m_pSelEngine->AddAlways(TRUE);
- m_pTableControl->invalidateSelectedRegion(curRow, curRow, rCells);
- bHandled = TRUE;
+ 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 );
+ bHandled = sal_True;
}
- m_pTableControl->m_nCurRow = curRow;
- m_pTableControl->ensureVisible(m_pTableControl->m_nCurColumn,m_pTableControl->m_nCurRow,false);
+ m_pTableControl->goTo( newCol, newRow );
return bHandled;
}
- //-------------------------------------------------------------------------------
- BOOL TableFunctionSet::IsSelectionAtPoint( const Point& rPoint )
+ //------------------------------------------------------------------------------------------------------------------
+ sal_Bool TableFunctionSet::IsSelectionAtPoint( const Point& rPoint )
{
- m_pTableControl->m_pSelEngine->AddAlways(FALSE);
- if(m_pTableControl->m_nRowSelected.empty())
- return FALSE;
+ m_pTableControl->getSelEngine()->AddAlways(sal_False);
+ if ( !m_pTableControl->hasRowSelection() )
+ return sal_False;
else
{
- RowPos curRow = m_pTableControl->getCurrentRow(rPoint);
- m_pTableControl->m_nAnchor = -1;
- bool selected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, curRow);
+ RowPos curRow = m_pTableControl->getRowAtPoint( rPoint );
+ m_pTableControl->setAnchor( ROW_INVALID );
+ bool selected = m_pTableControl->isRowSelected( curRow );
m_nCurrentRow = curRow;
return selected;
}
}
- //-------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableFunctionSet::DeselectAtPoint( const Point& rPoint )
{
(void)rPoint;
- long pos = 0;
- long i = 0;
- Rectangle rCells;
- for(std::vector<RowPos>::iterator it=m_pTableControl->m_nRowSelected.begin();
- it!=m_pTableControl->m_nRowSelected.end();++it)
- {
- if(*it == m_nCurrentRow)
- {
- pos = i;
- m_pTableControl->invalidateSelectedRegion(*it, *it, rCells);
- }
- ++i;
- }
- m_pTableControl->m_nRowSelected.erase(m_pTableControl->m_nRowSelected.begin()+pos);
+ Rectangle aCellRange;
+ m_pTableControl->invalidateSelectedRegion( m_nCurrentRow, m_nCurrentRow, aCellRange );
+ m_pTableControl->markRowAsDeselected( m_nCurrentRow );
}
- //-------------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
void TableFunctionSet::DeselectAll()
{
- if(!m_pTableControl->m_nRowSelected.empty())
+ if ( m_pTableControl->hasRowSelection() )
{
- Rectangle rCells;
- for(std::vector<RowPos>::iterator it=m_pTableControl->m_nRowSelected.begin();
- it!=m_pTableControl->m_nRowSelected.end();++it)
+ Rectangle aCellRange;
+ for ( size_t i=0; i<m_pTableControl->getSelectedRowCount(); ++i )
{
- m_pTableControl->invalidateSelectedRegion(*it, *it, rCells);
+ RowPos const rowIndex = m_pTableControl->getSelectedRowIndex(i);
+ m_pTableControl->invalidateSelectedRegion( rowIndex, rowIndex, aCellRange );
}
- m_pTableControl->m_nRowSelected.clear();
+
+ m_pTableControl->markAllRowsAsDeselected();
}
}
-//........................................................................
+//......................................................................................................................
} } // namespace svt::table
-//........................................................................
+//......................................................................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/tablecontrol_impl.hxx b/svtools/source/table/tablecontrol_impl.hxx
index 3f10f9ce2830..2f9cffd3089b 100644..100755
--- a/svtools/source/table/tablecontrol_impl.hxx
+++ b/svtools/source/table/tablecontrol_impl.hxx
@@ -28,14 +28,16 @@
#ifndef SVTOOLS_TABLECONTROL_IMPL_HXX
#define SVTOOLS_TABLECONTROL_IMPL_HXX
-#include <svtools/table/tablemodel.hxx>
+#include "svtools/table/tablemodel.hxx"
+#include "svtools/table/tablecontrolinterface.hxx"
-#include <svtools/table/abstracttablecontrol.hxx>
+#include "svtaccessiblefactory.hxx"
-#include <svtools/table/tablemodel.hxx>
-#include <vector>
#include <vcl/seleng.hxx>
+#include <vector>
+
+#include <boost/scoped_ptr.hpp>
class ScrollBar;
class ScrollBarBox;
@@ -45,7 +47,42 @@ namespace svt { namespace table
{
//........................................................................
- typedef ::std::vector< long > ArrayOfLong;
+ struct MutableColumnMetrics : protected ColumnMetrics
+ {
+ MutableColumnMetrics()
+ :ColumnMetrics()
+ {
+ }
+
+ MutableColumnMetrics( long const i_startPixel, long const i_endPixel )
+ :ColumnMetrics( i_startPixel, i_endPixel )
+ {
+ }
+
+ long getStart() const { return nStartPixel; }
+ long getEnd() const { return nEndPixel; }
+
+ void setEnd( long const i_end ) { nEndPixel = i_end; }
+ void move( long const i_offset ) { nStartPixel += i_offset; nEndPixel += i_offset; }
+
+ long getWidth() const { return nEndPixel - nStartPixel; }
+
+ ColumnMetrics const & operator()() { return *this; }
+ };
+
+ struct ColumnInfoPositionLess
+ {
+ bool operator()( MutableColumnMetrics const& i_colInfo, long const i_position )
+ {
+ return i_colInfo.getEnd() < i_position;
+ }
+ bool operator()( long const i_position, MutableColumnMetrics const& i_colInfo )
+ {
+ return i_position < i_colInfo.getStart();
+ }
+ };
+
+ typedef ::std::vector< MutableColumnMetrics > ColumnPositions;
class TableControl;
class TableDataWindow;
@@ -54,13 +91,14 @@ namespace svt { namespace table
//====================================================================
//= TableControl_Impl
//====================================================================
- class TableControl_Impl : public IAbstractTableControl
+ class TableControl_Impl :public ITableControl
+ ,public ITableModelListener
{
friend class TableGeometry;
friend class TableRowGeometry;
friend class TableColumnGeometry;
friend class SuspendInvariants;
- friend class TableFunctionSet;
+
private:
/// the control whose impl-instance we implemnt
TableControl& m_rAntiImpl;
@@ -68,14 +106,9 @@ namespace svt { namespace table
PTableModel m_pModel;
/// the input handler to use, usually the input handler as provided by ->m_pModel
PTableInputHandler m_pInputHandler;
- /// the widths of the single columns, measured in pixel
- ArrayOfLong m_aColumnWidthsPixel;
- /** the accumulated widths of the single columns, i.e. their exclusive right borders,
- <strong<not</strong> counting the space for a possible row header column
- */
- ArrayOfLong m_aAccColumnWidthsPixel;
+ /// info about the widths of our columns
+ ColumnPositions m_aColumnWidths;
- ArrayOfLong m_aVisibleColumnWidthsPixel;
/// the height of a single row in the table, measured in pixels
long m_nRowHeightPixel;
/// the height of the column header row in the table, measured in pixels
@@ -85,9 +118,13 @@ namespace svt { namespace table
/// the number of columns in the table control. Cached model value.
TableSize m_nColumnCount;
+
/// the number of rows in the table control. Cached model value.
TableSize m_nRowCount;
+ /// denotes whether or not the columns fitted into the available width, last time we checked
+ long m_bColumnsFit;
+
ColPos m_nCurColumn;
RowPos m_nCurRow;
ColPos m_nLeftColumn;
@@ -100,24 +137,27 @@ namespace svt { namespace table
The window's upper left corner is at position (0,0), relative to the
table control, which is the direct parent of the data window.
*/
- TableDataWindow* m_pDataWindow;
+ ::boost::scoped_ptr< TableDataWindow >
+ m_pDataWindow;
/// the vertical scrollbar, if any
ScrollBar* m_pVScroll;
/// the horizontal scrollbar, if any
- ScrollBar* m_pHScroll;
+ ScrollBar* m_pHScroll;
ScrollBarBox* m_pScrollCorner;
- //selection engine - for determining selection range, e.g. single, multiple
- SelectionEngine* m_pSelEngine;
- //vector which contains the selected rows
- std::vector<RowPos> m_nRowSelected;
- //part of selection engine
- TableFunctionSet* m_pTableFunctionSet;
- //part of selection engine
- RowPos m_nAnchor;
- bool m_bResizing;
- ColPos m_nResizingColumn;
- bool m_bResizingGrid;
- rtl::OUString m_aTooltipText;
+ //selection engine - for determining selection range, e.g. single, multiple
+ SelectionEngine* m_pSelEngine;
+ //vector which contains the selected rows
+ std::vector<RowPos> m_aSelectedRows;
+ //part of selection engine
+ TableFunctionSet* m_pTableFunctionSet;
+ //part of selection engine
+ RowPos m_nAnchor;
+ bool m_bUpdatingColWidths;
+
+ Link m_aSelectHdl;
+
+ AccessibleFactoryAccess m_aFactoryAccess;
+ IAccessibleTableControl* m_pAccessibleTable;
#if DBG_UTIL
#define INV_SCROLL_POSITION 1
@@ -130,21 +170,18 @@ namespace svt { namespace table
#endif
public:
-
-
- PTableModel getModel() const;
void setModel( PTableModel _pModel );
inline const PTableInputHandler& getInputHandler() const { return m_pInputHandler; }
- inline ColPos getCurColumn() const { return m_nCurColumn; }
- inline RowPos getCurRow() const { return m_nCurRow; }
- inline void setCurRow(RowPos curRow){ m_nCurRow = curRow; }
- inline RowPos getTopRow() const { return m_nTopRow; }
- inline long getRowCount() const { return m_nRowCount; }
- inline long getColumnCount() const { return m_nColumnCount; }
+ inline RowPos getCurRow() const { return m_nCurRow; }
+ inline void setCurRow( RowPos i_curRow ){ m_nCurRow = i_curRow; }
+
+ RowPos getAnchor() const { return m_nAnchor; }
+ void setAnchor( RowPos const i_anchor ) { m_nAnchor = i_anchor; }
- inline long getColHeaderHightPixel() const { return m_nColHeaderHeightPixel; }
+ inline RowPos getTopRow() const { return m_nTopRow; }
+ inline ColPos getLeftColumn() const { return m_nLeftColumn; }
inline const TableControl& getAntiImpl() const { return m_rAntiImpl; }
inline TableControl& getAntiImpl() { return m_rAntiImpl; }
@@ -182,45 +219,115 @@ namespace svt { namespace table
<TRUE/> if it's okay that the given cooordinate is only partially visible
*/
void ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility );
- /** returns the row, which contains the input point*/
- virtual RowPos getCurrentRow (const Point& rPoint);
-
- void setCursorAtCurrentCell(const Point& rPoint);
- /** checks whether the vector with the selected rows contains the current row*/
- BOOL isRowSelected(const ::std::vector<RowPos>& selectedRows, RowPos current);
-
- bool isRowSelected(RowPos current);
- /** 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 );
- /** to be called when a new row is added to the control*/
- void invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect );
- /** returns the vector, which contains the selected rows*/
- std::vector<RowPos>& getSelectedRows();
- /** updates the vector, which contains the selected rows after removing the row nRowPos*/
- void removeSelectedRow(RowPos _nRowPos);
- void invalidateRows();
- void clearSelection();
- // IAbstractTableControl
- virtual void hideCursor();
- virtual void showCursor();
- virtual bool dispatchAction( TableControlAction _eAction );
- virtual SelectionEngine* getSelEngine();
- virtual bool isTooltipActive();
- virtual rtl::OUString& setTooltip(const Point& rPoint );
- virtual void resizeColumn(const Point& rPoint);
- virtual bool startResizeColumn(const Point& rPoint);
- virtual bool endResizeColumn(const Point& rPoint);
-
- TableDataWindow* getDataWindow();
- ScrollBar* getHorzScrollbar();
- ScrollBar* getVertScrollbar();
-
- ::rtl::OUString convertToString(const ::com::sun::star::uno::Any& _value);
- Rectangle calcHeaderRect(bool bColHeader);
- Rectangle calcTableRect();
+
+ /** retrieves the content of the given cell, converted to a string
+ */
+ ::rtl::OUString getCellContentAsString( RowPos const i_row, ColPos const i_col );
+
+ /** 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 );
+
+ /** invalidates the part of the data window which is covered by the given row
+ @param i_firstRow
+ the index of the first row to include in the invalidation
+ @param i_lastRow
+ the index of the last row to include in the invalidation, or ROW_INVALID if the invalidation
+ should happen down to the bottom of the data window.
+ */
+ void invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow );
+
+ void checkCursorPosition();
+
+ bool hasRowSelection() const { return !m_aSelectedRows.empty(); }
+ size_t getSelectedRowCount() const { return m_aSelectedRows.size(); }
+ RowPos getSelectedRowIndex( size_t const i_selectionIndex ) const;
+
+ /** removes the given row index from m_aSelectedRows
+
+ @return
+ <TRUE/> if and only if the row was previously marked as selected
+ */
+ bool markRowAsDeselected( RowPos const i_rowIndex );
+
+ /** marks the given row as selectged, by putting it into m_aSelectedRows
+ @return
+ <TRUE/> if and only if the row was previously <em>not</em> marked as selected
+ */
+ bool markRowAsSelected( RowPos const i_rowIndex );
+
+ /** marks all rows as deselected
+ @return
+ <TRUE/> if and only if the selection actually changed by this operation
+ */
+ bool markAllRowsAsDeselected();
+
+ /** marks all rows as selected
+ @return
+ <FALSE/> if and only if all rows were selected already.
+ */
+ bool markAllRowsAsSelected();
+
+ void setSelectHandler( Link const & i_selectHandler ) { m_aSelectHdl = i_selectHandler; }
+ Link const& getSelectHandler() const { return m_aSelectHdl; }
+
+ // ITableControl
+ virtual void hideCursor();
+ virtual void showCursor();
+ virtual bool dispatchAction( TableControlAction _eAction );
+ virtual SelectionEngine* getSelEngine();
+ virtual PTableModel getModel() const;
+ virtual ColPos getCurrentColumn() const;
+ virtual RowPos getCurrentRow() const;
+ virtual bool activateCell( ColPos const i_col, RowPos const i_row );
+ virtual ::Size getTableSizePixel() const;
+ virtual void setPointer( Pointer const & i_pointer );
+ virtual void captureMouse();
+ virtual void releaseMouse();
+ virtual void invalidate( TableArea const i_what );
+ virtual long pixelWidthToAppFont( long const i_pixels ) const;
+ virtual void hideTracking();
+ virtual void showTracking( Rectangle const & i_location, sal_uInt16 const i_flags );
+ virtual RowPos getRowAtPoint( const Point& rPoint ) const;
+ virtual ColPos getColAtPoint( const Point& rPoint ) const;
+ virtual TableCell hitTest( const Point& rPoint ) const;
+ virtual ColumnMetrics getColumnMetrics( ColPos const i_column ) const;
+ virtual bool isRowSelected( RowPos i_row ) const;
+
+
+ TableDataWindow& getDataWindow() { return *m_pDataWindow; }
+ const TableDataWindow& getDataWindow() const { return *m_pDataWindow; }
+ ScrollBar* getHorzScrollbar();
+ ScrollBar* getVertScrollbar();
+
+ Rectangle calcHeaderRect(bool bColHeader);
+ Rectangle calcTableRect();
+
+ // A11Y
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
+ getAccessible( Window& i_parentWindow );
+ void disposeAccessible();
+
+ // ITableModelListener
+ virtual void rowsInserted( RowPos first, RowPos last );
+ virtual void rowsRemoved( RowPos first, RowPos last );
+ virtual void columnInserted( ColPos const i_colIndex );
+ virtual void columnRemoved( ColPos const i_colIndex );
+ virtual void allColumnsRemoved();
+ virtual void cellsUpdated( ColPos const i_firstCol, ColPos i_lastCol, RowPos const i_firstRow, RowPos const i_lastRow );
+ virtual void columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup );
+ virtual void tableMetricsChanged();
+
private:
+ bool impl_isAccessibleAlive() const;
+ void impl_commitAccessibleEvent(
+ sal_Int16 const i_eventID,
+ ::com::sun::star::uno::Any const & i_newValue,
+ ::com::sun::star::uno::Any const & i_oldValue
+ );
+
/** toggles the cursor visibility
The method is not bound to the classes public invariants, as it's used in
@@ -248,7 +355,7 @@ namespace svt { namespace table
specifies whether a possible only partially visible last row is
counted, too.
*/
- TableSize impl_getVisibleColumns( bool _bAcceptPartialRow ) const;
+ TableSize impl_getVisibleColumns( bool _bAcceptPartialCol ) const;
/** determines the rectangle occupied by the given cell
*/
@@ -261,15 +368,20 @@ namespace svt { namespace table
*/
void impl_ni_updateCachedModelValues();
- /** updates ->m_aColumnWidthsPixel with the current pixel widths of all model columns
+ /** updates the cached table metrics (row height etc.)
+ */
+ void impl_ni_updateCachedTableMetrics();
- The method takes into account the current zoom factor and map mode of the table
- control, plus any possible COLWIDTH_FIT_TO_VIEW widths in the model columns.
+ /** updates ->m_aColumnWidthsPixel with the current pixel widths of all model columns
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>.
*/
- void impl_ni_updateColumnWidths();
+ void impl_ni_updateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID );
/** updates the scrollbars of the control
@@ -293,6 +405,10 @@ namespace svt { namespace table
*/
TableSize impl_ni_ScrollRows( TableSize _nRowDelta );
+ /** equivalent to impl_ni_ScrollRows, but checks the instances invariants beforehand (in a non-product build only)
+ */
+ TableSize impl_scrollRows( TableSize const i_rowDelta );
+
/** scrolls the view by the given number of columns
The method is not bound to the classes public invariants, as it's used in
@@ -303,8 +419,13 @@ namespace svt { namespace table
from the given numbers to scroll in case the begin or the end of the
column range were reached.
*/
- TableSize impl_ni_ScrollColumns( TableSize _nRowDelta );
- /** retrieves the area occupied by the totality of (at least partially) visible cells
+ TableSize impl_ni_ScrollColumns( TableSize _nColumnDelta );
+
+ /** equivalent to impl_ni_ScrollColumns, but checks the instances invariants beforehand (in a non-product build only)
+ */
+ TableSize impl_scrollColumns( TableSize const i_columnDelta );
+
+ /** retrieves the area occupied by the totality of (at least partially) visible cells
The returned area includes row and column headers. Also, it takes into
account the the fact that there might be less columns than would normally
@@ -313,27 +434,37 @@ namespace svt { namespace table
As a result of respecting the partial visibility of rows and columns,
the returned area might be larger than the data window's output size.
*/
- void impl_getAllVisibleCellsArea( Rectangle& _rCellArea ) const;
+ Rectangle impl_getAllVisibleCellsArea() const;
/** retrieves the area occupied by all (at least partially) visible data cells.
Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea,
minus the row and column header areas.
*/
- void impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const;
+ Rectangle impl_getAllVisibleDataCellArea() const;
+
+ /** retrieves the column which covers the given ordinate
+ */
+ ColPos impl_getColumnForOrdinate( long const i_ordinate ) const;
- void impl_ni_getAccVisibleColWidths();
- void impl_updateLeftColumn();
+ /** retrieves the row which covers the given abscissa
+ */
+ RowPos impl_getRowForAbscissa( long const i_abscissa ) const;
+
+ /// invalidates the window area occupied by the given column
+ void impl_invalidateColumn( ColPos const i_column );
DECL_LINK( OnScroll, ScrollBar* );
+ DECL_LINK( OnUpdateScrollbars, void* );
};
+
//see seleng.hxx, seleng.cxx, FunctionSet overridables, part of selection engine
class TableFunctionSet : public FunctionSet
{
- friend class TableDataWindow;
private:
- TableControl_Impl* m_pTableControl;
- RowPos m_nCurrentRow;
+ TableControl_Impl* m_pTableControl;
+ RowPos m_nCurrentRow;
+
public:
TableFunctionSet(TableControl_Impl* _pTableControl);
virtual ~TableFunctionSet();
@@ -341,8 +472,8 @@ namespace svt { namespace table
virtual void BeginDrag();
virtual void CreateAnchor();
virtual void DestroyAnchor();
- virtual BOOL SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor);
- virtual BOOL IsSelectionAtPoint( const Point& rPoint );
+ virtual sal_Bool SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor);
+ virtual sal_Bool IsSelectionAtPoint( const Point& rPoint );
virtual void DeselectAtPoint( const Point& rPoint );
virtual void DeselectAll();
};
diff --git a/svtools/source/table/tabledatawindow.cxx b/svtools/source/table/tabledatawindow.cxx
index 9607ec93036c..7c546421555d 100644
--- a/svtools/source/table/tabledatawindow.cxx
+++ b/svtools/source/table/tabledatawindow.cxx
@@ -29,23 +29,31 @@
#include "precompiled_svtools.hxx"
#include "svtools/table/tablecontrol.hxx"
-#include "svtools/table/tabledatawindow.hxx"
+
+#include "tabledatawindow.hxx"
#include "tablecontrol_impl.hxx"
+#include "tablegeometry.hxx"
+#include "cellvalueconversion.hxx"
+
#include <vcl/help.hxx>
-//........................................................................
+//......................................................................................................................
namespace svt { namespace table
{
- class TableControl_Impl;
-//........................................................................
+//......................................................................................................................
- //====================================================================
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Any;
+ /** === end UNO using === **/
+
+ //==================================================================================================================
//= TableDataWindow
- //====================================================================
- //--------------------------------------------------------------------
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
TableDataWindow::TableDataWindow( TableControl_Impl& _rTableControl )
:Window( &_rTableControl.getAntiImpl() )
- ,m_rTableControl ( _rTableControl )
+ ,m_rTableControl( _rTableControl )
+ ,m_nTipWindowHandle( 0 )
{
// by default, use the background as determined by the style settings
const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() );
@@ -53,105 +61,164 @@ namespace svt { namespace table
SetFillColor( aWindowColor );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
+ TableDataWindow::~TableDataWindow()
+ {
+ impl_hideTipWindow();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::Paint( const Rectangle& rUpdateRect )
{
m_rTableControl.doPaintContent( rUpdateRect );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::SetBackground( const Wallpaper& rColor )
{
Window::SetBackground( rColor );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::SetControlBackground( const Color& rColor )
{
Window::SetControlBackground( rColor );
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::SetBackground()
{
Window::SetBackground();
}
- //--------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::SetControlBackground()
{
Window::SetControlBackground();
}
- //--------------------------------------------------------------------
- void TableDataWindow::MouseMove( const MouseEvent& rMEvt )
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableDataWindow::RequestHelp( const HelpEvent& rHEvt )
{
- Point aPoint = rMEvt.GetPosPixel();
- if ( !m_rTableControl.getInputHandler()->MouseMove( m_rTableControl, rMEvt ) )
+ sal_uInt16 const nHelpMode = rHEvt.GetMode();
+ if ( ( IsMouseCaptured() )
+ || ( ( nHelpMode & HELPMODE_QUICK ) == 0 )
+ )
+ {
+ Window::RequestHelp( rHEvt );
+ return;
+ }
+
+ ::rtl::OUString sHelpText;
+ sal_uInt16 nHelpStyle = 0;
+
+ Point const aMousePos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+ RowPos const hitRow = m_rTableControl.getRowAtPoint( aMousePos );
+ ColPos const hitCol = m_rTableControl.getColAtPoint( aMousePos );
+
+ PTableModel const pTableModel( m_rTableControl.getModel() );
+ if ( ( hitCol >= 0 ) && ( hitCol < pTableModel->getColumnCount() ) )
{
- if(m_rTableControl.getCurrentRow(aPoint)>=0 && m_rTableControl.isTooltipActive() )
+ if ( hitRow == ROW_COL_HEADERS )
{
- SetPointer(POINTER_ARROW);
- rtl::OUString& rHelpText = m_rTableControl.setTooltip(aPoint);
- Help::EnableBalloonHelp();
- Window::SetHelpText( rHelpText.getStr());
+ sHelpText = pTableModel->getColumnModel( hitCol )->getHelpText();
}
- else if(m_rTableControl.getCurrentRow(aPoint) == -1)
+ else if ( ( hitRow >= 0 ) && ( hitRow < pTableModel->getRowCount() ) )
{
- if(Help::IsBalloonHelpEnabled())
- Help::DisableBalloonHelp();
- m_rTableControl.resizeColumn(aPoint);
+ Any aCellToolTip;
+ pTableModel->getCellToolTip( hitCol, hitRow, aCellToolTip );
+ if ( !aCellToolTip.hasValue() )
+ {
+ // use the cell content
+ pTableModel->getCellContent( hitCol, hitRow, aCellToolTip );
+
+ // use the cell content as tool tip only if it doesn't fit into the cell.
+ bool const activeCell = ( hitRow == m_rTableControl.getCurrentRow() ) && ( hitCol == m_rTableControl.getCurrentColumn() );
+ bool const selectedCell = m_rTableControl.isRowSelected( hitRow );
+
+ Rectangle const aWindowRect( Point( 0, 0 ), GetOutputSizePixel() );
+ TableCellGeometry const aCell( m_rTableControl, aWindowRect, hitCol, hitRow );
+ Rectangle const aCellRect( aCell.getRect() );
+
+ PTableRenderer const pRenderer = pTableModel->getRenderer();
+ if ( pRenderer->FitsIntoCell( aCellToolTip, hitCol, hitRow, activeCell, selectedCell, *this, aCellRect ) )
+ aCellToolTip.clear();
+ }
+
+ sHelpText = CellValueConversion::convertToString( aCellToolTip );
+
+ if ( sHelpText.indexOf( '\n' ) >= 0 )
+ nHelpStyle = QUICKHELP_TIP_STYLE_BALLOON;
}
+ }
+
+ if ( sHelpText.getLength() )
+ {
+ Rectangle const aControlScreenRect(
+ OutputToScreenPixel( Point( 0, 0 ) ),
+ GetOutputSizePixel()
+ );
+
+ if ( m_nTipWindowHandle )
+ Help::UpdateTip( m_nTipWindowHandle, this, aControlScreenRect, sHelpText );
else
- {
- if(Help::IsBalloonHelpEnabled())
- Help::DisableBalloonHelp();
- Window::MouseMove( rMEvt );
- }
+ m_nTipWindowHandle = Help::ShowTip( this, aControlScreenRect, sHelpText, nHelpStyle );
}
+ else
+ impl_hideTipWindow();
}
- //--------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableDataWindow::impl_hideTipWindow()
+ {
+ if ( m_nTipWindowHandle != 0 )
+ {
+ Help::HideTip( m_nTipWindowHandle );
+ m_nTipWindowHandle = 0;
+ }
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void TableDataWindow::MouseMove( const MouseEvent& rMEvt )
+ {
+ if ( rMEvt.IsLeaveWindow() )
+ impl_hideTipWindow();
+
+ if ( !m_rTableControl.getInputHandler()->MouseMove( m_rTableControl, rMEvt ) )
+ {
+ Window::MouseMove( rMEvt );
+ }
+ }
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
- Point aPoint = rMEvt.GetPosPixel();
- RowPos nCurRow = m_rTableControl.getCurrentRow(aPoint);
- std::vector<RowPos> selectedRows(m_rTableControl.getSelectedRows());
+ impl_hideTipWindow();
+
+ Point const aPoint = rMEvt.GetPosPixel();
+ RowPos const hitRow = m_rTableControl.getRowAtPoint( aPoint );
+ bool const wasRowSelected = m_rTableControl.isRowSelected( hitRow );
+
if ( !m_rTableControl.getInputHandler()->MouseButtonDown( m_rTableControl, rMEvt ) )
- Window::MouseButtonDown( rMEvt );
- else
{
- if(nCurRow >= 0 && m_rTableControl.getSelEngine()->GetSelectionMode() != NO_SELECTION)
- {
- bool found = std::find(selectedRows.begin(),selectedRows.end(), nCurRow) != selectedRows.end();
+ Window::MouseButtonDown( rMEvt );
+ return;
+ }
- if( !found )
- {
- m_aSelectHdl.Call( NULL );
- }
- }
+ bool const isRowSelected = m_rTableControl.isRowSelected( hitRow );
+ if ( isRowSelected != wasRowSelected )
+ {
+ m_aSelectHdl.Call( NULL );
}
m_aMouseButtonDownHdl.Call((MouseEvent*) &rMEvt);
- m_rTableControl.getAntiImpl().LoseFocus();
}
- //--------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
void TableDataWindow::MouseButtonUp( const MouseEvent& rMEvt )
{
if ( !m_rTableControl.getInputHandler()->MouseButtonUp( m_rTableControl, rMEvt ) )
Window::MouseButtonUp( rMEvt );
+
m_aMouseButtonUpHdl.Call((MouseEvent*) &rMEvt);
- m_rTableControl.getAntiImpl().GetFocus();
+ m_rTableControl.getAntiImpl().GrabFocus();
}
- //--------------------------------------------------------------------
- void TableDataWindow::SetPointer( const Pointer& rPointer )
- {
- Window::SetPointer(rPointer);
- }
- //--------------------------------------------------------------------
- void TableDataWindow::CaptureMouse()
- {
- Window::CaptureMouse();
- }
- //--------------------------------------------------------------------
- void TableDataWindow::ReleaseMouse( )
- {
- Window::ReleaseMouse();
- }
- // -----------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------------------------------------------
long TableDataWindow::Notify(NotifyEvent& rNEvt )
{
long nDone = 0;
@@ -169,8 +236,8 @@ namespace svt { namespace table
}
return nDone ? nDone : Window::Notify( rNEvt );
}
-//........................................................................
+//......................................................................................................................
} } // namespace svt::table
-//........................................................................
+//......................................................................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/tabledatawindow.hxx b/svtools/source/table/tabledatawindow.hxx
new file mode 100644
index 000000000000..c26cd6ccd596
--- /dev/null
+++ b/svtools/source/table/tabledatawindow.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+************************************************************************/
+
+#ifndef SVTOOLS_SOURCE_TABLE_TABLEDATAWINDOW_HXX
+#define SVTOOLS_SOURCE_TABLE_TABLEDATAWINDOW_HXX
+
+#include <vcl/window.hxx>
+#include <vcl/seleng.hxx>
+
+//........................................................................
+namespace svt { namespace table
+{
+//........................................................................
+
+ class TableControl_Impl;
+ class TableFunctionSet;
+
+
+ //====================================================================
+ //= TableDataWindow
+ //====================================================================
+ /** the window containing the content area (including headers) of
+ a table control
+ */
+ class TableDataWindow : public Window
+ {
+ friend class TableFunctionSet;
+ private:
+ TableControl_Impl& m_rTableControl;
+ Link m_aMouseButtonDownHdl;
+ Link m_aMouseButtonUpHdl;
+ Link m_aSelectHdl;
+ sal_uLong m_nTipWindowHandle;
+
+ public:
+ 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; }
+
+ // Window overridables
+ virtual void Paint( const Rectangle& rRect );
+ virtual void MouseMove( const MouseEvent& rMEvt);
+ virtual void MouseButtonDown( const MouseEvent& rMEvt);
+ virtual void MouseButtonUp( const MouseEvent& rMEvt);
+ virtual long Notify(NotifyEvent& rNEvt);
+ virtual void SetControlBackground(const Color& rColor);
+ virtual void SetControlBackground();
+ virtual void RequestHelp( const HelpEvent& rHEvt );
+
+ void SetBackground(const Wallpaper& rColor);
+ void SetBackground();
+
+ private:
+ void impl_hideTipWindow();
+ };
+//........................................................................
+} } // namespace svt::table
+//........................................................................
+
+#endif // SVTOOLS_SOURCE_TABLE_TABLEDATAWINDOW_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/tablegeometry.cxx b/svtools/source/table/tablegeometry.cxx
index edd2a73cd624..e00e21c28911 100644
--- a/svtools/source/table/tablegeometry.cxx
+++ b/svtools/source/table/tablegeometry.cxx
@@ -28,107 +28,141 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
-
#include "tablegeometry.hxx"
#include "tablecontrol_impl.hxx"
#include <tools/debug.hxx>
-//........................................................................
+//......................................................................................................................
namespace svt { namespace table
{
-//........................................................................
+//......................................................................................................................
- //====================================================================
+ //==================================================================================================================
//= TableRowGeometry
- //====================================================================
- //--------------------------------------------------------------------
- TableRowGeometry::TableRowGeometry( const TableControl_Impl& _rControl, const Rectangle& _rBoundaries,
- RowPos _nRow )
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ TableRowGeometry::TableRowGeometry( TableControl_Impl const & _rControl, Rectangle const & _rBoundaries,
+ RowPos const _nRow, bool const i_allowVirtualRows )
:TableGeometry( _rControl, _rBoundaries )
,m_nRowPos( _nRow )
+ ,m_bAllowVirtualRows( i_allowVirtualRows )
{
if ( m_nRowPos == ROW_COL_HEADERS )
{
- //DBG_ASSERT( m_rControl.m_pModel->hasColumnHeaders(),
- // "TableRowGeometry::TableRowGeometry: why asking for the geoemtry of the non-existent column header row?" );
m_aRect.Top() = 0;
m_aRect.Bottom() = m_rControl.m_nColHeaderHeightPixel - 1;
}
else
{
- if ( ( m_nRowPos >= m_rControl.m_nTopRow ) && ( m_nRowPos < m_rControl.m_pModel->getRowCount() ) )
- {
- m_aRect.Top() = m_rControl.m_nColHeaderHeightPixel + ( m_nRowPos - m_rControl.m_nTopRow ) * m_rControl.m_nRowHeightPixel;
- m_aRect.Bottom() = m_aRect.Top() + m_rControl.m_nRowHeightPixel - 1;
- }
- else
- m_aRect.SetEmpty();
+ impl_initRect();
}
}
- //--------------------------------------------------------------------
- bool TableRowGeometry::moveDown()
+ //------------------------------------------------------------------------------------------------------------------
+ void TableRowGeometry::impl_initRect()
{
- if ( ++m_nRowPos < m_rControl.m_pModel->getRowCount() )
- m_aRect.Move( 0, m_rControl.m_nRowHeightPixel );
+ if ( ( m_nRowPos >= m_rControl.m_nTopRow ) && impl_isValidRow( m_nRowPos ) )
+ {
+ m_aRect.Top() = m_rControl.m_nColHeaderHeightPixel + ( m_nRowPos - m_rControl.m_nTopRow ) * m_rControl.m_nRowHeightPixel;
+ m_aRect.Bottom() = m_aRect.Top() + m_rControl.m_nRowHeightPixel - 1;
+ }
else
m_aRect.SetEmpty();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableRowGeometry::impl_isValidRow( RowPos const i_row ) const
+ {
+ return m_bAllowVirtualRows || ( i_row < m_rControl.m_pModel->getRowCount() );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableRowGeometry::moveDown()
+ {
+ if ( m_nRowPos == ROW_COL_HEADERS )
+ {
+ m_nRowPos = m_rControl.m_nTopRow;
+ impl_initRect();
+ }
+ else
+ {
+ if ( impl_isValidRow( ++m_nRowPos ) )
+ m_aRect.Move( 0, m_rControl.m_nRowHeightPixel );
+ else
+ m_aRect.SetEmpty();
+ }
return isValid();
}
- //====================================================================
+ //==================================================================================================================
//= TableColumnGeometry
- //====================================================================
- //--------------------------------------------------------------------
- TableColumnGeometry::TableColumnGeometry( const TableControl_Impl& _rControl, const Rectangle& _rBoundaries,
- ColPos _nCol )
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ TableColumnGeometry::TableColumnGeometry( TableControl_Impl const & _rControl, Rectangle const & _rBoundaries,
+ ColPos const _nCol, bool const i_allowVirtualColumns )
:TableGeometry( _rControl, _rBoundaries )
,m_nColPos( _nCol )
+ ,m_bAllowVirtualColumns( i_allowVirtualColumns )
{
if ( m_nColPos == COL_ROW_HEADERS )
{
-/* DBG_ASSERT( m_rControl.m_pModel->hasRowHeaders(),
- "TableColumnGeometry::TableColumnGeometry: why asking for the geoemtry of the non-existent row header column?" )*/;
m_aRect.Left() = 0;
m_aRect.Right() = m_rControl.m_nRowHeaderWidthPixel - 1;
}
else
{
- ColPos nLeftColumn = m_rControl.m_nLeftColumn;
- if ( ( m_nColPos >= nLeftColumn ) && ( m_nColPos < (ColPos)m_rControl.m_aColumnWidthsPixel.size() ) )
- {
- m_aRect.Left() = m_rControl.m_nRowHeaderWidthPixel;
- // TODO: take into account any possibly frozen columns
+ impl_initRect();
+ }
+ }
- for ( ColPos col = nLeftColumn; col < m_nColPos; ++col )
- m_aRect.Left() += m_rControl.m_aColumnWidthsPixel[ col ];
- m_aRect.Right() = m_aRect.Left() + m_rControl.m_aColumnWidthsPixel[ m_nColPos ] - 1;
- }
- else
- m_aRect.SetEmpty();
+ //------------------------------------------------------------------------------------------------------------------
+ void TableColumnGeometry::impl_initRect()
+ {
+ ColPos nLeftColumn = m_rControl.m_nLeftColumn;
+ if ( ( m_nColPos >= nLeftColumn ) && impl_isValidColumn( m_nColPos ) )
+ {
+ m_aRect.Left() = m_rControl.m_nRowHeaderWidthPixel;
+ // TODO: take into account any possibly frozen columns
+
+ for ( ColPos col = nLeftColumn; col < m_nColPos; ++col )
+ m_aRect.Left() += m_rControl.m_aColumnWidths[ col ].getWidth();
+ m_aRect.Right() = m_aRect.Left() + m_rControl.m_aColumnWidths[ m_nColPos ].getWidth() - 1;
}
+ else
+ m_aRect.SetEmpty();
}
- //--------------------------------------------------------------------
- bool TableColumnGeometry::moveRight()
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableColumnGeometry::impl_isValidColumn( ColPos const i_column ) const
{
- DBG_ASSERT( m_nColPos != COL_ROW_HEADERS, "TableColumnGeometry::moveRight: cannot move the row header column!" );
- // what would be COL_ROW_HEADERS + 1?
+ return m_bAllowVirtualColumns || ( i_column < ColPos( m_rControl.m_aColumnWidths.size() ) );
+ }
- if ( ++m_nColPos < (ColPos)m_rControl.m_aColumnWidthsPixel.size() )
+ //------------------------------------------------------------------------------------------------------------------
+ bool TableColumnGeometry::moveRight()
+ {
+ if ( m_nColPos == COL_ROW_HEADERS )
{
- m_aRect.Left() = m_aRect.Right() + 1;
- m_aRect.Right() += m_rControl.m_aColumnWidthsPixel[ m_nColPos ];
+ m_nColPos = m_rControl.m_nLeftColumn;
+ impl_initRect();
}
else
- m_aRect.SetEmpty();
+ {
+ if ( impl_isValidColumn( ++m_nColPos ) )
+ {
+ m_aRect.Left() = m_aRect.Right() + 1;
+ m_aRect.Right() += m_rControl.m_aColumnWidths[ m_nColPos ].getWidth();
+ }
+ else
+ m_aRect.SetEmpty();
+ }
return isValid();
}
-//........................................................................
+//......................................................................................................................
} } // namespace svt::table
-//........................................................................
+//......................................................................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/table/tablegeometry.hxx b/svtools/source/table/tablegeometry.hxx
index 979a78d0a5a2..9520e4992411 100644
--- a/svtools/source/table/tablegeometry.hxx
+++ b/svtools/source/table/tablegeometry.hxx
@@ -28,7 +28,7 @@
#ifndef SVTOOLS_TABLEGEOMETRY_HXX
#define SVTOOLS_TABLEGEOMETRY_HXX
-#include <svtools/table/tabletypes.hxx>
+#include "svtools/table/tabletypes.hxx"
#include <tools/gen.hxx>
@@ -76,18 +76,25 @@ namespace svt { namespace table
{
protected:
RowPos m_nRowPos;
+ bool m_bAllowVirtualRows;
public:
TableRowGeometry(
- const TableControl_Impl& _rControl,
- const Rectangle& _rBoundaries,
- RowPos _nRow
+ TableControl_Impl const & _rControl,
+ Rectangle const & _rBoundaries,
+ RowPos const _nRow,
+ bool const i_allowVirtualRows = false
+ // allow rows >= getRowCount()?
);
// status
RowPos getRow() const { return m_nRowPos; }
// operations
bool moveDown();
+
+ private:
+ void impl_initRect();
+ bool impl_isValidRow( RowPos const i_row ) const;
};
//====================================================================
@@ -97,18 +104,24 @@ namespace svt { namespace table
{
protected:
ColPos m_nColPos;
+ bool m_bAllowVirtualColumns;
public:
TableColumnGeometry(
- const TableControl_Impl& _rControl,
- const Rectangle& _rBoundaries,
- ColPos _nCol
+ TableControl_Impl const & _rControl,
+ Rectangle const & _rBoundaries,
+ ColPos const _nCol,
+ bool const i_allowVirtualColumns = false
);
// status
ColPos getCol() const { return m_nColPos; }
// operations
bool moveRight();
+
+ private:
+ void impl_initRect();
+ bool impl_isValidColumn( ColPos const i_column ) const;
};
//====================================================================
@@ -124,13 +137,14 @@ namespace svt { namespace table
public:
TableCellGeometry(
- const TableControl_Impl& _rControl,
- const Rectangle& _rBoundaries,
- ColPos _nCol,
- RowPos _nRow
+ TableControl_Impl const & _rControl,
+ Rectangle const & _rBoundaries,
+ ColPos const _nCol,
+ RowPos const _nRow,
+ bool const i_alllowVirtualCells = false
)
- :m_aRow( _rControl, _rBoundaries, _nRow )
- ,m_aCol( _rControl, _rBoundaries, _nCol )
+ :m_aRow( _rControl, _rBoundaries, _nRow, i_alllowVirtualCells )
+ ,m_aCol( _rControl, _rBoundaries, _nCol, i_alllowVirtualCells )
{
}