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