1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svtools.hxx" 26 27 #include "cellvalueconversion.hxx" 28 #include "svtools/table/gridtablerenderer.hxx" 29 #include "svtools/colorcfg.hxx" 30 31 /** === begin UNO includes === **/ 32 #include <com/sun/star/graphic/XGraphic.hpp> 33 /** === end UNO includes === **/ 34 35 #include <comphelper/componentcontext.hxx> 36 #include <comphelper/processfactory.hxx> 37 #include <tools/debug.hxx> 38 #include <tools/diagnose_ex.h> 39 #include <vcl/window.hxx> 40 #include <vcl/image.hxx> 41 #include <vcl/virdev.hxx> 42 #include <vcl/decoview.hxx> 43 44 //...................................................................................................................... 45 namespace svt { namespace table 46 { 47 //...................................................................................................................... 48 49 /** === begin UNO using === **/ 50 using ::com::sun::star::uno::Any; 51 using ::com::sun::star::uno::Reference; 52 using ::com::sun::star::uno::UNO_QUERY; 53 using ::com::sun::star::uno::XInterface; 54 using ::com::sun::star::uno::TypeClass_INTERFACE; 55 using ::com::sun::star::graphic::XGraphic; 56 using ::com::sun::star::style::HorizontalAlignment; 57 using ::com::sun::star::style::HorizontalAlignment_LEFT; 58 using ::com::sun::star::style::HorizontalAlignment_CENTER; 59 using ::com::sun::star::style::HorizontalAlignment_RIGHT; 60 using ::com::sun::star::style::VerticalAlignment; 61 using ::com::sun::star::style::VerticalAlignment_TOP; 62 using ::com::sun::star::style::VerticalAlignment_MIDDLE; 63 using ::com::sun::star::style::VerticalAlignment_BOTTOM; 64 /** === end UNO using === **/ 65 66 //================================================================================================================== 67 //= CachedSortIndicator 68 //================================================================================================================== 69 class CachedSortIndicator 70 { 71 public: CachedSortIndicator()72 CachedSortIndicator() 73 :m_lastHeaderHeight( 0 ) 74 ,m_lastArrowColor( COL_TRANSPARENT ) 75 { 76 } 77 78 BitmapEx const & getBitmapFor( OutputDevice const & i_device, long const i_headerHeight, StyleSettings const & i_style, bool const i_sortAscending ); 79 80 private: 81 long m_lastHeaderHeight; 82 Color m_lastArrowColor; 83 BitmapEx m_sortAscending; 84 BitmapEx m_sortDescending; 85 }; 86 87 //------------------------------------------------------------------------------------------------------------------ getBitmapFor(OutputDevice const & i_device,long const i_headerHeight,StyleSettings const & i_style,bool const i_sortAscending)88 BitmapEx const & CachedSortIndicator::getBitmapFor( OutputDevice const & i_device, long const i_headerHeight, 89 StyleSettings const & i_style, bool const i_sortAscending ) 90 { 91 BitmapEx & rBitmap( i_sortAscending ? m_sortAscending : m_sortDescending ); 92 if ( !rBitmap || ( i_headerHeight != m_lastHeaderHeight ) || ( i_style.GetActiveColor() != m_lastArrowColor ) ) 93 { 94 long const nSortIndicatorWidth = 2 * i_headerHeight / 3; 95 long const nSortIndicatorHeight = 2 * nSortIndicatorWidth / 3; 96 97 Point const aBitmapPos( 0, 0 ); 98 Size const aBitmapSize( nSortIndicatorWidth, nSortIndicatorHeight ); 99 VirtualDevice aDevice( i_device, 0, 0 ); 100 aDevice.SetOutputSizePixel( aBitmapSize ); 101 102 DecorationView aDecoView( &aDevice ); 103 aDecoView.DrawSymbol( 104 Rectangle( aBitmapPos, aBitmapSize ), 105 i_sortAscending ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN, 106 i_style.GetActiveColor() 107 ); 108 109 rBitmap = aDevice.GetBitmapEx( aBitmapPos, aBitmapSize ); 110 m_lastHeaderHeight = i_headerHeight; 111 m_lastArrowColor = i_style.GetActiveColor(); 112 } 113 return rBitmap; 114 } 115 116 //================================================================================================================== 117 //= GridTableRenderer_Impl 118 //================================================================================================================== 119 struct GridTableRenderer_Impl 120 { 121 ITableModel& rModel; 122 RowPos nCurrentRow; 123 bool bUseGridLines; 124 CachedSortIndicator aSortIndicator; 125 CellValueConversion aStringConverter; 126 GridTableRenderer_Implsvt::table::GridTableRenderer_Impl127 GridTableRenderer_Impl( ITableModel& _rModel ) 128 :rModel( _rModel ) 129 ,nCurrentRow( ROW_INVALID ) 130 ,bUseGridLines( true ) 131 ,aSortIndicator( ) 132 ,aStringConverter( ::comphelper::ComponentContext( ::comphelper::getProcessServiceFactory() ) ) 133 { 134 } 135 }; 136 137 //================================================================================================================== 138 //= helper 139 //================================================================================================================== 140 namespace 141 { lcl_getContentArea(GridTableRenderer_Impl const & i_impl,Rectangle const & i_cellArea)142 static Rectangle lcl_getContentArea( GridTableRenderer_Impl const & i_impl, Rectangle const & i_cellArea ) 143 { 144 Rectangle aContentArea( i_cellArea ); 145 if ( i_impl.bUseGridLines ) 146 { 147 --aContentArea.Right(); 148 --aContentArea.Bottom(); 149 } 150 return aContentArea; 151 } lcl_getTextRenderingArea(Rectangle const & i_contentArea)152 static Rectangle lcl_getTextRenderingArea( Rectangle const & i_contentArea ) 153 { 154 Rectangle aTextArea( i_contentArea ); 155 aTextArea.Left() += 2; aTextArea.Right() -= 2; 156 ++aTextArea.Top(); --aTextArea.Bottom(); 157 return aTextArea; 158 } 159 lcl_getAlignmentTextDrawFlags(GridTableRenderer_Impl const & i_impl,ColPos const i_columnPos)160 static sal_uLong lcl_getAlignmentTextDrawFlags( GridTableRenderer_Impl const & i_impl, ColPos const i_columnPos ) 161 { 162 sal_uLong nVertFlag = TEXT_DRAW_TOP; 163 VerticalAlignment const eVertAlign = i_impl.rModel.getVerticalAlign(); 164 switch ( eVertAlign ) 165 { 166 case VerticalAlignment_MIDDLE: nVertFlag = TEXT_DRAW_VCENTER; break; 167 case VerticalAlignment_BOTTOM: nVertFlag = TEXT_DRAW_BOTTOM; break; 168 default: 169 break; 170 } 171 172 sal_uLong nHorzFlag = TEXT_DRAW_LEFT; 173 HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnCount() > 0 174 ? i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign() 175 : HorizontalAlignment_CENTER; 176 switch ( eHorzAlign ) 177 { 178 case HorizontalAlignment_CENTER: nHorzFlag = TEXT_DRAW_CENTER; break; 179 case HorizontalAlignment_RIGHT: nHorzFlag = TEXT_DRAW_RIGHT; break; 180 default: 181 break; 182 } 183 184 return nVertFlag | nHorzFlag; 185 } 186 187 } 188 189 //================================================================================================================== 190 //= GridTableRenderer 191 //================================================================================================================== 192 //------------------------------------------------------------------------------------------------------------------ GridTableRenderer(ITableModel & _rModel)193 GridTableRenderer::GridTableRenderer( ITableModel& _rModel ) 194 :m_pImpl( new GridTableRenderer_Impl( _rModel ) ) 195 { 196 } 197 198 //------------------------------------------------------------------------------------------------------------------ ~GridTableRenderer()199 GridTableRenderer::~GridTableRenderer() 200 { 201 } 202 203 //------------------------------------------------------------------------------------------------------------------ getCurrentRow() const204 RowPos GridTableRenderer::getCurrentRow() const 205 { 206 return m_pImpl->nCurrentRow; 207 } 208 209 //------------------------------------------------------------------------------------------------------------------ useGridLines() const210 bool GridTableRenderer::useGridLines() const 211 { 212 return m_pImpl->bUseGridLines; 213 } 214 215 //------------------------------------------------------------------------------------------------------------------ useGridLines(bool const i_use)216 void GridTableRenderer::useGridLines( bool const i_use ) 217 { 218 m_pImpl->bUseGridLines = i_use; 219 } 220 221 //------------------------------------------------------------------------------------------------------------------ 222 namespace 223 { lcl_getEffectiveColor(::boost::optional<::Color> const & i_modelColor,StyleSettings const & i_styleSettings,::Color const & (StyleSettings::* i_getDefaultColor)()const)224 Color lcl_getEffectiveColor( 225 ::boost::optional< ::Color > const & i_modelColor, 226 StyleSettings const & i_styleSettings, 227 ::Color const & ( StyleSettings::*i_getDefaultColor ) () const 228 ) 229 { 230 if ( !!i_modelColor ) 231 return *i_modelColor; 232 return ( i_styleSettings.*i_getDefaultColor )(); 233 } 234 } 235 236 //------------------------------------------------------------------------------------------------------------------ PaintHeaderArea(OutputDevice & _rDevice,const Rectangle & _rArea,bool _bIsColHeaderArea,bool _bIsRowHeaderArea,const StyleSettings & _rStyle)237 void GridTableRenderer::PaintHeaderArea( 238 OutputDevice& _rDevice, const Rectangle& _rArea, bool _bIsColHeaderArea, bool _bIsRowHeaderArea, 239 const StyleSettings& _rStyle ) 240 { 241 OSL_PRECOND( _bIsColHeaderArea || _bIsRowHeaderArea, 242 "GridTableRenderer::PaintHeaderArea: invalid area flags!" ); 243 244 _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); 245 246 Color const background = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderBackgroundColor(), _rStyle, &StyleSettings::GetDialogColor ); 247 _rDevice.SetFillColor( background ); 248 249 _rDevice.SetLineColor(); 250 _rDevice.DrawRect( _rArea ); 251 252 // delimiter lines at bottom/right 253 ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() ); 254 ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 255 _rDevice.SetLineColor( lineColor ); 256 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 257 _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); 258 259 _rDevice.Pop(); 260 (void)_bIsColHeaderArea; 261 (void)_bIsRowHeaderArea; 262 } 263 264 //------------------------------------------------------------------------------------------------------------------ PaintColumnHeader(ColPos _nCol,bool _bActive,bool _bSelected,OutputDevice & _rDevice,const Rectangle & _rArea,const StyleSettings & _rStyle)265 void GridTableRenderer::PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected, 266 OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) 267 { 268 _rDevice.Push( PUSH_LINECOLOR); 269 270 String sHeaderText; 271 PColumnModel const pColumn = m_pImpl->rModel.getColumnModel( _nCol ); 272 DBG_ASSERT( !!pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" ); 273 if ( !!pColumn ) 274 sHeaderText = pColumn->getName(); 275 276 ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), _rStyle, &StyleSettings::GetFieldTextColor ); 277 _rDevice.SetTextColor( textColor ); 278 279 Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) ); 280 sal_uLong nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | TEXT_DRAW_CLIP; 281 if ( !m_pImpl->rModel.isEnabled() ) 282 nDrawTextFlags |= TEXT_DRAW_DISABLE; 283 _rDevice.DrawText( aTextRect, sHeaderText, nDrawTextFlags ); 284 285 ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); 286 ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 287 _rDevice.SetLineColor( lineColor ); 288 _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight()); 289 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 290 291 // draw sort indicator if the model data is sorted by the given column 292 ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter(); 293 ColumnSort aCurrentSortOrder; 294 if ( pSortAdapter != NULL ) 295 aCurrentSortOrder = pSortAdapter->getCurrentSortOrder(); 296 if ( aCurrentSortOrder.nColumnPos == _nCol ) 297 { 298 long const nHeaderHeight( _rArea.GetHeight() ); 299 BitmapEx const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor( _rDevice, nHeaderHeight, _rStyle, 300 aCurrentSortOrder.eSortDirection == ColumnSortAscending ); 301 Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() ); 302 long const nSortIndicatorPaddingX = 2; 303 long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2; 304 305 if ( ( nDrawTextFlags & TEXT_DRAW_RIGHT ) != 0 ) 306 { 307 // text is right aligned => draw the sort indicator at the left hand side 308 _rDevice.DrawBitmapEx( 309 Point( _rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY ), 310 aIndicatorBitmap 311 ); 312 } 313 else 314 { 315 // text is left-aligned or centered => draw the sort indicator at the right hand side 316 _rDevice.DrawBitmapEx( 317 Point( _rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY ), 318 aIndicatorBitmap 319 ); 320 } 321 } 322 323 _rDevice.Pop(); 324 325 (void)_bActive; 326 // no special painting for the active column at the moment 327 328 (void)_bSelected; 329 // selection for column header not yet implemented 330 } 331 332 //------------------------------------------------------------------------------------------------------------------ PrepareRow(RowPos _nRow,bool i_hasControlFocus,bool _bSelected,OutputDevice & _rDevice,const Rectangle & _rRowArea,const StyleSettings & _rStyle)333 void GridTableRenderer::PrepareRow( RowPos _nRow, bool i_hasControlFocus, bool _bSelected, 334 OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle ) 335 { 336 // remember the row for subsequent calls to the other ->ITableRenderer methods 337 m_pImpl->nCurrentRow = _nRow; 338 339 _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR); 340 341 ::Color backgroundColor = _rStyle.GetFieldColor(); 342 343 ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); 344 ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 345 346 ::Color const activeSelectionBackColor = 347 lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor ); 348 if ( _bSelected ) 349 { 350 // selected rows use the background color from the style 351 backgroundColor = i_hasControlFocus 352 ? activeSelectionBackColor 353 : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor ); 354 if ( !aLineColor ) 355 lineColor = backgroundColor; 356 } 357 else 358 { 359 ::boost::optional< ::std::vector< ::Color > > aRowColors = m_pImpl->rModel.getRowBackgroundColors(); 360 if ( !aRowColors ) 361 { 362 // use alternating default colors 363 Color const fieldColor = _rStyle.GetFieldColor(); 364 if ( _rStyle.GetHighContrastMode() || ( ( m_pImpl->nCurrentRow % 2 ) == 0 ) ) 365 { 366 backgroundColor = fieldColor; 367 } 368 else 369 { 370 Color hilightColor = activeSelectionBackColor; 371 hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() ); 372 hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() ); 373 hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() ); 374 backgroundColor = hilightColor; 375 } 376 } 377 else 378 { 379 if ( aRowColors->empty() ) 380 { 381 // all colors have the same background color 382 backgroundColor = _rStyle.GetFieldColor(); 383 } 384 else 385 { 386 backgroundColor = aRowColors->at( m_pImpl->nCurrentRow % aRowColors->size() ); 387 } 388 } 389 } 390 391 //m_pImpl->bUseGridLines ? _rDevice.SetLineColor( lineColor ) : _rDevice.SetLineColor(); 392 _rDevice.SetLineColor(); 393 _rDevice.SetFillColor( backgroundColor ); 394 _rDevice.DrawRect( _rRowArea ); 395 396 _rDevice.Pop(); 397 } 398 399 //------------------------------------------------------------------------------------------------------------------ PaintRowHeader(bool i_hasControlFocus,bool _bSelected,OutputDevice & _rDevice,const Rectangle & _rArea,const StyleSettings & _rStyle)400 void GridTableRenderer::PaintRowHeader( bool i_hasControlFocus, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, 401 const StyleSettings& _rStyle ) 402 { 403 _rDevice.Push( PUSH_LINECOLOR | PUSH_TEXTCOLOR ); 404 405 ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); 406 ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 407 _rDevice.SetLineColor( lineColor ); 408 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 409 410 Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) ); 411 ::rtl::OUString const rowTitle( m_pImpl->aStringConverter.convertToString( rowHeading ) ); 412 if ( rowTitle.getLength() ) 413 { 414 ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderTextColor(), _rStyle, &StyleSettings::GetFieldTextColor ); 415 _rDevice.SetTextColor( textColor ); 416 417 Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) ); 418 sal_uLong nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, 0 ) | TEXT_DRAW_CLIP; 419 if ( !m_pImpl->rModel.isEnabled() ) 420 nDrawTextFlags |= TEXT_DRAW_DISABLE; 421 // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitray .. 422 _rDevice.DrawText( aTextRect, rowTitle, nDrawTextFlags ); 423 } 424 425 (void)i_hasControlFocus; 426 (void)_bSelected; 427 _rDevice.Pop(); 428 } 429 430 //------------------------------------------------------------------------------------------------------------------ 431 struct GridTableRenderer::CellRenderContext 432 { 433 OutputDevice& rDevice; 434 Rectangle const aContentArea; 435 StyleSettings const & rStyle; 436 ColPos const nColumn; 437 bool const bSelected; 438 bool const bHasControlFocus; 439 CellRenderContextsvt::table::GridTableRenderer::CellRenderContext440 CellRenderContext( OutputDevice& i_device, Rectangle const & i_contentArea, 441 StyleSettings const & i_style, ColPos const i_column, bool const i_selected, bool const i_hasControlFocus ) 442 :rDevice( i_device ) 443 ,aContentArea( i_contentArea ) 444 ,rStyle( i_style ) 445 ,nColumn( i_column ) 446 ,bSelected( i_selected ) 447 ,bHasControlFocus( i_hasControlFocus ) 448 { 449 } 450 }; 451 452 //------------------------------------------------------------------------------------------------------------------ PaintCell(ColPos const i_column,bool _bSelected,bool i_hasControlFocus,OutputDevice & _rDevice,const Rectangle & _rArea,const StyleSettings & _rStyle)453 void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool i_hasControlFocus, 454 OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) 455 { 456 _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 457 458 Rectangle const aContentArea( lcl_getContentArea( *m_pImpl, _rArea ) ); 459 CellRenderContext const aRenderContext( _rDevice, aContentArea, _rStyle, i_column, _bSelected, i_hasControlFocus ); 460 impl_paintCellContent( aRenderContext ); 461 462 if ( m_pImpl->bUseGridLines ) 463 { 464 ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() ); 465 ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 466 467 if ( _bSelected && !aLineColor ) 468 { 469 // if no line color is specified by the model, use the usual selection color for lines in selected cells 470 lineColor = i_hasControlFocus 471 ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor ) 472 : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor ); 473 } 474 475 _rDevice.SetLineColor( lineColor ); 476 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 477 _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); 478 } 479 480 _rDevice.Pop(); 481 } 482 483 //------------------------------------------------------------------------------------------------------------------ impl_paintCellImage(CellRenderContext const & i_context,Image const & i_image)484 void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image ) 485 { 486 Point imagePos( Point( i_context.aContentArea.Left(), i_context.aContentArea.Top() ) ); 487 Size imageSize = i_image.GetSizePixel(); 488 if ( i_context.aContentArea.GetWidth() > imageSize.Width() ) 489 { 490 const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign(); 491 switch ( eHorzAlign ) 492 { 493 case HorizontalAlignment_CENTER: 494 imagePos.X() += ( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2; 495 break; 496 case HorizontalAlignment_RIGHT: 497 imagePos.X() = i_context.aContentArea.Right() - imageSize.Width(); 498 break; 499 default: 500 break; 501 } 502 503 } 504 else 505 imageSize.Width() = i_context.aContentArea.GetWidth(); 506 507 if ( i_context.aContentArea.GetHeight() > imageSize.Height() ) 508 { 509 const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign(); 510 switch ( eVertAlign ) 511 { 512 case VerticalAlignment_MIDDLE: 513 imagePos.Y() += ( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2; 514 break; 515 case VerticalAlignment_BOTTOM: 516 imagePos.Y() = i_context.aContentArea.Bottom() - imageSize.Height(); 517 break; 518 default: 519 break; 520 } 521 } 522 else 523 imageSize.Height() = i_context.aContentArea.GetHeight() - 1; 524 sal_uInt16 const nStyle = m_pImpl->rModel.isEnabled() ? 0 : IMAGE_DRAW_DISABLE; 525 i_context.rDevice.DrawImage( imagePos, imageSize, i_image, nStyle ); 526 } 527 528 //------------------------------------------------------------------------------------------------------------------ impl_paintCellContent(CellRenderContext const & i_context)529 void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context ) 530 { 531 Any aCellContent; 532 m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent ); 533 534 if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE ) 535 { 536 Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY ); 537 if ( !xContentInterface.is() ) 538 // allowed. kind of. 539 return; 540 541 Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY ); 542 ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." ); 543 544 const Image aImage( xGraphic ); 545 impl_paintCellImage( i_context, aImage ); 546 return; 547 } 548 549 const ::rtl::OUString sText( m_pImpl->aStringConverter.convertToString( aCellContent ) ); 550 impl_paintCellText( i_context, sText ); 551 } 552 553 //------------------------------------------------------------------------------------------------------------------ impl_paintCellText(CellRenderContext const & i_context,::rtl::OUString const & i_text)554 void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, ::rtl::OUString const & i_text ) 555 { 556 if ( i_context.bSelected ) 557 { 558 ::Color const textColor = i_context.bHasControlFocus 559 ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetHighlightTextColor ) 560 : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetDeactiveTextColor ); 561 i_context.rDevice.SetTextColor( textColor ); 562 } 563 else 564 { 565 ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor ); 566 i_context.rDevice.SetTextColor( textColor ); 567 } 568 569 Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) ); 570 sal_uLong nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | TEXT_DRAW_CLIP; 571 if ( !m_pImpl->rModel.isEnabled() ) 572 nDrawTextFlags |= TEXT_DRAW_DISABLE; 573 i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags ); 574 } 575 576 //------------------------------------------------------------------------------------------------------------------ ShowCellCursor(Window & _rView,const Rectangle & _rCursorRect)577 void GridTableRenderer::ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect) 578 { 579 _rView.ShowFocus( _rCursorRect ); 580 } 581 582 //------------------------------------------------------------------------------------------------------------------ HideCellCursor(Window & _rView,const Rectangle & _rCursorRect)583 void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect) 584 { 585 (void)_rCursorRect; 586 _rView.HideFocus(); 587 } 588 589 //------------------------------------------------------------------------------------------------------------------ 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) const590 bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent, ColPos const i_colPos, RowPos const i_rowPos, 591 bool const i_active, bool const i_selected, OutputDevice& i_targetDevice, Rectangle const & i_targetArea ) const 592 { 593 if ( !i_cellContent.hasValue() ) 594 return true; 595 596 if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE ) 597 { 598 Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY ); 599 if ( !xContentInterface.is() ) 600 return true; 601 602 Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY ); 603 if ( xGraphic.is() ) 604 // for the moment, assume it fits. We can always scale it down during painting ... 605 return true; 606 607 OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." ); 608 return true; 609 } 610 611 ::rtl::OUString const sText( m_pImpl->aStringConverter.convertToString( i_cellContent ) ); 612 if ( sText.getLength() == 0 ) 613 return true; 614 615 Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) ); 616 617 long const nTextHeight = i_targetDevice.GetTextHeight(); 618 if ( nTextHeight > aTargetArea.GetHeight() ) 619 return false; 620 621 long const nTextWidth = i_targetDevice.GetTextWidth( sText ); 622 if ( nTextWidth > aTargetArea.GetWidth() ) 623 return false; 624 625 OSL_UNUSED( i_active ); 626 OSL_UNUSED( i_selected ); 627 OSL_UNUSED( i_rowPos ); 628 OSL_UNUSED( i_colPos ); 629 return true; 630 } 631 632 //------------------------------------------------------------------------------------------------------------------ GetFormattedCellString(Any const & i_cellValue,ColPos const i_colPos,RowPos const i_rowPos,::rtl::OUString & o_cellString) const633 bool GridTableRenderer::GetFormattedCellString( Any const & i_cellValue, ColPos const i_colPos, RowPos const i_rowPos, ::rtl::OUString & o_cellString ) const 634 { 635 o_cellString = m_pImpl->aStringConverter.convertToString( i_cellValue ); 636 637 OSL_UNUSED( i_colPos ); 638 OSL_UNUSED( i_rowPos ); 639 return true; 640 } 641 642 //...................................................................................................................... 643 } } // namespace svt::table 644 //...................................................................................................................... 645 646