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: 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 //------------------------------------------------------------------------------------------------------------------ 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 127 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 { 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 } 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 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 //------------------------------------------------------------------------------------------------------------------ 193 GridTableRenderer::GridTableRenderer( ITableModel& _rModel ) 194 :m_pImpl( new GridTableRenderer_Impl( _rModel ) ) 195 { 196 } 197 198 //------------------------------------------------------------------------------------------------------------------ 199 GridTableRenderer::~GridTableRenderer() 200 { 201 } 202 203 //------------------------------------------------------------------------------------------------------------------ 204 RowPos GridTableRenderer::getCurrentRow() const 205 { 206 return m_pImpl->nCurrentRow; 207 } 208 209 //------------------------------------------------------------------------------------------------------------------ 210 bool GridTableRenderer::useGridLines() const 211 { 212 return m_pImpl->bUseGridLines; 213 } 214 215 //------------------------------------------------------------------------------------------------------------------ 216 void GridTableRenderer::useGridLines( bool const i_use ) 217 { 218 m_pImpl->bUseGridLines = i_use; 219 } 220 221 //------------------------------------------------------------------------------------------------------------------ 222 namespace 223 { 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 //------------------------------------------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------------------------------------------ 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 const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | TEXT_DRAW_CLIP; 281 _rDevice.DrawText( aTextRect, sHeaderText, nDrawTextFlags ); 282 283 ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); 284 ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 285 _rDevice.SetLineColor( lineColor ); 286 _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight()); 287 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 288 289 // draw sort indicator if the model data is sorted by the given column 290 ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter(); 291 ColumnSort aCurrentSortOrder; 292 if ( pSortAdapter != NULL ) 293 aCurrentSortOrder = pSortAdapter->getCurrentSortOrder(); 294 if ( aCurrentSortOrder.nColumnPos == _nCol ) 295 { 296 long const nHeaderHeight( _rArea.GetHeight() ); 297 BitmapEx const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor( _rDevice, nHeaderHeight, _rStyle, 298 aCurrentSortOrder.eSortDirection == ColumnSortAscending ); 299 Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() ); 300 long const nSortIndicatorPaddingX = 2; 301 long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2; 302 303 if ( ( nDrawTextFlags & TEXT_DRAW_RIGHT ) != 0 ) 304 { 305 // text is right aligned => draw the sort indicator at the left hand side 306 _rDevice.DrawBitmapEx( 307 Point( _rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY ), 308 aIndicatorBitmap 309 ); 310 } 311 else 312 { 313 // text is left-aligned or centered => draw the sort indicator at the right hand side 314 _rDevice.DrawBitmapEx( 315 Point( _rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY ), 316 aIndicatorBitmap 317 ); 318 } 319 } 320 321 _rDevice.Pop(); 322 323 (void)_bActive; 324 // no special painting for the active column at the moment 325 326 (void)_bSelected; 327 // selection for column header not yet implemented 328 } 329 330 //------------------------------------------------------------------------------------------------------------------ 331 void GridTableRenderer::PrepareRow( RowPos _nRow, bool i_hasControlFocus, bool _bSelected, 332 OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle ) 333 { 334 // remember the row for subsequent calls to the other ->ITableRenderer methods 335 m_pImpl->nCurrentRow = _nRow; 336 337 _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR); 338 339 ::Color backgroundColor = _rStyle.GetFieldColor(); 340 341 ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); 342 ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 343 344 ::Color const activeSelectionBackColor = 345 lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor ); 346 if ( _bSelected ) 347 { 348 // selected rows use the background color from the style 349 backgroundColor = i_hasControlFocus 350 ? activeSelectionBackColor 351 : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor ); 352 if ( !aLineColor ) 353 lineColor = backgroundColor; 354 } 355 else 356 { 357 ::boost::optional< ::std::vector< ::Color > > aRowColors = m_pImpl->rModel.getRowBackgroundColors(); 358 if ( !aRowColors ) 359 { 360 // use alternating default colors 361 Color const fieldColor = _rStyle.GetFieldColor(); 362 if ( _rStyle.GetHighContrastMode() || ( ( m_pImpl->nCurrentRow % 2 ) == 0 ) ) 363 { 364 backgroundColor = fieldColor; 365 } 366 else 367 { 368 Color hilightColor = activeSelectionBackColor; 369 hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() ); 370 hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() ); 371 hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() ); 372 backgroundColor = hilightColor; 373 } 374 } 375 else 376 { 377 if ( aRowColors->empty() ) 378 { 379 // all colors have the same background color 380 backgroundColor = _rStyle.GetFieldColor(); 381 } 382 else 383 { 384 backgroundColor = aRowColors->at( m_pImpl->nCurrentRow % aRowColors->size() ); 385 } 386 } 387 } 388 389 //m_pImpl->bUseGridLines ? _rDevice.SetLineColor( lineColor ) : _rDevice.SetLineColor(); 390 _rDevice.SetLineColor(); 391 _rDevice.SetFillColor( backgroundColor ); 392 _rDevice.DrawRect( _rRowArea ); 393 394 _rDevice.Pop(); 395 } 396 397 //------------------------------------------------------------------------------------------------------------------ 398 void GridTableRenderer::PaintRowHeader( bool i_hasControlFocus, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, 399 const StyleSettings& _rStyle ) 400 { 401 _rDevice.Push( PUSH_LINECOLOR | PUSH_TEXTCOLOR ); 402 403 ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() ); 404 ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 405 _rDevice.SetLineColor( lineColor ); 406 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 407 408 Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) ); 409 ::rtl::OUString const rowTitle( m_pImpl->aStringConverter.convertToString( rowHeading ) ); 410 if ( rowTitle.getLength() ) 411 { 412 ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderTextColor(), _rStyle, &StyleSettings::GetFieldTextColor ); 413 _rDevice.SetTextColor( textColor ); 414 415 Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) ); 416 sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, 0 ) | TEXT_DRAW_CLIP; 417 // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitray .. 418 _rDevice.DrawText( aTextRect, rowTitle, nDrawTextFlags ); 419 } 420 421 (void)i_hasControlFocus; 422 (void)_bSelected; 423 _rDevice.Pop(); 424 } 425 426 //------------------------------------------------------------------------------------------------------------------ 427 struct GridTableRenderer::CellRenderContext 428 { 429 OutputDevice& rDevice; 430 Rectangle const aContentArea; 431 StyleSettings const & rStyle; 432 ColPos const nColumn; 433 bool const bSelected; 434 bool const bHasControlFocus; 435 436 CellRenderContext( OutputDevice& i_device, Rectangle const & i_contentArea, 437 StyleSettings const & i_style, ColPos const i_column, bool const i_selected, bool const i_hasControlFocus ) 438 :rDevice( i_device ) 439 ,aContentArea( i_contentArea ) 440 ,rStyle( i_style ) 441 ,nColumn( i_column ) 442 ,bSelected( i_selected ) 443 ,bHasControlFocus( i_hasControlFocus ) 444 { 445 } 446 }; 447 448 //------------------------------------------------------------------------------------------------------------------ 449 void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool i_hasControlFocus, 450 OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) 451 { 452 _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 453 454 Rectangle const aContentArea( lcl_getContentArea( *m_pImpl, _rArea ) ); 455 CellRenderContext const aRenderContext( _rDevice, aContentArea, _rStyle, i_column, _bSelected, i_hasControlFocus ); 456 impl_paintCellContent( aRenderContext ); 457 458 if ( m_pImpl->bUseGridLines ) 459 { 460 ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() ); 461 ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor; 462 463 if ( _bSelected && !aLineColor ) 464 { 465 // if no line color is specified by the model, use the usual selection color for lines in selected cells 466 lineColor = i_hasControlFocus 467 ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor ) 468 : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor ); 469 } 470 471 _rDevice.SetLineColor( lineColor ); 472 _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); 473 _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); 474 } 475 476 _rDevice.Pop(); 477 } 478 479 //------------------------------------------------------------------------------------------------------------------ 480 void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image ) 481 { 482 Point imagePos( Point( i_context.aContentArea.Left(), i_context.aContentArea.Top() ) ); 483 Size imageSize = i_image.GetSizePixel(); 484 if ( i_context.aContentArea.GetWidth() > imageSize.Width() ) 485 { 486 const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign(); 487 switch ( eHorzAlign ) 488 { 489 case HorizontalAlignment_CENTER: 490 imagePos.X() += ( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2; 491 break; 492 case HorizontalAlignment_RIGHT: 493 imagePos.X() = i_context.aContentArea.Right() - imageSize.Width(); 494 break; 495 default: 496 break; 497 } 498 499 } 500 else 501 imageSize.Width() = i_context.aContentArea.GetWidth(); 502 503 if ( i_context.aContentArea.GetHeight() > imageSize.Height() ) 504 { 505 const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign(); 506 switch ( eVertAlign ) 507 { 508 case VerticalAlignment_MIDDLE: 509 imagePos.Y() += ( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2; 510 break; 511 case VerticalAlignment_BOTTOM: 512 imagePos.Y() = i_context.aContentArea.Bottom() - imageSize.Height(); 513 break; 514 default: 515 break; 516 } 517 } 518 else 519 imageSize.Height() = i_context.aContentArea.GetHeight() - 1; 520 521 i_context.rDevice.DrawImage( imagePos, imageSize, i_image, 0 ); 522 } 523 524 //------------------------------------------------------------------------------------------------------------------ 525 void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context ) 526 { 527 Any aCellContent; 528 m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent ); 529 530 if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE ) 531 { 532 Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY ); 533 if ( !xContentInterface.is() ) 534 // allowed. kind of. 535 return; 536 537 Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY ); 538 ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." ); 539 540 const Image aImage( xGraphic ); 541 impl_paintCellImage( i_context, aImage ); 542 return; 543 } 544 545 const ::rtl::OUString sText( m_pImpl->aStringConverter.convertToString( aCellContent ) ); 546 impl_paintCellText( i_context, sText ); 547 } 548 549 //------------------------------------------------------------------------------------------------------------------ 550 void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, ::rtl::OUString const & i_text ) 551 { 552 if ( i_context.bSelected ) 553 { 554 ::Color const textColor = i_context.bHasControlFocus 555 ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetHighlightTextColor ) 556 : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetDeactiveTextColor ); 557 i_context.rDevice.SetTextColor( textColor ); 558 } 559 else 560 { 561 ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor ); 562 i_context.rDevice.SetTextColor( textColor ); 563 } 564 565 Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) ); 566 sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | TEXT_DRAW_CLIP; 567 i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags ); 568 } 569 570 //------------------------------------------------------------------------------------------------------------------ 571 void GridTableRenderer::ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect) 572 { 573 _rView.ShowFocus( _rCursorRect ); 574 } 575 576 //------------------------------------------------------------------------------------------------------------------ 577 void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect) 578 { 579 (void)_rCursorRect; 580 _rView.HideFocus(); 581 } 582 583 //------------------------------------------------------------------------------------------------------------------ 584 bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent, ColPos const i_colPos, RowPos const i_rowPos, 585 bool const i_active, bool const i_selected, OutputDevice& i_targetDevice, Rectangle const & i_targetArea ) const 586 { 587 if ( !i_cellContent.hasValue() ) 588 return true; 589 590 if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE ) 591 { 592 Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY ); 593 if ( !xContentInterface.is() ) 594 return true; 595 596 Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY ); 597 if ( xGraphic.is() ) 598 // for the moment, assume it fits. We can always scale it down during painting ... 599 return true; 600 601 OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." ); 602 return true; 603 } 604 605 ::rtl::OUString const sText( m_pImpl->aStringConverter.convertToString( i_cellContent ) ); 606 if ( sText.getLength() == 0 ) 607 return true; 608 609 Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) ); 610 611 long const nTextHeight = i_targetDevice.GetTextHeight(); 612 if ( nTextHeight > aTargetArea.GetHeight() ) 613 return false; 614 615 long const nTextWidth = i_targetDevice.GetTextWidth( sText ); 616 if ( nTextWidth > aTargetArea.GetWidth() ) 617 return false; 618 619 OSL_UNUSED( i_active ); 620 OSL_UNUSED( i_selected ); 621 OSL_UNUSED( i_rowPos ); 622 OSL_UNUSED( i_colPos ); 623 return true; 624 } 625 626 //------------------------------------------------------------------------------------------------------------------ 627 bool GridTableRenderer::GetFormattedCellString( Any const & i_cellValue, ColPos const i_colPos, RowPos const i_rowPos, ::rtl::OUString & o_cellString ) const 628 { 629 o_cellString = m_pImpl->aStringConverter.convertToString( i_cellValue ); 630 631 OSL_UNUSED( i_colPos ); 632 OSL_UNUSED( i_rowPos ); 633 return true; 634 } 635 636 //...................................................................................................................... 637 } } // namespace svt::table 638 //...................................................................................................................... 639 640