LCOV - code coverage report
Current view: top level - svtools/source/table - tablecontrol_impl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 1120 0.1 %
Date: 2012-08-25 Functions: 2 126 1.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 1542 0.1 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4                 :            :  *
       5                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       6                 :            :  *
       7                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       8                 :            :  *
       9                 :            :  * This file is part of OpenOffice.org.
      10                 :            :  *
      11                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      12                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      13                 :            :  * only, as published by the Free Software Foundation.
      14                 :            :  *
      15                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      16                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      17                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18                 :            :  * GNU Lesser General Public License version 3 for more details
      19                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      20                 :            :  *
      21                 :            :  * You should have received a copy of the GNU Lesser General Public License
      22                 :            :  * version 3 along with OpenOffice.org.  If not, see
      23                 :            :  * <http://www.openoffice.org/license.html>
      24                 :            :  * for a copy of the LGPLv3 License.
      25                 :            :  *
      26                 :            : ************************************************************************/
      27                 :            : 
      28                 :            : 
      29                 :            : #include "svtools/table/tablecontrol.hxx"
      30                 :            : #include "svtools/table/defaultinputhandler.hxx"
      31                 :            : #include "svtools/table/tablemodel.hxx"
      32                 :            : 
      33                 :            : #include "tabledatawindow.hxx"
      34                 :            : #include "tablecontrol_impl.hxx"
      35                 :            : #include "tablegeometry.hxx"
      36                 :            : #include "cellvalueconversion.hxx"
      37                 :            : 
      38                 :            : #include <com/sun/star/accessibility/XAccessible.hpp>
      39                 :            : #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
      40                 :            : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
      41                 :            : #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
      42                 :            : 
      43                 :            : #include <comphelper/flagguard.hxx>
      44                 :            : #include <vcl/scrbar.hxx>
      45                 :            : #include <vcl/seleng.hxx>
      46                 :            : #include <rtl/ref.hxx>
      47                 :            : #include <vcl/image.hxx>
      48                 :            : #include <tools/diagnose_ex.h>
      49                 :            : 
      50                 :            : #include <functional>
      51                 :            : 
      52                 :            : #define MIN_COLUMN_WIDTH_PIXEL  4
      53                 :            : 
      54                 :            : //......................................................................................................................
      55                 :            : namespace svt { namespace table
      56                 :            : {
      57                 :            : //......................................................................................................................
      58                 :            : 
      59                 :            :     /** === begin UNO using === **/
      60                 :            :     using ::com::sun::star::accessibility::AccessibleTableModelChange;
      61                 :            :     using ::com::sun::star::uno::makeAny;
      62                 :            :     using ::com::sun::star::uno::Any;
      63                 :            :     using ::com::sun::star::accessibility::XAccessible;
      64                 :            :     using ::com::sun::star::uno::Reference;
      65                 :            :     /** === end UNO using === **/
      66                 :            :     namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
      67                 :            :     namespace AccessibleTableModelChangeType = ::com::sun::star::accessibility::AccessibleTableModelChangeType;
      68                 :            : 
      69                 :            :     //==================================================================================================================
      70                 :            :     //= SuppressCursor
      71                 :            :     //==================================================================================================================
      72                 :            :     class SuppressCursor
      73                 :            :     {
      74                 :            :     private:
      75                 :            :         ITableControl&  m_rTable;
      76                 :            : 
      77                 :            :     public:
      78                 :          0 :         SuppressCursor( ITableControl& _rTable )
      79                 :          0 :             :m_rTable( _rTable )
      80                 :            :         {
      81                 :          0 :             m_rTable.hideCursor();
      82                 :          0 :         }
      83                 :          0 :         ~SuppressCursor()
      84                 :            :         {
      85                 :          0 :             m_rTable.showCursor();
      86                 :          0 :         }
      87                 :            :     };
      88                 :            : 
      89                 :            :     //====================================================================
      90                 :            :     //= EmptyTableModel
      91                 :            :     //====================================================================
      92                 :            :     /** default implementation of an ->ITableModel, used as fallback when no
      93                 :            :         real model is present
      94                 :            : 
      95                 :            :         Instances of this class are static in any way, and provide the least
      96                 :            :         necessary default functionality for a table model.
      97                 :            :     */
      98         [ #  # ]:          0 :     class EmptyTableModel : public ITableModel
      99                 :            :     {
     100                 :            :     public:
     101                 :          0 :         EmptyTableModel()
     102                 :          0 :         {
     103                 :          0 :         }
     104                 :            : 
     105                 :            :         // ITableModel overridables
     106                 :          0 :         virtual TableSize           getColumnCount() const
     107                 :            :         {
     108                 :          0 :             return 0;
     109                 :            :         }
     110                 :          0 :         virtual TableSize           getRowCount() const
     111                 :            :         {
     112                 :          0 :             return 0;
     113                 :            :         }
     114                 :          0 :         virtual bool                hasColumnHeaders() const
     115                 :            :         {
     116                 :          0 :             return false;
     117                 :            :         }
     118                 :          0 :         virtual bool                hasRowHeaders() const
     119                 :            :         {
     120                 :          0 :             return false;
     121                 :            :         }
     122                 :          0 :         virtual bool                isCellEditable( ColPos col, RowPos row ) const
     123                 :            :         {
     124                 :            :             (void)col;
     125                 :            :             (void)row;
     126                 :          0 :             return false;
     127                 :            :         }
     128                 :          0 :         virtual PColumnModel        getColumnModel( ColPos column )
     129                 :            :         {
     130                 :            :             OSL_FAIL( "EmptyTableModel::getColumnModel: invalid call!" );
     131                 :            :             (void)column;
     132                 :          0 :             return PColumnModel();
     133                 :            :         }
     134                 :          0 :         virtual PTableRenderer      getRenderer() const
     135                 :            :         {
     136                 :          0 :             return PTableRenderer();
     137                 :            :         }
     138                 :          0 :         virtual PTableInputHandler  getInputHandler() const
     139                 :            :         {
     140                 :          0 :             return PTableInputHandler();
     141                 :            :         }
     142                 :          0 :         virtual TableMetrics        getRowHeight() const
     143                 :            :         {
     144                 :          0 :             return 5 * 100;
     145                 :            :         }
     146                 :          0 :         virtual void setRowHeight(TableMetrics _nRowHeight)
     147                 :            :         {
     148                 :            :             (void)_nRowHeight;
     149                 :          0 :         }
     150                 :          0 :         virtual TableMetrics        getColumnHeaderHeight() const
     151                 :            :         {
     152                 :          0 :             return 0;
     153                 :            :         }
     154                 :          0 :         virtual TableMetrics        getRowHeaderWidth() const
     155                 :            :         {
     156                 :          0 :             return 0;
     157                 :            :         }
     158                 :          0 :         virtual ScrollbarVisibility getVerticalScrollbarVisibility() const
     159                 :            :         {
     160                 :          0 :             return ScrollbarShowNever;
     161                 :            :         }
     162                 :          0 :         virtual ScrollbarVisibility getHorizontalScrollbarVisibility() const
     163                 :            :         {
     164                 :          0 :             return ScrollbarShowNever;
     165                 :            :         }
     166                 :          0 :         virtual void addTableModelListener( const PTableModelListener& i_listener )
     167                 :            :         {
     168                 :            :             (void)i_listener;
     169                 :          0 :         }
     170                 :          0 :         virtual void removeTableModelListener( const PTableModelListener& i_listener )
     171                 :            :         {
     172                 :            :             (void)i_listener;
     173                 :          0 :         }
     174                 :          0 :         virtual ::boost::optional< ::Color > getLineColor() const
     175                 :            :         {
     176                 :          0 :             return ::boost::optional< ::Color >();
     177                 :            :         }
     178                 :          0 :         virtual ::boost::optional< ::Color > getHeaderBackgroundColor() const
     179                 :            :         {
     180                 :          0 :             return ::boost::optional< ::Color >();
     181                 :            :         }
     182                 :          0 :         virtual ::boost::optional< ::Color > getHeaderTextColor() const
     183                 :            :         {
     184                 :          0 :             return ::boost::optional< ::Color >();
     185                 :            :         }
     186                 :          0 :         virtual ::boost::optional< ::Color > getTextColor() const
     187                 :            :         {
     188                 :          0 :             return ::boost::optional< ::Color >();
     189                 :            :         }
     190                 :          0 :         virtual ::boost::optional< ::Color > getTextLineColor() const
     191                 :            :         {
     192                 :          0 :             return ::boost::optional< ::Color >();
     193                 :            :         }
     194                 :          0 :         virtual ::boost::optional< ::std::vector< ::Color > > getRowBackgroundColors() const
     195                 :            :         {
     196                 :          0 :             return ::boost::optional< ::std::vector< ::Color > >();
     197                 :            :         }
     198                 :          0 :         virtual ::com::sun::star::style::VerticalAlignment getVerticalAlign() const
     199                 :            :         {
     200                 :          0 :             return com::sun::star::style::VerticalAlignment(0);
     201                 :            :         }
     202                 :          0 :         virtual ITableDataSort* getSortAdapter()
     203                 :            :         {
     204                 :          0 :             return NULL;
     205                 :            :         }
     206                 :          0 :         virtual void getCellContent( ColPos const i_col, RowPos const i_row, ::com::sun::star::uno::Any& o_cellContent )
     207                 :            :         {
     208                 :            :             (void)i_row;
     209                 :            :             (void)i_col;
     210                 :          0 :             o_cellContent.clear();
     211                 :          0 :         }
     212                 :          0 :         virtual void getCellToolTip( ColPos const, RowPos const, ::com::sun::star::uno::Any& )
     213                 :            :         {
     214                 :          0 :         }
     215                 :          0 :         virtual Any getRowHeading( RowPos const i_rowPos ) const
     216                 :            :         {
     217                 :            :             (void)i_rowPos;
     218                 :          0 :             return Any();
     219                 :            :         }
     220                 :            :     };
     221                 :            : 
     222                 :            : 
     223                 :            :     //====================================================================
     224                 :            :     //= TableControl_Impl
     225                 :            :     //====================================================================
     226                 :            :     DBG_NAME( TableControl_Impl )
     227                 :            : 
     228                 :            : #if DBG_UTIL
     229                 :            :     //====================================================================
     230                 :            :     //= SuspendInvariants
     231                 :            :     //====================================================================
     232                 :            :     class SuspendInvariants
     233                 :            :     {
     234                 :            :     private:
     235                 :            :         const TableControl_Impl&    m_rTable;
     236                 :            :         sal_Int32                   m_nSuspendFlags;
     237                 :            : 
     238                 :            :     public:
     239                 :            :         SuspendInvariants( const TableControl_Impl& _rTable, sal_Int32 _nSuspendFlags )
     240                 :            :             :m_rTable( _rTable )
     241                 :            :             ,m_nSuspendFlags( _nSuspendFlags )
     242                 :            :         {
     243                 :            :             //DBG_ASSERT( ( m_rTable.m_nRequiredInvariants & m_nSuspendFlags ) == m_nSuspendFlags,
     244                 :            :             //    "SuspendInvariants: cannot suspend what is already suspended!" );
     245                 :            :             const_cast< TableControl_Impl& >( m_rTable ).m_nRequiredInvariants &= ~m_nSuspendFlags;
     246                 :            :         }
     247                 :            :         ~SuspendInvariants()
     248                 :            :         {
     249                 :            :             const_cast< TableControl_Impl& >( m_rTable ).m_nRequiredInvariants |= m_nSuspendFlags;
     250                 :            :         }
     251                 :            :     };
     252                 :            :     #define DBG_SUSPEND_INV( flags ) \
     253                 :            :         SuspendInvariants aSuspendInv( *this, flags );
     254                 :            : #else
     255                 :            :     #define DBG_SUSPEND_INV( flags )
     256                 :            : #endif
     257                 :            : 
     258                 :            : #if DBG_UTIL
     259                 :            :     //====================================================================
     260                 :            :     const char* TableControl_Impl_checkInvariants( const void* _pInstance )
     261                 :            :     {
     262                 :            :         return static_cast< const TableControl_Impl* >( _pInstance )->impl_checkInvariants();
     263                 :            :     }
     264                 :            : 
     265                 :            :     namespace
     266                 :            :     {
     267                 :            :         template< typename SCALAR_TYPE >
     268                 :            :         bool lcl_checkLimitsExclusive( SCALAR_TYPE _nValue, SCALAR_TYPE _nMin, SCALAR_TYPE _nMax )
     269                 :            :         {
     270                 :            :             return ( _nValue > _nMin ) && ( _nValue < _nMax );
     271                 :            :         }
     272                 :            : 
     273                 :            :         template< typename SCALAR_TYPE >
     274                 :            :         bool lcl_checkLimitsExclusive_OrDefault_OrFallback( SCALAR_TYPE _nValue, SCALAR_TYPE _nMin, SCALAR_TYPE _nMax,
     275                 :            :             PTableModel _pModel, SCALAR_TYPE _nDefaultOrFallback )
     276                 :            :         {
     277                 :            :             if ( !_pModel )
     278                 :            :                 return _nValue == _nDefaultOrFallback;
     279                 :            :             if ( _nMax <= _nMin )
     280                 :            :                 return _nDefaultOrFallback == _nValue;
     281                 :            :             return lcl_checkLimitsExclusive( _nValue, _nMin, _nMax );
     282                 :            :         }
     283                 :            :     }
     284                 :            : 
     285                 :            :     //------------------------------------------------------------------------------------------------------------------
     286                 :            :     const sal_Char* TableControl_Impl::impl_checkInvariants() const
     287                 :            :     {
     288                 :            :         if ( !m_pModel )
     289                 :            :             return "no model, not even an EmptyTableModel";
     290                 :            : 
     291                 :            :         if ( !m_pDataWindow )
     292                 :            :             return "invalid data window!";
     293                 :            : 
     294                 :            :         if ( m_pModel->getColumnCount() != m_nColumnCount )
     295                 :            :             return "column counts are inconsistent!";
     296                 :            : 
     297                 :            :         if ( m_pModel->getRowCount() != m_nRowCount )
     298                 :            :             return "row counts are inconsistent!";
     299                 :            : 
     300                 :            :         if ( ( ( m_nCurColumn != COL_INVALID ) && !m_aColumnWidths.empty() && ( m_nCurColumn < 0 ) ) || ( m_nCurColumn >= (ColPos)m_aColumnWidths.size() ) )
     301                 :            :             return "current column is invalid!";
     302                 :            : 
     303                 :            :         if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nTopRow, (RowPos)-1, m_nRowCount, getModel(), (RowPos)0 ) )
     304                 :            :             return "invalid top row value!";
     305                 :            : 
     306                 :            :         if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nCurRow, (RowPos)-1, m_nRowCount, getModel(), ROW_INVALID ) )
     307                 :            :             return "invalid current row value!";
     308                 :            : 
     309                 :            :         if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nLeftColumn, (ColPos)-1, m_nColumnCount, getModel(), (ColPos)0 ) )
     310                 :            :             return "invalid current column value!";
     311                 :            : 
     312                 :            :         if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nCurColumn, (ColPos)-1, m_nColumnCount, getModel(), COL_INVALID ) )
     313                 :            :             return "invalid current column value!";
     314                 :            : 
     315                 :            :         if  ( m_pInputHandler != m_pModel->getInputHandler() )
     316                 :            :             return "input handler is not the model-provided one!";
     317                 :            : 
     318                 :            :         // m_aSelectedRows should have reasonable content
     319                 :            :         {
     320                 :            :             if ( m_aSelectedRows.size() > size_t( m_pModel->getRowCount() ) )
     321                 :            :                 return "there are more rows selected than actually exist";
     322                 :            :             for (   ::std::vector< RowPos >::const_iterator selRow = m_aSelectedRows.begin();
     323                 :            :                     selRow != m_aSelectedRows.end();
     324                 :            :                     ++selRow
     325                 :            :                 )
     326                 :            :             {
     327                 :            :                 if ( ( *selRow < 0 ) || ( *selRow >= m_pModel->getRowCount() ) )
     328                 :            :                     return "a non-existent row is selected";
     329                 :            :             }
     330                 :            :         }
     331                 :            : 
     332                 :            :         // m_nColHeaderHeightPixel consistent with the model's value?
     333                 :            :         {
     334                 :            :             TableMetrics nHeaderHeight = m_pModel->hasColumnHeaders() ? m_pModel->getColumnHeaderHeight() : 0;
     335                 :            :             nHeaderHeight = m_rAntiImpl.LogicToPixel( Size( 0, nHeaderHeight ), MAP_APPFONT ).Height();
     336                 :            :             if ( nHeaderHeight != m_nColHeaderHeightPixel )
     337                 :            :                 return "column header heights are inconsistent!";
     338                 :            :         }
     339                 :            : 
     340                 :            :         bool isDummyModel = dynamic_cast< const EmptyTableModel* >( m_pModel.get() ) != NULL;
     341                 :            :         if ( !isDummyModel )
     342                 :            :         {
     343                 :            :             TableMetrics nRowHeight = m_pModel->getRowHeight();
     344                 :            :             nRowHeight = m_rAntiImpl.LogicToPixel( Size( 0, nRowHeight ), MAP_APPFONT).Height();
     345                 :            :             if ( nRowHeight != m_nRowHeightPixel )
     346                 :            :                 return "row heights are inconsistent!";
     347                 :            :         }
     348                 :            : 
     349                 :            :         // m_nRowHeaderWidthPixel consistent with the model's value?
     350                 :            :         {
     351                 :            :             TableMetrics nHeaderWidth = m_pModel->hasRowHeaders() ? m_pModel->getRowHeaderWidth() : 0;
     352                 :            :             nHeaderWidth = m_rAntiImpl.LogicToPixel( Size( nHeaderWidth, 0 ), MAP_APPFONT ).Width();
     353                 :            :             if ( nHeaderWidth != m_nRowHeaderWidthPixel )
     354                 :            :                 return "row header widths are inconsistent!";
     355                 :            :         }
     356                 :            : 
     357                 :            :         // m_aColumnWidths consistency
     358                 :            :         if ( size_t( m_nColumnCount ) != m_aColumnWidths.size() )
     359                 :            :             return "wrong number of cached column widths";
     360                 :            : 
     361                 :            :         for (   ColumnPositions::const_iterator col = m_aColumnWidths.begin();
     362                 :            :                 col != m_aColumnWidths.end();
     363                 :            :             )
     364                 :            :         {
     365                 :            :             if ( col->getEnd() < col->getStart() )
     366                 :            :                 return "column widths: 'end' is expected to not be smaller than start";
     367                 :            : 
     368                 :            :             ColumnPositions::const_iterator nextCol = col + 1;
     369                 :            :             if ( nextCol != m_aColumnWidths.end() )
     370                 :            :                 if ( col->getEnd() != nextCol->getStart() )
     371                 :            :                     return "column widths: one column's end should be the next column's start";
     372                 :            :             col = nextCol;
     373                 :            :         }
     374                 :            : 
     375                 :            :         if ( m_nLeftColumn < m_nColumnCount )
     376                 :            :             if ( m_aColumnWidths[ m_nLeftColumn ].getStart() != m_nRowHeaderWidthPixel )
     377                 :            :                 return "the left-most column should start immediately after the row header";
     378                 :            : 
     379                 :            :         if ( m_nCursorHidden < 0 )
     380                 :            :             return "invalid hidden count for the cursor!";
     381                 :            : 
     382                 :            :         if ( ( m_nRequiredInvariants & INV_SCROLL_POSITION ) && m_pVScroll )
     383                 :            :         {
     384                 :            :             DBG_SUSPEND_INV( INV_SCROLL_POSITION );
     385                 :            :                 // prevent infinite recursion
     386                 :            : 
     387                 :            :             if ( m_nLeftColumn < 0 )
     388                 :            :                 return "invalid left-most column index";
     389                 :            :             if ( m_pVScroll->GetThumbPos() != m_nTopRow )
     390                 :            :                 return "vertical scroll bar |position| is incorrect!";
     391                 :            :             if ( m_pVScroll->GetRange().Max() != m_nRowCount )
     392                 :            :                 return "vertical scroll bar |range| is incorrect!";
     393                 :            :             if ( m_pVScroll->GetVisibleSize() != impl_getVisibleRows( false ) )
     394                 :            :                 return "vertical scroll bar |visible size| is incorrect!";
     395                 :            :         }
     396                 :            : 
     397                 :            :         if ( ( m_nRequiredInvariants & INV_SCROLL_POSITION ) && m_pHScroll )
     398                 :            :         {
     399                 :            :             DBG_SUSPEND_INV( INV_SCROLL_POSITION );
     400                 :            :                 // prevent infinite recursion
     401                 :            : 
     402                 :            :             if ( m_pHScroll->GetThumbPos() != m_nLeftColumn )
     403                 :            :                 return "horizontal scroll bar |position| is incorrect!";
     404                 :            :             if ( m_pHScroll->GetRange().Max() != m_nColumnCount )
     405                 :            :                 return "horizontal scroll bar |range| is incorrect!";
     406                 :            :             if ( m_pHScroll->GetVisibleSize() != impl_getVisibleColumns( false ) )
     407                 :            :                 return "horizontal scroll bar |visible size| is incorrect!";
     408                 :            :         }
     409                 :            : 
     410                 :            :         return NULL;
     411                 :            :     }
     412                 :            : #endif
     413                 :            : 
     414                 :            : #define DBG_CHECK_ME() \
     415                 :            :     DBG_CHKTHIS( TableControl_Impl, TableControl_Impl_checkInvariants )
     416                 :            : 
     417                 :            :     //------------------------------------------------------------------------------------------------------------------
     418                 :          0 :     TableControl_Impl::TableControl_Impl( TableControl& _rAntiImpl )
     419                 :            :         :m_rAntiImpl            ( _rAntiImpl                    )
     420                 :          0 :         ,m_pModel               ( new EmptyTableModel           )
     421                 :            :         ,m_pInputHandler        (                               )
     422                 :            :         ,m_nRowHeightPixel      ( 15                            )
     423                 :            :         ,m_nColHeaderHeightPixel( 0                             )
     424                 :            :         ,m_nRowHeaderWidthPixel ( 0                             )
     425                 :            :         ,m_nColumnCount         ( 0                             )
     426                 :            :         ,m_nRowCount            ( 0                             )
     427                 :            :         ,m_bColumnsFit          ( true                          )
     428                 :            :         ,m_nCurColumn           ( COL_INVALID                   )
     429                 :            :         ,m_nCurRow              ( ROW_INVALID                   )
     430                 :            :         ,m_nLeftColumn          ( 0                             )
     431                 :            :         ,m_nTopRow              ( 0                             )
     432                 :            :         ,m_nCursorHidden        ( 1                             )
     433         [ #  # ]:          0 :         ,m_pDataWindow          ( new TableDataWindow( *this )  )
     434                 :            :         ,m_pVScroll             ( NULL                          )
     435                 :            :         ,m_pHScroll             ( NULL                          )
     436                 :            :         ,m_pScrollCorner        ( NULL                          )
     437                 :            :         ,m_pSelEngine           (                               )
     438                 :            :         ,m_aSelectedRows        (                               )
     439         [ #  # ]:          0 :         ,m_pTableFunctionSet    ( new TableFunctionSet( this  ) )
     440                 :            :         ,m_nAnchor              ( -1                            )
     441                 :            :         ,m_bUpdatingColWidths   ( false                         )
     442         [ #  # ]:          0 :         ,m_pAccessibleTable     ( NULL                          )
           [ #  #  #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     443                 :            : #if DBG_UTIL
     444                 :            :         ,m_nRequiredInvariants ( INV_SCROLL_POSITION )
     445                 :            : #endif
     446                 :            :     {
     447                 :            :         DBG_CTOR( TableControl_Impl, TableControl_Impl_checkInvariants );
     448 [ #  # ][ #  # ]:          0 :         m_pSelEngine = new SelectionEngine( m_pDataWindow.get(), m_pTableFunctionSet );
     449         [ #  # ]:          0 :         m_pSelEngine->SetSelectionMode(SINGLE_SELECTION);
     450         [ #  # ]:          0 :         m_pDataWindow->SetPosPixel( Point( 0, 0 ) );
     451         [ #  # ]:          0 :         m_pDataWindow->Show();
     452                 :          0 :     }
     453                 :            : 
     454                 :            :     //------------------------------------------------------------------------------------------------------------------
     455 [ #  # ][ #  # ]:          0 :     TableControl_Impl::~TableControl_Impl()
         [ #  # ][ #  # ]
                 [ #  # ]
     456                 :            :     {
     457                 :            :         DBG_DTOR( TableControl_Impl, TableControl_Impl_checkInvariants );
     458                 :            : 
     459 [ #  # ][ #  # ]:          0 :         DELETEZ( m_pVScroll );
     460 [ #  # ][ #  # ]:          0 :         DELETEZ( m_pHScroll );
     461 [ #  # ][ #  # ]:          0 :         DELETEZ( m_pScrollCorner );
     462 [ #  # ][ #  # ]:          0 :         DELETEZ( m_pTableFunctionSet );
     463 [ #  # ][ #  # ]:          0 :         DELETEZ( m_pSelEngine );
     464         [ #  # ]:          0 :     }
     465                 :            : 
     466                 :            :     //------------------------------------------------------------------------------------------------------------------
     467                 :          0 :     void TableControl_Impl::setModel( PTableModel _pModel )
     468                 :            :     {
     469                 :            :         DBG_CHECK_ME();
     470                 :            : 
     471         [ #  # ]:          0 :         SuppressCursor aHideCursor( *this );
     472                 :            : 
     473         [ #  # ]:          0 :         if ( !!m_pModel )
     474 [ #  # ][ #  # ]:          0 :             m_pModel->removeTableModelListener( shared_from_this() );
                 [ #  # ]
     475                 :            : 
     476         [ #  # ]:          0 :         m_pModel = _pModel;
     477         [ #  # ]:          0 :         if ( !m_pModel)
     478 [ #  # ][ #  # ]:          0 :             m_pModel.reset( new EmptyTableModel );
     479                 :            : 
     480 [ #  # ][ #  # ]:          0 :         m_pModel->addTableModelListener( shared_from_this() );
                 [ #  # ]
     481                 :            : 
     482                 :          0 :         m_nCurRow = ROW_INVALID;
     483                 :          0 :         m_nCurColumn = COL_INVALID;
     484                 :            : 
     485                 :            :         // recalc some model-dependent cached info
     486         [ #  # ]:          0 :         impl_ni_updateCachedModelValues();
     487         [ #  # ]:          0 :         impl_ni_updateScrollbars();
     488                 :            : 
     489                 :            :         // completely invalidate
     490         [ #  # ]:          0 :         m_rAntiImpl.Invalidate();
     491                 :            : 
     492                 :            :         // reset cursor to (0,0)
     493         [ #  # ]:          0 :         if ( m_nRowCount ) m_nCurRow = 0;
     494 [ #  # ][ #  # ]:          0 :         if ( m_nColumnCount ) m_nCurColumn = 0;
     495                 :          0 :     }
     496                 :            : 
     497                 :            :     //------------------------------------------------------------------------------------------------------------------
     498                 :            :     namespace
     499                 :            :     {
     500                 :          0 :         bool lcl_adjustSelectedRows( ::std::vector< RowPos >& io_selectionIndexes, RowPos const i_firstAffectedRowIndex, TableSize const i_offset )
     501                 :            :         {
     502                 :          0 :             bool didChanges = false;
     503   [ #  #  #  # ]:          0 :             for (   ::std::vector< RowPos >::iterator selPos = io_selectionIndexes.begin();
                 [ #  # ]
     504                 :          0 :                     selPos != io_selectionIndexes.end();
     505                 :            :                     ++selPos
     506                 :            :                 )
     507                 :            :             {
     508 [ #  # ][ #  # ]:          0 :                 if ( *selPos < i_firstAffectedRowIndex )
     509                 :          0 :                     continue;
     510         [ #  # ]:          0 :                 *selPos += i_offset;
     511                 :          0 :                 didChanges = true;
     512                 :            :             }
     513                 :          0 :             return didChanges;
     514                 :            :         }
     515                 :            :     }
     516                 :            : 
     517                 :            :     //------------------------------------------------------------------------------------------------------------------
     518                 :          0 :     void TableControl_Impl::rowsInserted( RowPos i_first, RowPos i_last )
     519                 :            :     {
     520                 :            :         DBG_CHECK_ME();
     521                 :            :         OSL_PRECOND( i_last >= i_first, "TableControl_Impl::rowsInserted: invalid row indexes!" );
     522                 :            : 
     523                 :          0 :         TableSize const insertedRows = i_last - i_first + 1;
     524                 :            : 
     525                 :            :         // adjust selection, if necessary
     526                 :          0 :         bool const selectionChanged = lcl_adjustSelectedRows( m_aSelectedRows, i_first, insertedRows );
     527                 :            : 
     528                 :            :         // adjust our cached row count
     529                 :          0 :         m_nRowCount = m_pModel->getRowCount();
     530                 :            : 
     531                 :            :         // if the rows have been inserted before the current row, adjust this
     532         [ #  # ]:          0 :         if ( i_first <= m_nCurRow )
     533                 :          0 :             goTo( m_nCurColumn, m_nCurRow + insertedRows );
     534                 :            : 
     535                 :            :         // adjust scrollbars
     536                 :          0 :         impl_ni_updateScrollbars();
     537                 :            : 
     538                 :            :         // notify A1YY events
     539         [ #  # ]:          0 :         if ( impl_isAccessibleAlive() )
     540                 :            :         {
     541                 :            :             impl_commitAccessibleEvent( AccessibleEventId::TABLE_MODEL_CHANGED,
     542         [ #  # ]:          0 :                 makeAny( AccessibleTableModelChange( AccessibleTableModelChangeType::INSERT, i_first, i_last, 0, m_pModel->getColumnCount() ) ),
     543                 :            :                 Any()
     544 [ #  # ][ #  # ]:          0 :             );
     545                 :            :             impl_commitAccessibleEvent( AccessibleEventId::CHILD,
     546                 :          0 :                  makeAny( m_pAccessibleTable->getTableHeader( TCTYPE_ROWHEADERBAR ) ),
     547                 :            :                 Any()
     548 [ #  # ][ #  # ]:          0 :             );
                 [ #  # ]
     549                 :            : 
     550                 :            : //          for ( sal_Int32 i = 0 ; i <= m_pModel->getColumnCount(); ++i )
     551                 :            : //          {
     552                 :            : //              impl_commitAccessibleEvent(
     553                 :            : //                    CHILD,
     554                 :            : //                  makeAny( m_pAccessibleTable->getTable() ),
     555                 :            : //                  Any());
     556                 :            : //          }
     557                 :            :             // Huh? What's that? We're notifying |columnCount| CHILD events here, claiming the *table* itself
     558                 :            :             // has been inserted. Doesn't make much sense, does it?
     559                 :            :         }
     560                 :            : 
     561                 :            :         // schedule repaint
     562                 :          0 :         invalidateRowRange( i_first, ROW_INVALID );
     563                 :            : 
     564                 :            :         // call selection handlers, if necessary
     565         [ #  # ]:          0 :         if ( selectionChanged )
     566                 :          0 :             m_rAntiImpl.Select();
     567                 :          0 :     }
     568                 :            : 
     569                 :            :     //------------------------------------------------------------------------------------------------------------------
     570                 :          0 :     void TableControl_Impl::rowsRemoved( RowPos i_first, RowPos i_last )
     571                 :            :     {
     572                 :          0 :         sal_Int32 firstRemovedRow = i_first;
     573                 :          0 :         sal_Int32 lastRemovedRow = i_last;
     574                 :            : 
     575                 :            :         // adjust selection, if necessary
     576                 :          0 :         bool selectionChanged = false;
     577         [ #  # ]:          0 :         if ( i_first == -1 )
     578                 :            :         {
     579                 :          0 :             selectionChanged = markAllRowsAsDeselected();
     580                 :            : 
     581                 :          0 :             firstRemovedRow = 0;
     582                 :          0 :             lastRemovedRow = m_nRowCount - 1;
     583                 :            :         }
     584                 :            :         else
     585                 :            :         {
     586         [ #  # ]:          0 :             ENSURE_OR_RETURN_VOID( i_last >= i_first, "TableControl_Impl::rowsRemoved: illegal indexes!" );
     587                 :            : 
     588         [ #  # ]:          0 :             for ( sal_Int32 row = i_first; row <= i_last; ++row )
     589                 :            :             {
     590 [ #  # ][ #  # ]:          0 :                 if ( markRowAsDeselected( row ) )
     591                 :          0 :                     selectionChanged = true;
     592                 :            :             }
     593                 :            : 
     594 [ #  # ][ #  # ]:          0 :             if ( lcl_adjustSelectedRows( m_aSelectedRows, i_last + 1, i_first - i_last - 1 ) )
     595                 :          0 :                 selectionChanged = true;
     596                 :            :         }
     597                 :            : 
     598                 :            :         // adjust cached row count
     599         [ #  # ]:          0 :         m_nRowCount = m_pModel->getRowCount();
     600                 :            : 
     601                 :            :         // adjust the current row, if it is larger than the row count now
     602         [ #  # ]:          0 :         if ( m_nCurRow >= m_nRowCount )
     603                 :            :         {
     604         [ #  # ]:          0 :             if ( m_nRowCount > 0 )
     605         [ #  # ]:          0 :                 goTo( m_nCurColumn, m_nRowCount - 1 );
     606                 :            :             else
     607                 :          0 :                 m_nCurRow = ROW_INVALID;
     608                 :            :         }
     609                 :            : 
     610                 :            :         // adjust scrollbars
     611         [ #  # ]:          0 :         impl_ni_updateScrollbars();
     612                 :            : 
     613                 :            :         // notify A11Y events
     614 [ #  # ][ #  # ]:          0 :         if ( impl_isAccessibleAlive() )
     615                 :            :         {
     616                 :            :             impl_commitAccessibleEvent(
     617                 :            :                 AccessibleEventId::TABLE_MODEL_CHANGED,
     618                 :            :                 makeAny( AccessibleTableModelChange(
     619                 :            :                     AccessibleTableModelChangeType::DELETE,
     620                 :            :                     firstRemovedRow,
     621                 :            :                     lastRemovedRow,
     622                 :            :                     0,
     623         [ #  # ]:          0 :                     m_pModel->getColumnCount()
     624                 :            :                 ) ),
     625                 :            :                 Any()
     626 [ #  # ][ #  # ]:          0 :             );
     627                 :            :         }
     628                 :            : 
     629                 :            :         // schedule a repaint
     630         [ #  # ]:          0 :         invalidateRowRange( firstRemovedRow, ROW_INVALID );
     631                 :            : 
     632                 :            :         // call selection handlers, if necessary
     633         [ #  # ]:          0 :         if ( selectionChanged )
     634         [ #  # ]:          0 :             m_rAntiImpl.Select();
     635                 :            :     }
     636                 :            : 
     637                 :            :     //------------------------------------------------------------------------------------------------------------------
     638                 :          0 :     void TableControl_Impl::columnInserted( ColPos const i_colIndex )
     639                 :            :     {
     640                 :          0 :         m_nColumnCount = m_pModel->getColumnCount();
     641                 :          0 :         impl_ni_updateColumnWidths();
     642                 :          0 :         impl_ni_updateScrollbars();
     643                 :            : 
     644                 :          0 :         m_rAntiImpl.Invalidate();
     645                 :            : 
     646                 :            :         OSL_UNUSED( i_colIndex );
     647                 :          0 :    }
     648                 :            : 
     649                 :            :     //------------------------------------------------------------------------------------------------------------------
     650                 :          0 :     void TableControl_Impl::columnRemoved( ColPos const i_colIndex )
     651                 :            :     {
     652                 :          0 :         m_nColumnCount = m_pModel->getColumnCount();
     653                 :          0 :         impl_ni_updateColumnWidths();
     654                 :          0 :         impl_ni_updateScrollbars();
     655                 :            : 
     656                 :          0 :         m_rAntiImpl.Invalidate();
     657                 :            : 
     658                 :            :         OSL_UNUSED( i_colIndex );
     659                 :          0 :     }
     660                 :            : 
     661                 :            :     //------------------------------------------------------------------------------------------------------------------
     662                 :          0 :     void TableControl_Impl::allColumnsRemoved()
     663                 :            :     {
     664                 :          0 :         m_nColumnCount = m_pModel->getColumnCount();
     665                 :          0 :         impl_ni_updateColumnWidths();
     666                 :          0 :         impl_ni_updateScrollbars();
     667                 :            : 
     668                 :          0 :         m_rAntiImpl.Invalidate();
     669                 :          0 :     }
     670                 :            : 
     671                 :            :     //------------------------------------------------------------------------------------------------------------------
     672                 :          0 :     void TableControl_Impl::cellsUpdated( ColPos const i_firstCol, ColPos i_lastCol, RowPos const i_firstRow, RowPos const i_lastRow )
     673                 :            :     {
     674                 :          0 :         invalidateRowRange( i_firstRow, i_lastRow );
     675                 :            : 
     676                 :            :         OSL_UNUSED( i_firstCol );
     677                 :            :         OSL_UNUSED( i_lastCol );
     678                 :          0 :     }
     679                 :            : 
     680                 :            :     //------------------------------------------------------------------------------------------------------------------
     681                 :          0 :     void TableControl_Impl::tableMetricsChanged()
     682                 :            :     {
     683                 :          0 :         long const oldRowHeaderWidthPixel = m_nRowHeaderWidthPixel;
     684                 :          0 :         impl_ni_updateCachedTableMetrics();
     685         [ #  # ]:          0 :         if ( oldRowHeaderWidthPixel != m_nRowHeaderWidthPixel )
     686                 :          0 :             impl_ni_updateColumnWidths();
     687                 :          0 :         impl_ni_updateScrollbars();
     688                 :          0 :         m_rAntiImpl.Invalidate();
     689                 :          0 :     }
     690                 :            : 
     691                 :            :     //------------------------------------------------------------------------------------------------------------------
     692                 :          0 :     void TableControl_Impl::impl_invalidateColumn( ColPos const i_column )
     693                 :            :     {
     694                 :            :         DBG_CHECK_ME();
     695                 :            : 
     696         [ #  # ]:          0 :         Rectangle const aAllCellsArea( impl_getAllVisibleCellsArea() );
     697                 :            : 
     698         [ #  # ]:          0 :         const TableColumnGeometry aColumn( *this, aAllCellsArea, i_column );
     699 [ #  # ][ #  # ]:          0 :         if ( aColumn.isValid() )
     700         [ #  # ]:          0 :             m_rAntiImpl.Invalidate( aColumn.getRect() );
     701                 :          0 :     }
     702                 :            : 
     703                 :            :     //------------------------------------------------------------------------------------------------------------------
     704                 :          0 :     void TableControl_Impl::columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup )
     705                 :            :     {
     706                 :          0 :         ColumnAttributeGroup nGroup( i_attributeGroup );
     707         [ #  # ]:          0 :         if ( nGroup & COL_ATTRS_APPEARANCE )
     708                 :            :         {
     709                 :          0 :             impl_invalidateColumn( i_column );
     710                 :          0 :             nGroup &= ~COL_ATTRS_APPEARANCE;
     711                 :            :         }
     712                 :            : 
     713         [ #  # ]:          0 :         if ( nGroup & COL_ATTRS_WIDTH )
     714                 :            :         {
     715         [ #  # ]:          0 :             if ( !m_bUpdatingColWidths )
     716                 :            :             {
     717                 :          0 :                 impl_ni_updateColumnWidths( i_column );
     718                 :          0 :                 invalidate( TableAreaAll );
     719                 :          0 :                 impl_ni_updateScrollbars();
     720                 :            :             }
     721                 :            : 
     722                 :          0 :             nGroup &= ~COL_ATTRS_WIDTH;
     723                 :            :         }
     724                 :            : 
     725                 :            :         OSL_ENSURE( ( nGroup == COL_ATTRS_NONE ) || ( i_attributeGroup == COL_ATTRS_ALL ),
     726                 :            :             "TableControl_Impl::columnChanged: don't know how to handle this change!" );
     727                 :          0 :     }
     728                 :            : 
     729                 :            :     //------------------------------------------------------------------------------------------------------------------
     730                 :          0 :     Rectangle TableControl_Impl::impl_getAllVisibleCellsArea() const
     731                 :            :     {
     732                 :            :         DBG_CHECK_ME();
     733                 :            : 
     734         [ #  # ]:          0 :         Rectangle aArea( Point( 0, 0 ), Size( 0, 0 ) );
     735                 :            : 
     736                 :            :         // determine the right-most border of the last column which is
     737                 :            :         // at least partially visible
     738                 :          0 :         aArea.Right() = m_nRowHeaderWidthPixel;
     739         [ #  # ]:          0 :         if ( !m_aColumnWidths.empty() )
     740                 :            :         {
     741                 :            :             // the number of pixels which are scrolled out of the left hand
     742                 :            :             // side of the window
     743         [ #  # ]:          0 :             const long nScrolledOutLeft = m_nLeftColumn == 0 ? 0 : m_aColumnWidths[ m_nLeftColumn - 1 ].getEnd();
     744                 :            : 
     745                 :          0 :             ColumnPositions::const_reverse_iterator loop = m_aColumnWidths.rbegin();
     746   [ #  #  #  # ]:          0 :             do
                 [ #  # ]
     747                 :            :             {
     748         [ #  # ]:          0 :                 aArea.Right() = loop->getEnd() - nScrolledOutLeft + m_nRowHeaderWidthPixel;
     749         [ #  # ]:          0 :                 ++loop;
     750                 :            :             }
     751 [ #  # ][ #  # ]:          0 :             while ( (   loop != m_aColumnWidths.rend() )
                 [ #  # ]
     752         [ #  # ]:          0 :                  && (   loop->getEnd() - nScrolledOutLeft >= aArea.Right() )
     753                 :            :                  );
     754                 :            :         }
     755                 :            :         // so far, aArea.Right() denotes the first pixel *after* the cell area
     756                 :          0 :         --aArea.Right();
     757                 :            : 
     758                 :            :         // determine the last row which is at least partially visible
     759                 :          0 :         aArea.Bottom() =
     760                 :            :                 m_nColHeaderHeightPixel
     761                 :          0 :             +   impl_getVisibleRows( true ) * m_nRowHeightPixel
     762                 :          0 :             -   1;
     763                 :            : 
     764                 :          0 :         return aArea;
     765                 :            :     }
     766                 :            : 
     767                 :            :     //------------------------------------------------------------------------------------------------------------------
     768                 :          0 :     Rectangle TableControl_Impl::impl_getAllVisibleDataCellArea() const
     769                 :            :     {
     770                 :            :         DBG_CHECK_ME();
     771                 :            : 
     772                 :          0 :         Rectangle aArea( impl_getAllVisibleCellsArea() );
     773                 :          0 :         aArea.Left() = m_nRowHeaderWidthPixel;
     774                 :          0 :         aArea.Top() = m_nColHeaderHeightPixel;
     775                 :          0 :         return aArea;
     776                 :            :     }
     777                 :            : 
     778                 :            :     //------------------------------------------------------------------------------------------------------------------
     779                 :          0 :     void TableControl_Impl::impl_ni_updateCachedTableMetrics()
     780                 :            :     {
     781 [ #  # ][ #  # ]:          0 :         m_nRowHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getRowHeight() ), MAP_APPFONT ).Height();
     782                 :            : 
     783                 :          0 :         m_nColHeaderHeightPixel = 0;
     784         [ #  # ]:          0 :         if ( m_pModel->hasColumnHeaders() )
     785 [ #  # ][ #  # ]:          0 :            m_nColHeaderHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getColumnHeaderHeight() ), MAP_APPFONT ).Height();
     786                 :            : 
     787                 :          0 :         m_nRowHeaderWidthPixel = 0;
     788         [ #  # ]:          0 :         if ( m_pModel->hasRowHeaders() )
     789 [ #  # ][ #  # ]:          0 :             m_nRowHeaderWidthPixel = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT).Width();
     790                 :          0 :     }
     791                 :            : 
     792                 :            :     //------------------------------------------------------------------------------------------------------------------
     793                 :          0 :     void TableControl_Impl::impl_ni_updateCachedModelValues()
     794                 :            :     {
     795                 :          0 :         m_pInputHandler.reset();
     796                 :          0 :         m_nColumnCount = m_nRowCount = 0;
     797                 :            : 
     798                 :          0 :         impl_ni_updateCachedTableMetrics();
     799                 :          0 :         impl_ni_updateColumnWidths();
     800                 :            : 
     801         [ #  # ]:          0 :         m_pInputHandler = m_pModel->getInputHandler();
     802         [ #  # ]:          0 :         if ( !m_pInputHandler )
     803         [ #  # ]:          0 :             m_pInputHandler.reset( new DefaultInputHandler );
     804                 :            : 
     805                 :          0 :         m_nColumnCount = m_pModel->getColumnCount();
     806                 :          0 :         m_nRowCount = m_pModel->getRowCount();
     807                 :          0 :     }
     808                 :            : 
     809                 :            :     //------------------------------------------------------------------------------------------------------------------
     810                 :          0 :     void TableControl_Impl::impl_ni_updateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding )
     811                 :            :     {
     812         [ #  # ]:          0 :         ENSURE_OR_RETURN_VOID( !m_bUpdatingColWidths, "TableControl_Impl::impl_ni_updateColumnWidths: recursive call detected!" );
     813                 :            : 
     814         [ #  # ]:          0 :         m_aColumnWidths.resize( 0 );
     815         [ #  # ]:          0 :         if ( !m_pModel )
     816                 :            :             return;
     817                 :            : 
     818         [ #  # ]:          0 :         const TableSize colCount = m_pModel->getColumnCount();
     819         [ #  # ]:          0 :         if ( colCount == 0 )
     820                 :            :             return;
     821                 :            : 
     822                 :          0 :         m_bUpdatingColWidths = true;
     823         [ #  # ]:          0 :         const ::comphelper::FlagGuard aWidthUpdateFlag( m_bUpdatingColWidths );
     824                 :            : 
     825         [ #  # ]:          0 :         m_aColumnWidths.reserve( colCount );
     826                 :            : 
     827                 :            :         // the available horizontal space
     828                 :          0 :         long gridWidthPixel = m_rAntiImpl.GetOutputSizePixel().Width();
     829 [ #  # ][ #  # ]:          0 :         if ( m_pModel->hasRowHeaders() && ( gridWidthPixel != 0 ) )
         [ #  # ][ #  # ]
     830                 :            :         {
     831                 :          0 :             gridWidthPixel -= m_nRowHeaderWidthPixel;
     832                 :            :         }
     833 [ #  # ][ #  # ]:          0 :         if ( m_pModel->getVerticalScrollbarVisibility() != ScrollbarShowNever )
     834                 :            :         {
     835                 :          0 :             long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
     836                 :          0 :             gridWidthPixel -= nScrollbarMetrics;
     837                 :            :         }
     838                 :            : 
     839                 :            :         // TODO: shouldn't we take the visibility of the vertical scroll bar into account here, too?
     840 [ #  # ][ #  # ]:          0 :         long const gridWidthAppFont = m_rAntiImpl.PixelToLogic( Size( gridWidthPixel, 0 ), MAP_APPFONT ).Width();
                 [ #  # ]
     841                 :            : 
     842                 :            :         // determine the accumulated current width of all columns
     843         [ #  # ]:          0 :         for ( ColPos col = 0; col < colCount; ++col )
     844                 :            :         {
     845         [ #  # ]:          0 :             const PColumnModel pColumn = m_pModel->getColumnModel( col );
     846 [ #  # ][ #  # ]:          0 :             ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
         [ #  # ][ #  # ]
     847                 :            : 
     848         [ #  # ]:          0 :         }
     849                 :            : 
     850                 :            :         // collect some meta data for our columns:
     851                 :            :         // - their current (appt-font) metrics
     852                 :          0 :         long accumulatedCurrentWidth = 0;
     853         [ #  # ]:          0 :         ::std::vector< long > currentColWidths;
     854         [ #  # ]:          0 :         currentColWidths.reserve( colCount );
     855                 :            :         // - their effective minimal and maximal width (app-font!)
     856                 :            :         typedef ::std::vector< ::std::pair< long, long > >   ColumnLimits;
     857         [ #  # ]:          0 :         ColumnLimits effectiveColumnLimits;
     858         [ #  # ]:          0 :         effectiveColumnLimits.reserve( colCount );
     859                 :          0 :         long accumulatedMinWidth = 0;
     860                 :          0 :         long accumulatedMaxWidth = 0;
     861                 :            :         // - their relative flexibility
     862         [ #  # ]:          0 :         ::std::vector< ::sal_Int32 > columnFlexibilities;
     863         [ #  # ]:          0 :         columnFlexibilities.reserve( colCount );
     864                 :          0 :         long flexibilityDenominator = 0;
     865         [ #  # ]:          0 :         for ( ColPos col = 0; col < colCount; ++col )
     866                 :            :         {
     867         [ #  # ]:          0 :             PColumnModel const pColumn = m_pModel->getColumnModel( col );
     868 [ #  # ][ #  # ]:          0 :             ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
         [ #  # ][ #  # ]
     869                 :            : 
     870                 :            :             // current width
     871         [ #  # ]:          0 :             TableMetrics const currentWidth = pColumn->getWidth();
     872         [ #  # ]:          0 :             currentColWidths.push_back( currentWidth );
     873                 :            : 
     874                 :            :             // accumulated width
     875                 :          0 :             accumulatedCurrentWidth += currentWidth;
     876                 :            : 
     877                 :            :             // flexibility
     878         [ #  # ]:          0 :             ::sal_Int32 flexibility = pColumn->getFlexibility();
     879                 :            :             OSL_ENSURE( flexibility >= 0, "TableControl_Impl::impl_ni_updateColumnWidths: a column's flexibility should be non-negative." );
     880 [ #  # ][ #  # ]:          0 :             if  (   ( flexibility < 0 )                                 // normalization
         [ #  # ][ #  # ]
     881         [ #  # ]:          0 :                 ||  ( !pColumn->isResizable() )                         // column not resizeable => no auto-resize
     882                 :            :                 ||  ( col <= i_assumeInflexibleColumnsUpToIncluding )   // column shall be treated as inflexible => respec this
     883                 :            :                 )
     884                 :          0 :                 flexibility = 0;
     885                 :            : 
     886                 :            :             // min/max width
     887                 :          0 :             long effectiveMin = currentWidth, effectiveMax = currentWidth;
     888                 :            :             // if the column is not flexible, it will not be asked for min/max, but we assume the current width as limit then
     889         [ #  # ]:          0 :             if ( flexibility > 0 )
     890                 :            :             {
     891         [ #  # ]:          0 :                 long const minWidth = pColumn->getMinWidth();
     892         [ #  # ]:          0 :                 if ( minWidth > 0 )
     893                 :          0 :                     effectiveMin = minWidth;
     894                 :            :                 else
     895                 :          0 :                     effectiveMin = MIN_COLUMN_WIDTH_PIXEL;
     896                 :            : 
     897         [ #  # ]:          0 :                 long const maxWidth = pColumn->getMaxWidth();
     898                 :            :                 OSL_ENSURE( minWidth <= maxWidth, "TableControl_Impl::impl_ni_updateColumnWidths: pretty undecided 'bout its width limits, this column!" );
     899 [ #  # ][ #  # ]:          0 :                 if ( ( maxWidth > 0 ) && ( maxWidth >= minWidth ) )
     900                 :          0 :                     effectiveMax = maxWidth;
     901                 :            :                 else
     902                 :          0 :                     effectiveMax = gridWidthAppFont; // TODO: any better guess here?
     903                 :            : 
     904         [ #  # ]:          0 :                 if ( effectiveMin == effectiveMax )
     905                 :            :                     // if the min and the max are identical, this implies no flexibility at all
     906                 :          0 :                     flexibility = 0;
     907                 :            :             }
     908                 :            : 
     909         [ #  # ]:          0 :             columnFlexibilities.push_back( flexibility );
     910                 :          0 :             flexibilityDenominator += flexibility;
     911                 :            : 
     912 [ #  # ][ #  # ]:          0 :             effectiveColumnLimits.push_back( ::std::pair< long, long >( effectiveMin, effectiveMax ) );
     913                 :          0 :             accumulatedMinWidth += effectiveMin;
     914                 :          0 :             accumulatedMaxWidth += effectiveMax;
     915         [ #  # ]:          0 :         }
     916                 :            : 
     917         [ #  # ]:          0 :         ::std::vector< long > newWidths( currentColWidths );
     918         [ #  # ]:          0 :         if ( flexibilityDenominator == 0 )
     919                 :            :         {
     920                 :            :             // no column is flexible => don't adjust anything
     921                 :            :         }
     922         [ #  # ]:          0 :         else if ( gridWidthAppFont > accumulatedCurrentWidth )
     923                 :            :         {   // we have space to give away ...
     924                 :          0 :             long distributeAppFontUnits = gridWidthAppFont - accumulatedCurrentWidth;
     925         [ #  # ]:          0 :             if ( gridWidthAppFont > accumulatedMaxWidth )
     926                 :            :             {
     927                 :            :                 // ... but the column's maximal widths are still less than we have
     928                 :            :                 // => set them all to max
     929         [ #  # ]:          0 :                 for ( size_t i = 0; i < size_t( colCount ); ++i )
     930                 :            :                 {
     931 [ #  # ][ #  # ]:          0 :                     newWidths[i] = effectiveColumnLimits[i].second;
     932                 :            :                 }
     933                 :            :             }
     934                 :            :             else
     935                 :            :             {
     936                 :          0 :                 bool startOver = false;
     937         [ #  # ]:          0 :                 do
     938                 :            :                 {
     939                 :          0 :                     startOver = false;
     940                 :            :                     // distribute the remaining space amongst all columns with a positive flexibility
     941 [ #  # ][ #  # ]:          0 :                     for ( size_t i=0; i<newWidths.size() && !startOver; ++i )
                 [ #  # ]
     942                 :            :                     {
     943         [ #  # ]:          0 :                         long const columnFlexibility = columnFlexibilities[i];
     944         [ #  # ]:          0 :                         if ( columnFlexibility == 0 )
     945                 :          0 :                             continue;
     946                 :            : 
     947         [ #  # ]:          0 :                         long newColWidth = currentColWidths[i] + columnFlexibility * distributeAppFontUnits / flexibilityDenominator;
     948                 :            : 
     949 [ #  # ][ #  # ]:          0 :                         if ( newColWidth > effectiveColumnLimits[i].second )
     950                 :            :                         {   // that was too much, we hit the col's maximum
     951                 :            :                             // set the new width to exactly this maximum
     952         [ #  # ]:          0 :                             newColWidth = effectiveColumnLimits[i].second;
     953                 :            :                             // adjust the flexibility denominator ...
     954                 :          0 :                             flexibilityDenominator -= columnFlexibility;
     955         [ #  # ]:          0 :                             columnFlexibilities[i] = 0;
     956                 :            :                             // ... and the remaining width ...
     957         [ #  # ]:          0 :                             long const difference = newColWidth - currentColWidths[i];
     958                 :          0 :                             distributeAppFontUnits -= difference;
     959                 :            :                             // ... this way, we ensure that the width not taken up by this column is consumed by the other
     960                 :            :                             // flexible ones (if there are some)
     961                 :            : 
     962                 :            :                             // and start over with the first column, since there might be earlier columns which need
     963                 :            :                             // to be recalculated now
     964                 :          0 :                             startOver = true;
     965                 :            :                         }
     966                 :            : 
     967         [ #  # ]:          0 :                         newWidths[i] = newColWidth;
     968                 :            :                     }
     969                 :            :                 }
     970                 :            :                 while ( startOver );
     971                 :            :             }
     972                 :            :         }
     973         [ #  # ]:          0 :         else if ( gridWidthAppFont < accumulatedCurrentWidth )
     974                 :            :         {   // we need to take away some space from the columns which allow it ...
     975                 :          0 :             long takeAwayAppFontUnits = accumulatedCurrentWidth - gridWidthAppFont;
     976         [ #  # ]:          0 :             if ( gridWidthAppFont < accumulatedMinWidth )
     977                 :            :             {
     978                 :            :                 // ... but the column's minimal widths are still more than we have
     979                 :            :                 // => set them all to min
     980         [ #  # ]:          0 :                 for ( size_t i = 0; i < size_t( colCount ); ++i )
     981                 :            :                 {
     982 [ #  # ][ #  # ]:          0 :                     newWidths[i] = effectiveColumnLimits[i].first;
     983                 :            :                 }
     984                 :            :             }
     985                 :            :             else
     986                 :            :             {
     987                 :          0 :                 bool startOver = false;
     988         [ #  # ]:          0 :                 do
     989                 :            :                 {
     990                 :          0 :                     startOver = false;
     991                 :            :                     // take away the space we need from the columns with a positive flexibility
     992 [ #  # ][ #  # ]:          0 :                     for ( size_t i=0; i<newWidths.size() && !startOver; ++i )
                 [ #  # ]
     993                 :            :                     {
     994         [ #  # ]:          0 :                         long const columnFlexibility = columnFlexibilities[i];
     995         [ #  # ]:          0 :                         if ( columnFlexibility == 0 )
     996                 :          0 :                             continue;
     997                 :            : 
     998         [ #  # ]:          0 :                         long newColWidth = currentColWidths[i] - columnFlexibility * takeAwayAppFontUnits / flexibilityDenominator;
     999                 :            : 
    1000 [ #  # ][ #  # ]:          0 :                         if ( newColWidth < effectiveColumnLimits[i].first )
    1001                 :            :                         {   // that was too much, we hit the col's minimum
    1002                 :            :                             // set the new width to exactly this minimum
    1003         [ #  # ]:          0 :                             newColWidth = effectiveColumnLimits[i].first;
    1004                 :            :                             // adjust the flexibility denominator ...
    1005                 :          0 :                             flexibilityDenominator -= columnFlexibility;
    1006         [ #  # ]:          0 :                             columnFlexibilities[i] = 0;
    1007                 :            :                             // ... and the remaining width ...
    1008         [ #  # ]:          0 :                             long const difference = currentColWidths[i] - newColWidth;
    1009                 :          0 :                             takeAwayAppFontUnits -= difference;
    1010                 :            : 
    1011                 :            :                             // and start over with the first column, since there might be earlier columns which need
    1012                 :            :                             // to be recalculated now
    1013                 :          0 :                             startOver = true;
    1014                 :            :                         }
    1015                 :            : 
    1016         [ #  # ]:          0 :                         newWidths[i] = newColWidth;
    1017                 :            :                     }
    1018                 :            :                 }
    1019                 :            :                 while ( startOver );
    1020                 :            :             }
    1021                 :            :         }
    1022                 :            : 
    1023                 :            :         // now that we have calculated the app-font widths, get the actual pixels
    1024                 :          0 :         long accumulatedWidthPixel = m_nRowHeaderWidthPixel;
    1025         [ #  # ]:          0 :         for ( ColPos col = 0; col < colCount; ++col )
    1026                 :            :         {
    1027 [ #  # ][ #  # ]:          0 :             long const colWidth = m_rAntiImpl.LogicToPixel( Size( newWidths[col], 0 ), MAP_APPFONT ).Width();
         [ #  # ][ #  # ]
    1028                 :          0 :             const long columnStart = accumulatedWidthPixel;
    1029                 :          0 :             const long columnEnd = columnStart + colWidth;
    1030         [ #  # ]:          0 :             m_aColumnWidths.push_back( MutableColumnMetrics( columnStart, columnEnd ) );
    1031                 :          0 :             accumulatedWidthPixel = columnEnd;
    1032                 :            : 
    1033                 :            :             // and don't forget to forward this to the column models
    1034         [ #  # ]:          0 :             PColumnModel const pColumn = m_pModel->getColumnModel( col );
    1035 [ #  # ][ #  # ]:          0 :             ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
         [ #  # ][ #  # ]
    1036 [ #  # ][ #  # ]:          0 :             pColumn->setWidth( newWidths[col] );
    1037         [ #  # ]:          0 :         }
    1038                 :            : 
    1039                 :            :         // if the column resizing happened to leave some space at the right, but there are columns
    1040                 :            :         // scrolled out to the left, scroll them in
    1041   [ #  #  #  # ]:          0 :         while   (   ( m_nLeftColumn > 0 )
                 [ #  # ]
    1042                 :          0 :                 &&  ( accumulatedWidthPixel - m_aColumnWidths[ m_nLeftColumn - 1 ].getStart() <= gridWidthPixel )
    1043                 :            :                 )
    1044                 :            :         {
    1045                 :          0 :             --m_nLeftColumn;
    1046                 :            :         }
    1047                 :            : 
    1048                 :            :         // now adjust the column metrics, since they currently ignore the horizontal scroll position
    1049         [ #  # ]:          0 :         if ( m_nLeftColumn > 0 )
    1050                 :            :         {
    1051                 :          0 :             const long offsetPixel = m_aColumnWidths[ 0 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getStart();
    1052 [ #  # ][ #  # ]:          0 :             for (   ColumnPositions::iterator colPos = m_aColumnWidths.begin();
    1053                 :          0 :                     colPos != m_aColumnWidths.end();
    1054                 :            :                     ++colPos
    1055                 :            :                  )
    1056                 :            :             {
    1057                 :          0 :                 colPos->move( offsetPixel );
    1058                 :            :             }
    1059         [ #  # ]:          0 :         }
    1060                 :            :     }
    1061                 :            : 
    1062                 :            :     //------------------------------------------------------------------------------------------------------------------
    1063                 :            :     namespace
    1064                 :            :     {
    1065                 :            :         //..............................................................................................................
    1066                 :            :         /// determines whether a scrollbar is needed for the given values
    1067                 :          0 :         bool lcl_determineScrollbarNeed( long const i_position, ScrollbarVisibility const i_visibility,
    1068                 :            :             long const i_availableSpace, long const i_neededSpace )
    1069                 :            :         {
    1070         [ #  # ]:          0 :             if ( i_visibility == ScrollbarShowNever )
    1071                 :          0 :                 return false;
    1072         [ #  # ]:          0 :             if ( i_visibility == ScrollbarShowAlways )
    1073                 :          0 :                 return true;
    1074         [ #  # ]:          0 :             if ( i_position > 0 )
    1075                 :          0 :                 return true;
    1076         [ #  # ]:          0 :             if ( i_availableSpace >= i_neededSpace )
    1077                 :          0 :                 return false;
    1078                 :          0 :             return true;
    1079                 :            :         }
    1080                 :            : 
    1081                 :            :         //..............................................................................................................
    1082                 :          0 :         void lcl_setButtonRepeat( Window& _rWindow, sal_uLong _nDelay )
    1083                 :            :         {
    1084         [ #  # ]:          0 :             AllSettings aSettings = _rWindow.GetSettings();
    1085         [ #  # ]:          0 :             MouseSettings aMouseSettings = aSettings.GetMouseSettings();
    1086                 :            : 
    1087         [ #  # ]:          0 :             aMouseSettings.SetButtonRepeat( _nDelay );
    1088         [ #  # ]:          0 :             aSettings.SetMouseSettings( aMouseSettings );
    1089                 :            : 
    1090 [ #  # ][ #  # ]:          0 :             _rWindow.SetSettings( aSettings, sal_True );
                 [ #  # ]
    1091                 :          0 :         }
    1092                 :            : 
    1093                 :            :         //..............................................................................................................
    1094                 :          0 :         void lcl_updateScrollbar( Window& _rParent, ScrollBar*& _rpBar,
    1095                 :            :             bool const i_needBar, long _nVisibleUnits,
    1096                 :            :             long _nPosition, long _nLineSize, long _nRange,
    1097                 :            :             bool _bHorizontal, const Link& _rScrollHandler )
    1098                 :            :         {
    1099                 :            :             // do we currently have the scrollbar?
    1100                 :          0 :             bool bHaveBar = _rpBar != NULL;
    1101                 :            : 
    1102                 :            :             // do we need to correct the scrollbar visibility?
    1103 [ #  # ][ #  # ]:          0 :             if ( bHaveBar && !i_needBar )
    1104                 :            :             {
    1105         [ #  # ]:          0 :                 if ( _rpBar->IsTracking() )
    1106                 :          0 :                     _rpBar->EndTracking();
    1107         [ #  # ]:          0 :                 DELETEZ( _rpBar );
    1108                 :            :             }
    1109 [ #  # ][ #  # ]:          0 :             else if ( !bHaveBar && i_needBar )
    1110                 :            :             {
    1111                 :            :                 _rpBar = new ScrollBar(
    1112                 :            :                     &_rParent,
    1113                 :            :                     WB_DRAG | ( _bHorizontal ? WB_HSCROLL : WB_VSCROLL )
    1114 [ #  # ][ #  # ]:          0 :                 );
    1115                 :          0 :                 _rpBar->SetScrollHdl( _rScrollHandler );
    1116                 :            :                 // get some speed into the scrolling ....
    1117                 :          0 :                 lcl_setButtonRepeat( *_rpBar, 0 );
    1118                 :            :             }
    1119                 :            : 
    1120         [ #  # ]:          0 :             if ( _rpBar )
    1121                 :            :             {
    1122         [ #  # ]:          0 :                 _rpBar->SetRange( Range( 0, _nRange ) );
    1123                 :          0 :                 _rpBar->SetVisibleSize( _nVisibleUnits );
    1124                 :          0 :                 _rpBar->SetPageSize( _nVisibleUnits );
    1125                 :          0 :                 _rpBar->SetLineSize( _nLineSize );
    1126                 :          0 :                 _rpBar->SetThumbPos( _nPosition );
    1127                 :          0 :                 _rpBar->Show();
    1128                 :            :             }
    1129                 :          0 :         }
    1130                 :            : 
    1131                 :            :         //..............................................................................................................
    1132                 :            :         /** returns the number of rows fitting into the given range,
    1133                 :            :             for the given row height. Partially fitting rows are counted, too, if the
    1134                 :            :             respective parameter says so.
    1135                 :            :         */
    1136                 :          0 :         TableSize lcl_getRowsFittingInto( long _nOverallHeight, long _nRowHeightPixel, bool _bAcceptPartialRow = false )
    1137                 :            :         {
    1138                 :            :             return  _bAcceptPartialRow
    1139                 :            :                 ?   ( _nOverallHeight + ( _nRowHeightPixel - 1 ) ) / _nRowHeightPixel
    1140         [ #  # ]:          0 :                 :   _nOverallHeight / _nRowHeightPixel;
    1141                 :            :         }
    1142                 :            : 
    1143                 :            :         //..............................................................................................................
    1144                 :            :         /** returns the number of columns fitting into the given area,
    1145                 :            :             with the first visible column as given. Partially fitting columns are counted, too,
    1146                 :            :             if the respective parameter says so.
    1147                 :            :         */
    1148                 :          0 :         TableSize lcl_getColumnsVisibleWithin( const Rectangle& _rArea, ColPos _nFirstVisibleColumn,
    1149                 :            :             const TableControl_Impl& _rControl, bool _bAcceptPartialRow )
    1150                 :            :         {
    1151                 :          0 :             TableSize visibleColumns = 0;
    1152         [ #  # ]:          0 :             TableColumnGeometry aColumn( _rControl, _rArea, _nFirstVisibleColumn );
    1153 [ #  # ][ #  # ]:          0 :             while ( aColumn.isValid() )
    1154                 :            :             {
    1155         [ #  # ]:          0 :                 if ( !_bAcceptPartialRow )
    1156         [ #  # ]:          0 :                     if ( aColumn.getRect().Right() > _rArea.Right() )
    1157                 :            :                         // this column is only partially visible, and this is not allowed
    1158                 :          0 :                         break;
    1159                 :            : 
    1160         [ #  # ]:          0 :                 aColumn.moveRight();
    1161                 :          0 :                 ++visibleColumns;
    1162                 :            :             }
    1163                 :          0 :             return visibleColumns;
    1164                 :            :         }
    1165                 :            : 
    1166                 :            :     }
    1167                 :            : 
    1168                 :            :     //------------------------------------------------------------------------------------------------------------------
    1169                 :          0 :     void TableControl_Impl::impl_ni_updateScrollbars()
    1170                 :            :     {
    1171         [ #  # ]:          0 :         SuppressCursor aHideCursor( *this );
    1172                 :            : 
    1173                 :            :         // the width/height of a scrollbar, needed several times below
    1174                 :          0 :         long const nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
    1175                 :            : 
    1176                 :            :         // determine the playground for the data cells (excluding headers)
    1177                 :            :         // TODO: what if the control is smaller than needed for the headers/scrollbars?
    1178         [ #  # ]:          0 :         Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() );
    1179                 :          0 :         aDataCellPlayground.Left() = m_nRowHeaderWidthPixel;
    1180                 :          0 :         aDataCellPlayground.Top() = m_nColHeaderHeightPixel;
    1181         [ #  # ]:          0 :         m_nRowCount = m_pModel->getRowCount();
    1182         [ #  # ]:          0 :         m_nColumnCount = m_pModel->getColumnCount();
    1183                 :            : 
    1184         [ #  # ]:          0 :         if ( m_aColumnWidths.empty() )
    1185         [ #  # ]:          0 :             impl_ni_updateColumnWidths();
    1186                 :            :         OSL_ENSURE( m_aColumnWidths.size() == size_t( m_nColumnCount ), "TableControl_Impl::impl_ni_updateScrollbars: inconsistency!" );
    1187                 :          0 :         const long nAllColumnsWidth =   m_aColumnWidths.empty()
    1188                 :            :                                     ?   0
    1189         [ #  # ]:          0 :                                     :   m_aColumnWidths[ m_nColumnCount - 1 ].getEnd() - m_aColumnWidths[ 0 ].getStart();
    1190                 :            : 
    1191         [ #  # ]:          0 :         const ScrollbarVisibility eVertScrollbar = m_pModel->getVerticalScrollbarVisibility();
    1192         [ #  # ]:          0 :         const ScrollbarVisibility eHorzScrollbar = m_pModel->getHorizontalScrollbarVisibility();
    1193                 :            : 
    1194                 :            :         // do we need a vertical scrollbar?
    1195                 :            :         bool bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
    1196         [ #  # ]:          0 :             m_nTopRow, eVertScrollbar, aDataCellPlayground.GetHeight(), m_nRowHeightPixel * m_nRowCount );
    1197                 :          0 :         bool bFirstRoundVScrollNeed = false;
    1198         [ #  # ]:          0 :         if ( bNeedVerticalScrollbar )
    1199                 :            :         {
    1200                 :          0 :             aDataCellPlayground.Right() -= nScrollbarMetrics;
    1201                 :          0 :             bFirstRoundVScrollNeed = true;
    1202                 :            :         }
    1203                 :            :         // do we need a horizontal scrollbar?
    1204         [ #  # ]:          0 :         const bool bNeedHorizontalScrollbar = lcl_determineScrollbarNeed( m_nLeftColumn, eHorzScrollbar, aDataCellPlayground.GetWidth(), nAllColumnsWidth );
    1205         [ #  # ]:          0 :         if ( bNeedHorizontalScrollbar )
    1206                 :            :         {
    1207                 :          0 :             aDataCellPlayground.Bottom() -= nScrollbarMetrics;
    1208                 :            : 
    1209                 :            :             // now that we just found that we need a horizontal scrollbar,
    1210                 :            :             // the need for a vertical one may have changed, since the horizontal
    1211                 :            :             // SB might just occupy enough space so that not all rows do fit
    1212                 :            :             // anymore
    1213         [ #  # ]:          0 :             if  ( !bFirstRoundVScrollNeed )
    1214                 :            :             {
    1215                 :            :                 bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
    1216         [ #  # ]:          0 :                     m_nTopRow, eVertScrollbar, aDataCellPlayground.GetHeight(), m_nRowHeightPixel * m_nRowCount );
    1217         [ #  # ]:          0 :                 if ( bNeedVerticalScrollbar )
    1218                 :            :                 {
    1219                 :          0 :                     aDataCellPlayground.Right() -= nScrollbarMetrics;
    1220                 :            :                 }
    1221                 :            :             }
    1222                 :            :         }
    1223                 :            :         // create or destroy the vertical scrollbar, as needed
    1224                 :            :         lcl_updateScrollbar(
    1225                 :            :             m_rAntiImpl,
    1226                 :            :             m_pVScroll,
    1227                 :            :             bNeedVerticalScrollbar,
    1228                 :            :             lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ),
    1229                 :            :                                                                     // visible units
    1230                 :            :             m_nTopRow,                                              // current position
    1231                 :            :             1,                                                      // line size
    1232                 :            :             m_nRowCount,                                            // range
    1233                 :            :             false,                                                  // vertical
    1234                 :            :             LINK( this, TableControl_Impl, OnScroll )               // scroll handler
    1235 [ #  # ][ #  # ]:          0 :         );
                 [ #  # ]
    1236                 :            :         // position it
    1237         [ #  # ]:          0 :         if ( m_pVScroll )
    1238                 :            :         {
    1239                 :            :             Rectangle aScrollbarArea(
    1240                 :          0 :                 Point( aDataCellPlayground.Right() + 1, 0 ),
    1241                 :          0 :                 Size( nScrollbarMetrics, aDataCellPlayground.Bottom() + 1 )
    1242         [ #  # ]:          0 :             );
    1243                 :            :             m_pVScroll->SetPosSizePixel(
    1244 [ #  # ][ #  # ]:          0 :                 aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() );
    1245                 :            :         }
    1246                 :            : 
    1247                 :            :         // create or destroy the horizontal scrollbar, as needed
    1248                 :            :         lcl_updateScrollbar(
    1249                 :            :             m_rAntiImpl,
    1250                 :            :             m_pHScroll,
    1251                 :            :             bNeedHorizontalScrollbar,
    1252                 :            :             lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false ),
    1253                 :            :                                                                     // visible units
    1254                 :            :             m_nLeftColumn,                                          // current position
    1255                 :            :             1,                                                      // line size
    1256                 :            :             m_nColumnCount,                                         // range
    1257                 :            :             true,                                                   // horizontal
    1258                 :            :             LINK( this, TableControl_Impl, OnScroll )               // scroll handler
    1259 [ #  # ][ #  # ]:          0 :         );
                 [ #  # ]
    1260                 :            :         // position it
    1261         [ #  # ]:          0 :         if ( m_pHScroll )
    1262                 :            :         {
    1263         [ #  # ]:          0 :             TableSize const nVisibleUnits = lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false );
    1264                 :          0 :             TableMetrics const nRange = m_nColumnCount;
    1265         [ #  # ]:          0 :             if( m_nLeftColumn + nVisibleUnits == nRange - 1 )
    1266                 :            :             {
    1267 [ #  # ][ #  # ]:          0 :                 if ( m_aColumnWidths[ nRange - 1 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getEnd() + m_aColumnWidths[ nRange-1 ].getWidth() > aDataCellPlayground.GetWidth() )
    1268                 :            :                 {
    1269         [ #  # ]:          0 :                     m_pHScroll->SetVisibleSize( nVisibleUnits -1 );
    1270                 :          0 :                     m_pHScroll->SetPageSize( nVisibleUnits - 1 );
    1271                 :            :                 }
    1272                 :            :             }
    1273                 :            :             Rectangle aScrollbarArea(
    1274                 :          0 :                 Point( 0, aDataCellPlayground.Bottom() + 1 ),
    1275                 :          0 :                 Size( aDataCellPlayground.Right() + 1, nScrollbarMetrics )
    1276         [ #  # ]:          0 :             );
    1277                 :            :             m_pHScroll->SetPosSizePixel(
    1278 [ #  # ][ #  # ]:          0 :                 aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() );
    1279                 :            :         }
    1280                 :            : 
    1281                 :            :         // the corner window connecting the two scrollbars in the lower right corner
    1282                 :          0 :         bool bHaveScrollCorner = NULL != m_pScrollCorner;
    1283 [ #  # ][ #  # ]:          0 :         bool bNeedScrollCorner = ( NULL != m_pHScroll ) && ( NULL != m_pVScroll );
    1284 [ #  # ][ #  # ]:          0 :         if ( bHaveScrollCorner && !bNeedScrollCorner )
    1285                 :            :         {
    1286 [ #  # ][ #  # ]:          0 :             DELETEZ( m_pScrollCorner );
    1287                 :            :         }
    1288 [ #  # ][ #  # ]:          0 :         else if ( !bHaveScrollCorner && bNeedScrollCorner )
    1289                 :            :         {
    1290 [ #  # ][ #  # ]:          0 :             m_pScrollCorner = new ScrollBarBox( &m_rAntiImpl );
    1291         [ #  # ]:          0 :             m_pScrollCorner->SetSizePixel( Size( nScrollbarMetrics, nScrollbarMetrics ) );
    1292         [ #  # ]:          0 :             m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) );
    1293         [ #  # ]:          0 :             m_pScrollCorner->Show();
    1294                 :            :         }
    1295 [ #  # ][ #  # ]:          0 :         else if(bHaveScrollCorner && bNeedScrollCorner)
    1296                 :            :         {
    1297         [ #  # ]:          0 :             m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) );
    1298         [ #  # ]:          0 :             m_pScrollCorner->Show();
    1299                 :            :         }
    1300                 :            : 
    1301                 :            :         // resize the data window
    1302                 :          0 :         m_pDataWindow->SetSizePixel( Size(
    1303         [ #  # ]:          0 :             aDataCellPlayground.GetWidth() + m_nRowHeaderWidthPixel,
    1304         [ #  # ]:          0 :             aDataCellPlayground.GetHeight() + m_nColHeaderHeightPixel
    1305 [ #  # ][ #  # ]:          0 :         ) );
    1306                 :          0 :     }
    1307                 :            : 
    1308                 :            :     //------------------------------------------------------------------------------------------------------------------
    1309                 :          0 :     void TableControl_Impl::onResize()
    1310                 :            :     {
    1311                 :            :         DBG_CHECK_ME();
    1312                 :            : 
    1313                 :          0 :         impl_ni_updateColumnWidths();
    1314                 :          0 :         impl_ni_updateScrollbars();
    1315                 :          0 :         checkCursorPosition();
    1316                 :          0 :     }
    1317                 :            : 
    1318                 :            :     //------------------------------------------------------------------------------------------------------------------
    1319                 :          0 :     void TableControl_Impl::doPaintContent( const Rectangle& _rUpdateRect )
    1320                 :            :     {
    1321                 :            :         DBG_CHECK_ME();
    1322                 :            : 
    1323 [ #  # ][ #  # ]:          0 :         if ( !getModel() )
                 [ #  # ]
    1324                 :            :             return;
    1325 [ #  # ][ #  # ]:          0 :         PTableRenderer pRenderer = getModel()->getRenderer();
                 [ #  # ]
    1326                 :            :         DBG_ASSERT( !!pRenderer, "TableDataWindow::doPaintContent: invalid renderer!" );
    1327         [ #  # ]:          0 :         if ( !pRenderer )
    1328                 :            :             return;
    1329                 :            : 
    1330                 :            :         // our current style settings, to be passed to the renderer
    1331                 :          0 :         const StyleSettings& rStyle = m_rAntiImpl.GetSettings().GetStyleSettings();
    1332         [ #  # ]:          0 :         m_nRowCount = m_pModel->getRowCount();
    1333                 :            :         // the area occupied by all (at least partially) visible cells, including
    1334                 :            :         // headers
    1335         [ #  # ]:          0 :         Rectangle const aAllCellsWithHeaders( impl_getAllVisibleCellsArea() );
    1336                 :            : 
    1337                 :            :         // ............................
    1338                 :            :         // draw the header column area
    1339 [ #  # ][ #  # ]:          0 :         if ( m_pModel->hasColumnHeaders() )
    1340                 :            :         {
    1341                 :            :             TableRowGeometry const aHeaderRow( *this, Rectangle( Point( 0, 0 ),
    1342 [ #  # ][ #  # ]:          0 :                 aAllCellsWithHeaders.BottomRight() ), ROW_COL_HEADERS );
                 [ #  # ]
    1343                 :          0 :             Rectangle const aColRect(aHeaderRow.getRect());
    1344                 :          0 :             pRenderer->PaintHeaderArea(
    1345                 :          0 :                 *m_pDataWindow, aColRect, true, false, rStyle
    1346         [ #  # ]:          0 :             );
    1347                 :            :             // Note that strictly, aHeaderRow.getRect() also contains the intersection between column
    1348                 :            :             // and row header area. However, below we go to paint this intersection, again,
    1349                 :            :             // so this hopefully doesn't hurt if we already paint it here.
    1350                 :            : 
    1351 [ #  # ][ #  # ]:          0 :             for ( TableCellGeometry aCell( aHeaderRow, m_nLeftColumn );
         [ #  # ][ #  # ]
    1352                 :            :                   aCell.isValid();
    1353                 :            :                   aCell.moveRight()
    1354                 :            :                 )
    1355                 :            :             {
    1356 [ #  # ][ #  # ]:          0 :                 if ( _rUpdateRect.GetIntersection( aCell.getRect() ).IsEmpty() )
         [ #  # ][ #  # ]
    1357                 :          0 :                     continue;
    1358                 :            : 
    1359         [ #  # ]:          0 :                 bool isActiveColumn = ( aCell.getColumn() == getCurrentColumn() );
    1360                 :          0 :                 bool isSelectedColumn = false;
    1361                 :          0 :                 pRenderer->PaintColumnHeader( aCell.getColumn(), isActiveColumn, isSelectedColumn,
    1362 [ #  # ][ #  # ]:          0 :                     *m_pDataWindow, aCell.getRect(), rStyle );
    1363                 :            :             }
    1364                 :            :         }
    1365                 :            :         // the area occupied by the row header, if any
    1366         [ #  # ]:          0 :         Rectangle aRowHeaderArea;
    1367 [ #  # ][ #  # ]:          0 :         if ( m_pModel->hasRowHeaders() )
    1368                 :            :         {
    1369                 :          0 :             aRowHeaderArea = aAllCellsWithHeaders;
    1370                 :          0 :             aRowHeaderArea.Right() = m_nRowHeaderWidthPixel - 1;
    1371                 :            : 
    1372         [ #  # ]:          0 :             TableSize const nVisibleRows = impl_getVisibleRows( true );
    1373                 :          0 :             TableSize nActualRows = nVisibleRows;
    1374         [ #  # ]:          0 :             if ( m_nTopRow + nActualRows > m_nRowCount )
    1375                 :          0 :                 nActualRows = m_nRowCount - m_nTopRow;
    1376                 :          0 :             aRowHeaderArea.Bottom() = m_nColHeaderHeightPixel + m_nRowHeightPixel * nActualRows - 1;
    1377                 :            : 
    1378         [ #  # ]:          0 :             pRenderer->PaintHeaderArea( *m_pDataWindow, aRowHeaderArea, false, true, rStyle );
    1379                 :            :             // Note that strictly, aRowHeaderArea also contains the intersection between column
    1380                 :            :             // and row header area. However, below we go to paint this intersection, again,
    1381                 :            :             // so this hopefully doesn't hurt if we already paint it here.
    1382                 :            : 
    1383 [ #  # ][ #  # ]:          0 :             if ( m_pModel->hasColumnHeaders() )
    1384                 :            :             {
    1385                 :            :                 TableCellGeometry const aIntersection( *this, Rectangle( Point( 0, 0 ),
    1386 [ #  # ][ #  # ]:          0 :                     aAllCellsWithHeaders.BottomRight() ), COL_ROW_HEADERS, ROW_COL_HEADERS );
                 [ #  # ]
    1387         [ #  # ]:          0 :                 Rectangle const aInters( aIntersection.getRect() );
    1388                 :          0 :                 pRenderer->PaintHeaderArea(
    1389                 :          0 :                     *m_pDataWindow, aInters, true, true, rStyle
    1390         [ #  # ]:          0 :                 );
    1391                 :            :             }
    1392                 :            :         }
    1393                 :            : 
    1394                 :            :         // ............................
    1395                 :            :         // draw the table content row by row
    1396                 :            : 
    1397 [ #  # ][ #  # ]:          0 :         TableSize colCount = getModel()->getColumnCount();
                 [ #  # ]
    1398                 :            : 
    1399                 :            :         // paint all rows
    1400         [ #  # ]:          0 :         Rectangle const aAllDataCellsArea( impl_getAllVisibleDataCellArea() );
    1401 [ #  # ][ #  # ]:          0 :         for ( TableRowGeometry aRowIterator( *this, aAllCellsWithHeaders, getTopRow() );
         [ #  # ][ #  # ]
    1402                 :            :               aRowIterator.isValid();
    1403                 :            :               aRowIterator.moveDown() )
    1404                 :            :         {
    1405 [ #  # ][ #  # ]:          0 :             if ( _rUpdateRect.GetIntersection( aRowIterator.getRect() ).IsEmpty() )
                 [ #  # ]
    1406                 :          0 :                 continue;
    1407                 :            : 
    1408         [ #  # ]:          0 :             bool const isActiveRow = ( aRowIterator.getRow() == getCurrentRow() );
    1409         [ #  # ]:          0 :             bool const isSelectedRow = isRowSelected( aRowIterator.getRow() );
    1410                 :            : 
    1411         [ #  # ]:          0 :             Rectangle const aRect = aRowIterator.getRect().GetIntersection( aAllDataCellsArea );
    1412                 :            : 
    1413                 :            :             // give the redenderer a chance to prepare the row
    1414                 :          0 :             pRenderer->PrepareRow(
    1415                 :            :                 aRowIterator.getRow(), isActiveRow, isSelectedRow,
    1416                 :          0 :                 *m_pDataWindow, aRect, rStyle
    1417         [ #  # ]:          0 :             );
    1418                 :            : 
    1419                 :            :             // paint the row header
    1420 [ #  # ][ #  # ]:          0 :             if ( m_pModel->hasRowHeaders() )
    1421                 :            :             {
    1422         [ #  # ]:          0 :                 const Rectangle aCurrentRowHeader( aRowHeaderArea.GetIntersection( aRowIterator.getRect() ) );
    1423                 :          0 :                 pRenderer->PaintRowHeader( isActiveRow, isSelectedRow, *m_pDataWindow, aCurrentRowHeader,
    1424         [ #  # ]:          0 :                     rStyle );
    1425                 :            :             }
    1426                 :            : 
    1427         [ #  # ]:          0 :             if ( !colCount )
    1428                 :          0 :                 continue;
    1429                 :            : 
    1430                 :            :             // paint all cells in this row
    1431 [ #  # ][ #  # ]:          0 :             for ( TableCellGeometry aCell( aRowIterator, m_nLeftColumn );
         [ #  # ][ #  # ]
    1432                 :            :                   aCell.isValid();
    1433                 :            :                   aCell.moveRight()
    1434                 :            :                 )
    1435                 :            :             {
    1436                 :          0 :                 bool isSelectedColumn = false;
    1437                 :          0 :                 pRenderer->PaintCell( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow,
    1438 [ #  # ][ #  # ]:          0 :                                 *m_pDataWindow, aCell.getRect(), rStyle );
         [ #  # ][ #  # ]
    1439                 :            :             }
    1440 [ #  # ][ #  # ]:          0 :         }
    1441                 :            :     }
    1442                 :            :     //------------------------------------------------------------------------------------------------------------------
    1443                 :          0 :     void TableControl_Impl::hideCursor()
    1444                 :            :     {
    1445                 :            :         DBG_CHECK_ME();
    1446                 :            : 
    1447         [ #  # ]:          0 :         if ( ++m_nCursorHidden == 1 )
    1448                 :          0 :             impl_ni_doSwitchCursor( false );
    1449                 :          0 :     }
    1450                 :            : 
    1451                 :            :     //------------------------------------------------------------------------------------------------------------------
    1452                 :          0 :     void TableControl_Impl::showCursor()
    1453                 :            :     {
    1454                 :            :         DBG_CHECK_ME();
    1455                 :            : 
    1456                 :            :         DBG_ASSERT( m_nCursorHidden > 0, "TableControl_Impl::showCursor: cursor not hidden!" );
    1457         [ #  # ]:          0 :         if ( --m_nCursorHidden == 0 )
    1458                 :          0 :             impl_ni_doSwitchCursor( true );
    1459                 :          0 :     }
    1460                 :            : 
    1461                 :            :     //------------------------------------------------------------------------------------------------------------------
    1462                 :          0 :     bool TableControl_Impl::dispatchAction( TableControlAction _eAction )
    1463                 :            :     {
    1464                 :            :         DBG_CHECK_ME();
    1465                 :            : 
    1466                 :          0 :         bool bSuccess = false;
    1467                 :          0 :         bool selectionChanged = false;
    1468                 :            : 
    1469         [ #  # ]:          0 :         Rectangle rCells;
    1470   [ #  #  #  #  :          0 :         switch ( _eAction )
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1471                 :            :         {
    1472                 :            :         case cursorDown:
    1473         [ #  # ]:          0 :         if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
    1474                 :            :         {
    1475                 :            :             //if other rows already selected, deselect them
    1476         [ #  # ]:          0 :             if(!m_aSelectedRows.empty())
    1477                 :            :             {
    1478   [ #  #  #  # ]:          0 :                 for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
                 [ #  # ]
    1479                 :          0 :                         it!=m_aSelectedRows.end();++it)
    1480                 :            :                 {
    1481 [ #  # ][ #  # ]:          0 :                     invalidateSelectedRegion(*it, *it, rCells);
                 [ #  # ]
    1482                 :            :                 }
    1483                 :          0 :                 m_aSelectedRows.clear();
    1484                 :            :             }
    1485         [ #  # ]:          0 :             if(m_nCurRow < m_nRowCount-1)
    1486                 :            :             {
    1487                 :          0 :                 ++m_nCurRow;
    1488         [ #  # ]:          0 :                 m_aSelectedRows.push_back(m_nCurRow);
    1489                 :            :             }
    1490                 :            :             else
    1491         [ #  # ]:          0 :                 m_aSelectedRows.push_back(m_nCurRow);
    1492         [ #  # ]:          0 :             invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1493         [ #  # ]:          0 :             ensureVisible(m_nCurColumn,m_nCurRow,false);
    1494                 :          0 :             selectionChanged = true;
    1495                 :          0 :             bSuccess = true;
    1496                 :            :         }
    1497                 :            :         else
    1498                 :            :         {
    1499         [ #  # ]:          0 :             if ( m_nCurRow < m_nRowCount - 1 )
    1500         [ #  # ]:          0 :                 bSuccess = goTo( m_nCurColumn, m_nCurRow + 1 );
    1501                 :            :         }
    1502                 :          0 :             break;
    1503                 :            : 
    1504                 :            :         case cursorUp:
    1505         [ #  # ]:          0 :         if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
    1506                 :            :         {
    1507         [ #  # ]:          0 :             if(!m_aSelectedRows.empty())
    1508                 :            :             {
    1509   [ #  #  #  # ]:          0 :                 for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
                 [ #  # ]
    1510                 :          0 :                     it!=m_aSelectedRows.end();++it)
    1511                 :            :                 {
    1512 [ #  # ][ #  # ]:          0 :                     invalidateSelectedRegion(*it, *it, rCells);
                 [ #  # ]
    1513                 :            :                 }
    1514                 :          0 :                 m_aSelectedRows.clear();
    1515                 :            :             }
    1516         [ #  # ]:          0 :             if(m_nCurRow>0)
    1517                 :            :             {
    1518                 :          0 :                 --m_nCurRow;
    1519         [ #  # ]:          0 :                 m_aSelectedRows.push_back(m_nCurRow);
    1520         [ #  # ]:          0 :                 invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1521                 :            :             }
    1522                 :            :             else
    1523                 :            :             {
    1524         [ #  # ]:          0 :                 m_aSelectedRows.push_back(m_nCurRow);
    1525         [ #  # ]:          0 :                 invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1526                 :            :             }
    1527         [ #  # ]:          0 :             ensureVisible(m_nCurColumn,m_nCurRow,false);
    1528                 :          0 :             selectionChanged = true;
    1529                 :          0 :             bSuccess = true;
    1530                 :            :         }
    1531                 :            :         else
    1532                 :            :         {
    1533         [ #  # ]:          0 :             if ( m_nCurRow > 0 )
    1534         [ #  # ]:          0 :                 bSuccess = goTo( m_nCurColumn, m_nCurRow - 1 );
    1535                 :            :         }
    1536                 :          0 :         break;
    1537                 :            :         case cursorLeft:
    1538         [ #  # ]:          0 :             if ( m_nCurColumn > 0 )
    1539         [ #  # ]:          0 :                 bSuccess = goTo( m_nCurColumn - 1, m_nCurRow );
    1540                 :            :             else
    1541 [ #  # ][ #  # ]:          0 :                 if ( ( m_nCurColumn == 0) && ( m_nCurRow > 0 ) )
    1542         [ #  # ]:          0 :                     bSuccess = goTo( m_nColumnCount - 1, m_nCurRow - 1 );
    1543                 :          0 :             break;
    1544                 :            : 
    1545                 :            :         case cursorRight:
    1546         [ #  # ]:          0 :             if ( m_nCurColumn < m_nColumnCount - 1 )
    1547         [ #  # ]:          0 :                 bSuccess = goTo( m_nCurColumn + 1, m_nCurRow );
    1548                 :            :             else
    1549 [ #  # ][ #  # ]:          0 :                 if ( ( m_nCurColumn == m_nColumnCount - 1 ) && ( m_nCurRow < m_nRowCount - 1 ) )
    1550         [ #  # ]:          0 :                     bSuccess = goTo( 0, m_nCurRow + 1 );
    1551                 :          0 :             break;
    1552                 :            : 
    1553                 :            :         case cursorToLineStart:
    1554         [ #  # ]:          0 :             bSuccess = goTo( 0, m_nCurRow );
    1555                 :          0 :             break;
    1556                 :            : 
    1557                 :            :         case cursorToLineEnd:
    1558         [ #  # ]:          0 :             bSuccess = goTo( m_nColumnCount - 1, m_nCurRow );
    1559                 :          0 :             break;
    1560                 :            : 
    1561                 :            :         case cursorToFirstLine:
    1562         [ #  # ]:          0 :             bSuccess = goTo( m_nCurColumn, 0 );
    1563                 :          0 :             break;
    1564                 :            : 
    1565                 :            :         case cursorToLastLine:
    1566         [ #  # ]:          0 :             bSuccess = goTo( m_nCurColumn, m_nRowCount - 1 );
    1567                 :          0 :             break;
    1568                 :            : 
    1569                 :            :         case cursorPageUp:
    1570                 :            :         {
    1571 [ #  # ][ #  # ]:          0 :             RowPos nNewRow = ::std::max( (RowPos)0, m_nCurRow - impl_getVisibleRows( false ) );
    1572         [ #  # ]:          0 :             bSuccess = goTo( m_nCurColumn, nNewRow );
    1573                 :            :         }
    1574                 :          0 :         break;
    1575                 :            : 
    1576                 :            :         case cursorPageDown:
    1577                 :            :         {
    1578 [ #  # ][ #  # ]:          0 :             RowPos nNewRow = ::std::min( m_nRowCount - 1, m_nCurRow + impl_getVisibleRows( false ) );
    1579         [ #  # ]:          0 :             bSuccess = goTo( m_nCurColumn, nNewRow );
    1580                 :            :         }
    1581                 :          0 :         break;
    1582                 :            : 
    1583                 :            :         case cursorTopLeft:
    1584         [ #  # ]:          0 :             bSuccess = goTo( 0, 0 );
    1585                 :          0 :             break;
    1586                 :            : 
    1587                 :            :         case cursorBottomRight:
    1588         [ #  # ]:          0 :             bSuccess = goTo( m_nColumnCount - 1, m_nRowCount - 1 );
    1589                 :          0 :             break;
    1590                 :            : 
    1591                 :            :         case cursorSelectRow:
    1592                 :            :         {
    1593         [ #  # ]:          0 :             if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
    1594                 :          0 :                 return bSuccess = false;
    1595                 :            :             //pos is the position of the current row in the vector of selected rows, if current row is selected
    1596         [ #  # ]:          0 :             int pos = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
    1597                 :            :             //if current row is selected, it should be deselected, when ALT+SPACE are pressed
    1598         [ #  # ]:          0 :             if(pos>-1)
    1599                 :            :             {
    1600 [ #  # ][ #  # ]:          0 :                 m_aSelectedRows.erase(m_aSelectedRows.begin()+pos);
    1601 [ #  # ][ #  # ]:          0 :                 if(m_aSelectedRows.empty() && m_nAnchor != -1)
                 [ #  # ]
    1602                 :          0 :                     m_nAnchor = -1;
    1603                 :            :             }
    1604                 :            :             //else select the row->put it in the vector
    1605                 :            :             else
    1606         [ #  # ]:          0 :                 m_aSelectedRows.push_back(m_nCurRow);
    1607         [ #  # ]:          0 :             invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1608                 :          0 :             selectionChanged = true;
    1609                 :          0 :             bSuccess = true;
    1610                 :            :         }
    1611                 :          0 :             break;
    1612                 :            :         case cursorSelectRowUp:
    1613                 :            :         {
    1614         [ #  # ]:          0 :             if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
    1615                 :          0 :                 return bSuccess = false;
    1616         [ #  # ]:          0 :             else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
    1617                 :            :             {
    1618                 :            :                 //if there are other selected rows, deselect them
    1619                 :          0 :                 return false;
    1620                 :            :             }
    1621                 :            :             else
    1622                 :            :             {
    1623                 :            :                 //there are other selected rows
    1624         [ #  # ]:          0 :                 if(!m_aSelectedRows.empty())
    1625                 :            :                 {
    1626                 :            :                     //the anchor wasn't set -> a region is not selected, that's why clear all selection
    1627                 :            :                     //and select the current row
    1628         [ #  # ]:          0 :                     if(m_nAnchor==-1)
    1629                 :            :                     {
    1630   [ #  #  #  # ]:          0 :                         for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
                 [ #  # ]
    1631                 :          0 :                             it!=m_aSelectedRows.end();++it)
    1632                 :            :                         {
    1633 [ #  # ][ #  # ]:          0 :                             invalidateSelectedRegion(*it, *it, rCells);
                 [ #  # ]
    1634                 :            :                         }
    1635                 :          0 :                         m_aSelectedRows.clear();
    1636         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1637         [ #  # ]:          0 :                         invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1638                 :            :                     }
    1639                 :            :                     else
    1640                 :            :                     {
    1641                 :            :                         //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected
    1642         [ #  # ]:          0 :                         int prevRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
    1643         [ #  # ]:          0 :                         int nextRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow-1);
    1644         [ #  # ]:          0 :                         if(prevRow>-1)
    1645                 :            :                          {
    1646                 :            :                              //if m_nCurRow isn't the upper one, can move up, otherwise not
    1647         [ #  # ]:          0 :                             if(m_nCurRow>0)
    1648                 :          0 :                                  m_nCurRow--;
    1649                 :            :                              else
    1650                 :          0 :                                  return bSuccess = true;
    1651                 :            :                              //if nextRow already selected, deselect it, otherwise select it
    1652 [ #  # ][ #  # ]:          0 :                              if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
         [ #  # ][ #  # ]
    1653                 :            :                              {
    1654 [ #  # ][ #  # ]:          0 :                                  m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
    1655         [ #  # ]:          0 :                                  invalidateSelectedRegion(m_nCurRow+1, m_nCurRow+1, rCells);
    1656                 :            :                              }
    1657                 :            :                              else
    1658                 :            :                             {
    1659         [ #  # ]:          0 :                                  m_aSelectedRows.push_back(m_nCurRow);
    1660         [ #  # ]:          0 :                                  invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1661                 :            :                              }
    1662                 :            :                          }
    1663                 :            :                         else
    1664                 :            :                         {
    1665         [ #  # ]:          0 :                             if(m_nCurRow>0)
    1666                 :            :                             {
    1667         [ #  # ]:          0 :                                 m_aSelectedRows.push_back(m_nCurRow);
    1668                 :          0 :                                 m_nCurRow--;
    1669         [ #  # ]:          0 :                                 m_aSelectedRows.push_back(m_nCurRow);
    1670         [ #  # ]:          0 :                                 invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
    1671                 :            :                             }
    1672                 :            :                         }
    1673                 :            :                     }
    1674                 :            :                 }
    1675                 :            :                 else
    1676                 :            :                 {
    1677                 :            :                     //if nothing is selected and the current row isn't the upper one
    1678                 :            :                     //select the current and one row above
    1679                 :            :                     //otherwise select only the upper row
    1680         [ #  # ]:          0 :                     if(m_nCurRow>0)
    1681                 :            :                     {
    1682         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1683                 :          0 :                         m_nCurRow--;
    1684         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1685         [ #  # ]:          0 :                         invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells);
    1686                 :            :                     }
    1687                 :            :                     else
    1688                 :            :                     {
    1689         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1690         [ #  # ]:          0 :                         invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1691                 :            :                     }
    1692                 :            :                 }
    1693         [ #  # ]:          0 :                 m_pSelEngine->SetAnchor(sal_True);
    1694                 :          0 :                 m_nAnchor = m_nCurRow;
    1695         [ #  # ]:          0 :                 ensureVisible(m_nCurColumn, m_nCurRow, false);
    1696                 :          0 :                 selectionChanged = true;
    1697                 :          0 :                 bSuccess = true;
    1698                 :            :             }
    1699                 :            :         }
    1700                 :          0 :         break;
    1701                 :            :         case cursorSelectRowDown:
    1702                 :            :         {
    1703         [ #  # ]:          0 :             if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
    1704                 :          0 :                 bSuccess = false;
    1705         [ #  # ]:          0 :             else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
    1706                 :            :             {
    1707                 :          0 :                 bSuccess = false;
    1708                 :            :             }
    1709                 :            :             else
    1710                 :            :             {
    1711         [ #  # ]:          0 :                 if(!m_aSelectedRows.empty())
    1712                 :            :                 {
    1713                 :            :                     //the anchor wasn't set -> a region is not selected, that's why clear all selection
    1714                 :            :                     //and select the current row
    1715         [ #  # ]:          0 :                     if(m_nAnchor==-1)
    1716                 :            :                     {
    1717   [ #  #  #  # ]:          0 :                         for(std::vector<RowPos>::iterator it=m_aSelectedRows.begin();
                 [ #  # ]
    1718                 :          0 :                             it!=m_aSelectedRows.end();++it)
    1719                 :            :                         {
    1720 [ #  # ][ #  # ]:          0 :                             invalidateSelectedRegion(*it, *it, rCells);
                 [ #  # ]
    1721                 :            :                         }
    1722                 :          0 :                         m_aSelectedRows.clear();
    1723         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1724         [ #  # ]:          0 :                         invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1725                 :            :                         }
    1726                 :            :                     else
    1727                 :            :                     {
    1728                 :            :                         //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected
    1729         [ #  # ]:          0 :                         int prevRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
    1730         [ #  # ]:          0 :                         int nextRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow+1);
    1731         [ #  # ]:          0 :                         if(prevRow>-1)
    1732                 :            :                          {
    1733                 :            :                              //if m_nCurRow isn't the last one, can move down, otherwise not
    1734         [ #  # ]:          0 :                              if(m_nCurRow<m_nRowCount-1)
    1735                 :          0 :                                  m_nCurRow++;
    1736                 :            :                              else
    1737                 :          0 :                                 return bSuccess = true;
    1738                 :            :                              //if next row already selected, deselect it, otherwise select it
    1739 [ #  # ][ #  # ]:          0 :                              if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
         [ #  # ][ #  # ]
    1740                 :            :                              {
    1741 [ #  # ][ #  # ]:          0 :                                  m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
    1742         [ #  # ]:          0 :                                  invalidateSelectedRegion(m_nCurRow-1, m_nCurRow-1, rCells);
    1743                 :            :                              }
    1744                 :            :                              else
    1745                 :            :                              {
    1746         [ #  # ]:          0 :                                  m_aSelectedRows.push_back(m_nCurRow);
    1747         [ #  # ]:          0 :                                  invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1748                 :            :                              }
    1749                 :            :                         }
    1750                 :            :                         else
    1751                 :            :                         {
    1752         [ #  # ]:          0 :                             if(m_nCurRow<m_nRowCount-1)
    1753                 :            :                             {
    1754         [ #  # ]:          0 :                                 m_aSelectedRows.push_back(m_nCurRow);
    1755                 :          0 :                                 m_nCurRow++;
    1756         [ #  # ]:          0 :                                 m_aSelectedRows.push_back(m_nCurRow);
    1757         [ #  # ]:          0 :                                 invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
    1758                 :            :                             }
    1759                 :            :                         }
    1760                 :            :                     }
    1761                 :            :                 }
    1762                 :            :                 else
    1763                 :            :                 {
    1764                 :            :                     //there wasn't any selection, select current and row beneath, otherwise only row beneath
    1765         [ #  # ]:          0 :                     if(m_nCurRow<m_nRowCount-1)
    1766                 :            :                     {
    1767         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1768                 :          0 :                         m_nCurRow++;
    1769         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1770         [ #  # ]:          0 :                         invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells);
    1771                 :            :                     }
    1772                 :            :                     else
    1773                 :            :                     {
    1774         [ #  # ]:          0 :                         m_aSelectedRows.push_back(m_nCurRow);
    1775         [ #  # ]:          0 :                         invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells);
    1776                 :            :                     }
    1777                 :            :                 }
    1778         [ #  # ]:          0 :                 m_pSelEngine->SetAnchor(sal_True);
    1779                 :          0 :                 m_nAnchor = m_nCurRow;
    1780         [ #  # ]:          0 :                 ensureVisible(m_nCurColumn, m_nCurRow, false);
    1781                 :          0 :                 selectionChanged = true;
    1782                 :          0 :                 bSuccess = true;
    1783                 :            :             }
    1784                 :            :         }
    1785                 :          0 :         break;
    1786                 :            : 
    1787                 :            :         case cursorSelectRowAreaTop:
    1788                 :            :         {
    1789         [ #  # ]:          0 :             if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
    1790                 :          0 :                 bSuccess = false;
    1791         [ #  # ]:          0 :             else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
    1792                 :          0 :                 bSuccess = false;
    1793                 :            :             else
    1794                 :            :             {
    1795                 :            :                 //select the region between the current and the upper row
    1796                 :          0 :                 RowPos iter = m_nCurRow;
    1797         [ #  # ]:          0 :                 invalidateSelectedRegion(m_nCurRow, 0, rCells);
    1798                 :            :                 //put the rows in vector
    1799         [ #  # ]:          0 :                 while(iter>=0)
    1800                 :            :                 {
    1801 [ #  # ][ #  # ]:          0 :                     if ( !isRowSelected( iter ) )
    1802         [ #  # ]:          0 :                         m_aSelectedRows.push_back(iter);
    1803                 :          0 :                     --iter;
    1804                 :            :                 }
    1805                 :          0 :                 m_nCurRow = 0;
    1806                 :          0 :                 m_nAnchor = m_nCurRow;
    1807         [ #  # ]:          0 :                 m_pSelEngine->SetAnchor(sal_True);
    1808         [ #  # ]:          0 :                 ensureVisible(m_nCurColumn, 0, false);
    1809                 :          0 :                 selectionChanged = true;
    1810                 :          0 :                 bSuccess = true;
    1811                 :            :             }
    1812                 :            :         }
    1813                 :          0 :         break;
    1814                 :            : 
    1815                 :            :         case cursorSelectRowAreaBottom:
    1816                 :            :         {
    1817         [ #  # ]:          0 :             if(m_pSelEngine->GetSelectionMode() == NO_SELECTION)
    1818                 :          0 :                 return bSuccess = false;
    1819         [ #  # ]:          0 :             else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION)
    1820                 :          0 :                 return bSuccess = false;
    1821                 :            :             //select the region between the current and the last row
    1822                 :          0 :             RowPos iter = m_nCurRow;
    1823         [ #  # ]:          0 :             invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells);
    1824                 :            :             //put the rows in the vector
    1825         [ #  # ]:          0 :             while(iter<=m_nRowCount)
    1826                 :            :             {
    1827 [ #  # ][ #  # ]:          0 :                 if ( !isRowSelected( iter ) )
    1828         [ #  # ]:          0 :                     m_aSelectedRows.push_back(iter);
    1829                 :          0 :                 ++iter;
    1830                 :            :             }
    1831                 :          0 :             m_nCurRow = m_nRowCount-1;
    1832                 :          0 :             m_nAnchor = m_nCurRow;
    1833         [ #  # ]:          0 :             m_pSelEngine->SetAnchor(sal_True);
    1834         [ #  # ]:          0 :             ensureVisible(m_nCurColumn, m_nRowCount-1, false);
    1835                 :          0 :             selectionChanged = true;
    1836                 :          0 :             bSuccess = true;
    1837                 :            :         }
    1838                 :          0 :         break;
    1839                 :            :         default:
    1840                 :            :             OSL_FAIL( "TableControl_Impl::dispatchAction: unsupported action!" );
    1841                 :          0 :             break;
    1842                 :            :         }
    1843                 :            : 
    1844 [ #  # ][ #  # ]:          0 :         if ( bSuccess && selectionChanged )
    1845                 :            :         {
    1846         [ #  # ]:          0 :             m_rAntiImpl.Select();
    1847                 :            :         }
    1848                 :            : 
    1849                 :          0 :         return bSuccess;
    1850                 :            :     }
    1851                 :            : 
    1852                 :            :     //------------------------------------------------------------------------------------------------------------------
    1853                 :          0 :     void TableControl_Impl::impl_ni_doSwitchCursor( bool _bShow )
    1854                 :            :     {
    1855 [ #  # ][ #  # ]:          0 :         PTableRenderer pRenderer = !!m_pModel ? m_pModel->getRenderer() : PTableRenderer();
                 [ #  # ]
    1856         [ #  # ]:          0 :         if ( !!pRenderer )
    1857                 :            :         {
    1858         [ #  # ]:          0 :             Rectangle aCellRect;
    1859         [ #  # ]:          0 :             impl_getCellRect( m_nCurColumn, m_nCurRow, aCellRect );
    1860         [ #  # ]:          0 :             if ( _bShow )
    1861         [ #  # ]:          0 :                 pRenderer->ShowCellCursor( *m_pDataWindow, aCellRect );
    1862                 :            :             else
    1863         [ #  # ]:          0 :                 pRenderer->HideCellCursor( *m_pDataWindow, aCellRect );
    1864         [ #  # ]:          0 :         }
    1865                 :          0 :     }
    1866                 :            : 
    1867                 :            :     //------------------------------------------------------------------------------------------------------------------
    1868                 :          0 :     void TableControl_Impl::impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const
    1869                 :            :     {
    1870                 :            :         DBG_CHECK_ME();
    1871                 :            : 
    1872 [ #  # ][ #  # ]:          0 :         if  (   !m_pModel
         [ #  # ][ #  # ]
    1873                 :            :             ||  ( COL_INVALID == _nColumn )
    1874                 :            :             ||  ( ROW_INVALID == _nRow )
    1875                 :            :             )
    1876                 :            :         {
    1877                 :          0 :             _rCellRect.SetEmpty();
    1878                 :          0 :             return;
    1879                 :            :         }
    1880                 :            : 
    1881 [ #  # ][ #  # ]:          0 :         TableCellGeometry aCell( *this, impl_getAllVisibleCellsArea(), _nColumn, _nRow );
    1882         [ #  # ]:          0 :         _rCellRect = aCell.getRect();
    1883                 :            :     }
    1884                 :            : 
    1885                 :            :     //------------------------------------------------------------------------------------------------------------------
    1886                 :          0 :     RowPos TableControl_Impl::getRowAtPoint( const Point& rPoint ) const
    1887                 :            :     {
    1888                 :            :         DBG_CHECK_ME();
    1889                 :          0 :         return impl_getRowForAbscissa( rPoint.Y() );
    1890                 :            :     }
    1891                 :            : 
    1892                 :            :     //------------------------------------------------------------------------------------------------------------------
    1893                 :          0 :     ColPos TableControl_Impl::getColAtPoint( const Point& rPoint ) const
    1894                 :            :     {
    1895                 :            :         DBG_CHECK_ME();
    1896                 :          0 :         return impl_getColumnForOrdinate( rPoint.X() );
    1897                 :            :     }
    1898                 :            : 
    1899                 :            :     //------------------------------------------------------------------------------------------------------------------
    1900                 :          0 :     TableCell TableControl_Impl::hitTest( Point const & i_point ) const
    1901                 :            :     {
    1902                 :          0 :         TableCell aCell( getColAtPoint( i_point ), getRowAtPoint( i_point ) );
    1903         [ #  # ]:          0 :         if ( aCell.nColumn > COL_ROW_HEADERS )
    1904                 :            :         {
    1905         [ #  # ]:          0 :             PColumnModel const pColumn = m_pModel->getColumnModel( aCell.nColumn );
    1906                 :          0 :             MutableColumnMetrics const & rColInfo( m_aColumnWidths[ aCell.nColumn ] );
    1907 [ #  # ][ #  # ]:          0 :             if  (   ( rColInfo.getEnd() - 3 <= i_point.X() )
           [ #  #  #  # ]
    1908                 :          0 :                 &&  ( rColInfo.getEnd() >= i_point.X() )
    1909         [ #  # ]:          0 :                 &&  pColumn->isResizable()
    1910                 :            :                 )
    1911                 :            :             {
    1912                 :          0 :                 aCell.eArea = ColumnDivider;
    1913         [ #  # ]:          0 :             }
    1914                 :            :         }
    1915                 :          0 :         return aCell;
    1916                 :            :     }
    1917                 :            : 
    1918                 :            :     //------------------------------------------------------------------------------------------------------------------
    1919                 :          0 :     ColumnMetrics TableControl_Impl::getColumnMetrics( ColPos const i_column ) const
    1920                 :            :     {
    1921                 :            :         DBG_CHECK_ME();
    1922                 :            : 
    1923 [ #  # ][ #  # ]:          0 :         ENSURE_OR_RETURN( ( i_column >= 0 ) && ( i_column < m_pModel->getColumnCount() ),
                 [ #  # ]
    1924                 :            :             "TableControl_Impl::getColumnMetrics: illegal column index!", ColumnMetrics() );
    1925                 :          0 :         return (ColumnMetrics const &)m_aColumnWidths[ i_column ];
    1926                 :            :     }
    1927                 :            : 
    1928                 :            :     //------------------------------------------------------------------------------------------------------------------
    1929                 :          0 :     PTableModel TableControl_Impl::getModel() const
    1930                 :            :     {
    1931                 :          0 :         return m_pModel;
    1932                 :            :     }
    1933                 :            : 
    1934                 :            :     //------------------------------------------------------------------------------------------------------------------
    1935                 :          0 :     RowPos TableControl_Impl::getCurrentColumn() const
    1936                 :            :     {
    1937                 :          0 :         return m_nCurColumn;
    1938                 :            :     }
    1939                 :            : 
    1940                 :            :     //------------------------------------------------------------------------------------------------------------------
    1941                 :          0 :     RowPos TableControl_Impl::getCurrentRow() const
    1942                 :            :     {
    1943                 :          0 :         return m_nCurRow;
    1944                 :            :     }
    1945                 :            : 
    1946                 :            :     //------------------------------------------------------------------------------------------------------------------
    1947                 :          0 :     ::Size TableControl_Impl::getTableSizePixel() const
    1948                 :            :     {
    1949                 :          0 :         return m_pDataWindow->GetOutputSizePixel();
    1950                 :            :     }
    1951                 :            : 
    1952                 :            :     //------------------------------------------------------------------------------------------------------------------
    1953                 :          0 :     void TableControl_Impl::setPointer( Pointer const & i_pointer )
    1954                 :            :     {
    1955                 :            :         DBG_CHECK_ME();
    1956                 :          0 :         m_pDataWindow->SetPointer( i_pointer );
    1957                 :          0 :     }
    1958                 :            : 
    1959                 :            :     //------------------------------------------------------------------------------------------------------------------
    1960                 :          0 :     void TableControl_Impl::captureMouse()
    1961                 :            :     {
    1962                 :          0 :         m_pDataWindow->CaptureMouse();
    1963                 :          0 :     }
    1964                 :            : 
    1965                 :            :     //------------------------------------------------------------------------------------------------------------------
    1966                 :          0 :     void TableControl_Impl::releaseMouse()
    1967                 :            :     {
    1968                 :          0 :         m_pDataWindow->ReleaseMouse();
    1969                 :          0 :     }
    1970                 :            : 
    1971                 :            :     //------------------------------------------------------------------------------------------------------------------
    1972                 :          0 :     void TableControl_Impl::invalidate( TableArea const i_what )
    1973                 :            :     {
    1974   [ #  #  #  #  :          0 :         switch ( i_what )
                      # ]
    1975                 :            :         {
    1976                 :            :         case TableAreaColumnHeaders:
    1977         [ #  # ]:          0 :             m_pDataWindow->Invalidate( calcHeaderRect( true ) );
    1978                 :          0 :             break;
    1979                 :            : 
    1980                 :            :         case TableAreaRowHeaders:
    1981         [ #  # ]:          0 :             m_pDataWindow->Invalidate( calcHeaderRect( false ) );
    1982                 :          0 :             break;
    1983                 :            : 
    1984                 :            :         case TableAreaDataArea:
    1985         [ #  # ]:          0 :             m_pDataWindow->Invalidate( impl_getAllVisibleDataCellArea() );
    1986                 :          0 :             break;
    1987                 :            : 
    1988                 :            :         case TableAreaAll:
    1989                 :          0 :             m_pDataWindow->Invalidate();
    1990                 :          0 :             break;
    1991                 :            :         }
    1992                 :          0 :     }
    1993                 :            : 
    1994                 :            :     //------------------------------------------------------------------------------------------------------------------
    1995                 :          0 :     long TableControl_Impl::pixelWidthToAppFont( long const i_pixels ) const
    1996                 :            :     {
    1997         [ #  # ]:          0 :         return m_pDataWindow->PixelToLogic( Size( i_pixels, 0 ), MAP_APPFONT ).Width();
    1998                 :            :     }
    1999                 :            : 
    2000                 :            :     //------------------------------------------------------------------------------------------------------------------
    2001                 :          0 :     void TableControl_Impl::hideTracking()
    2002                 :            :     {
    2003                 :          0 :         m_pDataWindow->HideTracking();
    2004                 :          0 :     }
    2005                 :            : 
    2006                 :            :     //------------------------------------------------------------------------------------------------------------------
    2007                 :          0 :     void TableControl_Impl::showTracking( Rectangle const & i_location, sal_uInt16 const i_flags )
    2008                 :            :     {
    2009                 :          0 :         m_pDataWindow->ShowTracking( i_location, i_flags );
    2010                 :          0 :     }
    2011                 :            : 
    2012                 :            :     //------------------------------------------------------------------------------------------------------------------
    2013                 :          0 :     bool TableControl_Impl::activateCell( ColPos const i_col, RowPos const i_row )
    2014                 :            :     {
    2015                 :            :         DBG_CHECK_ME();
    2016                 :          0 :         return goTo( i_col, i_row );
    2017                 :            :     }
    2018                 :            : 
    2019                 :            :     //------------------------------------------------------------------------------------------------------------------
    2020                 :          0 :     void TableControl_Impl::invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect)
    2021                 :            :     {
    2022                 :            :         DBG_CHECK_ME();
    2023                 :            :         //get the visible area of the table control and set the Left and right border of the region to be repainted
    2024         [ #  # ]:          0 :         Rectangle const aAllCells( impl_getAllVisibleCellsArea() );
    2025                 :          0 :         _rCellRect.Left() = aAllCells.Left();
    2026                 :          0 :         _rCellRect.Right() = aAllCells.Right();
    2027                 :            :         //if only one row is selected
    2028         [ #  # ]:          0 :         if(_nPrevRow == _nCurRow)
    2029                 :            :         {
    2030         [ #  # ]:          0 :             Rectangle aCellRect;
    2031         [ #  # ]:          0 :             impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
    2032                 :          0 :             _rCellRect.Top() = aCellRect.Top();
    2033                 :          0 :             _rCellRect.Bottom() = aCellRect.Bottom();
    2034                 :            :         }
    2035                 :            :         //if the region is above the current row
    2036         [ #  # ]:          0 :         else if(_nPrevRow < _nCurRow )
    2037                 :            :         {
    2038         [ #  # ]:          0 :             Rectangle aCellRect;
    2039         [ #  # ]:          0 :             impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
    2040                 :          0 :             _rCellRect.Top() = aCellRect.Top();
    2041         [ #  # ]:          0 :             impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
    2042                 :          0 :             _rCellRect.Bottom() = aCellRect.Bottom();
    2043                 :            :         }
    2044                 :            :         //if the region is beneath the current row
    2045                 :            :         else
    2046                 :            :         {
    2047         [ #  # ]:          0 :             Rectangle aCellRect;
    2048         [ #  # ]:          0 :             impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
    2049                 :          0 :             _rCellRect.Top() = aCellRect.Top();
    2050         [ #  # ]:          0 :             impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
    2051                 :          0 :             _rCellRect.Bottom() = aCellRect.Bottom();
    2052                 :            :         }
    2053         [ #  # ]:          0 :         m_pDataWindow->Invalidate(_rCellRect);
    2054                 :          0 :     }
    2055                 :            :     //------------------------------------------------------------------------------------------------------------------
    2056                 :          0 :     void TableControl_Impl::invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow )
    2057                 :            :     {
    2058         [ #  # ]:          0 :         if ( m_nCursorHidden == 2 )
    2059                 :            :             // WTF? what kind of hack is this?
    2060                 :          0 :             --m_nCursorHidden;
    2061                 :            : 
    2062         [ #  # ]:          0 :         RowPos const firstRow = i_firstRow < m_nTopRow ? m_nTopRow : i_firstRow;
    2063         [ #  # ]:          0 :         RowPos const lastVisibleRow = m_nTopRow + impl_getVisibleRows( true ) - 1;
    2064 [ #  # ][ #  # ]:          0 :         RowPos const lastRow = ( ( i_lastRow == ROW_INVALID ) || ( i_lastRow > lastVisibleRow ) ) ? lastVisibleRow : i_lastRow;
    2065                 :            : 
    2066         [ #  # ]:          0 :         Rectangle aInvalidateRect;
    2067                 :            : 
    2068         [ #  # ]:          0 :         Rectangle const aVisibleCellsArea( impl_getAllVisibleCellsArea() );
    2069         [ #  # ]:          0 :         TableRowGeometry aRow( *this, aVisibleCellsArea, firstRow, true );
    2070 [ #  # ][ #  # ]:          0 :         while ( aRow.isValid() && ( aRow.getRow() <= lastRow ) )
         [ #  # ][ #  # ]
    2071                 :            :         {
    2072         [ #  # ]:          0 :             aInvalidateRect.Union( aRow.getRect() );
    2073         [ #  # ]:          0 :             aRow.moveDown();
    2074                 :            :         }
    2075                 :            : 
    2076         [ #  # ]:          0 :         if ( i_lastRow == ROW_INVALID )
    2077                 :          0 :             aInvalidateRect.Bottom() = m_pDataWindow->GetOutputSizePixel().Height();
    2078                 :            : 
    2079         [ #  # ]:          0 :         m_pDataWindow->Invalidate( aInvalidateRect );
    2080                 :          0 :     }
    2081                 :            : 
    2082                 :            :     //------------------------------------------------------------------------------
    2083                 :          0 :     void TableControl_Impl::checkCursorPosition()
    2084                 :            :     {
    2085                 :            :         DBG_CHECK_ME();
    2086                 :            : 
    2087                 :          0 :         TableSize nVisibleRows = impl_getVisibleRows(true);
    2088                 :          0 :         TableSize nVisibleCols = impl_getVisibleColumns(true);
    2089 [ #  # ][ #  # ]:          0 :         if  (   ( m_nTopRow + nVisibleRows > m_nRowCount )
    2090                 :            :             &&  ( m_nRowCount >= nVisibleRows )
    2091                 :            :             )
    2092                 :            :         {
    2093                 :          0 :             --m_nTopRow;
    2094                 :            :         }
    2095                 :            :         else
    2096                 :            :         {
    2097                 :          0 :             m_nTopRow = 0;
    2098                 :            :         }
    2099                 :            : 
    2100 [ #  # ][ #  # ]:          0 :         if  (   ( m_nLeftColumn + nVisibleCols > m_nColumnCount )
    2101                 :            :             &&  ( m_nColumnCount >= nVisibleCols )
    2102                 :            :             )
    2103                 :            :         {
    2104                 :          0 :             --m_nLeftColumn;
    2105                 :            :         }
    2106                 :            :         else
    2107                 :            :         {
    2108                 :          0 :             m_nLeftColumn = 0;
    2109                 :            :         }
    2110                 :            : 
    2111                 :          0 :         m_pDataWindow->Invalidate();
    2112                 :          0 :     }
    2113                 :            : 
    2114                 :            :     //--------------------------------------------------------------------
    2115                 :          0 :     TableSize TableControl_Impl::impl_getVisibleRows( bool _bAcceptPartialRow ) const
    2116                 :            :     {
    2117                 :            :         DBG_CHECK_ME();
    2118                 :            : 
    2119                 :            :         DBG_ASSERT( m_pDataWindow, "TableControl_Impl::impl_getVisibleRows: no data window!" );
    2120                 :            : 
    2121                 :            :         return lcl_getRowsFittingInto(
    2122                 :          0 :             m_pDataWindow->GetOutputSizePixel().Height() - m_nColHeaderHeightPixel,
    2123                 :            :             m_nRowHeightPixel,
    2124                 :            :             _bAcceptPartialRow
    2125                 :          0 :         );
    2126                 :            :     }
    2127                 :            : 
    2128                 :            :     //--------------------------------------------------------------------
    2129                 :          0 :     TableSize TableControl_Impl::impl_getVisibleColumns( bool _bAcceptPartialCol ) const
    2130                 :            :     {
    2131                 :            :         DBG_CHECK_ME();
    2132                 :            : 
    2133                 :            :         DBG_ASSERT( m_pDataWindow, "TableControl_Impl::impl_getVisibleColumns: no data window!" );
    2134                 :            : 
    2135                 :            :         return lcl_getColumnsVisibleWithin(
    2136                 :          0 :             Rectangle( Point( 0, 0 ), m_pDataWindow->GetOutputSizePixel() ),
    2137                 :            :             m_nLeftColumn,
    2138                 :            :             *this,
    2139                 :            :             _bAcceptPartialCol
    2140 [ #  # ][ #  # ]:          0 :         );
    2141                 :            :     }
    2142                 :            : 
    2143                 :            :     //--------------------------------------------------------------------
    2144                 :          0 :     bool TableControl_Impl::goTo( ColPos _nColumn, RowPos _nRow )
    2145                 :            :     {
    2146                 :            :         DBG_CHECK_ME();
    2147                 :            : 
    2148                 :            :         // TODO: give veto listeners a chance
    2149                 :            : 
    2150 [ #  # ][ #  # ]:          0 :         if  (  ( _nColumn < 0 ) || ( _nColumn >= m_nColumnCount )
         [ #  # ][ #  # ]
    2151                 :            :             || ( _nRow < 0 ) || ( _nRow >= m_nRowCount )
    2152                 :            :             )
    2153                 :            :         {
    2154                 :            :             OSL_ENSURE( false, "TableControl_Impl::goTo: invalid row or column index!" );
    2155                 :          0 :             return false;
    2156                 :            :         }
    2157                 :            : 
    2158         [ #  # ]:          0 :         SuppressCursor aHideCursor( *this );
    2159                 :          0 :         m_nCurColumn = _nColumn;
    2160                 :          0 :         m_nCurRow = _nRow;
    2161                 :            : 
    2162                 :            :         // ensure that the new cell is visible
    2163         [ #  # ]:          0 :         ensureVisible( m_nCurColumn, m_nCurRow, false );
    2164         [ #  # ]:          0 :         return true;
    2165                 :            :     }
    2166                 :            : 
    2167                 :            :     //--------------------------------------------------------------------
    2168                 :          0 :     void TableControl_Impl::ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility )
    2169                 :            :     {
    2170                 :            :         DBG_CHECK_ME();
    2171                 :            :         DBG_ASSERT( ( _nColumn >= 0 ) && ( _nColumn < m_nColumnCount )
    2172                 :            :                  && ( _nRow >= 0 ) && ( _nRow < m_nRowCount ),
    2173                 :            :                  "TableControl_Impl::ensureVisible: invalid coordinates!" );
    2174                 :            : 
    2175         [ #  # ]:          0 :         SuppressCursor aHideCursor( *this );
    2176                 :            : 
    2177         [ #  # ]:          0 :         if ( _nColumn < m_nLeftColumn )
    2178         [ #  # ]:          0 :             impl_scrollColumns( _nColumn - m_nLeftColumn );
    2179                 :            :         else
    2180                 :            :         {
    2181         [ #  # ]:          0 :             TableSize nVisibleColumns = impl_getVisibleColumns( _bAcceptPartialVisibility );
    2182         [ #  # ]:          0 :             if ( _nColumn > m_nLeftColumn + nVisibleColumns - 1 )
    2183                 :            :             {
    2184         [ #  # ]:          0 :                 impl_scrollColumns( _nColumn - ( m_nLeftColumn + nVisibleColumns - 1 ) );
    2185                 :            :                 // TODO: since not all columns have the same width, this might in theory result
    2186                 :            :                 // in the column still not being visible.
    2187                 :            :             }
    2188                 :            :         }
    2189                 :            : 
    2190         [ #  # ]:          0 :         if ( _nRow < m_nTopRow )
    2191         [ #  # ]:          0 :             impl_scrollRows( _nRow - m_nTopRow );
    2192                 :            :         else
    2193                 :            :         {
    2194         [ #  # ]:          0 :             TableSize nVisibleRows = impl_getVisibleRows( _bAcceptPartialVisibility );
    2195         [ #  # ]:          0 :             if ( _nRow > m_nTopRow + nVisibleRows - 1 )
    2196         [ #  # ]:          0 :                 impl_scrollRows( _nRow - ( m_nTopRow + nVisibleRows - 1 ) );
    2197         [ #  # ]:          0 :         }
    2198                 :          0 :     }
    2199                 :            : 
    2200                 :            :     //--------------------------------------------------------------------
    2201                 :          0 :     ::rtl::OUString TableControl_Impl::getCellContentAsString( RowPos const i_row, ColPos const i_col )
    2202                 :            :     {
    2203                 :          0 :         ::com::sun::star::uno::Any content;
    2204         [ #  # ]:          0 :         m_pModel->getCellContent( i_col, i_row, content );
    2205         [ #  # ]:          0 :         return CellValueConversion::convertToString( content );
    2206                 :            :     }
    2207                 :            : 
    2208                 :            :     //--------------------------------------------------------------------
    2209                 :          0 :     TableSize TableControl_Impl::impl_ni_ScrollRows( TableSize _nRowDelta )
    2210                 :            :     {
    2211                 :            :         // compute new top row
    2212                 :            :         RowPos nNewTopRow =
    2213                 :            :             ::std::max(
    2214         [ #  # ]:          0 :                 ::std::min( (RowPos)( m_nTopRow + _nRowDelta ), (RowPos)( m_nRowCount - 1 ) ),
    2215                 :            :                 (RowPos)0
    2216         [ #  # ]:          0 :             );
    2217                 :            : 
    2218                 :          0 :         RowPos nOldTopRow = m_nTopRow;
    2219                 :          0 :         m_nTopRow = nNewTopRow;
    2220                 :            : 
    2221                 :            :         // if updates are enabled currently, scroll the viewport
    2222         [ #  # ]:          0 :         if ( m_nTopRow != nOldTopRow )
    2223                 :            :         {
    2224                 :            :             DBG_SUSPEND_INV( INV_SCROLL_POSITION );
    2225         [ #  # ]:          0 :             SuppressCursor aHideCursor( *this );
    2226                 :            :             // TODO: call a onStartScroll at our listener (or better an own onStartScroll,
    2227                 :            :             // which hides the cursor and then calls the listener)
    2228                 :            :             // Same for onEndScroll
    2229                 :            : 
    2230                 :            :             // scroll the view port, if possible
    2231                 :          0 :             long nPixelDelta = m_nRowHeightPixel * ( m_nTopRow - nOldTopRow );
    2232                 :            : 
    2233         [ #  # ]:          0 :             Rectangle aDataArea( Point( 0, m_nColHeaderHeightPixel ), m_pDataWindow->GetOutputSizePixel() );
    2234                 :            : 
    2235 [ #  # ][ #  # ]:          0 :             if  (   m_pDataWindow->GetBackground().IsScrollable()
         [ #  # ][ #  # ]
    2236         [ #  # ]:          0 :                 &&  abs( nPixelDelta ) < aDataArea.GetHeight()
    2237                 :            :                 )
    2238                 :            :             {
    2239         [ #  # ]:          0 :                 m_pDataWindow->Scroll( 0, (long)-nPixelDelta, aDataArea, SCROLL_CLIP | SCROLL_UPDATE | SCROLL_CHILDREN);
    2240                 :            :             }
    2241                 :            :             else
    2242         [ #  # ]:          0 :                 m_pDataWindow->Invalidate( INVALIDATE_UPDATE );
    2243                 :            : 
    2244                 :            :             // update the position at the vertical scrollbar
    2245 [ #  # ][ #  # ]:          0 :             m_pVScroll->SetThumbPos( m_nTopRow );
    2246                 :            :         }
    2247                 :            : 
    2248                 :            :         // The scroll bar availaility might change when we scrolled. This is because we do not hide
    2249                 :            :         // the scrollbar when it is, in theory, unnecessary, but currently at a position > 0. In this case, it will
    2250                 :            :         // be auto-hidden when it's scrolled back to pos 0.
    2251         [ #  # ]:          0 :         if ( m_nTopRow == 0 )
    2252         [ #  # ]:          0 :             m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
    2253                 :            : 
    2254                 :          0 :         return (TableSize)( m_nTopRow - nOldTopRow );
    2255                 :            :     }
    2256                 :            : 
    2257                 :            :     //--------------------------------------------------------------------
    2258                 :          0 :     TableSize TableControl_Impl::impl_scrollRows( TableSize const i_rowDelta )
    2259                 :            :     {
    2260                 :            :         DBG_CHECK_ME();
    2261                 :          0 :         return impl_ni_ScrollRows( i_rowDelta );
    2262                 :            :     }
    2263                 :            : 
    2264                 :            :     //--------------------------------------------------------------------
    2265                 :          0 :     TableSize TableControl_Impl::impl_ni_ScrollColumns( TableSize _nColumnDelta )
    2266                 :            :     {
    2267                 :            :         // compute new left column
    2268                 :            :         const ColPos nNewLeftColumn =
    2269                 :            :             ::std::max(
    2270         [ #  # ]:          0 :                 ::std::min( (ColPos)( m_nLeftColumn + _nColumnDelta ), (ColPos)( m_nColumnCount - 1 ) ),
    2271                 :            :                 (ColPos)0
    2272         [ #  # ]:          0 :             );
    2273                 :            : 
    2274                 :          0 :         const ColPos nOldLeftColumn = m_nLeftColumn;
    2275                 :          0 :         m_nLeftColumn = nNewLeftColumn;
    2276                 :            : 
    2277                 :            :         // if updates are enabled currently, scroll the viewport
    2278         [ #  # ]:          0 :         if ( m_nLeftColumn != nOldLeftColumn )
    2279                 :            :         {
    2280                 :            :             DBG_SUSPEND_INV( INV_SCROLL_POSITION );
    2281         [ #  # ]:          0 :             SuppressCursor aHideCursor( *this );
    2282                 :            :             // TODO: call a onStartScroll at our listener (or better an own onStartScroll,
    2283                 :            :             // which hides the cursor and then calls the listener)
    2284                 :            :             // Same for onEndScroll
    2285                 :            : 
    2286                 :            :             // scroll the view port, if possible
    2287         [ #  # ]:          0 :             const Rectangle aDataArea( Point( m_nRowHeaderWidthPixel, 0 ), m_pDataWindow->GetOutputSizePixel() );
    2288                 :            : 
    2289                 :            :             long nPixelDelta =
    2290                 :          0 :                     m_aColumnWidths[ nOldLeftColumn ].getStart()
    2291                 :          0 :                 -   m_aColumnWidths[ m_nLeftColumn ].getStart();
    2292                 :            : 
    2293                 :            :             // update our column positions
    2294                 :            :             // Do this *before* scrolling, as SCROLL_UPDATE will trigger a paint, which already needs the correct
    2295                 :            :             // information in m_aColumnWidths
    2296 [ #  # ][ #  # ]:          0 :             for (   ColumnPositions::iterator colPos = m_aColumnWidths.begin();
    2297                 :          0 :                     colPos != m_aColumnWidths.end();
    2298                 :            :                     ++colPos
    2299                 :            :                  )
    2300                 :            :             {
    2301                 :          0 :                 colPos->move( nPixelDelta );
    2302                 :            :             }
    2303                 :            : 
    2304                 :            :             // scroll the window content (if supported and possible), or invalidate the complete window
    2305 [ #  # ][ #  # ]:          0 :             if  (   m_pDataWindow->GetBackground().IsScrollable()
         [ #  # ][ #  # ]
    2306         [ #  # ]:          0 :                 &&  abs( nPixelDelta ) < aDataArea.GetWidth()
    2307                 :            :                 )
    2308                 :            :             {
    2309         [ #  # ]:          0 :                 m_pDataWindow->Scroll( nPixelDelta, 0, aDataArea, SCROLL_CLIP | SCROLL_UPDATE );
    2310                 :            :             }
    2311                 :            :             else
    2312         [ #  # ]:          0 :                 m_pDataWindow->Invalidate( INVALIDATE_UPDATE );
    2313                 :            : 
    2314                 :            :             // update the position at the horizontal scrollbar
    2315 [ #  # ][ #  # ]:          0 :             m_pHScroll->SetThumbPos( m_nLeftColumn );
    2316                 :            :         }
    2317                 :            : 
    2318                 :            :         // The scroll bar availaility might change when we scrolled. This is because we do not hide
    2319                 :            :         // the scrollbar when it is, in theory, unnecessary, but currently at a position > 0. In this case, it will
    2320                 :            :         // be auto-hidden when it's scrolled back to pos 0.
    2321         [ #  # ]:          0 :         if ( m_nLeftColumn == 0 )
    2322         [ #  # ]:          0 :             m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
    2323                 :            : 
    2324                 :          0 :         return (TableSize)( m_nLeftColumn - nOldLeftColumn );
    2325                 :            :     }
    2326                 :            : 
    2327                 :            :     //------------------------------------------------------------------------------------------------------------------
    2328                 :          0 :     TableSize TableControl_Impl::impl_scrollColumns( TableSize const i_columnDelta )
    2329                 :            :     {
    2330                 :            :         DBG_CHECK_ME();
    2331                 :          0 :         return impl_ni_ScrollColumns( i_columnDelta );
    2332                 :            :     }
    2333                 :            : 
    2334                 :            :     //------------------------------------------------------------------------------------------------------------------
    2335                 :          0 :     SelectionEngine* TableControl_Impl::getSelEngine()
    2336                 :            :     {
    2337                 :          0 :         return m_pSelEngine;
    2338                 :            :     }
    2339                 :            : 
    2340                 :            :     //------------------------------------------------------------------------------------------------------------------
    2341                 :          0 :     ScrollBar* TableControl_Impl::getHorzScrollbar()
    2342                 :            :     {
    2343                 :          0 :         return m_pHScroll;
    2344                 :            :     }
    2345                 :            : 
    2346                 :            :     //------------------------------------------------------------------------------------------------------------------
    2347                 :          0 :     ScrollBar* TableControl_Impl::getVertScrollbar()
    2348                 :            :     {
    2349                 :          0 :         return m_pVScroll;
    2350                 :            :     }
    2351                 :            : 
    2352                 :            :     //------------------------------------------------------------------------------------------------------------------
    2353                 :          0 :     bool TableControl_Impl::isRowSelected( RowPos i_row ) const
    2354                 :            :     {
    2355 [ #  # ][ #  # ]:          0 :         return ::std::find( m_aSelectedRows.begin(), m_aSelectedRows.end(), i_row ) != m_aSelectedRows.end();
    2356                 :            :     }
    2357                 :            : 
    2358                 :            :     //------------------------------------------------------------------------------------------------------------------
    2359                 :          0 :     RowPos TableControl_Impl::getSelectedRowIndex( size_t const i_selectionIndex ) const
    2360                 :            :     {
    2361         [ #  # ]:          0 :         if ( i_selectionIndex < m_aSelectedRows.size() )
    2362                 :          0 :             return m_aSelectedRows[ i_selectionIndex ];
    2363                 :          0 :         return ROW_INVALID;
    2364                 :            :     }
    2365                 :            : 
    2366                 :            :     //------------------------------------------------------------------------------------------------------------------
    2367                 :          0 :     int TableControl_Impl::getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current)
    2368                 :            :     {
    2369         [ #  # ]:          0 :         std::vector<RowPos>::const_iterator it = ::std::find(selectedRows.begin(),selectedRows.end(),current);
    2370 [ #  # ][ #  # ]:          0 :         if ( it != selectedRows.end() )
    2371                 :            :         {
    2372         [ #  # ]:          0 :             return it - selectedRows.begin();
    2373                 :            :         }
    2374                 :          0 :         return -1;
    2375                 :            :     }
    2376                 :            : 
    2377                 :            :     //--------------------------------------------------------------------
    2378                 :          0 :     ColPos TableControl_Impl::impl_getColumnForOrdinate( long const i_ordinate ) const
    2379                 :            :     {
    2380                 :            :         DBG_CHECK_ME();
    2381                 :            : 
    2382 [ #  # ][ #  # ]:          0 :         if ( ( m_aColumnWidths.empty() ) || ( i_ordinate < 0 ) )
                 [ #  # ]
    2383                 :          0 :             return COL_INVALID;
    2384                 :            : 
    2385         [ #  # ]:          0 :         if ( i_ordinate < m_nRowHeaderWidthPixel )
    2386                 :          0 :             return COL_ROW_HEADERS;
    2387                 :            : 
    2388                 :          0 :         long const ordinate = i_ordinate - m_nRowHeaderWidthPixel;
    2389                 :            : 
    2390                 :            :         ColumnPositions::const_iterator lowerBound = ::std::lower_bound(
    2391                 :            :             m_aColumnWidths.begin(),
    2392                 :            :             m_aColumnWidths.end(),
    2393                 :            :             MutableColumnMetrics(ordinate+1, ordinate+1),
    2394                 :            :             ColumnInfoPositionLess()
    2395         [ #  # ]:          0 :         );
    2396 [ #  # ][ #  # ]:          0 :         if ( lowerBound == m_aColumnWidths.end() )
    2397                 :            :         {
    2398                 :            :             // point is *behind* the start of the last column ...
    2399 [ #  # ][ #  # ]:          0 :             if ( ordinate < m_aColumnWidths.rbegin()->getEnd() )
    2400                 :            :                 // ... but still before its end
    2401                 :          0 :                 return m_nColumnCount - 1;
    2402                 :          0 :             return COL_INVALID;
    2403                 :            :         }
    2404         [ #  # ]:          0 :         return lowerBound - m_aColumnWidths.begin();
    2405                 :            :     }
    2406                 :            : 
    2407                 :            :     //--------------------------------------------------------------------
    2408                 :          0 :     RowPos TableControl_Impl::impl_getRowForAbscissa( long const i_abscissa ) const
    2409                 :            :     {
    2410                 :            :         DBG_CHECK_ME();
    2411                 :            : 
    2412         [ #  # ]:          0 :         if ( i_abscissa < 0 )
    2413                 :          0 :             return ROW_INVALID;
    2414                 :            : 
    2415         [ #  # ]:          0 :         if ( i_abscissa < m_nColHeaderHeightPixel )
    2416                 :          0 :             return ROW_COL_HEADERS;
    2417                 :            : 
    2418                 :          0 :         long const abscissa = i_abscissa - m_nColHeaderHeightPixel;
    2419                 :          0 :         long const row = m_nTopRow + abscissa / m_nRowHeightPixel;
    2420         [ #  # ]:          0 :         return row < m_pModel->getRowCount() ? row : ROW_INVALID;
    2421                 :            :     }
    2422                 :            : 
    2423                 :            :     //--------------------------------------------------------------------
    2424                 :          0 :     bool TableControl_Impl::markRowAsDeselected( RowPos const i_rowIndex )
    2425                 :            :     {
    2426                 :            :         DBG_CHECK_ME();
    2427                 :            : 
    2428         [ #  # ]:          0 :         ::std::vector< RowPos >::iterator selPos = ::std::find( m_aSelectedRows.begin(), m_aSelectedRows.end(), i_rowIndex );
    2429 [ #  # ][ #  # ]:          0 :         if ( selPos == m_aSelectedRows.end() )
    2430                 :          0 :             return false;
    2431                 :            : 
    2432         [ #  # ]:          0 :         m_aSelectedRows.erase( selPos );
    2433                 :          0 :         return true;
    2434                 :            :     }
    2435                 :            : 
    2436                 :            :     //--------------------------------------------------------------------
    2437                 :          0 :     bool TableControl_Impl::markRowAsSelected( RowPos const i_rowIndex )
    2438                 :            :     {
    2439                 :            :         DBG_CHECK_ME();
    2440                 :            : 
    2441         [ #  # ]:          0 :         if ( isRowSelected( i_rowIndex ) )
    2442                 :          0 :             return false;
    2443                 :            : 
    2444                 :          0 :         SelectionMode const eSelMode = getSelEngine()->GetSelectionMode();
    2445      [ #  #  # ]:          0 :         switch ( eSelMode )
    2446                 :            :         {
    2447                 :            :         case SINGLE_SELECTION:
    2448         [ #  # ]:          0 :             if ( !m_aSelectedRows.empty() )
    2449                 :            :             {
    2450                 :            :                 OSL_ENSURE( m_aSelectedRows.size() == 1, "TableControl::markRowAsSelected: SingleSelection with more than one selected element?" );
    2451                 :          0 :                 m_aSelectedRows[0] = i_rowIndex;
    2452                 :          0 :                 break;
    2453                 :            :             }
    2454                 :            :             // fall through
    2455                 :            : 
    2456                 :            :         case MULTIPLE_SELECTION:
    2457                 :          0 :             m_aSelectedRows.push_back( i_rowIndex );
    2458                 :          0 :             break;
    2459                 :            : 
    2460                 :            :         default:
    2461                 :            :             OSL_ENSURE( false, "TableControl_Impl::markRowAsSelected: unsupported selection mode!" );
    2462                 :          0 :             return false;
    2463                 :            :         }
    2464                 :            : 
    2465                 :          0 :         return true;
    2466                 :            :     }
    2467                 :            : 
    2468                 :            :     //--------------------------------------------------------------------
    2469                 :          0 :     bool TableControl_Impl::markAllRowsAsDeselected()
    2470                 :            :     {
    2471         [ #  # ]:          0 :         if ( m_aSelectedRows.empty() )
    2472                 :          0 :             return false;
    2473                 :            : 
    2474                 :          0 :         m_aSelectedRows.clear();
    2475                 :          0 :         return true;
    2476                 :            :     }
    2477                 :            : 
    2478                 :            :     //--------------------------------------------------------------------
    2479                 :          0 :     bool TableControl_Impl::markAllRowsAsSelected()
    2480                 :            :     {
    2481                 :            :         DBG_CHECK_ME();
    2482                 :            : 
    2483                 :          0 :         SelectionMode const eSelMode = getSelEngine()->GetSelectionMode();
    2484         [ #  # ]:          0 :         ENSURE_OR_RETURN_FALSE( eSelMode == MULTIPLE_SELECTION, "TableControl_Impl::markAllRowsAsSelected: unsupported selection mode!" );
    2485                 :            : 
    2486         [ #  # ]:          0 :         if ( m_aSelectedRows.size() == size_t( m_pModel->getRowCount() ) )
    2487                 :            :         {
    2488                 :            :         #if OSL_DEBUG_LEVEL > 0
    2489                 :            :             for ( TableSize row = 0; row < m_pModel->getRowCount(); ++row )
    2490                 :            :             {
    2491                 :            :                 OSL_ENSURE( isRowSelected( row ), "TableControl_Impl::markAllRowsAsSelected: inconsistency in the selected rows!" );
    2492                 :            :             }
    2493                 :            :         #endif
    2494                 :            :             // already all rows marked as selected
    2495                 :          0 :             return false;
    2496                 :            :         }
    2497                 :            : 
    2498                 :          0 :         m_aSelectedRows.clear();
    2499 [ #  # ][ #  # ]:          0 :         for ( RowPos i=0; i < m_pModel->getRowCount(); ++i )
    2500         [ #  # ]:          0 :             m_aSelectedRows.push_back(i);
    2501                 :            : 
    2502                 :          0 :         return true;
    2503                 :            :     }
    2504                 :            : 
    2505                 :            :     //--------------------------------------------------------------------
    2506                 :          0 :     Rectangle TableControl_Impl::calcHeaderRect(bool bColHeader)
    2507                 :            :     {
    2508         [ #  # ]:          0 :         Rectangle const aRectTableWithHeaders( impl_getAllVisibleCellsArea() );
    2509         [ #  # ]:          0 :         Size const aSizeTableWithHeaders( aRectTableWithHeaders.GetSize() );
    2510         [ #  # ]:          0 :         if ( bColHeader )
    2511         [ #  # ]:          0 :             return Rectangle( aRectTableWithHeaders.TopLeft(), Size( aSizeTableWithHeaders.Width(), m_nColHeaderHeightPixel ) );
    2512                 :            :         else
    2513         [ #  # ]:          0 :             return Rectangle( aRectTableWithHeaders.TopLeft(), Size( m_nRowHeaderWidthPixel, aSizeTableWithHeaders.Height() ) );
    2514                 :            :     }
    2515                 :            : 
    2516                 :            :     //--------------------------------------------------------------------
    2517                 :          0 :     Rectangle TableControl_Impl::calcTableRect()
    2518                 :            :     {
    2519                 :          0 :         return impl_getAllVisibleDataCellArea();
    2520                 :            :     }
    2521                 :            : 
    2522                 :            :     //--------------------------------------------------------------------
    2523                 :          0 :     IMPL_LINK( TableControl_Impl, OnUpdateScrollbars, void*, /**/ )
    2524                 :            :     {
    2525                 :            :         DBG_CHECK_ME();
    2526                 :          0 :         impl_ni_updateScrollbars();
    2527                 :          0 :         return 1L;
    2528                 :            :     }
    2529                 :            : 
    2530                 :            :     //--------------------------------------------------------------------
    2531                 :          0 :     IMPL_LINK( TableControl_Impl, OnScroll, ScrollBar*, _pScrollbar )
    2532                 :            :     {
    2533                 :            :         DBG_ASSERT( ( _pScrollbar == m_pVScroll ) || ( _pScrollbar == m_pHScroll ),
    2534                 :            :             "TableControl_Impl::OnScroll: where did this come from?" );
    2535                 :            : 
    2536         [ #  # ]:          0 :         if ( _pScrollbar == m_pVScroll )
    2537                 :          0 :             impl_ni_ScrollRows( _pScrollbar->GetDelta() );
    2538                 :            :         else
    2539                 :          0 :             impl_ni_ScrollColumns( _pScrollbar->GetDelta() );
    2540                 :            : 
    2541                 :          0 :         return 0L;
    2542                 :            :     }
    2543                 :            : 
    2544                 :            :     //------------------------------------------------------------------------------------------------------------------
    2545                 :          0 :     Reference< XAccessible > TableControl_Impl::getAccessible( Window& i_parentWindow )
    2546                 :            :     {
    2547                 :            :         DBG_TESTSOLARMUTEX();
    2548         [ #  # ]:          0 :         if ( m_pAccessibleTable == NULL )
    2549                 :            :         {
    2550         [ #  # ]:          0 :             Reference< XAccessible > const xAccParent = i_parentWindow.GetAccessible();
    2551         [ #  # ]:          0 :             if ( xAccParent.is() )
    2552                 :            :             {
    2553         [ #  # ]:          0 :                 m_pAccessibleTable = m_aFactoryAccess.getFactory().createAccessibleTableControl(
    2554                 :            :                     xAccParent, m_rAntiImpl
    2555         [ #  # ]:          0 :                 );
    2556                 :          0 :             }
    2557                 :            :         }
    2558                 :            : 
    2559                 :          0 :         Reference< XAccessible > xAccessible;
    2560         [ #  # ]:          0 :         if ( m_pAccessibleTable )
    2561 [ #  # ][ #  # ]:          0 :             xAccessible = m_pAccessibleTable->getMyself();
    2562                 :          0 :         return xAccessible;
    2563                 :            :     }
    2564                 :            : 
    2565                 :            :     //------------------------------------------------------------------------------------------------------------------
    2566                 :          0 :     void TableControl_Impl::disposeAccessible()
    2567                 :            :     {
    2568         [ #  # ]:          0 :         if ( m_pAccessibleTable )
    2569                 :          0 :             m_pAccessibleTable->dispose();
    2570                 :          0 :         m_pAccessibleTable = NULL;
    2571                 :          0 :     }
    2572                 :            : 
    2573                 :            :     //------------------------------------------------------------------------------------------------------------------
    2574                 :          0 :     bool TableControl_Impl::impl_isAccessibleAlive() const
    2575                 :            :     {
    2576                 :            :         DBG_CHECK_ME();
    2577 [ #  # ][ #  # ]:          0 :         return ( NULL != m_pAccessibleTable ) && m_pAccessibleTable->isAlive();
    2578                 :            :     }
    2579                 :            : 
    2580                 :            :     //------------------------------------------------------------------------------------------------------------------
    2581                 :          0 :     void TableControl_Impl::impl_commitAccessibleEvent( sal_Int16 const i_eventID, Any const & i_newValue, Any const & i_oldValue )
    2582                 :            :     {
    2583                 :            :         DBG_CHECK_ME();
    2584         [ #  # ]:          0 :         if ( impl_isAccessibleAlive() )
    2585                 :          0 :              m_pAccessibleTable->commitEvent( i_eventID, i_newValue, i_oldValue );
    2586                 :          0 :     }
    2587                 :            : 
    2588                 :            :     //==================================================================================================================
    2589                 :            :     //= TableFunctionSet
    2590                 :            :     //==================================================================================================================
    2591                 :            :     //------------------------------------------------------------------------------------------------------------------
    2592                 :          0 :     TableFunctionSet::TableFunctionSet(TableControl_Impl* _pTableControl)
    2593                 :            :         :m_pTableControl( _pTableControl)
    2594                 :          0 :         ,m_nCurrentRow( ROW_INVALID )
    2595                 :            :     {
    2596                 :          0 :     }
    2597                 :            :     //------------------------------------------------------------------------------------------------------------------
    2598                 :          0 :     TableFunctionSet::~TableFunctionSet()
    2599                 :            :     {
    2600         [ #  # ]:          0 :     }
    2601                 :            :     //------------------------------------------------------------------------------------------------------------------
    2602                 :          0 :     void TableFunctionSet::BeginDrag()
    2603                 :            :     {
    2604                 :          0 :     }
    2605                 :            :     //------------------------------------------------------------------------------------------------------------------
    2606                 :          0 :     void TableFunctionSet::CreateAnchor()
    2607                 :            :     {
    2608                 :          0 :         m_pTableControl->setAnchor( m_pTableControl->getCurRow() );
    2609                 :          0 :     }
    2610                 :            : 
    2611                 :            :     //------------------------------------------------------------------------------------------------------------------
    2612                 :          0 :     void TableFunctionSet::DestroyAnchor()
    2613                 :            :     {
    2614                 :          0 :         m_pTableControl->setAnchor( ROW_INVALID );
    2615                 :          0 :     }
    2616                 :            : 
    2617                 :            :     //------------------------------------------------------------------------------------------------------------------
    2618                 :          0 :     sal_Bool TableFunctionSet::SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor)
    2619                 :            :     {
    2620                 :          0 :         sal_Bool bHandled = sal_False;
    2621                 :            :         // newRow is the row which includes the point, getCurRow() is the last selected row, before the mouse click
    2622                 :          0 :         RowPos newRow = m_pTableControl->getRowAtPoint( rPoint );
    2623         [ #  # ]:          0 :         if ( newRow == ROW_COL_HEADERS )
    2624                 :          0 :             newRow = m_pTableControl->getTopRow();
    2625                 :            : 
    2626                 :          0 :         ColPos newCol = m_pTableControl->getColAtPoint( rPoint );
    2627         [ #  # ]:          0 :         if ( newCol == COL_ROW_HEADERS )
    2628                 :          0 :             newCol = m_pTableControl->getLeftColumn();
    2629                 :            : 
    2630 [ #  # ][ #  # ]:          0 :         if ( ( newRow == ROW_INVALID ) || ( newCol == COL_INVALID ) )
    2631                 :          0 :             return sal_False;
    2632                 :            : 
    2633         [ #  # ]:          0 :         if ( bDontSelectAtCursor )
    2634                 :            :         {
    2635         [ #  # ]:          0 :             if ( m_pTableControl->getSelectedRowCount() > 1 )
    2636                 :          0 :                 m_pTableControl->getSelEngine()->AddAlways(sal_True);
    2637                 :          0 :             bHandled = sal_True;
    2638                 :            :         }
    2639         [ #  # ]:          0 :         else if ( m_pTableControl->getAnchor() == m_pTableControl->getCurRow() )
    2640                 :            :         {
    2641                 :            :             //selecting region,
    2642                 :          0 :             int diff = m_pTableControl->getCurRow() - newRow;
    2643                 :            :             //selected region lies above the last selection
    2644         [ #  # ]:          0 :             if( diff >= 0)
    2645                 :            :             {
    2646                 :            :                 //put selected rows in vector
    2647         [ #  # ]:          0 :                 while ( m_pTableControl->getAnchor() >= newRow )
    2648                 :            :                 {
    2649         [ #  # ]:          0 :                     m_pTableControl->markRowAsSelected( m_pTableControl->getAnchor() );
    2650                 :          0 :                     m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
    2651                 :          0 :                     diff--;
    2652                 :            :                 }
    2653                 :          0 :                 m_pTableControl->setAnchor( m_pTableControl->getAnchor() + 1 );
    2654                 :            :             }
    2655                 :            :             //selected region lies beneath the last selected row
    2656                 :            :             else
    2657                 :            :             {
    2658         [ #  # ]:          0 :                 while ( m_pTableControl->getAnchor() <= newRow )
    2659                 :            :                 {
    2660         [ #  # ]:          0 :                     m_pTableControl->markRowAsSelected( m_pTableControl->getAnchor() );
    2661                 :          0 :                     m_pTableControl->setAnchor( m_pTableControl->getAnchor() + 1 );
    2662                 :          0 :                     diff++;
    2663                 :            :                 }
    2664                 :          0 :                 m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
    2665                 :            :             }
    2666         [ #  # ]:          0 :             Rectangle aCellRect;
    2667         [ #  # ]:          0 :             m_pTableControl->invalidateSelectedRegion( m_pTableControl->getCurRow(), newRow, aCellRect );
    2668                 :          0 :             bHandled = sal_True;
    2669                 :            :         }
    2670                 :            :         //no region selected
    2671                 :            :         else
    2672                 :            :         {
    2673         [ #  # ]:          0 :             if ( !m_pTableControl->hasRowSelection() )
    2674         [ #  # ]:          0 :                 m_pTableControl->markRowAsSelected( newRow );
    2675                 :            :             else
    2676                 :            :             {
    2677 [ #  # ][ #  # ]:          0 :                 if ( m_pTableControl->getSelEngine()->GetSelectionMode() == SINGLE_SELECTION )
    2678                 :            :                 {
    2679         [ #  # ]:          0 :                     DeselectAll();
    2680         [ #  # ]:          0 :                     m_pTableControl->markRowAsSelected( newRow );
    2681                 :            :                 }
    2682                 :            :                 else
    2683                 :            :                 {
    2684         [ #  # ]:          0 :                     m_pTableControl->markRowAsSelected( newRow );
    2685                 :            :                 }
    2686                 :            :             }
    2687 [ #  # ][ #  # ]:          0 :             if ( m_pTableControl->getSelectedRowCount() > 1 && m_pTableControl->getSelEngine()->GetSelectionMode() != SINGLE_SELECTION )
         [ #  # ][ #  # ]
    2688 [ #  # ][ #  # ]:          0 :                 m_pTableControl->getSelEngine()->AddAlways(sal_True);
    2689                 :            : 
    2690         [ #  # ]:          0 :             Rectangle aCellRect;
    2691         [ #  # ]:          0 :             m_pTableControl->invalidateSelectedRegion( newRow, newRow, aCellRect );
    2692                 :          0 :             bHandled = sal_True;
    2693                 :            :         }
    2694                 :          0 :         m_pTableControl->goTo( newCol, newRow );
    2695                 :          0 :         return bHandled;
    2696                 :            :     }
    2697                 :            :     //------------------------------------------------------------------------------------------------------------------
    2698                 :          0 :     sal_Bool TableFunctionSet::IsSelectionAtPoint( const Point& rPoint )
    2699                 :            :     {
    2700                 :          0 :         m_pTableControl->getSelEngine()->AddAlways(sal_False);
    2701         [ #  # ]:          0 :         if ( !m_pTableControl->hasRowSelection() )
    2702                 :          0 :             return sal_False;
    2703                 :            :         else
    2704                 :            :         {
    2705                 :          0 :             RowPos curRow = m_pTableControl->getRowAtPoint( rPoint );
    2706                 :          0 :             m_pTableControl->setAnchor( ROW_INVALID );
    2707                 :          0 :             bool selected = m_pTableControl->isRowSelected( curRow );
    2708                 :          0 :             m_nCurrentRow = curRow;
    2709                 :          0 :             return selected;
    2710                 :            :         }
    2711                 :            :     }
    2712                 :            :     //------------------------------------------------------------------------------------------------------------------
    2713                 :          0 :     void TableFunctionSet::DeselectAtPoint( const Point& rPoint )
    2714                 :            :     {
    2715                 :            :         (void)rPoint;
    2716         [ #  # ]:          0 :         Rectangle aCellRange;
    2717         [ #  # ]:          0 :         m_pTableControl->invalidateSelectedRegion( m_nCurrentRow, m_nCurrentRow, aCellRange );
    2718         [ #  # ]:          0 :         m_pTableControl->markRowAsDeselected( m_nCurrentRow );
    2719                 :          0 :     }
    2720                 :            : 
    2721                 :            :     //------------------------------------------------------------------------------------------------------------------
    2722                 :          0 :     void TableFunctionSet::DeselectAll()
    2723                 :            :     {
    2724         [ #  # ]:          0 :         if ( m_pTableControl->hasRowSelection() )
    2725                 :            :         {
    2726         [ #  # ]:          0 :             Rectangle aCellRange;
    2727         [ #  # ]:          0 :             for ( size_t i=0; i<m_pTableControl->getSelectedRowCount(); ++i )
    2728                 :            :             {
    2729         [ #  # ]:          0 :                 RowPos const rowIndex = m_pTableControl->getSelectedRowIndex(i);
    2730         [ #  # ]:          0 :                 m_pTableControl->invalidateSelectedRegion( rowIndex, rowIndex, aCellRange );
    2731                 :            :             }
    2732                 :            : 
    2733                 :          0 :             m_pTableControl->markAllRowsAsDeselected();
    2734                 :            :         }
    2735                 :          0 :     }
    2736                 :            : 
    2737                 :            : //......................................................................................................................
    2738 [ +  - ][ +  - ]:        843 : } } // namespace svt::table
    2739                 :            : //......................................................................................................................
    2740                 :            : 
    2741                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10