diff options
author | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-05-11 09:04:33 +0200 |
---|---|---|
committer | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-05-11 09:04:33 +0200 |
commit | 8fe1b22df970e2049d8143bf64a23b0ea4b6ad53 (patch) | |
tree | 29c908ea6f9f816671f0b7627d5a4980b2e9844c /svtools/source/table | |
parent | 45bf9199f52c19f3302c25b799133027b4addcd1 (diff) | |
parent | 54841bec35525663331fcc8081c316d264332277 (diff) |
unoawt: merge after pulling from CWS slidecopy
Diffstat (limited to 'svtools/source/table')
-rw-r--r-- | svtools/source/table/defaultinputhandler.cxx | 57 | ||||
-rw-r--r-- | svtools/source/table/gridtablerenderer.cxx | 276 | ||||
-rw-r--r-- | svtools/source/table/tablecontrol.cxx | 130 | ||||
-rw-r--r-- | svtools/source/table/tablecontrol_impl.cxx | 1415 | ||||
-rw-r--r-- | svtools/source/table/tablecontrol_impl.hxx | 161 | ||||
-rw-r--r-- | svtools/source/table/tabledatawindow.cxx | 84 | ||||
-rw-r--r-- | svtools/source/table/tablegeometry.cxx | 8 |
7 files changed, 1374 insertions, 757 deletions
diff --git a/svtools/source/table/defaultinputhandler.cxx b/svtools/source/table/defaultinputhandler.cxx index b11357db95d1..ad8f7a7562d3 100644 --- a/svtools/source/table/defaultinputhandler.cxx +++ b/svtools/source/table/defaultinputhandler.cxx @@ -50,6 +50,7 @@ namespace svt { namespace table //-------------------------------------------------------------------- DefaultInputHandler::DefaultInputHandler() :m_pImpl( new DefaultInputHandler_Impl ) + ,m_bResize(false) { } @@ -62,8 +63,12 @@ namespace svt { namespace table //-------------------------------------------------------------------- bool DefaultInputHandler::MouseMove( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt ) { - (void)_rControl; - (void)_rMEvt; + Point aPoint = _rMEvt.GetPosPixel(); + if(m_bResize) + { + _rControl.resizeColumn(aPoint); + return true; + } return false; } @@ -72,41 +77,60 @@ namespace svt { namespace table { bool bHandled = false; Point aPoint = _rMEvt.GetPosPixel(); - if(_rControl.isClickInVisibleArea(aPoint)) + RowPos nRow = _rControl.getCurrentRow(aPoint); + if(nRow == -1) + { + m_bResize = _rControl.startResizeColumn(aPoint); + bHandled = true; + } + else if(nRow >= 0) { if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION) { - LoseFocus(_rControl); _rControl.setCursorAtCurrentCell(aPoint); bHandled = true; } else { - bHandled = _rControl.getSelEngine()->SelMouseButtonDown(_rMEvt); + if(!_rControl.isRowSelected(nRow)) + bHandled = _rControl.getSelEngine()->SelMouseButtonDown(_rMEvt); + else + bHandled = true; } } return bHandled; } - //-------------------------------------------------------------------- bool DefaultInputHandler::MouseButtonUp( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt ) { bool bHandled = false; Point aPoint = _rMEvt.GetPosPixel(); - if(_rControl.isClickInVisibleArea(aPoint)) + if(_rControl.getCurrentRow(aPoint) >= 0) { - if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION) + if(m_bResize) + { + m_bResize = _rControl.endResizeColumn(aPoint); + bHandled = true; + } + else if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION) { - GetFocus(_rControl); - _rControl.setCursorAtCurrentCell(aPoint); bHandled = true; } else + { bHandled = _rControl.getSelEngine()->SelMouseButtonUp(_rMEvt); + } + } + else + { + if(m_bResize) + { + m_bResize = _rControl.endResizeColumn(aPoint); + bHandled = true; + } } return bHandled; } - //-------------------------------------------------------------------- bool DefaultInputHandler::KeyInput( IAbstractTableControl& _rControl, const KeyEvent& rKEvt ) { @@ -134,11 +158,11 @@ namespace svt { namespace table { KEY_PAGEDOWN, KEY_MOD1, cursorToLastLine }, { KEY_HOME, KEY_MOD1, cursorTopLeft }, { KEY_END, KEY_MOD1, cursorBottomRight }, - { KEY_SPACE, KEY_MOD1, cursorSelectRow }, - { KEY_UP, KEY_SHIFT, cursorSelectRowUp }, - { KEY_DOWN, KEY_SHIFT, cursorSelectRowDown }, - { KEY_END, KEY_SHIFT, cursorSelectRowAreaBottom }, - { KEY_HOME, KEY_SHIFT, cursorSelectRowAreaTop }, + { KEY_SPACE, KEY_MOD1, cursorSelectRow }, + { KEY_UP, KEY_SHIFT, cursorSelectRowUp }, + { KEY_DOWN, KEY_SHIFT, cursorSelectRowDown }, + { KEY_END, KEY_SHIFT, cursorSelectRowAreaBottom }, + { KEY_HOME, KEY_SHIFT, cursorSelectRowAreaTop }, { 0, 0, invalidTableControlAction } }; @@ -205,7 +229,6 @@ namespace svt { namespace table // TODO return false; } - //........................................................................ } } // namespace svt::table //........................................................................ diff --git a/svtools/source/table/gridtablerenderer.cxx b/svtools/source/table/gridtablerenderer.cxx index ada2e463c8af..a3f954e0bef5 100644 --- a/svtools/source/table/gridtablerenderer.cxx +++ b/svtools/source/table/gridtablerenderer.cxx @@ -31,6 +31,7 @@ #include <tools/debug.hxx> #include <vcl/window.hxx> +#include <vcl/image.hxx> //........................................................................ namespace svt { namespace table @@ -78,15 +79,15 @@ namespace svt { namespace table OSL_PRECOND( _bIsColHeaderArea || _bIsRowHeaderArea, "GridTableRenderer::PaintHeaderArea: invalid area flags!" ); - // fill the rows with alternating background colors - _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); - - _rDevice.SetLineColor(); - _rDevice.SetFillColor( _rStyle.GetDialogColor() ); + _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR); + Color background = m_pImpl->rModel.getHeaderBackgroundColor(); + if( background != 0xFFFFFF) + _rDevice.SetFillColor(background); + else + _rDevice.SetFillColor(_rStyle.GetDialogColor()); + _rDevice.SetLineColor(_rStyle.GetSeparatorColor()); _rDevice.DrawRect( _rArea ); - // delimiter lines at bottom/right - _rDevice.SetLineColor( _rStyle.GetDialogTextColor() ); _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); @@ -99,31 +100,38 @@ namespace svt { namespace table void GridTableRenderer::PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) { - _rDevice.Push( PUSH_LINECOLOR ); - - _rDevice.SetLineColor( _rStyle.GetDialogTextColor() ); - _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + _rDevice.Push( PUSH_LINECOLOR); + _rDevice.SetLineColor(_rStyle.GetSeparatorColor()); + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight()); String sHeaderText; - PColumnModel pColumn = m_pImpl->rModel.getColumnModel( _nCol ); DBG_ASSERT( !!pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" ); if ( !!pColumn ) sHeaderText = pColumn->getName(); - Color aRowBackground = _rStyle.GetFieldColor(); - if ( _bSelected ) - { - aRowBackground = COL_BLUE; - } - _rDevice.DrawText( _rArea, sHeaderText, TEXT_DRAW_LEFT | TEXT_DRAW_TOP ); + _rDevice.SetTextColor(m_pImpl->rModel.getTextColor()); + ULONG nHorFlag = TEXT_DRAW_LEFT; + ULONG nVerFlag = TEXT_DRAW_TOP; + if(m_pImpl->rModel.getVerticalAlign() == 1) + nVerFlag = TEXT_DRAW_VCENTER; + else if(m_pImpl->rModel.getVerticalAlign() == 2) + nVerFlag = TEXT_DRAW_BOTTOM; + if(m_pImpl->rModel.getColumnModel(_nCol)->getHorizontalAlign() == 1) + nHorFlag = TEXT_DRAW_CENTER; + else if(m_pImpl->rModel.getColumnModel(_nCol)->getHorizontalAlign() == 2) + nHorFlag = TEXT_DRAW_RIGHT; + Rectangle aRect(_rArea); + aRect.Left()+=4; aRect.Right()-=4; + aRect.Bottom()-=2; + _rDevice.DrawText( aRect, sHeaderText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP); _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); _rDevice.Pop(); (void)_bActive; // no special painting for the active column at the moment - //(void)_bSelected; - // TODO: selection not yet implemented + (void)_bSelected; + //selection for column header not yet implemented } //-------------------------------------------------------------------- @@ -133,86 +141,218 @@ namespace svt { namespace table // remember the row for subsequent calls to the other ->ITableRenderer methods m_pImpl->nCurrentRow = _nRow; - // fill the rows with alternating background colors - _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); - - _rDevice.SetLineColor(); - - Color aRowBackground = _rStyle.GetFieldColor(); + _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR); + Color aRowBackground = m_pImpl->rModel.getOddRowBackgroundColor(); + Color line = m_pImpl->rModel.getLineColor(); + Color aRowBackground2 = m_pImpl->rModel.getEvenRowBackgroundColor(); + //if row is selected background color becomes blue, and lines should be also blue + //if they aren't user defined + if(_bSelected) + { + Color aSelected(_rStyle.GetHighlightColor()); + aRowBackground = aSelected; + if(line == 0xFFFFFF) + _rDevice.SetLineColor(aRowBackground); + else + _rDevice.SetLineColor(line); + } + //if row not selected, check the cases whether user defined backgrounds are set + //and set line color to be the same + else + { + if(aRowBackground2 != 0xFFFFFF && _nRow%2) + { + aRowBackground = aRowBackground2; + if(line == 0xFFFFFF) + _rDevice.SetLineColor(aRowBackground); + else + _rDevice.SetLineColor(line); + } + //fill the rows with alternating background colors if second background color is specified + else if(aRowBackground != 0xFFFFFF && line == 0xFFFFFF) + _rDevice.SetLineColor(aRowBackground); + else + { + //if Line color is set, then it was user defined and should be visible + //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible + _rDevice.SetLineColor(line); + } + } _rDevice.SetFillColor( aRowBackground ); - _rDevice.DrawRect( _rRowArea ); - // TODO: active? selected? + // TODO: active? _rDevice.Pop(); - (void) _bSelected; (void)_bActive; - - // no special painting for the active row at the moment - - //(void)_bSelected; - // TODO: selection not yet implemented } //-------------------------------------------------------------------- void GridTableRenderer::PaintRowHeader( bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, rtl::OUString& _rText ) { - _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); - - _rDevice.SetLineColor( _rStyle.GetDialogTextColor() ); + _rDevice.Push( PUSH_LINECOLOR); + _rDevice.SetLineColor(_rStyle.GetSeparatorColor()); _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); - _rDevice.DrawText( _rArea, _rText, TEXT_DRAW_LEFT); + _rDevice.SetTextColor(m_pImpl->rModel.getTextColor()); + ULONG nHorFlag = TEXT_DRAW_LEFT; + ULONG nVerFlag = TEXT_DRAW_TOP; + if(m_pImpl->rModel.getVerticalAlign() == 1) + nVerFlag = TEXT_DRAW_VCENTER; + else if(m_pImpl->rModel.getVerticalAlign() == 2) + nVerFlag = TEXT_DRAW_BOTTOM; + if(m_pImpl->rModel.getColumnModel(0)->getHorizontalAlign() == 1) + nHorFlag = TEXT_DRAW_CENTER; + else if(m_pImpl->rModel.getColumnModel(0)->getHorizontalAlign() == 2) + nHorFlag = TEXT_DRAW_RIGHT; + Rectangle aRect(_rArea); + aRect.Left()+=4; aRect.Right()-=4; + aRect.Bottom()-=2; + _rDevice.DrawText( aRect, _rText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP); // TODO: active? selected? (void)_bActive; (void)_bSelected; - + //at the moment no special paint for selected row header _rDevice.Pop(); } //-------------------------------------------------------------------- - void GridTableRenderer::PaintCell( ColPos _nColumn, bool _bSelected, bool _bActive, - OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, rtl::OUString& _rText ) + void GridTableRenderer::PaintCellImage( ColPos _nColumn, bool _bSelected, bool _bActive, + OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, Image* _pCellData ) { - _rDevice.Push( PUSH_LINECOLOR ); - - // draw the grid - _rDevice.SetLineColor( COL_LIGHTGRAY ); - // TODO: the LIGHTGRAY should probably be a property/setting - _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); - _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); - + _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_CLIPREGION); + _rDevice.IntersectClipRegion( _rArea ); + Color background1 = m_pImpl->rModel.getOddRowBackgroundColor(); + Color background2 = m_pImpl->rModel.getEvenRowBackgroundColor(); + Color line = m_pImpl->rModel.getLineColor(); + //if row is selected and line color isn't user specified, set it blue + if(_bSelected) + { + if(line == 0xFFFFFF) + _rDevice.SetLineColor(_rStyle.GetHighlightColor()); + else + _rDevice.SetLineColor(line); + } + //else set line color to the color of row background + else + { + if(background2 != 0xFFFFFF && m_pImpl->nCurrentRow%2) + { + if(line == 0xFFFFFF) + _rDevice.SetLineColor(background2); + else + _rDevice.SetLineColor(line); + } + else if(background1 != 0xFFFFFF && line == 0xFFFFFF) + _rDevice.SetLineColor(background1); + else { + //if line color is set, then it was user defined and should be visible + //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible + _rDevice.SetLineColor(line); + } + } + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + { // TODO: remove those temporary place holders Rectangle aRect( _rArea ); ++aRect.Left(); --aRect.Right(); - ++aRect.Top(); --aRect.Bottom(); + aRect.Top(); aRect.Bottom(); + Point imagePos(Point(aRect.Left(), aRect.Top())); + Size imageSize = _pCellData->GetSizePixel(); + if(aRect.GetWidth() > imageSize.Width()) + { + if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 1) + imagePos.X() = aRect.Left()+((double)(aRect.GetWidth() - imageSize.Width()))/2; + else if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 2) + imagePos.X() = aRect.Right() - imageSize.Width(); + } + else + imageSize.Width() = aRect.GetWidth(); + if(aRect.GetHeight() > imageSize.Height()) + { + if(m_pImpl->rModel.getVerticalAlign() == 1) + imagePos.Y() = aRect.Top()+((double)(aRect.GetHeight() - imageSize.Height()))/2; + else if(m_pImpl->rModel.getVerticalAlign() == 2) + imagePos.Y() = aRect.Bottom() - imageSize.Height(); + } + else + imageSize.Height() = aRect.GetHeight()-1; + Image& image (*_pCellData); + _rDevice.DrawImage(imagePos, imageSize, image, 0); + } + _rDevice.Pop(); - String sText; - if(_bSelected) - { - Color aRed(COL_BLUE); - _rDevice.SetFillColor( aRed ); - _rDevice.SetTextColor(COL_WHITE); - } - _rDevice.DrawRect( _rArea ); - (void)_nColumn; - _rDevice.DrawText( aRect, _rText, TEXT_DRAW_LEFT | TEXT_DRAW_TOP); + (void)_bActive; + // no special painting for the active cell at the moment + } + + //-------------------------------------------------------------------- + void GridTableRenderer::PaintCellString( ColPos _nColumn, bool _bSelected, bool _bActive, + OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, rtl::OUString& _rText ) + { + _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); + Color background1 = m_pImpl->rModel.getOddRowBackgroundColor(); + Color background2 = m_pImpl->rModel.getEvenRowBackgroundColor(); + Color line = m_pImpl->rModel.getLineColor(); + //if row is selected and line color isn't user specified, set it blue + if(_bSelected) + { + if(line == 0xFFFFFF) + _rDevice.SetLineColor(_rStyle.GetHighlightColor()); + else + _rDevice.SetLineColor(line); + } + //else set line color to the color of row background + else + { + if(background2 != 0xFFFFFF && m_pImpl->nCurrentRow%2) + { + if(line == 0xFFFFFF) + _rDevice.SetLineColor(background2); + else + _rDevice.SetLineColor(line); + } + else if(background1 != 0xFFFFFF && line == 0xFFFFFF) + _rDevice.SetLineColor(background1); + else + { + //if Line color is set, then it was user defined and should be visible + //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible + _rDevice.SetLineColor(line); } + } + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + { + // TODO: remove those temporary place holders + Rectangle aRect( _rArea ); + ++aRect.Left(); --aRect.Right(); + aRect.Top(); aRect.Bottom(); if(_bSelected) { - _rDevice.SetFillColor( _rStyle.GetFieldColor() ); - _rDevice.SetTextColor(COL_BLACK); + _rDevice.SetTextColor(_rStyle.GetHighlightTextColor()); + } + else + _rDevice.SetTextColor(m_pImpl->rModel.getTextColor()); + ULONG nHorFlag = TEXT_DRAW_LEFT; + ULONG nVerFlag = TEXT_DRAW_TOP; + if(m_pImpl->rModel.getVerticalAlign() == 1) + nVerFlag = TEXT_DRAW_VCENTER; + else if(m_pImpl->rModel.getVerticalAlign() == 2) + nVerFlag = TEXT_DRAW_BOTTOM; + if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 1) + nHorFlag = TEXT_DRAW_CENTER; + else if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 2) + nHorFlag = TEXT_DRAW_RIGHT; + Rectangle textRect(_rArea); + textRect.Left()+=4; textRect.Right()-=4; + textRect.Bottom()-=2; + _rDevice.DrawText( textRect, _rText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP); } - _rDevice.Pop(); - (void)_bActive; -// // no special painting for the active cell at the moment - (void)_rStyle; -// // TODO: do we need this? + // no special painting for the active cell at the moment } //-------------------------------------------------------------------- @@ -224,7 +364,7 @@ namespace svt { namespace table //-------------------------------------------------------------------- void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect) { - (void)_rCursorRect; + (void)_rCursorRect; _rView.HideFocus(); } diff --git a/svtools/source/table/tablecontrol.cxx b/svtools/source/table/tablecontrol.cxx index 262c32ae8ebc..8c95fab6120b 100644 --- a/svtools/source/table/tablecontrol.cxx +++ b/svtools/source/table/tablecontrol.cxx @@ -30,6 +30,7 @@ #include "svtools/table/tablecontrol.hxx" #include "tablegeometry.hxx" #include "tablecontrol_impl.hxx" +#include "accessibletableimp.hxx" #include "svtools/table/tabledatawindow.hxx" #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <com/sun/star/accessibility/AccessibleRole.hpp> @@ -68,15 +69,19 @@ namespace svt { namespace table TableControl::TableControl( Window* _pParent, WinBits _nStyle ) :Control( _pParent, _nStyle ) ,m_pImpl( new TableControl_Impl( *this ) ) + ,m_bSelectionChanged(false) { - m_pImpl->getDataWindow()->SetMouseButtonDownHdl( LINK( this, TableControl, ImplMouseButtonDownHdl ) ); - m_pImpl->getDataWindow()->SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) ); + TableDataWindow* aTableData = m_pImpl->getDataWindow(); + aTableData->SetMouseButtonDownHdl( LINK( this, TableControl, ImplMouseButtonDownHdl ) ); + aTableData->SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) ); + aTableData->SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) ); m_pAccessTable.reset(new ::svt::table::AccessibleTableControl_Impl()); } //-------------------------------------------------------------------- TableControl::~TableControl() { + ImplCallEventListeners( VCLEVENT_OBJECT_DYING ); DELETEZ( m_pImpl ); if ( m_pAccessTable->m_pAccessible ) { @@ -106,6 +111,14 @@ namespace svt { namespace table { if ( !m_pImpl->getInputHandler()->KeyInput( *m_pImpl, rKEvt ) ) Control::KeyInput( rKEvt ); + else + { + if(m_bSelectionChanged) + { + Select(); + m_bSelectionChanged = false; + } + } } //-------------------------------------------------------------------- void TableControl::Resize() @@ -162,13 +175,21 @@ namespace svt { namespace table return m_pImpl->goTo( _nColPos, _nRowPos ); } //-------------------------------------------------------------------- - void TableControl::InvalidateDataWindow(RowPos _nRowStart, bool _bRemoved) + void TableControl::InvalidateDataWindow(RowPos _nRowStart, RowPos _nRowEnd, bool _bRemoved) { Rectangle _rRect; if(_bRemoved) - return m_pImpl->invalidateRows(_nRowStart, _rRect); + m_pImpl->invalidateRows(); else - return m_pImpl->invalidateRow(_nRowStart, _rRect); + { + if(m_bSelectionChanged) + { + m_pImpl->invalidateSelectedRegion(_nRowStart, _nRowEnd, _rRect); + m_bSelectionChanged = false; + } + else + m_pImpl->invalidateRow(_nRowStart, _rRect); + } } //-------------------------------------------------------------------- std::vector<sal_Int32>& TableControl::GetSelectedRows() @@ -176,7 +197,7 @@ namespace svt { namespace table return m_pImpl->getSelectedRows(); } //-------------------------------------------------------------------- - void TableControl::removeSelectedRow(RowPos _nRowPos) + void TableControl::RemoveSelectedRow(RowPos _nRowPos) { m_pImpl->removeSelectedRow(_nRowPos); } @@ -187,20 +208,6 @@ namespace svt { namespace table return m_pImpl->getCurrentRow( rPoint ); } - //-------------------------------------------------------------------- - - IMPL_LINK( TableControl, ImplMouseButtonDownHdl, MouseEvent*, pData ) - { - CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, pData ); - return 1; - } - - IMPL_LINK( TableControl, ImplMouseButtonUpHdl, MouseEvent*, pData ) - { - CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, pData ); - return 1; - } - SelectionEngine* TableControl::getSelEngine() { return m_pImpl->getSelEngine(); @@ -240,6 +247,7 @@ namespace svt { namespace table ::rtl::OUString TableControl::GetAccessibleObjectName( AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const { ::rtl::OUString aRetText; + //Window* pWin; switch( eObjType ) { case TCTYPE_GRIDCONTROL: @@ -255,7 +263,7 @@ namespace svt { namespace table aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ColumnHeaderBar" ) ); break; case TCTYPE_TABLECELL: - aRetText = GetCellContent(_nRow, _nCol); + aRetText = GetRowName(_nRow); break; case TCTYPE_ROWHEADERCELL: aRetText = GetRowName(_nRow); @@ -328,20 +336,23 @@ namespace svt { namespace table // ----------------------------------------------------------------------------- -::rtl::OUString TableControl::GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos) const +::com::sun::star::uno::Any TableControl::GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos) const { - ::rtl::OUString cellContent = ::rtl::OUString::createFromAscii(""); - std::vector<std::vector<rtl::OUString> >& aTableContent = GetModel()->getCellContent(); + ::com::sun::star::uno::Any cellContent(::com::sun::star::uno::Any(::rtl::OUString::createFromAscii(""))); + std::vector<std::vector< ::com::sun::star::uno::Any > >& aTableContent = GetModel()->getCellContent(); if(&aTableContent) - { - std::vector<rtl::OUString>& aRowContent = aTableContent[_nRowPos]; - if(&aRowContent) - cellContent = aRowContent[_nColPos]; - } + cellContent = aTableContent[_nRowPos][_nColPos]; return cellContent; } // ----------------------------------------------------------------------------- +::rtl::OUString TableControl::GetAccessibleCellText( sal_Int32 _nRowPos, sal_Int32 _nColPos) +{ + ::com::sun::star::uno::Any cellContent = GetCellContent(_nRowPos, _nColPos); + return m_pImpl->convertToString(cellContent); +} +// ----------------------------------------------------------------------------- + void TableControl::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet, AccessibleTableControlObjType eObjType ) const @@ -374,10 +385,6 @@ void TableControl::FillAccessibleStateSet( break; case TCTYPE_TABLECELL: { - //sal_Int32 nRow = GetCurRow(); - //sal_uInt16 nColumn = GetCurColumnId(); - //if ( IsFieldVisible(nRow,nColumn) ) - // rStateSet.AddState( AccessibleStateType::VISIBLE ); rStateSet.AddState( AccessibleStateType::TRANSIENT ); rStateSet.AddState( AccessibleStateType::SELECTABLE); if( GetSelectedRowCount()>0) @@ -516,25 +523,56 @@ void TableControl::commitGridControlEvent( sal_Int16 _nEventId, const Any& _rNew Rectangle TableControl::calcHeaderRect(sal_Bool _bIsColumnBar,BOOL _bOnScreen) { (void)_bOnScreen; - Rectangle aRectTable, aRectTableWithHeaders; - m_pImpl->impl_getAllVisibleDataCellArea(aRectTable); - m_pImpl->impl_getAllVisibleCellsArea(aRectTableWithHeaders); - Size aSizeTable(aRectTable.GetSize()); - Size aSizeTableWithHeaders(aRectTableWithHeaders.GetSize()); - if(_bIsColumnBar) - return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width()-aSizeTable.Width(), aSizeTableWithHeaders.Height())); - else - return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width(), aSizeTableWithHeaders.Height()-aSizeTable.Height())); + return m_pImpl->calcHeaderRect(_bIsColumnBar); } // ----------------------------------------------------------------------------- Rectangle TableControl::calcTableRect(BOOL _bOnScreen) { (void)_bOnScreen; - Rectangle aRect; - m_pImpl->impl_getAllVisibleDataCellArea(aRect); - return aRect; + return m_pImpl->calcTableRect(); +} +//-------------------------------------------------------------------- +::com::sun::star::uno::Sequence< sal_Int32 >& TableControl::getColumnsForTooltip() +{ + return m_nCols; +} +//-------------------------------------------------------------------- +::com::sun::star::uno::Sequence< ::rtl::OUString >& TableControl::getTextForTooltip() +{ + return m_aText; +} +//-------------------------------------------------------------------- +void TableControl::setTooltip(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aText, const ::com::sun::star::uno::Sequence< sal_Int32 >& nCols ) +{ + m_aText = aText; + m_nCols = nCols; +} +// ----------------------------------------------------------------------- +void TableControl::selectionChanged(bool _bChanged) +{ + m_bSelectionChanged = _bChanged; +} +// ----------------------------------------------------------------------- +IMPL_LINK( TableControl, ImplSelectHdl, void*, EMPTYARG ) +{ + Select(); + return 1; +} +IMPL_LINK( TableControl, ImplMouseButtonDownHdl, MouseEvent*, pData ) +{ + CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, pData ); + return 1; +} +IMPL_LINK( TableControl, ImplMouseButtonUpHdl, MouseEvent*, pData ) +{ + CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, pData ); + return 1; +} +// ----------------------------------------------------------------------- +void TableControl::Select() +{ + ImplCallEventListenersAndHandler( VCLEVENT_TABLEROW_SELECT, m_aSelectHdl, this ); } - //........................................................................ }} // namespace svt::table //........................................................................ diff --git a/svtools/source/table/tablecontrol_impl.cxx b/svtools/source/table/tablecontrol_impl.cxx index aacfc28d05be..1526dbdb778d 100644 --- a/svtools/source/table/tablecontrol_impl.cxx +++ b/svtools/source/table/tablecontrol_impl.cxx @@ -33,9 +33,13 @@ #include "tablecontrol_impl.hxx" #include "tablegeometry.hxx" #include "svtools/table/tabledatawindow.hxx" - +#include <com/sun/star/awt/XControl.hpp> #include <vcl/scrbar.hxx> #include <vcl/seleng.hxx> +#include <rtl/ref.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <vcl/image.hxx> +#include <com/sun/star/graphic/XGraphic.hpp> #include <functional> #include <stdlib.h> @@ -98,22 +102,22 @@ namespace svt { namespace table { return false; } - virtual void setRowHeaders(bool _bRowHeaders) + virtual void setRowHeaders(bool _bRowHeaders) { (void)_bRowHeaders; } - virtual void setColumnHeaders(bool _bColumnHeaders) - { - (void)_bColumnHeaders; - } - void setColumnCount(TableSize _nColCount) - { - (void) _nColCount; - } - void setRowCount(TableSize _nRowCount) + virtual void setColumnHeaders(bool _bColumnHeaders) { - (void)_nRowCount; + (void)_bColumnHeaders; } + void setColumnCount(TableSize _nColCount) + { + (void) _nColCount; + } + void setRowCount(TableSize _nRowCount) + { + (void)_nRowCount; + } virtual bool isCellEditable( ColPos col, RowPos row ) const { (void)col; @@ -166,39 +170,83 @@ namespace svt { namespace table { return 0; } - virtual ScrollbarVisibility getVerticalScrollbarVisibility(int overAllHeight, int actHeight) const - { - (void)overAllHeight; - (void)actHeight; - return ScrollbarShowNever; - } - virtual ScrollbarVisibility getHorizontalScrollbarVisibility(int overAllWidth, int actWidth) const - { - (void)overAllWidth; - (void)actWidth; - return ScrollbarShowNever; - } - virtual void setCellContent(std::vector<std::vector<rtl::OUString> > pCellEntryType) - { - (void)pCellEntryType; - } - virtual std::vector<std::vector<rtl::OUString> >& getCellContent() + virtual ScrollbarVisibility getVerticalScrollbarVisibility(int , int ) const { - return *( new std::vector<std::vector<rtl::OUString> >); + return ScrollbarShowNever; } - virtual void setRowHeaderName(std::vector<rtl::OUString> pCellEntryType) + virtual ScrollbarVisibility getHorizontalScrollbarVisibility(int , int ) const { - (void)pCellEntryType; + return ScrollbarShowNever; } - virtual std::vector<rtl::OUString>& getRowHeaderName() - { - aRowHeaderNames.clear(); - aRowHeaderNames.push_back(rtl::OUString::createFromAscii("")); - return aRowHeaderNames; - } - - private: - std::vector<rtl::OUString> aRowHeaderNames; + virtual bool hasVerticalScrollbar() + { + return false; + } + virtual bool hasHorizontalScrollbar() + { + return false; + } + virtual void setCellContent(const std::vector<std::vector< ::com::sun::star::uno::Any > >& ) + { + } + virtual ::com::sun::star::util::Color getLineColor() + { + return 0; + } + virtual void setLineColor(::com::sun::star::util::Color ) + { + } + virtual ::com::sun::star::util::Color getHeaderBackgroundColor() + { + return -1; + } + virtual void setHeaderBackgroundColor(::com::sun::star::util::Color ) + { + } + virtual ::com::sun::star::util::Color getTextColor() + { + return 0; + } + virtual void setTextColor(::com::sun::star::util::Color ) + { + } + virtual ::com::sun::star::util::Color getOddRowBackgroundColor() + { + return -1; + } + virtual void setOddRowBackgroundColor(::com::sun::star::util::Color ) + { + } + virtual ::com::sun::star::style::VerticalAlignment getVerticalAlign() + { + return com::sun::star::style::VerticalAlignment(0); + } + virtual void setVerticalAlign(com::sun::star::style::VerticalAlignment ) + { + } + virtual ::com::sun::star::util::Color getEvenRowBackgroundColor() + { + return -1; + } + virtual void setEvenRowBackgroundColor(::com::sun::star::util::Color ) + { + } + virtual std::vector<std::vector< ::com::sun::star::uno::Any > >& getCellContent() + { + return m_aCellContent; + } + virtual void setRowHeaderName(const std::vector<rtl::OUString>& ) + { + } + virtual std::vector<rtl::OUString>& getRowHeaderName() + { + aRowHeaderNames.clear(); + aRowHeaderNames.push_back(rtl::OUString::createFromAscii("")); + return aRowHeaderNames; + } + private: + std::vector<rtl::OUString> aRowHeaderNames; + std::vector<std::vector< ::com::sun::star::uno::Any > > m_aCellContent; }; @@ -222,8 +270,8 @@ namespace svt { namespace table :m_rTable( _rTable ) ,m_nSuspendFlags( _nSuspendFlags ) { - DBG_ASSERT( ( m_rTable.m_nRequiredInvariants & m_nSuspendFlags ) == m_nSuspendFlags, - "SuspendInvariants: cannot suspend what is already suspended!" ); + //DBG_ASSERT( ( m_rTable.m_nRequiredInvariants & m_nSuspendFlags ) == m_nSuspendFlags, + // "SuspendInvariants: cannot suspend what is already suspended!" ); const_cast< TableControl_Impl& >( m_rTable ).m_nRequiredInvariants &= ~m_nSuspendFlags; } ~SuspendInvariants() @@ -303,7 +351,7 @@ namespace svt { namespace table // m_nColHeaderHeightPixel consistent with the model's value? { TableMetrics nHeaderHeight = m_pModel->hasColumnHeaders() ? m_pModel->getColumnHeaderHeight() : 0; - nHeaderHeight = m_rAntiImpl.LogicToPixel( Size( 0, nHeaderHeight ), MAP_100TH_MM ).Height(); + nHeaderHeight = m_rAntiImpl.LogicToPixel( Size( 0, nHeaderHeight ), MAP_APPFONT ).Height(); if ( nHeaderHeight != m_nColHeaderHeightPixel ) return "column header heights are inconsistent!"; } @@ -312,7 +360,7 @@ namespace svt { namespace table if ( !isDummyModel ) { TableMetrics nRowHeight = m_pModel->getRowHeight(); - nRowHeight = m_rAntiImpl.LogicToPixel( Size( 0, nRowHeight ), MAP_100TH_MM ).Height(); + nRowHeight = m_rAntiImpl.LogicToPixel( Size( 0, nRowHeight ), MAP_APPFONT).Height(); if ( nRowHeight != m_nRowHeightPixel ) return "row heights are inconsistent!"; } @@ -320,13 +368,12 @@ namespace svt { namespace table // m_nRowHeaderWidthPixel consistent with the model's value? { TableMetrics nHeaderWidth = m_pModel->hasRowHeaders() ? m_pModel->getRowHeaderWidth() : 0; - nHeaderWidth = m_rAntiImpl.LogicToPixel( Size( nHeaderWidth, 0 ), MAP_100TH_MM ).Width(); + nHeaderWidth = m_rAntiImpl.LogicToPixel( Size( nHeaderWidth, 0 ), MAP_APPFONT ).Width(); if ( nHeaderWidth != m_nRowHeaderWidthPixel ) return "row header widths are inconsistent!"; } // TODO: check m_aColumnWidthsPixel and m_aAccColumnWidthsPixel - if ( m_nCursorHidden < 0 ) return "invalid hidden count for the cursor!"; @@ -369,30 +416,33 @@ namespace svt { namespace table ,m_pModel ( new EmptyTableModel ) ,m_pInputHandler ( ) ,m_nRowHeightPixel ( 15 ) - ,m_nColHeaderHeightPixel( 0 ) + ,m_nColHeaderHeightPixel( 0 ) ,m_nRowHeaderWidthPixel ( 0 ) ,m_nColumnCount ( 0 ) ,m_nRowCount ( 0 ) ,m_nCurColumn ( COL_INVALID ) ,m_nCurRow ( ROW_INVALID ) ,m_nLeftColumn ( 0 ) - ,m_nTopRow ( 0 ) + ,m_nTopRow ( 0 ) ,m_nCursorHidden ( 1 ) ,m_pDataWindow ( new TableDataWindow( *this ) ) - ,m_pVScroll ( NULL ) + ,m_pVScroll ( NULL ) ,m_pHScroll ( NULL ) ,m_pScrollCorner ( NULL ) - ,m_pSelEngine ( ) - ,m_nRowSelected ( ) - ,m_pTableFunctionSet ( new TableFunctionSet(this ) ) - ,m_nAnchor (-1 ) + ,m_pSelEngine ( ) + ,m_nRowSelected ( ) + ,m_pTableFunctionSet ( new TableFunctionSet(this ) ) + ,m_nAnchor (-1 ) + ,m_bResizing ( false ) + ,m_nResizingColumn ( 0 ) + ,m_bResizingGrid ( false ) #if DBG_UTIL ,m_nRequiredInvariants ( INV_SCROLL_POSITION ) #endif { DBG_CTOR( TableControl_Impl, TableControl_Impl_checkInvariants ); - m_pSelEngine = new SelectionEngine(m_pDataWindow, m_pTableFunctionSet); - m_pSelEngine->SetSelectionMode(SINGLE_SELECTION); + m_pSelEngine = new SelectionEngine(m_pDataWindow, m_pTableFunctionSet); + m_pSelEngine->SetSelectionMode(SINGLE_SELECTION); m_pDataWindow->SetPosPixel( Point( 0, 0 ) ); m_pDataWindow->Show(); } @@ -427,14 +477,10 @@ namespace svt { namespace table TempHideCursor aHideCursor( *this ); - // TODO: revoke as table listener from the model - m_pModel = _pModel; - if ( !m_pModel ) + if ( !m_pModel) m_pModel.reset( new EmptyTableModel ); - // TODO: register as table listener - //m_pModel->addTableModelListener(PTableModelListener(m_pTableModelListener)); m_nCurRow = ROW_INVALID; m_nCurColumn = COL_INVALID; @@ -504,11 +550,11 @@ namespace svt { namespace table m_pInputHandler.reset(); m_nColumnCount = m_nRowCount = 0; - m_nRowHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getRowHeight() ), MAP_100TH_MM ).Height(); - if ( m_pModel->hasColumnHeaders() ) - m_nColHeaderHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getColumnHeaderHeight() ), MAP_100TH_MM ).Height(); + m_nRowHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getRowHeight() ), MAP_APPFONT ).Height(); + if ( m_pModel->hasColumnHeaders() ) + m_nColHeaderHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getColumnHeaderHeight() ), MAP_APPFONT ).Height(); if ( m_pModel->hasRowHeaders() ) - m_nRowHeaderWidthPixel = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_100TH_MM ).Width(); + m_nRowHeaderWidthPixel = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT).Width(); impl_ni_updateColumnWidths(); @@ -529,34 +575,116 @@ namespace svt { namespace table return; TableSize colCount = m_pModel->getColumnCount(); + m_aColumnWidthsPixel.reserve( colCount ); m_aAccColumnWidthsPixel.reserve( colCount ); - long accumulatedPixelWidth = 0; - for ( ColPos col = 0; col < colCount; ++col ) + if(colCount>0) { - PColumnModel pColumn = m_pModel->getColumnModel( col ); - DBG_ASSERT( !!pColumn, "TableControl_Impl::impl_ni_updateColumnWidths: invalid column returned by the model!" ); - if ( !pColumn ) - continue; - - TableMetrics colWidth = pColumn->getWidth(); - DBG_ASSERT( ( colWidth == COLWIDTH_FIT_TO_VIEW ) || ( colWidth > 0 ), - "TableControl_Impl::impl_ni_updateColumnWidths: invalid column width!" ); - - long pixelWidth = 0; - if ( colWidth == COLWIDTH_FIT_TO_VIEW ) + std::vector<sal_Int32> aPrePixelWidths(0); + long accumulatedPixelWidth = 0; + int lastResizableCol = -1; + double gridWidth = m_rAntiImpl.GetOutputSizePixel().Width(); + if(m_pModel->hasRowHeaders()) + { + TableMetrics rowHeaderWidth = m_pModel->getRowHeaderWidth(); + gridWidth-= m_rAntiImpl.LogicToPixel( Size( rowHeaderWidth, 0 ), MAP_APPFONT ).Width(); + } + if(m_pModel->hasVerticalScrollbar()) { - // TODO - DBG_ERROR( "TableControl_Impl::impl_ni_updateColumnWidths: COLWIDTH_FIT_TO_VIEW not implemented, yet!" ); + sal_Int32 scrollbarWidth = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize(); + gridWidth-=scrollbarWidth; + } + double colWidthsSum = 0.0; + double colWithoutFixedWidthsSum = 0.0; + double minColWithoutFixedSum = 0.0; + for ( ColPos col = 0; col < colCount; ++col ) + { + PColumnModel pColumn = m_pModel->getColumnModel( col ); + DBG_ASSERT( !!pColumn, "TableControl_Impl::impl_ni_updateColumnWidths: invalid column returned by the model!" ); + if ( !pColumn ) + continue; + TableMetrics colWidth = 0; + TableMetrics colPrefWidth = pColumn->getPreferredWidth(); + bool bResizable = pColumn->isResizable(); + if(pColumn->getMinWidth() == 0 && bResizable) + { + pColumn->setMinWidth(1); + minColWithoutFixedSum+=m_rAntiImpl.LogicToPixel( Size( 1, 0 ), MAP_APPFONT ).Width(); + } + if(pColumn->getMaxWidth() == 0 && bResizable) + pColumn->setMaxWidth(m_rAntiImpl.LogicToPixel( Size( (int)gridWidth, 0 ), MAP_APPFONT ).Width()); + if( colPrefWidth != 0) + { + if(m_bResizingGrid) + { + colWidth = pColumn->getWidth(); + pColumn->setPreferredWidth(0); + } + else + { + colWidth = colPrefWidth; + pColumn->setWidth(colPrefWidth); + } + } + else + colWidth = pColumn->getWidth(); + long pixelWidth = m_rAntiImpl.LogicToPixel( Size( colWidth, 0 ), MAP_APPFONT ).Width(); + if(bResizable && colPrefWidth == 0) + { + colWithoutFixedWidthsSum+=pixelWidth; + lastResizableCol = col; + } + colWidthsSum+=pixelWidth; + aPrePixelWidths.push_back(pixelWidth); + } + double gridWidthWithoutFixed = gridWidth - colWidthsSum + colWithoutFixedWidthsSum; + double scalingFactor = 1.0; + if(m_bResizingGrid) + { + if(gridWidthWithoutFixed > (minColWithoutFixedSum+colWidthsSum - colWithoutFixedWidthsSum)) + scalingFactor = gridWidthWithoutFixed/colWithoutFixedWidthsSum; } else { - pixelWidth = m_rAntiImpl.LogicToPixel( Size( colWidth, 0 ), MAP_100TH_MM ).Width(); + if(colWidthsSum < gridWidthWithoutFixed) + { + if(colWithoutFixedWidthsSum>0) + scalingFactor = gridWidthWithoutFixed/colWithoutFixedWidthsSum; + } + } + for ( ColPos i = 0; i < colCount; ++i ) + { + PColumnModel pColumn = m_pModel->getColumnModel( i ); + DBG_ASSERT( !!pColumn, "TableControl_Impl::impl_ni_updateColumnWidths: invalid column returned by the model!" ); + if ( !pColumn ) + continue; + if(pColumn->isResizable() && pColumn->getPreferredWidth() == 0) + { + aPrePixelWidths[i]*=scalingFactor; + TableMetrics logicColWidth = m_rAntiImpl.PixelToLogic( Size( aPrePixelWidths[i], 0 ), MAP_APPFONT ).Width(); + pColumn->setWidth(logicColWidth); + } + m_aColumnWidthsPixel.push_back( aPrePixelWidths[i] ); + m_aAccColumnWidthsPixel.push_back( accumulatedPixelWidth += aPrePixelWidths[i] ); + } + if(gridWidth > m_aAccColumnWidthsPixel[colCount-1]) + { + if(lastResizableCol >= 0) + { + PColumnModel pColumn = m_pModel->getColumnModel(lastResizableCol); + m_aColumnWidthsPixel[lastResizableCol]+=gridWidth-m_aAccColumnWidthsPixel[colCount-1]; + TableMetrics logicColWidth1 = m_rAntiImpl.PixelToLogic( Size( m_aColumnWidthsPixel[lastResizableCol], 0 ), MAP_APPFONT ).Width(); + pColumn->setWidth(logicColWidth1); + while(lastResizableCol < colCount) + { + if(lastResizableCol == 0) + m_aAccColumnWidthsPixel[0] = m_aColumnWidthsPixel[lastResizableCol]; + else + m_aAccColumnWidthsPixel[lastResizableCol]=m_aAccColumnWidthsPixel[lastResizableCol-1]+m_aColumnWidthsPixel[lastResizableCol]; + ++lastResizableCol; + } + } } - - m_aColumnWidthsPixel.push_back( pixelWidth ); - - m_aAccColumnWidthsPixel.push_back( accumulatedPixelWidth += pixelWidth ); } } @@ -678,6 +806,13 @@ namespace svt { namespace table Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() ); aDataCellPlayground.Left() = m_nRowHeaderWidthPixel; aDataCellPlayground.Top() = m_nColHeaderHeightPixel; + m_nRowCount = m_pModel->getRowCount(); + m_nColumnCount = m_pModel->getColumnCount(); + + if(m_aAccColumnWidthsPixel.empty()) + { + impl_ni_updateColumnWidths(); + } // do we need a vertical scrollbar? bool bFirstRoundVScrollNeed = false; @@ -709,15 +844,6 @@ namespace svt { namespace table aDataCellPlayground.Right() -= nScrollbarMetrics; } } - else - { - Size regionWithoutHeader = m_rAntiImpl.PixelToLogic(Size(aDataCellPlayground.Right() - aDataCellPlayground.Left(),0),MAP_100TH_MM); - TableMetrics nColWidth = regionWithoutHeader.Width()/m_nColumnCount; - for ( ColPos col = 0; col < m_nColumnCount; ++col ) - m_pModel->getColumnModel(col)->setWidth(nColWidth); - m_rAntiImpl.SetModel(m_pModel); - } - // create or destroy the vertical scrollbar, as needed lcl_updateScrollbar( m_rAntiImpl, @@ -780,6 +906,11 @@ namespace svt { namespace table m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) ); m_pScrollCorner->Show(); } + else if(bHaveScrollCorner && bNeedScrollCorner) + { + m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) ); + m_pScrollCorner->Show(); + } // resize the data window m_pDataWindow->SetSizePixel( Size( @@ -792,10 +923,26 @@ namespace svt { namespace table void TableControl_Impl::onResize() { DBG_CHECK_ME(); - impl_ni_updateScrollbars(); - //Rectangle aAllCells; - // impl_getAllVisibleCellsArea( aAllCells ); - //m_pSelEngine->SetVisibleArea(aAllCells); + if(m_nRowCount != 0) + { + if(m_nColumnCount != 0) + { + if(m_bResizingGrid) + impl_ni_updateColumnWidths(); + invalidateRows(); + m_bResizingGrid = true; + } + } + else + { + //In the case that column headers are defined but data hasn't yet been set, + //only column headers will be shown + if(m_pModel->hasColumnHeaders()) + if(m_nColHeaderHeightPixel>1) + m_pDataWindow->SetSizePixel( m_rAntiImpl.GetOutputSizePixel()); + if(m_nColumnCount != 0) + impl_ni_updateScrollbars(); + } } //-------------------------------------------------------------------- @@ -805,7 +952,6 @@ namespace svt { namespace table if ( !getModel() ) return; - PTableRenderer pRenderer = getModel()->getRenderer(); DBG_ASSERT( !!pRenderer, "TableDataWindow::Paint: invalid renderer!" ); if ( !pRenderer ) @@ -813,21 +959,28 @@ namespace svt { namespace table // our current style settings, to be passed to the renderer const StyleSettings& rStyle = m_rAntiImpl.GetSettings().GetStyleSettings(); - + m_nRowCount = m_pModel->getRowCount(); + TableSize nVisibleRows = impl_getVisibleRows(true); + TableSize nActualRows = m_nRowCount; + if(m_nRowCount>nVisibleRows) + nActualRows = nVisibleRows; // the area occupied by all (at least partially) visible cells, including // headers Rectangle aAllCellsWithHeaders; impl_getAllVisibleCellsArea( aAllCellsWithHeaders ); - m_nRowCount = m_pModel->getRowCount(); // ............................ // draw the header column area - if ( getModel()->hasColumnHeaders() ) + if ( m_pModel->hasColumnHeaders() ) { TableRowGeometry aHeaderRow( *this, Rectangle( Point( 0, 0 ), aAllCellsWithHeaders.BottomRight() ), ROW_COL_HEADERS ); + Rectangle aColRect(aHeaderRow.getRect()); + //to avoid double lines when scrolling horizontally + if(m_nLeftColumn != 0) + --aColRect.Left(); pRenderer->PaintHeaderArea( - *m_pDataWindow, aHeaderRow.getRect(), true, false, rStyle + *m_pDataWindow, aColRect, true, false, rStyle ); // Note that strictly, aHeaderRow.getRect() also contains the intersection between column // and row header area. However, below we go to paint this intersection, again, @@ -850,14 +1003,18 @@ namespace svt { namespace table // the area occupied by the row header, if any Rectangle aRowHeaderArea; - if ( getModel()->hasRowHeaders() ) + if ( m_pModel->hasRowHeaders() ) { aRowHeaderArea = aAllCellsWithHeaders; aRowHeaderArea.Right() = m_nRowHeaderWidthPixel - 1; - aRowHeaderArea.Bottom() = m_nRowHeightPixel * m_nRowCount + m_nColHeaderHeightPixel - 1; - pRenderer->PaintHeaderArea( - *m_pDataWindow, aRowHeaderArea, false, true, rStyle - ); + if(m_nTopRow+nActualRows>m_nRowCount) + aRowHeaderArea.Bottom() = m_nRowHeightPixel * (nActualRows -1)+ m_nColHeaderHeightPixel - 1; + else + aRowHeaderArea.Bottom() = m_nRowHeightPixel * nActualRows + m_nColHeaderHeightPixel - 1; + //to avoid double lines when scrolling vertically + if(m_nTopRow != 0) + --aRowHeaderArea.Top(); + pRenderer->PaintHeaderArea(*m_pDataWindow, aRowHeaderArea, false, true, rStyle); // Note that strictly, aRowHeaderArea also contains the intersection between column // and row header area. However, below we go to paint this intersection, again, // so this hopefully doesn't hurt if we already paint it here. @@ -866,8 +1023,15 @@ namespace svt { namespace table { TableCellGeometry aIntersection( *this, Rectangle( Point( 0, 0 ), aAllCellsWithHeaders.BottomRight() ), COL_ROW_HEADERS, ROW_COL_HEADERS ); + Rectangle aInters(aIntersection.getRect()); + //to avoid double line when scrolling vertically + if( m_nTopRow != 0 ) + { + --aInters.Top(); + --aInters.Bottom(); + } pRenderer->PaintHeaderArea( - *m_pDataWindow, aIntersection.getRect(), true, true, rStyle + *m_pDataWindow, aInters, true, true, rStyle ); } } @@ -880,113 +1044,69 @@ namespace svt { namespace table // paint all rows Rectangle aAllDataCellsArea; impl_getAllVisibleDataCellArea( aAllDataCellsArea ); - - //get the vector, which contains row vectors, each containing the data for the cells in this row - std::vector<std::vector<rtl::OUString> >& aCellContent = m_pModel->getCellContent(); - //if the vector is empty, fill it with empty data, so the table can be painted - if(aCellContent.empty()) - { - std::vector<rtl::OUString> emptyCells; - while(m_nRowCount!=0) - { - aCellContent.push_back(emptyCells); - --m_nRowCount; - } - } - std::vector<std::vector<rtl::OUString> >::iterator it = aCellContent.begin()+m_nTopRow; - //get the vector, which contains the row header titles - std::vector<rtl::OUString>& aRowHeaderContent = m_pModel->getRowHeaderName(); - ::std::vector<rtl::OUString>::iterator itRowName = aRowHeaderContent.begin(); - - if(m_pModel->hasRowHeaders()) - { - aRowHeaderContent = m_pModel->getRowHeaderName(); - //if the vector is empty, fill it with empty strings, so the table can be painted - if(aRowHeaderContent.empty()) - { - while(m_nRowCount!=0) - { - aRowHeaderContent.push_back(rtl::OUString::createFromAscii("")); - --m_nRowCount; - } - } - itRowName = aRowHeaderContent.begin()+m_nTopRow; - } + ::std::vector< std::vector< ::com::sun::star::uno::Any > >& aCellContent = m_pModel->getCellContent(); for ( TableRowGeometry aRowIterator( *this, aAllCellsWithHeaders, getTopRow() ); aRowIterator.isValid(); aRowIterator.moveDown() ) { if ( _rUpdateRect.GetIntersection( aRowIterator.getRect() ).IsEmpty() ) - { - if(m_pModel->hasRowHeaders()) - ++itRowName; - ++it; continue; - } bool isActiveRow = ( aRowIterator.getRow() == getCurRow() ); bool isSelectedRow = false; if(!m_nRowSelected.empty()) { for(std::vector<RowPos>::iterator itSel=m_nRowSelected.begin(); - itSel!=m_nRowSelected.end();++itSel) + itSel!=m_nRowSelected.end();++itSel) { if(*itSel == aRowIterator.getRow()) isSelectedRow = true; } } - std::vector<rtl::OUString> aCellData; - if(it != aCellContent.end()) - { - aCellData = *it; - ++it; - } - ::std::vector<rtl::OUString>::iterator iter = aCellData.begin()+m_nLeftColumn; - + Rectangle aRect = aRowIterator.getRect().GetIntersection( aAllDataCellsArea ); + //to avoid double lines + if( aRowIterator.getRow() != 0 ) + --aRect.Top(); + if(m_nLeftColumn != 0) + --aRect.Left(); // give the redenderer a chance to prepare the row pRenderer->PrepareRow( aRowIterator.getRow(), isActiveRow, isSelectedRow, - *m_pDataWindow, aRowIterator.getRect().GetIntersection( aAllDataCellsArea ), rStyle ); + *m_pDataWindow, aRect, rStyle ); // paint the row header if ( m_pModel->hasRowHeaders() ) { - rtl::OUString rowHeaderName; - if(itRowName != aRowHeaderContent.end()) - { - rowHeaderName = *itRowName; - ++itRowName; - } Rectangle aCurrentRowHeader( aRowHeaderArea.GetIntersection( aRowIterator.getRect() ) ); + rtl::OUString rowHeaderName = m_pModel->getRowHeaderName()[aRowIterator.getRow()]; pRenderer->PaintRowHeader( isActiveRow, isSelectedRow, *m_pDataWindow, aCurrentRowHeader, rStyle, rowHeaderName ); } if ( !colCount ) continue; - // paint all cells in this row for ( TableCellGeometry aCell( aRowIterator, m_nLeftColumn ); aCell.isValid(); aCell.moveRight() ) { - // if ( _rUpdateRect.GetIntersection( aCell.getRect() ).IsEmpty() ) - // continue; - - //bool isActiveCell = isActiveRow && ( aCell.getColumn() == getCurColumn() ); bool isSelectedColumn = false; - rtl::OUString cellData; - if(aCellData.empty()) - cellData=rtl::OUString::createFromAscii(""); - else if(iter != aCellData.end()) + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >xGraphic; + ::com::sun::star::uno::Any rCellData = aCellContent[aRowIterator.getRow()][aCell.getColumn()]; + if(rCellData>>=xGraphic) + { + Image* pImage = new Image(xGraphic); + if(pImage!=NULL) + pRenderer->PaintCellImage( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow, + *m_pDataWindow, aCell.getRect(), rStyle, pImage ); + } + else { - cellData = *iter; - ++iter; + ::rtl::OUString sContent = convertToString(rCellData); + pRenderer->PaintCellString( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow, + *m_pDataWindow, aCell.getRect(), rStyle, sContent ); } - pRenderer->PaintCell( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow, - *m_pDataWindow, aCell.getRect(), rStyle, cellData ); - } + } } } - //-------------------------------------------------------------------- void TableControl_Impl::hideCursor() { @@ -1016,70 +1136,70 @@ namespace svt { namespace table switch ( _eAction ) { case cursorDown: - if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + { + //if other rows already selected, deselect them + if(m_nRowSelected.size()>0) { - //if other rows already selected, deselect them - if(m_nRowSelected.size()>0) - { - for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); - it!=m_nRowSelected.end();++it) - { - invalidateSelectedRow(*it,rCells); - m_pDataWindow->Invalidate(rCells); - } - m_nRowSelected.clear(); - } - if(m_nCurRow < m_nRowCount-1) + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + it!=m_nRowSelected.end();++it) { - ++m_nCurRow; - m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(*it, *it, rCells); } - else - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - ensureVisible(m_nCurColumn,m_nCurRow,false); - bSuccess = true; + m_nRowSelected.clear(); } - else + if(m_nCurRow < m_nRowCount-1) { - if ( m_nCurRow < m_nRowCount - 1 ) - bSuccess = goTo( m_nCurColumn, m_nCurRow + 1 ); + ++m_nCurRow; + m_nRowSelected.push_back(m_nCurRow); } + else + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); + ensureVisible(m_nCurColumn,m_nCurRow,false); + m_rAntiImpl.selectionChanged(true); + bSuccess = true; + } + else + { + if ( m_nCurRow < m_nRowCount - 1 ) + bSuccess = goTo( m_nCurColumn, m_nCurRow + 1 ); + } break; case cursorUp: - if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + { + if(m_nRowSelected.size()>0) { - if(m_nRowSelected.size()>0) - { - for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); it!=m_nRowSelected.end();++it) - { - invalidateSelectedRow(*it,rCells); - m_pDataWindow->Invalidate(rCells); - } - m_nRowSelected.clear(); - } - if(m_nCurRow>0) { - --m_nCurRow; - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); + invalidateSelectedRegion(*it, *it, rCells); } - else - { - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - } - ensureVisible(m_nCurColumn,m_nCurRow,false); - bSuccess = true; + m_nRowSelected.clear(); + } + if(m_nCurRow>0) + { + --m_nCurRow; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); } else { - if ( m_nCurRow > 0 ) - bSuccess = goTo( m_nCurColumn, m_nCurRow - 1 ); + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); } - break; + ensureVisible(m_nCurColumn,m_nCurRow,false); + m_rAntiImpl.selectionChanged(true); + bSuccess = true; + } + else + { + if ( m_nCurRow > 0 ) + bSuccess = goTo( m_nCurColumn, m_nCurRow - 1 ); + } + break; case cursorLeft: if ( m_nCurColumn > 0 ) bSuccess = goTo( m_nCurColumn - 1, m_nCurRow ); @@ -1133,225 +1253,251 @@ namespace svt { namespace table case cursorBottomRight: bSuccess = goTo( m_nColumnCount - 1, m_nRowCount - 1 ); break; - - case cursorSelectRow: + case cursorSelectRow: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + return bSuccess = false; + //pos is the position of the current row in the vector of selected rows, if current row is selected + int pos = getRowSelectedNumber(m_nRowSelected, m_nCurRow); + //if current row is selected, it should be deselected, when ALT+SPACE are pressed + if(pos>-1) + { + m_nRowSelected.erase(m_nRowSelected.begin()+pos); + if(m_nRowSelected.empty() && m_nAnchor != -1) + m_nAnchor = -1; + } + //else select the row->put it in the vector + else + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); + m_rAntiImpl.selectionChanged(true); + bSuccess = true; + } + break; + case cursorSelectRowUp: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + return bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) { - if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) - return bSuccess = false; - //pos is the position of the current row in the vector of selected rows, if current row is selected - int pos = getRowSelectedNumber(m_nRowSelected, m_nCurRow); - //if current row is selected, it should be deselected, when ALT+SPACE are pressed - if(pos>-1) - m_nRowSelected.erase(m_nRowSelected.begin()+pos); - //else select the row->put it in the vector - else - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - bSuccess = true; + //if there are other selected rows, deselect them + return false; } - break; - case cursorSelectRowUp: + else { - if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) - return bSuccess = false; - else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + //there are other selected rows + if(m_nRowSelected.size()>0) { - //if there are other selected rows, deselect them - return false; - } - else - { - //there are other selected rows - if(m_nRowSelected.size()>0) + //the anchor wasn't set -> a region is not selected, that's why clear all selection + //and select the current row + if(m_nAnchor==-1) { - //the anchor wasn't set -> a region is not selected, that's why clear all selection - //and select the current row - if(m_nAnchor==-1) - { - for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); it!=m_nRowSelected.end();++it) - { - invalidateSelectedRow(*it,rCells); - m_pDataWindow->Invalidate(rCells); - } - m_nRowSelected.clear(); - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); + { + invalidateSelectedRegion(*it, *it, rCells); } + m_nRowSelected.clear(); + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); + } + else + { + //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected + int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow); + int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow-1); + if(prevRow>-1) + { + //if m_nCurRow isn't the upper one, can move up, otherwise not + if(m_nCurRow>0) + m_nCurRow--; + else + return bSuccess = true; + //if nextRow already selected, deselect it, otherwise select it + if(nextRow>-1 && m_nRowSelected[nextRow] == m_nCurRow) + { + m_nRowSelected.erase(m_nRowSelected.begin()+prevRow); + invalidateSelectedRegion(m_nCurRow+1, m_nCurRow+1, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); + } + } else { - //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected - int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow); - int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow-1); - if(prevRow>-1) + if(m_nCurRow>0) { - //if m_nCurRow isn't the upper one, can move up, otherwise not - if(m_nCurRow>0) - m_nCurRow--; - else - return bSuccess = true; - //if nextRow already selected, deselect it, otherwise select it - if(m_nRowSelected[nextRow] == m_nCurRow) - { - m_nRowSelected.erase(m_nRowSelected.begin()+prevRow); - invalidateSelectedRow(m_nCurRow+1, rCells); - } - else - { - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - } + m_nRowSelected.push_back(m_nCurRow); + m_nCurRow--; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells); } } } + } + else + { + //if nothing is selected and the current row isn't the upper one + //select the current and one row above + //otherwise select only the upper row + if(m_nCurRow>0) + { + m_nRowSelected.push_back(m_nCurRow); + m_nCurRow--; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells); + } else { - //if nothing is selected and the current row isn't the upper one - //select the current and one row above - //otherwise select only the upper row - if(m_nCurRow>0) - { - m_nRowSelected.push_back(m_nCurRow); - m_nCurRow--; - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells); - } - else - { - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - } + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); } - m_pSelEngine->SetAnchor(TRUE); - m_nAnchor = m_nCurRow; - ensureVisible(m_nCurColumn, m_nCurRow, false); - bSuccess = true; } + m_pSelEngine->SetAnchor(TRUE); + m_nAnchor = m_nCurRow; + ensureVisible(m_nCurColumn, m_nCurRow, false); + m_rAntiImpl.selectionChanged(true); + bSuccess = true; } - break; - case cursorSelectRowDown: + } + break; + case cursorSelectRowDown: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) { - if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) - bSuccess = false; - else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) - { - bSuccess = false; - } - else + bSuccess = false; + } + else + { + if(m_nRowSelected.size()>0) { - if(m_nRowSelected.size()>0) + //the anchor wasn't set -> a region is not selected, that's why clear all selection + //and select the current row + if(m_nAnchor==-1) { - //the anchor wasn't set -> a region is not selected, that's why clear all selection - //and select the current row - if(m_nAnchor==-1) - { - for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); it!=m_nRowSelected.end();++it) - { - invalidateSelectedRow(*it,rCells); - m_pDataWindow->Invalidate(rCells); - } - m_nRowSelected.clear(); - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - } - else { - //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected - int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow); - int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow+1); - if(prevRow>-1) - { - //if m_nCurRow isn't the last one, can move down, otherwise not - if(m_nCurRow<m_nRowCount) - m_nCurRow++; - else - return bSuccess = true; - //if net row already selected, deselect it, otherwise select it - if(m_nRowSelected[nextRow] == m_nCurRow) - { - m_nRowSelected.erase(m_nRowSelected.begin()+prevRow); - invalidateSelectedRow(m_nCurRow-1, rCells); - } - else - { - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); - } - } + invalidateSelectedRegion(*it, *it, rCells); + } + m_nRowSelected.clear(); + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); } - } else { - //there wasn't any selection, select curennt and row beneath, otherwise onlyrow beneath - if(m_nCurRow<m_nRowCount-1) - { - m_nRowSelected.push_back(m_nCurRow); - m_nCurRow++; - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells); + //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected + int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow); + int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow+1); + if(prevRow>-1) + { + //if m_nCurRow isn't the last one, can move down, otherwise not + if(m_nCurRow<m_nRowCount-1) + m_nCurRow++; + else + return bSuccess = true; + //if next row already selected, deselect it, otherwise select it + if(nextRow>-1 && m_nRowSelected[nextRow] == m_nCurRow) + { + m_nRowSelected.erase(m_nRowSelected.begin()+prevRow); + invalidateSelectedRegion(m_nCurRow-1, m_nCurRow-1, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); + } } else { - m_nRowSelected.push_back(m_nCurRow); - invalidateSelectedRow(m_nCurRow, rCells); + if(m_nCurRow<m_nRowCount-1) + { + m_nRowSelected.push_back(m_nCurRow); + m_nCurRow++; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells); + } } } - m_pSelEngine->SetAnchor(TRUE); - m_nAnchor = m_nCurRow; - ensureVisible(m_nCurColumn, m_nCurRow, false); - bSuccess = true; } - } - break; - case cursorSelectRowAreaTop: - { - if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) - bSuccess = false; - else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) - bSuccess = false; else { - //select the region between the current and the upper row - RowPos iter = m_nCurRow; - invalidateSelectedRegion(m_nCurRow, 0, rCells); - //put the rows in vector - while(iter>=0) + //there wasn't any selection, select current and row beneath, otherwise only row beneath + if(m_nCurRow<m_nRowCount-1) + { + m_nRowSelected.push_back(m_nCurRow); + m_nCurRow++; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells); + } + else { - if(!isRowSelected(m_nRowSelected, iter)) - m_nRowSelected.push_back(iter); - --iter; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow, m_nCurRow, rCells); } - m_nCurRow = 0; - m_nAnchor = m_nCurRow; - m_pSelEngine->SetAnchor(TRUE); - ensureVisible(m_nCurColumn, 0, false); - bSuccess = true; } + m_pSelEngine->SetAnchor(TRUE); + m_nAnchor = m_nCurRow; + ensureVisible(m_nCurColumn, m_nCurRow, false); + m_rAntiImpl.selectionChanged(true); + bSuccess = true; } + } break; - case cursorSelectRowAreaBottom: + case cursorSelectRowAreaTop: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + bSuccess = false; + else { - if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) - return bSuccess = false; - else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) - return bSuccess = false; - //select the region between the current and the last row + //select the region between the current and the upper row RowPos iter = m_nCurRow; - invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells); - //put the rows in the vector - while(iter<=m_nRowCount) + invalidateSelectedRegion(m_nCurRow, 0, rCells); + //put the rows in vector + while(iter>=0) { if(!isRowSelected(m_nRowSelected, iter)) m_nRowSelected.push_back(iter); - ++iter; + --iter; } - m_nCurRow = m_nRowCount-1; + m_nCurRow = 0; m_nAnchor = m_nCurRow; m_pSelEngine->SetAnchor(TRUE); - ensureVisible(m_nCurColumn, m_nRowCount, false); + ensureVisible(m_nCurColumn, 0, false); + m_rAntiImpl.selectionChanged(true); bSuccess = true; } + } + break; + case cursorSelectRowAreaBottom: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + return bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + return bSuccess = false; + //select the region between the current and the last row + RowPos iter = m_nCurRow; + invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells); + //put the rows in the vector + while(iter<=m_nRowCount) + { + if(!isRowSelected(m_nRowSelected, iter)) + m_nRowSelected.push_back(iter); + ++iter; + } + m_nCurRow = m_nRowCount-1; + m_nAnchor = m_nCurRow; + m_pSelEngine->SetAnchor(TRUE); + ensureVisible(m_nCurColumn, m_nRowCount-1, false); + m_rAntiImpl.selectionChanged(true); + bSuccess = true; + } break; default: DBG_ERROR( "TableControl_Impl::dispatchAction: unsupported action!" ); @@ -1367,16 +1513,12 @@ namespace svt { namespace table { Rectangle aCellRect; impl_getCellRect( m_nCurColumn, m_nCurRow, aCellRect ); - - // const StyleSettings& rStyle = m_rAntiImpl.GetSettings().GetStyleSettings(); + if(!m_pModel->hasRowHeaders() && m_nCurColumn == 0) + aCellRect.Left()++; if ( _bShow ) - { pRenderer->ShowCellCursor( *m_pDataWindow, aCellRect); - } else - { pRenderer->HideCellCursor( *m_pDataWindow, aCellRect); - } } } @@ -1394,16 +1536,12 @@ namespace svt { namespace table return; } - DBG_ASSERT( ( _nColumn >= 0 ) && ( _nColumn < m_pModel->getColumnCount() ), - "TableControl_Impl::impl_getCellRect: invalid column index!" ); - DBG_ASSERT( ( _nRow >= 0 ) && ( _nRow < m_pModel->getRowCount() ), - "TableControl_Impl::impl_getCellRect: invalid row index!" ); - Rectangle aAllCells; impl_getAllVisibleCellsArea( aAllCells ); TableCellGeometry aCell( *this, aAllCells, _nColumn, _nRow ); _rCellRect = aCell.getRect(); + _rCellRect.Top()--;_rCellRect.Left()--; } //------------------------------------------------------------------------------- RowPos TableControl_Impl::getCurrentRow(const Point& rPoint) @@ -1412,8 +1550,7 @@ namespace svt { namespace table Rectangle rCellRect; RowPos newRowPos = -2;//-1 is HeaderRow ColPos newColPos = 0; - //To Do: when only row position needed, the second loop isn't necessary, Please proove this!!! - for(int i=0;i<m_nRowCount;i++) + for(int i=-1;i<m_nRowCount;i++) { for(int j=-1;j<m_nColumnCount;j++) { @@ -1422,9 +1559,7 @@ namespace svt { namespace table { newRowPos = i; newColPos = j; - if(newColPos == -1) - m_nCurColumn = 0; - else + if(newColPos != -1) m_nCurColumn = newColPos; return newRowPos; } @@ -1432,7 +1567,7 @@ namespace svt { namespace table } return newRowPos; } - //------------------------------------------------------------------------------- + //------------------------------------------------------------------------------- void TableControl_Impl::setCursorAtCurrentCell(const Point& rPoint) { DBG_CHECK_ME(); @@ -1440,7 +1575,6 @@ namespace svt { namespace table Rectangle rCellRect; RowPos newRowPos = -2;//-1 is HeaderRow ColPos newColPos = 0; - //To Do: when only row position needed, the second loop isn't necessary, Please proove this!!! for(int i=0;i<m_nRowCount;i++) { for(int j=-1;j<m_nColumnCount;j++) @@ -1460,7 +1594,6 @@ namespace svt { namespace table } showCursor(); } - //------------------------------------------------------------------------------- void TableControl_Impl::invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect) { @@ -1475,14 +1608,14 @@ namespace svt { namespace table if(_nPrevRow == _nCurRow) { impl_getCellRect(m_nCurColumn,_nCurRow,rCells); - _rCellRect.Top()=rCells.Top(); + _rCellRect.Top()=--rCells.Top(); _rCellRect.Bottom()=rCells.Bottom(); } //if the region is above the current row else if(_nPrevRow < _nCurRow ) { impl_getCellRect(m_nCurColumn,_nPrevRow,rCells); - _rCellRect.Top()=rCells.Top(); + _rCellRect.Top()= --rCells.Top(); impl_getCellRect(m_nCurColumn,_nCurRow,rCells); _rCellRect.Bottom()=rCells.Bottom(); } @@ -1490,46 +1623,31 @@ namespace svt { namespace table else { impl_getCellRect(m_nCurColumn,_nCurRow,rCells); - _rCellRect.Top()=rCells.Top(); + _rCellRect.Top()= --rCells.Top(); impl_getCellRect(m_nCurColumn,_nPrevRow,rCells); _rCellRect.Bottom()=rCells.Bottom(); } m_pDataWindow->Invalidate(_rCellRect); } - - //------------------------------------------------------------------------------- - //To Do: not really needed, because in method above one row can be invalidate. Please Prove this!!! - void TableControl_Impl::invalidateSelectedRow(RowPos _nCurRow, Rectangle& _rCellRect) - { - DBG_CHECK_ME(); - Rectangle aAllCells; - impl_getAllVisibleCellsArea( aAllCells ); - _rCellRect.Left() = aAllCells.Left(); - _rCellRect.Right() = aAllCells.Right(); - Rectangle rCells; - impl_getCellRect(m_nCurColumn,_nCurRow,rCells); - _rCellRect.Top()=rCells.Top(); - _rCellRect.Bottom()=rCells.Bottom(); - m_pDataWindow->Invalidate(_rCellRect); - } //------------------------------------------------------------------------------- //this method is to be called, when a new row is added void TableControl_Impl::invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect) { - //DBG_CHECK_ME(); - TempHideCursor aHideCursor( *this ); + if(m_nCurRow < 0) + m_nCurRow = 0; + if(m_nCursorHidden == 2) + --m_nCursorHidden; impl_getAllVisibleCellsArea( _rCellRect ); TableRowGeometry _rRow( *this, _rCellRect, _nRowPos); impl_ni_updateScrollbars(); m_pDataWindow->Invalidate(_rRow.getRect()); } - //------------------------------------------------------------------------------- std::vector<RowPos>& TableControl_Impl::getSelectedRows() { return m_nRowSelected; } - + //------------------------------------------------------------------------------- void TableControl_Impl::removeSelectedRow(RowPos _nRowPos) { int i =0; @@ -1556,57 +1674,23 @@ namespace svt { namespace table else m_nCurRow = _nRowPos-1; } - //------------------------------------------------------------------------------- - void TableControl_Impl::invalidateRows(RowPos _nRowStart, Rectangle& _rCellRect) + //------------------------------------------------------------------------------ + void TableControl_Impl::invalidateRows() { - //DBG_CHECK_ME(); - (void)_nRowStart; - (void)_rCellRect; - /*TempHideCursor aHideCursor(*this); - Rectangle aAllCells; - impl_getAllVisibleCellsArea( aAllCells ); - TableRowGeometry _rRow( *this, aAllCells, _nRowStart); - _rCellRect = _rRow.getRect(); - Rectangle rCells1; - impl_getCellRect(m_nCurColumn,m_nRowCount,rCells1); - _rCellRect.Bottom() = rCells1.Bottom();*/ - /*if(_nRowStart != _nRowEnd) - { - TableRowGeometry _rRow( *this, aAllCells, _nRowEnd); - _rCellRect.Bottom() = _rRow.getRect().Bottom(); - } - */ - //_rCellRect.Right() = aAllCells.Right(); - //_rCellRect.Left() = aAllCells.Left(); - //Rectangle rCells1; - //impl_getCellRect(m_nCurColumn,_nRowStart,rCells1); - //_rCellRect.Top()=rCells1.Top(); - //Rectangle rCells2; - //impl_getCellRect(m_nCurColumn,_nRowEnd,rCells2); - //_rCellRect.Bottom()=rCells2.Bottom(); impl_ni_updateScrollbars(); - //m_pDataWindow->Invalidate(_rCellRect); + TableSize nVisibleRows = impl_getVisibleRows(true); + TableSize nVisibleCols = impl_getVisibleColumns(true); + if(m_nTopRow+nVisibleRows>m_nRowCount && m_nRowCount>=nVisibleRows) + m_nTopRow--; + else + m_nTopRow = 0; + if(m_nLeftColumn+nVisibleCols>m_nColumnCount && m_nColumnCount>=nVisibleCols) + m_nLeftColumn--; + else + m_nLeftColumn = 0; m_pDataWindow->Invalidate(); } - - //------------------------------------------------------------------------------- - bool TableControl_Impl::isClickInVisibleArea(const Point& rPoint) - { - DBG_CHECK_ME(); - long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize(); - //clickable area is in the visible table control area without the scrollbars - Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() ); - aDataCellPlayground.Top() = m_nColHeaderHeightPixel; - aDataCellPlayground.Right() -= nScrollbarMetrics; - aDataCellPlayground.Bottom() -= nScrollbarMetrics; - if((rPoint.X() >= aDataCellPlayground.Left() && rPoint.X() <= aDataCellPlayground.Right()) && rPoint.Y() >= aDataCellPlayground.Top() && rPoint.Y() <= aDataCellPlayground.Bottom()) - { - return true; - } - else - return false; - } //-------------------------------------------------------------------- TableSize TableControl_Impl::impl_getVisibleRows( bool _bAcceptPartialRow ) const { @@ -1654,20 +1738,6 @@ namespace svt { namespace table // ensure that the new cell is visible ensureVisible( m_nCurColumn, m_nCurRow, false ); - - // TODO: invalidate all and new column/row header, if present, to enforce - // re-painting them - //if(!m_nRowSelected.empty()) - //{ - // Rectangle rCells; - // for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); - // it!=m_nRowSelected.end();++it) - // { - // invalidateSelectedRow(*it,rCells); - // } - // m_nRowSelected.clear(); - //} - // TODO: notify listeners about new position return true; } @@ -1735,7 +1805,7 @@ namespace svt { namespace table && abs( nPixelDelta ) < aDataArea.GetHeight() ) { - m_pDataWindow->Scroll( 0, (long)-nPixelDelta, aDataArea, SCROLL_CLIP | SCROLL_UPDATE ); + m_pDataWindow->Scroll( 0, (long)-nPixelDelta, aDataArea, SCROLL_CLIP | SCROLL_UPDATE | SCROLL_CHILDREN); } else m_pDataWindow->Invalidate( INVALIDATE_UPDATE ); @@ -1791,42 +1861,310 @@ namespace svt { namespace table return (TableSize)( m_nLeftColumn - nOldLeftColumn ); } - + //------------------------------------------------------------------------------- SelectionEngine* TableControl_Impl::getSelEngine() { return m_pSelEngine; } + //------------------------------------------------------------------------------- TableDataWindow* TableControl_Impl::getDataWindow() { return m_pDataWindow; } - BOOL TableControl_Impl::isRowSelected(::std::vector<RowPos> selectedRows, RowPos current) + //------------------------------------------------------------------------------- + ScrollBar* TableControl_Impl::getHorzScrollbar() + { + return m_pHScroll; + } + //------------------------------------------------------------------------------- + ScrollBar* TableControl_Impl::getVertScrollbar() + { + return m_pVScroll; + } + //------------------------------------------------------------------------------- + BOOL TableControl_Impl::isRowSelected(const ::std::vector<RowPos>& selectedRows, RowPos current) + { + return ::std::find(selectedRows.begin(),selectedRows.end(),current) != selectedRows.end(); + } + //------------------------------------------------------------------------------- + bool TableControl_Impl::isRowSelected(RowPos current) + { + return ::std::find(m_nRowSelected.begin(),m_nRowSelected.end(),current) != m_nRowSelected.end(); + } + //------------------------------------------------------------------------------- + int TableControl_Impl::getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current) { - for(::std::vector<RowPos>::iterator it=selectedRows.begin(); - it!=selectedRows.end();++it) + std::vector<RowPos>::const_iterator it = ::std::find(selectedRows.begin(),selectedRows.end(),current); + if ( it != selectedRows.end() ) { - if(*it == current) - return TRUE; + return it - selectedRows.begin(); } - return FALSE; + return -1; } - - int TableControl_Impl::getRowSelectedNumber(::std::vector<RowPos> selectedRows, RowPos current) + //------------------------------------------------------------------------------- + ::rtl::OUString& TableControl_Impl::setTooltip(const Point& rPoint ) { - int pos = -1; - int i = 0; - for(std::vector<RowPos>::iterator it=selectedRows.begin();it!=selectedRows.end();++it) + ::rtl::OUString aTooltipText; + RowPos current = getCurrentRow(rPoint); + com::sun::star::uno::Sequence< sal_Int32 > cols = m_rAntiImpl.getColumnsForTooltip(); + com::sun::star::uno::Sequence< ::rtl::OUString > text = m_rAntiImpl.getTextForTooltip(); + if(text.getLength()==0 && cols.getLength()==0) { - if(*it == current) - return pos = i; - ++i; + ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][m_nCurColumn]; + aTooltipText = convertToString(content); + } + else if(text.getLength() == 0) + { + for(int i=0; i<cols.getLength(); i++) + { + if(i==0) + { + ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]]; + aTooltipText = convertToString(content); + } + else + { + aTooltipText+= ::rtl::OUString::createFromAscii("\n"); + ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]]; + aTooltipText += convertToString(content); + } + } } - return pos; + else if(cols.getLength() == 0) + { + for(int i=0; i<text.getLength(); i++) + { + if(i==0) + aTooltipText = text[i]; + else + { + aTooltipText+= ::rtl::OUString::createFromAscii("\n"); + aTooltipText+= text[i]; + } + } + } + else + { + int nCols = cols.getLength(); + int mText = text.getLength(); + if(nCols < mText ) + cols.realloc(mText); + else if(mText < nCols) + text.realloc(nCols); + for(int i=0; i<cols.getLength(); i++) + { + if(i==0) + { + ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]]; + aTooltipText = text[i] + convertToString(content); + } + else + { + aTooltipText+= ::rtl::OUString::createFromAscii("\n"); + aTooltipText+= text[i]; + if(nCols > i) + { + ::com::sun::star::uno::Any content = m_pModel->getCellContent()[current][cols[i]]; + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >xGraphic; + aTooltipText += convertToString(content); + } + } + } + } + return m_aTooltipText = aTooltipText; } - - void TableControl_Impl::setCellContent(CellEntryType* pCellEntryType) + //-------------------------------------------------------------------- + void TableControl_Impl::resizeColumn(const Point& rPoint) + { + Pointer aNewPointer(POINTER_ARROW); + int headerRowWidth = 0; + if(m_pModel->hasRowHeaders()) + headerRowWidth = m_rAntiImpl.LogicToPixel( Size(m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width(); + int resizingColumn=m_nCurColumn-m_nLeftColumn; + PColumnModel pColumn = m_pModel->getColumnModel(m_nCurColumn); + impl_ni_getAccVisibleColWidths(); + int newColWidth = m_aColumnWidthsPixel[m_nCurColumn]; + //subtract 1 from m_aAccColumnWidthPixel because right border should be part of the current cell + if(m_aVisibleColumnWidthsPixel[resizingColumn]-1 == rPoint.X() && pColumn->isResizable()) + aNewPointer = Pointer( POINTER_HSPLIT ); + //MouseButton was pressed but not yet released, mouse is moving + if(m_bResizing) + { + if(rPoint.X() > m_pDataWindow->GetOutputSizePixel().Width() || rPoint.X() < m_aVisibleColumnWidthsPixel[resizingColumn]-newColWidth) + aNewPointer = Pointer( POINTER_NOTALLOWED); + else + aNewPointer = Pointer( POINTER_HSPLIT ); + m_pDataWindow->HideTracking(); + int lineHeight = 0; + if(m_pModel->hasColumnHeaders()) + lineHeight+= m_nColHeaderHeightPixel; + lineHeight+=m_nRowHeightPixel*m_nRowCount; + int gridHeight = m_pDataWindow->GetOutputSizePixel().Height(); + if(lineHeight >= gridHeight) + lineHeight = gridHeight; + m_pDataWindow->ShowTracking(Rectangle(Point(rPoint.X(),0), Size(1, lineHeight )), + SHOWTRACK_SPLIT | SHOWTRACK_WINDOW); + } + m_pDataWindow->SetPointer(aNewPointer); + } + //-------------------------------------------------------------------- + bool TableControl_Impl::startResizeColumn(const Point& rPoint) + { + m_bResizingGrid = false; + m_nResizingColumn = m_nCurColumn; + PColumnModel pColumn = m_pModel->getColumnModel(m_nResizingColumn); + if(m_aVisibleColumnWidthsPixel[m_nResizingColumn-m_nLeftColumn]-1 == rPoint.X() && pColumn->isResizable()) + { + m_pDataWindow->CaptureMouse(); + m_bResizing = true; + } + return m_bResizing; + } + //-------------------------------------------------------------------- + bool TableControl_Impl::endResizeColumn(const Point& rPoint) { - (void)pCellEntryType; + if(m_bResizing) + { + m_pDataWindow->HideTracking(); + PColumnModel pColumn = m_pModel->getColumnModel(m_nResizingColumn); + int maxWidth = pColumn->getMaxWidth(); + int minWidth = pColumn->getMinWidth(); + int resizeCol = m_nResizingColumn-m_nLeftColumn; + //new position of mouse + int actX = rPoint.X(); + //old position of right border + int oldX = m_aVisibleColumnWidthsPixel[resizeCol]; + //position of left border if cursor in the first cell + int leftX = 0; + if(m_nResizingColumn > m_nLeftColumn) + leftX = m_aVisibleColumnWidthsPixel[resizeCol-1]; + else if(m_nResizingColumn == 0 && m_pModel->hasRowHeaders()) + leftX = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width(); + int actWidth = actX - leftX; + int newActWidth = 0; + //minimize the column width + if(oldX > actX && actX >= leftX) + { + if(minWidth < actWidth) + { + newActWidth = m_rAntiImpl.PixelToLogic( Size( actWidth, 0 ), MAP_APPFONT ).Width(); + pColumn->setPreferredWidth(newActWidth); + } + else + pColumn->setPreferredWidth(minWidth); + if(m_nLeftColumn != 0) + impl_updateLeftColumn(); + } + else if(oldX < actX) + { + if(actWidth < maxWidth) + { + newActWidth = m_rAntiImpl.PixelToLogic( Size( actWidth, 0 ), MAP_APPFONT ).Width(); + pColumn->setPreferredWidth(newActWidth); + } + else + pColumn->setPreferredWidth(maxWidth); + } + m_nCurColumn = m_nResizingColumn; + impl_ni_updateColumnWidths(); + impl_ni_updateScrollbars(); + m_pDataWindow->Invalidate(INVALIDATE_UPDATE); + m_pDataWindow->SetPointer(Pointer()); + m_bResizing = false; + m_bResizingGrid = true; + } + m_pDataWindow->ReleaseMouse(); + return m_bResizing; + } + //------------------------------------------------------------------------------- + void TableControl_Impl::impl_ni_getAccVisibleColWidths() + { + TableSize nVisCols = impl_getVisibleColumns(true); + int widthsPixel = 0; + m_aVisibleColumnWidthsPixel.resize(0); + m_aVisibleColumnWidthsPixel.reserve(nVisCols); + int headerRowWidth = 0; + if(m_pModel->hasRowHeaders()) + { + headerRowWidth = m_rAntiImpl.LogicToPixel( Size(m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width(); + widthsPixel+=headerRowWidth; + } + int col = m_nLeftColumn; + while(nVisCols) + { + m_aVisibleColumnWidthsPixel.push_back(widthsPixel+=m_aColumnWidthsPixel[col]); + col++; + nVisCols--; + } + } + //------------------------------------------------------------------------------- + void TableControl_Impl::impl_updateLeftColumn() + { + int nVisCols = m_aVisibleColumnWidthsPixel.size(); + int headerRowWidth = 0; + //sum of currently visible columns + int widthsPixel = 0; + //header pixel should be added, because header doesn't vanish when scrolling + if(m_pModel->hasRowHeaders()) + { + headerRowWidth = m_rAntiImpl.LogicToPixel( Size(m_pModel->getRowHeaderWidth(), 0 ), MAP_APPFONT ).Width(); + widthsPixel+=headerRowWidth; + } + int col = m_nLeftColumn; + //add column width of the neighbour of the left column + widthsPixel+=m_aColumnWidthsPixel[col-1]; + //compute the sum of the new column widths + while(nVisCols) + { + PColumnModel pColumn = m_pModel->getColumnModel(col); + int colWidth = pColumn->getWidth(); + int colPrefWidth = pColumn->getPreferredWidth(); + if(colPrefWidth!=0) + colWidth = colPrefWidth; + widthsPixel += m_rAntiImpl.LogicToPixel( Size( colWidth, 0 ), MAP_APPFONT ).Width(); + col++; + nVisCols--; + } + //when the sum of all visible columns and the next to the left column is smaller than + //window width, then update m_nLeftColumn + if(widthsPixel<m_pDataWindow->GetOutputSizePixel().Width()) + m_nLeftColumn--; + } + //-------------------------------------------------------------------- + rtl::OUString TableControl_Impl::convertToString(const ::com::sun::star::uno::Any& value) + { + sal_Int32 nInt = 0; + sal_Bool bBool = false; + double fDouble = 0; + ::rtl::OUString sNewString; + ::rtl::OUString sConvertString; + if(value >>= sConvertString) + sNewString = sConvertString; + else if(value >>= nInt) + sNewString = sConvertString.valueOf(nInt); + else if(value >>= bBool) + sNewString = sConvertString.valueOf(bBool); + else if(value >>= fDouble) + sNewString = sConvertString.valueOf(fDouble); + return sNewString; + } + Rectangle TableControl_Impl::calcHeaderRect(bool bColHeader) + { + Rectangle aRectTable, aRectTableWithHeaders; + impl_getAllVisibleDataCellArea(aRectTable); + impl_getAllVisibleCellsArea(aRectTableWithHeaders); + Size aSizeTable(aRectTable.GetSize()); + Size aSizeTableWithHeaders(aRectTableWithHeaders.GetSize()); + if(bColHeader) + return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width()-aSizeTable.Width(), aSizeTableWithHeaders.Height())); + else + return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width(), aSizeTableWithHeaders.Height()-aSizeTable.Height())); + } + Rectangle TableControl_Impl::calcTableRect() + { + Rectangle aRect; + impl_getAllVisibleDataCellArea(aRect); + return aRect; } //-------------------------------------------------------------------- @@ -1842,34 +2180,33 @@ namespace svt { namespace table return 0L; } - //--------------------------------------------------------------------------------------- - TableFunctionSet::TableFunctionSet(TableControl_Impl* _pTableControl): - m_pTableControl( _pTableControl) - ,m_nCurrentRow (-2) + TableFunctionSet::TableFunctionSet(TableControl_Impl* _pTableControl) + :m_pTableControl( _pTableControl) + ,m_nCurrentRow (-2) { } - + //------------------------------------------------------------------------------- TableFunctionSet::~TableFunctionSet() { } - + //------------------------------------------------------------------------------- void TableFunctionSet::BeginDrag() { } - + //------------------------------------------------------------------------------- void TableFunctionSet::CreateAnchor() { m_pTableControl->m_nAnchor = m_pTableControl->m_nCurRow; } - - void TableFunctionSet::DestroyAnchor() - { + //------------------------------------------------------------------------------- + void TableFunctionSet::DestroyAnchor() + { m_pTableControl->m_nAnchor = -1; - } - - BOOL TableFunctionSet::SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor) - { + } + //------------------------------------------------------------------------------- + BOOL TableFunctionSet::SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor) + { BOOL bHandled = FALSE; Rectangle rCells; //curRow is the row where the mouse click happened, m_nCurRow is the last selected row, before the mouse click @@ -1886,9 +2223,6 @@ namespace svt { namespace table { //selecting region, int diff = m_pTableControl->m_nCurRow - curRow; - //bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, m_pTableControl->m_nAnchor); - /* if(!isAlreadySelected && m_nCurrentRow != m_pTableControl->m_nCurRow) - m_pTableControl->m_nRowSelected.push_back(m_nAnchor);*/ //selected region lies above the last selection if( diff >= 0) { @@ -1924,9 +2258,7 @@ namespace svt { namespace table else { if(m_pTableControl->m_nRowSelected.empty()) - { m_pTableControl->m_nRowSelected.push_back(curRow); - } else { if(m_pTableControl->m_pSelEngine->GetSelectionMode()==SINGLE_SELECTION) @@ -1943,14 +2275,14 @@ namespace svt { namespace table } if(m_pTableControl->m_nRowSelected.size()>1 && m_pTableControl->m_pSelEngine->GetSelectionMode()!=SINGLE_SELECTION) m_pTableControl->m_pSelEngine->AddAlways(TRUE); - m_pTableControl->invalidateSelectedRow(curRow,rCells); + m_pTableControl->invalidateSelectedRegion(curRow, curRow, rCells); bHandled = TRUE; } m_pTableControl->m_nCurRow = curRow; m_pTableControl->ensureVisible(m_pTableControl->m_nCurColumn,m_pTableControl->m_nCurRow,false); return bHandled; } - + //------------------------------------------------------------------------------- BOOL TableFunctionSet::IsSelectionAtPoint( const Point& rPoint ) { m_pTableControl->m_pSelEngine->AddAlways(FALSE); @@ -1965,7 +2297,7 @@ namespace svt { namespace table return selected; } } - + //------------------------------------------------------------------------------- void TableFunctionSet::DeselectAtPoint( const Point& rPoint ) { (void)rPoint; @@ -1978,21 +2310,22 @@ namespace svt { namespace table if(*it == m_nCurrentRow) { pos = i; - m_pTableControl->invalidateSelectedRow(*it,rCells); + m_pTableControl->invalidateSelectedRegion(*it, *it, rCells); } ++i; } m_pTableControl->m_nRowSelected.erase(m_pTableControl->m_nRowSelected.begin()+pos); } + //------------------------------------------------------------------------------- void TableFunctionSet::DeselectAll() { if(!m_pTableControl->m_nRowSelected.empty()) { Rectangle rCells; for(std::vector<RowPos>::iterator it=m_pTableControl->m_nRowSelected.begin(); - it!=m_pTableControl->m_nRowSelected.end();++it) + it!=m_pTableControl->m_nRowSelected.end();++it) { - m_pTableControl->invalidateSelectedRow(*it,rCells); + m_pTableControl->invalidateSelectedRegion(*it, *it, rCells); } m_pTableControl->m_nRowSelected.clear(); } diff --git a/svtools/source/table/tablecontrol_impl.hxx b/svtools/source/table/tablecontrol_impl.hxx index dc875cd137fe..0a487c77c76c 100644 --- a/svtools/source/table/tablecontrol_impl.hxx +++ b/svtools/source/table/tablecontrol_impl.hxx @@ -39,6 +39,7 @@ #include <vector> #include <vcl/seleng.hxx> + class ScrollBar; class ScrollBarBox; @@ -62,60 +63,64 @@ namespace svt { namespace table friend class TableRowGeometry; friend class TableColumnGeometry; friend class SuspendInvariants; - friend class TableFunctionSet; + friend class TableFunctionSet; private: /// the control whose impl-instance we implemnt - TableControl& m_rAntiImpl; + TableControl& m_rAntiImpl; /// the model of the table control - PTableModel m_pModel; + PTableModel m_pModel; /// the input handler to use, usually the input handler as provided by ->m_pModel - PTableInputHandler m_pInputHandler; + PTableInputHandler m_pInputHandler; /// the widths of the single columns, measured in pixel - ArrayOfLong m_aColumnWidthsPixel; + ArrayOfLong m_aColumnWidthsPixel; /** the accumulated widths of the single columns, i.e. their exclusive right borders, <strong<not</strong> counting the space for a possible row header column */ - ArrayOfLong m_aAccColumnWidthsPixel; + ArrayOfLong m_aAccColumnWidthsPixel; + + ArrayOfLong m_aVisibleColumnWidthsPixel; /// the height of a single row in the table, measured in pixels - long m_nRowHeightPixel; + long m_nRowHeightPixel; /// the height of the column header row in the table, measured in pixels - long m_nColHeaderHeightPixel; + long m_nColHeaderHeightPixel; /// the width of the row header column in the table, measured in pixels - long m_nRowHeaderWidthPixel; + long m_nRowHeaderWidthPixel; /// the number of columns in the table control. Cached model value. - TableSize m_nColumnCount; + TableSize m_nColumnCount; /// the number of rows in the table control. Cached model value. - TableSize m_nRowCount; + TableSize m_nRowCount; - ColPos m_nCurColumn; - RowPos m_nCurRow; - ColPos m_nLeftColumn; - RowPos m_nTopRow; + ColPos m_nCurColumn; + RowPos m_nCurRow; + ColPos m_nLeftColumn; + RowPos m_nTopRow; - sal_Int32 m_nCursorHidden; + sal_Int32 m_nCursorHidden; /** the window to contain all data content, including header bars The window's upper left corner is at position (0,0), relative to the table control, which is the direct parent of the data window. */ - TableDataWindow* m_pDataWindow; + TableDataWindow* m_pDataWindow; /// the vertical scrollbar, if any - ScrollBar* m_pVScroll; + ScrollBar* m_pVScroll; /// the horizontal scrollbar, if any ScrollBar* m_pHScroll; - ScrollBarBox* m_pScrollCorner; - //selection engine - for determining selection range, e.g. single, multiple - SelectionEngine* m_pSelEngine; - //vector which contains the selected rows - std::vector<RowPos> m_nRowSelected; - //part of selection engine - TableFunctionSet* m_pTableFunctionSet; - //part of selection engine - RowPos m_nAnchor; - - + ScrollBarBox* m_pScrollCorner; + //selection engine - for determining selection range, e.g. single, multiple + SelectionEngine* m_pSelEngine; + //vector which contains the selected rows + std::vector<RowPos> m_nRowSelected; + //part of selection engine + TableFunctionSet* m_pTableFunctionSet; + //part of selection engine + RowPos m_nAnchor; + bool m_bResizing; + ColPos m_nResizingColumn; + bool m_bResizingGrid; + rtl::OUString m_aTooltipText; #if DBG_UTIL #define INV_SCROLL_POSITION 1 @@ -146,7 +151,6 @@ namespace svt { namespace table inline const TableControl& getAntiImpl() const { return m_rAntiImpl; } inline TableControl& getAntiImpl() { return m_rAntiImpl; } - void setCellContent(CellEntryType* pCellEntryType); public: TableControl_Impl( TableControl& _rAntiImpl ); @@ -181,53 +185,42 @@ namespace svt { namespace table <TRUE/> if it's okay that the given cooordinate is only partially visible */ void ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility ); - /** returns the row, which contains the input point*/ - RowPos getCurrentRow (const Point& rPoint); - - void setCursorAtCurrentCell(const Point& rPoint); - /** proves whether the vector with the selected rows contains the current row*/ - BOOL isRowSelected(::std::vector<RowPos> selectedRows, RowPos current); - /** returns the position of the current row in the selecttion vector */ - int getRowSelectedNumber(::std::vector<RowPos> selectedRows, RowPos current); - /** _rCellRect contains the region, which should be invalidate after some action e.g. selectiong row*/ - void invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect ); - /** _rCellRect contains the region, which should be invalidate after some action e.g. selectiong row*/ - //vielleicht kann man mit den anderen verschmelzen, mit einer berprfung ob prev==curr? - void invalidateSelectedRow( RowPos _nCurRow, Rectangle& _rCellRect ); - /** to be called when a new row is added to the control*/ - void invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect ); - /** returns the vector, which contains the selected rows*/ - std::vector<RowPos>& getSelectedRows(); - /** updates the vector, which contains the selected rows after removing the row nRowPos*/ - void removeSelectedRow(RowPos _nRowPos); - void invalidateRows(RowPos _nRowStart, Rectangle& _rCellRect ); - //virtual void DoubleClick(); - + /** returns the row, which contains the input point*/ + virtual RowPos getCurrentRow (const Point& rPoint); + + void setCursorAtCurrentCell(const Point& rPoint); + /** checks whether the vector with the selected rows contains the current row*/ + BOOL isRowSelected(const ::std::vector<RowPos>& selectedRows, RowPos current); + + bool isRowSelected(RowPos current); + /** returns the position of the current row in the selection vector */ + int getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current); + /** _rCellRect contains the region, which should be invalidate after some action e.g. selecting row*/ + void invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect ); + /** to be called when a new row is added to the control*/ + void invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect ); + /** returns the vector, which contains the selected rows*/ + std::vector<RowPos>& getSelectedRows(); + /** updates the vector, which contains the selected rows after removing the row nRowPos*/ + void removeSelectedRow(RowPos _nRowPos); + void invalidateRows(); // IAbstractTableControl virtual void hideCursor(); virtual void showCursor(); virtual bool dispatchAction( TableControlAction _eAction ); - virtual bool isClickInVisibleArea(const Point& rPoint); - virtual SelectionEngine* getSelEngine(); - - TableDataWindow* getDataWindow(); - /** retrieves the area occupied by the totality of (at least partially) visible cells - - The returned area includes row and column headers. Also, it takes into - account the the fact that there might be less columns than would normally - find room in the control. - - As a result of respecting the partial visibility of rows and columns, - the returned area might be larger than the data window's output size. - */ - void impl_getAllVisibleCellsArea( Rectangle& _rCellArea ) const; - - /** retrieves the area occupied by all (at least partially) visible data cells. - - Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea, - minus the row and column header areas. - */ - void impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const; + virtual SelectionEngine* getSelEngine(); + virtual rtl::OUString& setTooltip(const Point& rPoint ); + virtual void resizeColumn(const Point& rPoint); + virtual bool startResizeColumn(const Point& rPoint); + virtual bool endResizeColumn(const Point& rPoint); + + TableDataWindow* getDataWindow(); + ScrollBar* getHorzScrollbar(); + ScrollBar* getVertScrollbar(); + + ::rtl::OUString convertToString(const ::com::sun::star::uno::Any& _value); + Rectangle calcHeaderRect(bool bColHeader); + Rectangle calcTableRect(); private: /** toggles the cursor visibility @@ -312,10 +305,30 @@ namespace svt { namespace table column range were reached. */ TableSize impl_ni_ScrollColumns( TableSize _nRowDelta ); + /** retrieves the area occupied by the totality of (at least partially) visible cells + + The returned area includes row and column headers. Also, it takes into + account the the fact that there might be less columns than would normally + find room in the control. + + As a result of respecting the partial visibility of rows and columns, + the returned area might be larger than the data window's output size. + */ + void impl_getAllVisibleCellsArea( Rectangle& _rCellArea ) const; + + /** retrieves the area occupied by all (at least partially) visible data cells. + + Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea, + minus the row and column header areas. + */ + void impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const; + + void impl_ni_getAccVisibleColWidths(); + void impl_updateLeftColumn(); DECL_LINK( OnScroll, ScrollBar* ); }; - //see seleng.hxx, seleng.cxx, FunctionSet overwritables, part of selection engine + //see seleng.hxx, seleng.cxx, FunctionSet overridables, part of selection engine class TableFunctionSet : public FunctionSet { friend class TableDataWindow; diff --git a/svtools/source/table/tabledatawindow.cxx b/svtools/source/table/tabledatawindow.cxx index 246710488b42..e307071e2699 100644 --- a/svtools/source/table/tabledatawindow.cxx +++ b/svtools/source/table/tabledatawindow.cxx @@ -30,6 +30,7 @@ #include "svtools/table/tablecontrol.hxx" #include "svtools/table/tabledatawindow.hxx" #include "tablecontrol_impl.hxx" +#include <vcl/help.hxx> //........................................................................ namespace svt { namespace table @@ -44,10 +45,8 @@ namespace svt { namespace table TableDataWindow::TableDataWindow( TableControl_Impl& _rTableControl ) :Window( &_rTableControl.getAntiImpl() ) ,m_rTableControl ( _rTableControl ) + ,m_nRowAlreadySelected( -1 ) { - Color backgroundColor = m_rTableControl.getAntiImpl().GetSettings().GetStyleSettings().GetFieldColor(); - SetBackground( backgroundColor ); - SetControlBackground( backgroundColor ); } //-------------------------------------------------------------------- @@ -55,28 +54,99 @@ namespace svt { namespace table { m_rTableControl.doPaintContent( rUpdateRect ); } + //-------------------------------------------------------------------- void TableDataWindow::MouseMove( const MouseEvent& rMEvt ) { + Point aPoint = rMEvt.GetPosPixel(); if ( !m_rTableControl.getInputHandler()->MouseMove( m_rTableControl, rMEvt ) ) - Window::MouseMove( rMEvt ); + { + if(m_rTableControl.getCurrentRow(aPoint)>=0 ) + { + SetPointer(POINTER_ARROW); + rtl::OUString& rHelpText = m_rTableControl.setTooltip(aPoint); + Help::EnableBalloonHelp(); + Window::SetHelpText( rHelpText.getStr()); + } + else if(m_rTableControl.getCurrentRow(aPoint) == -1) + { + if(Help::IsBalloonHelpEnabled()) + Help::DisableBalloonHelp(); + m_rTableControl.resizeColumn(aPoint); + } + else + { + if(Help::IsBalloonHelpEnabled()) + Help::DisableBalloonHelp(); + Window::MouseMove( rMEvt ); + } + } } + //-------------------------------------------------------------------- void TableDataWindow::MouseButtonDown( const MouseEvent& rMEvt ) { + Point aPoint = rMEvt.GetPosPixel(); + RowPos nCurRow = m_rTableControl.getCurrentRow(aPoint); if ( !m_rTableControl.getInputHandler()->MouseButtonDown( m_rTableControl, rMEvt ) ) Window::MouseButtonDown( rMEvt ); else - m_aMouseButtonDownHdl.Call( (MouseEvent*) &rMEvt); + { + if(nCurRow >= 0 && m_rTableControl.getSelEngine()->GetSelectionMode() != NO_SELECTION) + { + if( m_nRowAlreadySelected != nCurRow ) + { + m_nRowAlreadySelected = nCurRow; + m_aSelectHdl.Call( NULL ); + } + else + m_aMouseButtonDownHdl.Call((MouseEvent*) &rMEvt); + } + else + m_aMouseButtonDownHdl.Call((MouseEvent*) &rMEvt); + } m_rTableControl.getAntiImpl().LoseFocus(); } + //-------------------------------------------------------------------- void TableDataWindow::MouseButtonUp( const MouseEvent& rMEvt ) { if ( !m_rTableControl.getInputHandler()->MouseButtonUp( m_rTableControl, rMEvt ) ) Window::MouseButtonUp( rMEvt ); else - m_aMouseButtonUpHdl.Call( (MouseEvent*) &rMEvt); + m_aMouseButtonUpHdl.Call((MouseEvent*) &rMEvt); m_rTableControl.getAntiImpl().GetFocus(); } - + //-------------------------------------------------------------------- + void TableDataWindow::SetPointer( const Pointer& rPointer ) + { + Window::SetPointer(rPointer); + } + //-------------------------------------------------------------------- + void TableDataWindow::CaptureMouse() + { + Window::CaptureMouse(); + } + //-------------------------------------------------------------------- + void TableDataWindow::ReleaseMouse( ) + { + Window::ReleaseMouse(); + } + // ----------------------------------------------------------------------- + long TableDataWindow::Notify(NotifyEvent& rNEvt ) + { + long nDone = 0; + if ( rNEvt.GetType() == EVENT_COMMAND ) + { + const CommandEvent& rCEvt = *rNEvt.GetCommandEvent(); + if ( rCEvt.GetCommand() == COMMAND_WHEEL ) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) + { + nDone = HandleScrollCommand( rCEvt, m_rTableControl.getHorzScrollbar(), m_rTableControl.getVertScrollbar() ); + } + } + } + return nDone ? nDone : Window::Notify( rNEvt ); + } //........................................................................ } } // namespace svt::table //........................................................................ diff --git a/svtools/source/table/tablegeometry.cxx b/svtools/source/table/tablegeometry.cxx index 58bdb531c921..d60de9e6438f 100644 --- a/svtools/source/table/tablegeometry.cxx +++ b/svtools/source/table/tablegeometry.cxx @@ -49,8 +49,8 @@ namespace svt { namespace table { if ( m_nRowPos == ROW_COL_HEADERS ) { - DBG_ASSERT( m_rControl.m_pModel->hasColumnHeaders(), - "TableRowGeometry::TableRowGeometry: why asking for the geoemtry of the non-existent column header row?" ); + //DBG_ASSERT( m_rControl.m_pModel->hasColumnHeaders(), + // "TableRowGeometry::TableRowGeometry: why asking for the geoemtry of the non-existent column header row?" ); m_aRect.Top() = 0; m_aRect.Bottom() = m_rControl.m_nColHeaderHeightPixel - 1; } @@ -87,8 +87,8 @@ namespace svt { namespace table { if ( m_nColPos == COL_ROW_HEADERS ) { - DBG_ASSERT( m_rControl.m_pModel->hasRowHeaders(), - "TableColumnGeometry::TableColumnGeometry: why asking for the geoemtry of the non-existent row header column?" ); +/* DBG_ASSERT( m_rControl.m_pModel->hasRowHeaders(), + "TableColumnGeometry::TableColumnGeometry: why asking for the geoemtry of the non-existent row header column?" )*/; m_aRect.Left() = 0; m_aRect.Right() = m_rControl.m_nRowHeaderWidthPixel - 1; } |