diff options
Diffstat (limited to 'svtools/source/table/gridtablerenderer.cxx')
-rw-r--r-- | svtools/source/table/gridtablerenderer.cxx | 663 |
1 files changed, 450 insertions, 213 deletions
diff --git a/svtools/source/table/gridtablerenderer.cxx b/svtools/source/table/gridtablerenderer.cxx index 5fb61a9f385e..1e230d372c24 100644 --- a/svtools/source/table/gridtablerenderer.cxx +++ b/svtools/source/table/gridtablerenderer.cxx @@ -27,51 +27,209 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" +#include "cellvalueconversion.hxx" #include "svtools/table/gridtablerenderer.hxx" +#include "svtools/colorcfg.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/graphic/XGraphic.hpp> +/** === end UNO includes === **/ #include <tools/debug.hxx> +#include <tools/diagnose_ex.h> #include <vcl/window.hxx> #include <vcl/image.hxx> +#include <vcl/virdev.hxx> +#include <vcl/decoview.hxx> -//........................................................................ +//...................................................................................................................... namespace svt { namespace table { -//........................................................................ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::TypeClass_INTERFACE; + using ::com::sun::star::graphic::XGraphic; + using ::com::sun::star::style::HorizontalAlignment; + using ::com::sun::star::style::HorizontalAlignment_LEFT; + using ::com::sun::star::style::HorizontalAlignment_CENTER; + using ::com::sun::star::style::HorizontalAlignment_RIGHT; + using ::com::sun::star::style::VerticalAlignment; + using ::com::sun::star::style::VerticalAlignment_TOP; + using ::com::sun::star::style::VerticalAlignment_MIDDLE; + using ::com::sun::star::style::VerticalAlignment_BOTTOM; + /** === end UNO using === **/ + + //================================================================================================================== + //= CachedSortIndicator + //================================================================================================================== + class CachedSortIndicator + { + public: + CachedSortIndicator() + :m_lastHeaderHeight( 0 ) + ,m_lastArrowColor( COL_TRANSPARENT ) + { + } + + BitmapEx const & getBitmapFor( OutputDevice const & i_device, long const i_headerHeight, StyleSettings const & i_style, bool const i_sortAscending ); + + private: + long m_lastHeaderHeight; + Color m_lastArrowColor; + BitmapEx m_sortAscending; + BitmapEx m_sortDescending; + }; + + //------------------------------------------------------------------------------------------------------------------ + BitmapEx const & CachedSortIndicator::getBitmapFor( OutputDevice const & i_device, long const i_headerHeight, + StyleSettings const & i_style, bool const i_sortAscending ) + { + BitmapEx & rBitmap( i_sortAscending ? m_sortAscending : m_sortDescending ); + if ( !rBitmap || ( i_headerHeight != m_lastHeaderHeight ) || ( i_style.GetActiveColor() != m_lastArrowColor ) ) + { + long const nSortIndicatorWidth = 2 * i_headerHeight / 3; + long const nSortIndicatorHeight = 2 * nSortIndicatorWidth / 3; + + Point const aBitmapPos( 0, 0 ); + Size const aBitmapSize( nSortIndicatorWidth, nSortIndicatorHeight ); + VirtualDevice aDevice( i_device, 0, 0 ); + aDevice.SetOutputSizePixel( aBitmapSize ); + + DecorationView aDecoView( &aDevice ); + aDecoView.DrawSymbol( + Rectangle( aBitmapPos, aBitmapSize ), + i_sortAscending ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN, + i_style.GetActiveColor() + ); + + rBitmap = aDevice.GetBitmapEx( aBitmapPos, aBitmapSize ); + m_lastHeaderHeight = i_headerHeight; + m_lastArrowColor = i_style.GetActiveColor(); + } + return rBitmap; + } + //================================================================================================================== + //= GridTableRenderer_Impl + //================================================================================================================== struct GridTableRenderer_Impl { - ITableModel& rModel; - RowPos nCurrentRow; + ITableModel& rModel; + RowPos nCurrentRow; + bool bUseGridLines; + CachedSortIndicator aSortIndicator; GridTableRenderer_Impl( ITableModel& _rModel ) :rModel( _rModel ) ,nCurrentRow( ROW_INVALID ) + ,bUseGridLines( true ) { } }; - //==================================================================== + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + static Rectangle lcl_getContentArea( GridTableRenderer_Impl const & i_impl, Rectangle const & i_cellArea ) + { + Rectangle aContentArea( i_cellArea ); + if ( i_impl.bUseGridLines ) + { + --aContentArea.Right(); + --aContentArea.Bottom(); + } + return aContentArea; + } + static Rectangle lcl_getTextRenderingArea( Rectangle const & i_contentArea ) + { + Rectangle aTextArea( i_contentArea ); + aTextArea.Left() += 2; aTextArea.Right() -= 2; + ++aTextArea.Top(); --aTextArea.Bottom(); + return aTextArea; + } + + static sal_uLong lcl_getAlignmentTextDrawFlags( GridTableRenderer_Impl const & i_impl, ColPos const i_columnPos ) + { + sal_uLong nVertFlag = TEXT_DRAW_TOP; + VerticalAlignment const eVertAlign = i_impl.rModel.getVerticalAlign(); + switch ( eVertAlign ) + { + case VerticalAlignment_MIDDLE: nVertFlag = TEXT_DRAW_VCENTER; break; + case VerticalAlignment_BOTTOM: nVertFlag = TEXT_DRAW_BOTTOM; break; + default: + break; + } + + sal_uLong nHorzFlag = TEXT_DRAW_LEFT; + HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign(); + switch ( eHorzAlign ) + { + case HorizontalAlignment_CENTER: nHorzFlag = TEXT_DRAW_CENTER; break; + case HorizontalAlignment_RIGHT: nHorzFlag = TEXT_DRAW_RIGHT; break; + default: + break; + } + + return nVertFlag | nHorzFlag; + } + + } + + //================================================================================================================== //= GridTableRenderer - //==================================================================== - //-------------------------------------------------------------------- + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ GridTableRenderer::GridTableRenderer( ITableModel& _rModel ) :m_pImpl( new GridTableRenderer_Impl( _rModel ) ) { } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ GridTableRenderer::~GridTableRenderer() { - DELETEZ( m_pImpl ); } - //-------------------------------------------------------------------- - RowPos GridTableRenderer::getCurrentRow() + //------------------------------------------------------------------------------------------------------------------ + RowPos GridTableRenderer::getCurrentRow() const { return m_pImpl->nCurrentRow; } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ + bool GridTableRenderer::useGridLines() const + { + return m_pImpl->bUseGridLines; + } + + //------------------------------------------------------------------------------------------------------------------ + void GridTableRenderer::useGridLines( bool const i_use ) + { + m_pImpl->bUseGridLines = i_use; + } + + //------------------------------------------------------------------------------------------------------------------ + namespace + { + Color lcl_getEffectiveColor( + ::boost::optional< ::Color > const & i_modelColor, + StyleSettings const & i_styleSettings, + ::Color const & ( StyleSettings::*i_getDefaultColor ) () const + ) + { + if ( !!i_modelColor ) + return *i_modelColor; + return ( i_styleSettings.*i_getDefaultColor )(); + } + } + + //------------------------------------------------------------------------------------------------------------------ void GridTableRenderer::PaintHeaderArea( OutputDevice& _rDevice, const Rectangle& _rArea, bool _bIsColHeaderArea, bool _bIsRowHeaderArea, const StyleSettings& _rStyle ) @@ -79,15 +237,18 @@ namespace svt { namespace table OSL_PRECOND( _bIsColHeaderArea || _bIsRowHeaderArea, "GridTableRenderer::PaintHeaderArea: invalid area flags!" ); - _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR); - Color background = m_pImpl->rModel.getHeaderBackgroundColor(); - if( background != 0xFFFFFF) - _rDevice.SetFillColor(background); - else - _rDevice.SetFillColor(_rStyle.GetDialogColor()); - _rDevice.SetLineColor(_rStyle.GetSeparatorColor()); + _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); + + Color const background = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderBackgroundColor(), _rStyle, &StyleSettings::GetDialogColor ); + _rDevice.SetFillColor( background ); + + _rDevice.SetLineColor(); _rDevice.DrawRect( _rArea ); + // delimiter lines at bottom/right + ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() ); + ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; + _rDevice.SetLineColor( lineColor ); _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); @@ -96,48 +257,73 @@ namespace svt { namespace table (void)_bIsRowHeaderArea; } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ void GridTableRenderer::PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) { _rDevice.Push( PUSH_LINECOLOR); - _rDevice.SetLineColor(_rStyle.GetSeparatorColor()); - _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight()); String sHeaderText; - PColumnModel pColumn = m_pImpl->rModel.getColumnModel( _nCol ); + PColumnModel const pColumn = m_pImpl->rModel.getColumnModel( _nCol ); DBG_ASSERT( !!pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" ); if ( !!pColumn ) sHeaderText = pColumn->getName(); - if(m_pImpl->rModel.getTextColor() != 0x000000) - _rDevice.SetTextColor(m_pImpl->rModel.getTextColor()); - else - _rDevice.SetTextColor(_rStyle.GetFieldTextColor()); - sal_uLong nHorFlag = TEXT_DRAW_LEFT; - sal_uLong nVerFlag = TEXT_DRAW_TOP; - if(m_pImpl->rModel.getVerticalAlign() == 1) - nVerFlag = TEXT_DRAW_VCENTER; - else if(m_pImpl->rModel.getVerticalAlign() == 2) - nVerFlag = TEXT_DRAW_BOTTOM; - if(m_pImpl->rModel.getColumnModel(_nCol)->getHorizontalAlign() == 1) - nHorFlag = TEXT_DRAW_CENTER; - else if(m_pImpl->rModel.getColumnModel(_nCol)->getHorizontalAlign() == 2) - nHorFlag = TEXT_DRAW_RIGHT; - Rectangle aRect(_rArea); - aRect.Left()+=4; aRect.Right()-=4; - aRect.Bottom()-=2; - _rDevice.DrawText( aRect, sHeaderText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP); + + ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), _rStyle, &StyleSettings::GetFieldTextColor ); + _rDevice.SetTextColor( textColor ); + + Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) ); + sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | TEXT_DRAW_CLIP; + _rDevice.DrawText( aTextRect, sHeaderText, nDrawTextFlags ); + + ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); + ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; + _rDevice.SetLineColor( lineColor ); + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight()); _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); + + // draw sort indicator if the model data is sorted by the given column + ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter(); + ColumnSort aCurrentSortOrder; + if ( pSortAdapter != NULL ) + aCurrentSortOrder = pSortAdapter->getCurrentSortOrder(); + if ( aCurrentSortOrder.nColumnPos == _nCol ) + { + long const nHeaderHeight( _rArea.GetHeight() ); + BitmapEx const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor( _rDevice, nHeaderHeight, _rStyle, + aCurrentSortOrder.eSortDirection == ColumnSortAscending ); + Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() ); + long const nSortIndicatorPaddingX = 2; + long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2; + + if ( ( nDrawTextFlags & TEXT_DRAW_RIGHT ) != 0 ) + { + // text is right aligned => draw the sort indicator at the left hand side + _rDevice.DrawBitmapEx( + Point( _rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY ), + aIndicatorBitmap + ); + } + else + { + // text is left-aligned or centered => draw the sort indicator at the right hand side + _rDevice.DrawBitmapEx( + Point( _rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY ), + aIndicatorBitmap + ); + } + } + _rDevice.Pop(); (void)_bActive; // no special painting for the active column at the moment (void)_bSelected; - //selection for column header not yet implemented + // selection for column header not yet implemented } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ void GridTableRenderer::PrepareRow( RowPos _nRow, bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle ) { @@ -146,237 +332,288 @@ namespace svt { namespace table _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR); - Color aRowBackground = m_pImpl->rModel.getOddRowBackgroundColor(); - Color line = m_pImpl->rModel.getLineColor(); - Color aRowBackground2 = m_pImpl->rModel.getEvenRowBackgroundColor(); - Color fieldColor = _rStyle.GetFieldColor(); - if(aRowBackground == 0xFFFFFF) - aRowBackground = fieldColor; - if(aRowBackground2 == 0xFFFFFF) - aRowBackground2 = fieldColor; - //if row is selected background color becomes blue, and lines should be also blue - //if they aren't user defined - if(_bSelected) + ::Color backgroundColor = _rStyle.GetFieldColor(); + + ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() ); + ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; + + if ( _bSelected ) { - Color aSelected(_rStyle.GetHighlightColor()); - aRowBackground = aSelected; - if(line == 0xFFFFFF) - _rDevice.SetLineColor(aRowBackground); - else - _rDevice.SetLineColor(line); + // selected rows use the background color from the style + backgroundColor = _rStyle.GetHighlightColor(); + if ( !aLineColor ) + lineColor = backgroundColor; } - //if row not selected, check the cases whether user defined backgrounds are set - //and set line color to be the same else { - if(aRowBackground2 != fieldColor && _nRow%2) + ::boost::optional< ::std::vector< ::Color > > aRowColors = m_pImpl->rModel.getRowBackgroundColors(); + if ( !aRowColors ) { - aRowBackground = aRowBackground2; - if(line == 0xFFFFFF) - _rDevice.SetLineColor(aRowBackground); + // use alternating default colors + Color const fieldColor = _rStyle.GetFieldColor(); + if ( _rStyle.GetHighContrastMode() || ( ( m_pImpl->nCurrentRow % 2 ) == 0 ) ) + { + backgroundColor = fieldColor; + } else - _rDevice.SetLineColor(line); + { + Color hilightColor = _rStyle.GetHighlightColor(); + hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() ); + hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() ); + hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() ); + backgroundColor = hilightColor; + } } - //fill the rows with alternating background colors if second background color is specified - else if(aRowBackground != fieldColor && line == 0xFFFFFF) - _rDevice.SetLineColor(aRowBackground); else { - //if Line color is set, then it was user defined and should be visible - //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible - _rDevice.SetLineColor(line); + if ( aRowColors->empty() ) + { + // all colors have the same background color + backgroundColor = _rStyle.GetFieldColor(); + } + else + { + backgroundColor = aRowColors->at( m_pImpl->nCurrentRow % aRowColors->size() ); + } } } - _rDevice.SetFillColor( aRowBackground ); - _rDevice.DrawRect( _rRowArea ); - // TODO: active? + //m_pImpl->bUseGridLines ? _rDevice.SetLineColor( lineColor ) : _rDevice.SetLineColor(); + _rDevice.SetLineColor(); + _rDevice.SetFillColor( backgroundColor ); + _rDevice.DrawRect( _rRowArea ); _rDevice.Pop(); + (void)_bActive; + // row containing the active cell not rendered any special at the moment } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ void GridTableRenderer::PaintRowHeader( bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, - const StyleSettings& _rStyle, rtl::OUString& _rText ) + const StyleSettings& _rStyle ) { - _rDevice.Push( PUSH_LINECOLOR); - _rDevice.SetLineColor(_rStyle.GetSeparatorColor()); + _rDevice.Push( PUSH_LINECOLOR | PUSH_TEXTCOLOR ); + + ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); + ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; + _rDevice.SetLineColor( lineColor ); _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); - if(m_pImpl->rModel.getTextColor() != 0x000000) - _rDevice.SetTextColor(m_pImpl->rModel.getTextColor()); - else - _rDevice.SetTextColor(_rStyle.GetFieldTextColor()); - sal_uLong nHorFlag = TEXT_DRAW_LEFT; - sal_uLong nVerFlag = TEXT_DRAW_TOP; - if(m_pImpl->rModel.getVerticalAlign() == 1) - nVerFlag = TEXT_DRAW_VCENTER; - else if(m_pImpl->rModel.getVerticalAlign() == 2) - nVerFlag = TEXT_DRAW_BOTTOM; - if(m_pImpl->rModel.getColumnModel(0)->getHorizontalAlign() == 1) - nHorFlag = TEXT_DRAW_CENTER; - else if(m_pImpl->rModel.getColumnModel(0)->getHorizontalAlign() == 2) - nHorFlag = TEXT_DRAW_RIGHT; - Rectangle aRect(_rArea); - aRect.Left()+=4; aRect.Right()-=4; - aRect.Bottom()-=2; - _rDevice.DrawText( aRect, _rText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP); + + Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) ); + ::rtl::OUString const rowTitle( CellValueConversion::convertToString( rowHeading ) ); + if ( rowTitle.getLength() ) + { + ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderTextColor(), _rStyle, &StyleSettings::GetFieldTextColor ); + _rDevice.SetTextColor( textColor ); + + Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) ); + sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, 0 ) | TEXT_DRAW_CLIP; + // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitray .. + _rDevice.DrawText( aTextRect, rowTitle, nDrawTextFlags ); + } + // TODO: active? selected? (void)_bActive; (void)_bSelected; - //at the moment no special paint for selected row header _rDevice.Pop(); } - //-------------------------------------------------------------------- - void GridTableRenderer::PaintCellImage( ColPos _nColumn, bool _bSelected, bool _bActive, - OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, Image* _pCellData ) - { - _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR); - Color background1 = m_pImpl->rModel.getOddRowBackgroundColor(); - Color background2 = m_pImpl->rModel.getEvenRowBackgroundColor(); - Color line = m_pImpl->rModel.getLineColor(); - //if row is selected and line color isn't user specified, set it blue - if(_bSelected) + //------------------------------------------------------------------------------------------------------------------ + struct GridTableRenderer::CellRenderContext + { + OutputDevice& rDevice; + Rectangle const aContentArea; + StyleSettings const & rStyle; + ColPos const nColumn; + bool const bSelected; + + CellRenderContext( OutputDevice& i_device, Rectangle const & i_contentArea, + StyleSettings const & i_style, ColPos const i_column, bool const i_selected ) + :rDevice( i_device ) + ,aContentArea( i_contentArea ) + ,rStyle( i_style ) + ,nColumn( i_column ) + ,bSelected( i_selected ) { - if(line == 0xFFFFFF) - _rDevice.SetLineColor(_rStyle.GetHighlightColor()); - else - _rDevice.SetLineColor(line); } - //else set line color to the color of row background - else + }; + + //------------------------------------------------------------------------------------------------------------------ + void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool _bActive, + OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) + { + _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); + + Rectangle const aContentArea( lcl_getContentArea( *m_pImpl, _rArea ) ); + CellRenderContext const aRenderContext( _rDevice, aContentArea, _rStyle, i_column, _bSelected ); + impl_paintCellContent( aRenderContext ); + + if ( m_pImpl->bUseGridLines ) { - if(background2 != 0xFFFFFF && m_pImpl->nCurrentRow%2) - { - if(line == 0xFFFFFF) - _rDevice.SetLineColor(background2); - else - _rDevice.SetLineColor(line); - } - else if(background1 != 0xFFFFFF && line == 0xFFFFFF) - _rDevice.SetLineColor(background1); - else + ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() ); + ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; + + if ( _bSelected && !aLineColor ) { - //if line color is set, then it was user defined and should be visible - //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible - _rDevice.SetLineColor(line); + // if no line color is specified by the model, use the usual selection color for lines in selected cells + lineColor = _rStyle.GetHighlightColor(); } - } - _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); - Rectangle aRect( _rArea ); - ++aRect.Left(); --aRect.Right(); - aRect.Top(); aRect.Bottom(); - Point imagePos(Point(aRect.Left(), aRect.Top())); - Size imageSize = _pCellData->GetSizePixel(); - if(aRect.GetWidth() > imageSize.Width()) - { - if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 1) - imagePos.X() = aRect.Left()+((double)(aRect.GetWidth() - imageSize.Width()))/2; - else if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 2) - imagePos.X() = aRect.Right() - imageSize.Width(); - } - else - imageSize.Width() = aRect.GetWidth(); - if(aRect.GetHeight() > imageSize.Height()) - { - if(m_pImpl->rModel.getVerticalAlign() == 1) - imagePos.Y() = aRect.Top()+((double)(aRect.GetHeight() - imageSize.Height()))/2; - else if(m_pImpl->rModel.getVerticalAlign() == 2) - imagePos.Y() = aRect.Bottom() - imageSize.Height(); + _rDevice.SetLineColor( lineColor ); + _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); } - else - imageSize.Height() = aRect.GetHeight()-1; - Image& image (*_pCellData); - _rDevice.DrawImage(imagePos, imageSize, image, 0); + _rDevice.Pop(); (void)_bActive; // no special painting for the active cell at the moment } - //-------------------------------------------------------------------- - void GridTableRenderer::PaintCellString( ColPos _nColumn, bool _bSelected, bool _bActive, - OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, rtl::OUString& _rText ) - { - _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); - Color background1 = m_pImpl->rModel.getOddRowBackgroundColor(); - Color background2 = m_pImpl->rModel.getEvenRowBackgroundColor(); - Color line = m_pImpl->rModel.getLineColor(); - //if row is selected and line color isn't user specified, set it blue - if(_bSelected) + //------------------------------------------------------------------------------------------------------------------ + void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image ) + { + Point imagePos( Point( i_context.aContentArea.Left(), i_context.aContentArea.Top() ) ); + Size imageSize = i_image.GetSizePixel(); + if ( i_context.aContentArea.GetWidth() > imageSize.Width() ) { - if(line == 0xFFFFFF) - _rDevice.SetLineColor(_rStyle.GetHighlightColor()); - else - _rDevice.SetLineColor(line); + const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign(); + switch ( eHorzAlign ) + { + case HorizontalAlignment_CENTER: + imagePos.X() += ( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2; + break; + case HorizontalAlignment_RIGHT: + imagePos.X() = i_context.aContentArea.Right() - imageSize.Width(); + break; + default: + break; + } + } - //else set line color to the color of row background else + imageSize.Width() = i_context.aContentArea.GetWidth(); + + if ( i_context.aContentArea.GetHeight() > imageSize.Height() ) { - if(background2 != 0xFFFFFF && m_pImpl->nCurrentRow%2) + const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign(); + switch ( eVertAlign ) { - if(line == 0xFFFFFF) - _rDevice.SetLineColor(background2); - else - _rDevice.SetLineColor(line); - } - else if(background1 != 0xFFFFFF && line == 0xFFFFFF) - _rDevice.SetLineColor(background1); - else - { - //if Line color is set, then it was user defined and should be visible - //if it wasn't set, it'll be the same as the default background color, so lines still won't be visible - _rDevice.SetLineColor(line); + case VerticalAlignment_MIDDLE: + imagePos.Y() += ( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2; + break; + case VerticalAlignment_BOTTOM: + imagePos.Y() = i_context.aContentArea.Bottom() - imageSize.Height(); + break; + default: + break; } } - _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + else + imageSize.Height() = i_context.aContentArea.GetHeight() - 1; + + i_context.rDevice.DrawImage( imagePos, imageSize, i_image, 0 ); + } + + //------------------------------------------------------------------------------------------------------------------ + void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context ) + { + Any aCellContent; + m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent ); + + if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE ) + { + Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY ); + if ( !xContentInterface.is() ) + // allowed. kind of. + return; - Rectangle aRect( _rArea ); - ++aRect.Left(); --aRect.Right(); - aRect.Top(); aRect.Bottom(); - if(_bSelected) - _rDevice.SetTextColor(_rStyle.GetHighlightTextColor()); - else if(m_pImpl->rModel.getTextColor() != 0x000000) - _rDevice.SetTextColor(m_pImpl->rModel.getTextColor()); + Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY ); + ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." ); + + const Image aImage( xGraphic ); + impl_paintCellImage( i_context, aImage ); + return; + } + + const ::rtl::OUString sText( CellValueConversion::convertToString( aCellContent ) ); + impl_paintCellText( i_context, sText ); + } + + //------------------------------------------------------------------------------------------------------------------ + void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, ::rtl::OUString const & i_text ) + { + if ( i_context.bSelected ) + i_context.rDevice.SetTextColor( i_context.rStyle.GetHighlightTextColor() ); else - _rDevice.SetTextColor(_rStyle.GetFieldTextColor()); - sal_uLong nHorFlag = TEXT_DRAW_LEFT; - sal_uLong nVerFlag = TEXT_DRAW_TOP; - if(m_pImpl->rModel.getVerticalAlign() == 1) - nVerFlag = TEXT_DRAW_VCENTER; - else if(m_pImpl->rModel.getVerticalAlign() == 2) - nVerFlag = TEXT_DRAW_BOTTOM; - if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 1) - nHorFlag = TEXT_DRAW_CENTER; - else if(m_pImpl->rModel.getColumnModel(_nColumn)->getHorizontalAlign() == 2) - nHorFlag = TEXT_DRAW_RIGHT; - Rectangle textRect(_rArea); - textRect.Left()+=4; textRect.Right()-=4; - textRect.Bottom()-=2; - _rDevice.DrawText( textRect, _rText, nHorFlag | nVerFlag | TEXT_DRAW_CLIP); + { + ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor ); + i_context.rDevice.SetTextColor( textColor ); + } - _rDevice.Pop(); - (void)_bActive; - // no special painting for the active cell at the moment + Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) ); + sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | TEXT_DRAW_CLIP; + i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags ); } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ void GridTableRenderer::ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect) { _rView.ShowFocus( _rCursorRect ); } - //-------------------------------------------------------------------- + //------------------------------------------------------------------------------------------------------------------ void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect) { - (void)_rCursorRect; + (void)_rCursorRect; _rView.HideFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent, ColPos const i_colPos, RowPos const i_rowPos, + bool const i_active, bool const i_selected, OutputDevice& i_targetDevice, Rectangle const & i_targetArea ) + { + if ( !i_cellContent.hasValue() ) + return true; + + if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE ) + { + Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY ); + if ( !xContentInterface.is() ) + return true; + + Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY ); + if ( xGraphic.is() ) + // for the moment, assume it fits. We can always scale it down during painting ... + return true; + + OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." ); + return true; + } + + ::rtl::OUString const sText( CellValueConversion::convertToString( i_cellContent ) ); + if ( sText.getLength() == 0 ) + return true; + + Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) ); + + long const nTextHeight = i_targetDevice.GetTextHeight(); + if ( nTextHeight > aTargetArea.GetHeight() ) + return false; + + long const nTextWidth = i_targetDevice.GetTextWidth( sText ); + if ( nTextWidth > aTargetArea.GetWidth() ) + return false; + OSL_UNUSED( i_active ); + OSL_UNUSED( i_selected ); + OSL_UNUSED( i_rowPos ); + OSL_UNUSED( i_colPos ); + return true; } -//........................................................................ +//...................................................................................................................... } } // namespace svt::table -//........................................................................ +//...................................................................................................................... |