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_sc.hxx" 26 27 28 // ============================================================================ 29 #include "csvgrid.hxx" 30 31 #include <algorithm> 32 #include <svtools/colorcfg.hxx> 33 #include <svl/smplhint.hxx> 34 #include <tools/poly.hxx> 35 #include "scmod.hxx" 36 #include "asciiopt.hxx" 37 #include "impex.hxx" 38 #include "AccessibleCsvControl.hxx" 39 40 // *** edit engine *** 41 #include "scitems.hxx" 42 #include <editeng/eeitem.hxx> 43 44 45 #include <editeng/colritem.hxx> 46 #include <editeng/fhgtitem.hxx> 47 #include <editeng/fontitem.hxx> 48 #include <svl/itemset.hxx> 49 #include "editutil.hxx" 50 // *** edit engine *** 51 52 53 // ============================================================================ 54 55 struct Func_SetType 56 { 57 sal_Int32 mnType; 58 inline Func_SetType( sal_Int32 nType ) : mnType( nType ) {} 59 inline void operator()( ScCsvColState& rState ) { rState.mnType = mnType; } 60 }; 61 62 struct Func_Select 63 { 64 bool mbSelect; 65 inline Func_Select( bool bSelect ) : mbSelect( bSelect ) {} 66 inline void operator()( ScCsvColState& rState ) { rState.Select( mbSelect ); } 67 }; 68 69 70 // ============================================================================ 71 72 ScCsvGrid::ScCsvGrid( ScCsvControl& rParent ) : 73 ScCsvControl( rParent ), 74 mrColorConfig( SC_MOD()->GetColorConfig() ), 75 mpEditEngine( new ScEditEngineDefaulter( EditEngine::CreatePool(), sal_True ) ), 76 maHeaderFont( GetFont() ), 77 maColStates( 1 ), 78 maTypeNames( 1 ), 79 mnFirstImpLine( 0 ), 80 mnRecentSelCol( CSV_COLUMN_INVALID ) 81 { 82 mpEditEngine->SetRefDevice( &maBackgrDev ); 83 mpEditEngine->SetRefMapMode( MapMode( MAP_PIXEL ) ); 84 maEdEngSize = mpEditEngine->GetPaperSize(); 85 86 maPopup.SetMenuFlags( maPopup.GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS ); 87 88 EnableRTL( false ); // #107812# RTL 89 InitColors(); 90 InitFonts(); 91 ImplClearSplits(); 92 mrColorConfig.AddListener(this); 93 } 94 95 ScCsvGrid::~ScCsvGrid() 96 { 97 mrColorConfig.RemoveListener(this); 98 } 99 100 101 // common grid handling ------------------------------------------------------- 102 103 void ScCsvGrid::UpdateLayoutData() 104 { 105 DisableRepaint(); 106 SetFont( maMonoFont ); 107 Execute( CSVCMD_SETCHARWIDTH, GetTextWidth( String( 'X' ) ) ); 108 Execute( CSVCMD_SETLINEHEIGHT, GetTextHeight() + 1 ); 109 SetFont( maHeaderFont ); 110 Execute( CSVCMD_SETHDRHEIGHT, GetTextHeight() + 1 ); 111 UpdateOffsetX(); 112 EnableRepaint(); 113 } 114 115 void ScCsvGrid::UpdateOffsetX() 116 { 117 sal_Int32 nLastLine = GetLastVisLine() + 1; 118 sal_Int32 nDigits = 2; 119 while( nLastLine /= 10 ) ++nDigits; 120 nDigits = Max( nDigits, sal_Int32( 3 ) ); 121 Execute( CSVCMD_SETHDRWIDTH, GetTextWidth( String( '0' ) ) * nDigits ); 122 } 123 124 void ScCsvGrid::ApplyLayout( const ScCsvLayoutData& rOldData ) 125 { 126 ScCsvDiff nDiff = GetLayoutData().GetDiff( rOldData ); 127 if( nDiff == CSV_DIFF_EQUAL ) return; 128 129 DisableRepaint(); 130 131 if( nDiff & CSV_DIFF_RULERCURSOR ) 132 { 133 ImplInvertCursor( rOldData.mnPosCursor ); 134 ImplInvertCursor( GetRulerCursorPos() ); 135 } 136 137 if( nDiff & CSV_DIFF_POSCOUNT ) 138 { 139 if( GetPosCount() < rOldData.mnPosCount ) 140 { 141 SelectAll( false ); 142 maSplits.RemoveRange( GetPosCount(), rOldData.mnPosCount ); 143 } 144 else 145 maSplits.Remove( rOldData.mnPosCount ); 146 maSplits.Insert( GetPosCount() ); 147 maColStates.resize( maSplits.Count() - 1 ); 148 } 149 150 if( nDiff & CSV_DIFF_LINEOFFSET ) 151 { 152 Execute( CSVCMD_UPDATECELLTEXTS ); 153 UpdateOffsetX(); 154 } 155 156 ScCsvDiff nHVDiff = nDiff & (CSV_DIFF_HORIZONTAL | CSV_DIFF_VERTICAL); 157 if( nHVDiff == CSV_DIFF_POSOFFSET ) 158 ImplDrawHorzScrolled( rOldData.mnPosOffset ); 159 else if( nHVDiff != CSV_DIFF_EQUAL ) 160 InvalidateGfx(); 161 162 EnableRepaint(); 163 164 if( nDiff & (CSV_DIFF_POSOFFSET | CSV_DIFF_LINEOFFSET) ) 165 AccSendVisibleEvent(); 166 } 167 168 void ScCsvGrid::SetFirstImportedLine( sal_Int32 nLine ) 169 { 170 ImplDrawFirstLineSep( false ); 171 mnFirstImpLine = nLine; 172 ImplDrawFirstLineSep( true ); 173 ImplDrawGridDev(); 174 Repaint(); 175 } 176 177 sal_Int32 ScCsvGrid::GetNoScrollCol( sal_Int32 nPos ) const 178 { 179 sal_Int32 nNewPos = nPos; 180 if( nNewPos != CSV_POS_INVALID ) 181 { 182 if( nNewPos < GetFirstVisPos() + CSV_SCROLL_DIST ) 183 { 184 sal_Int32 nScroll = (GetFirstVisPos() > 0) ? CSV_SCROLL_DIST : 0; 185 nNewPos = GetFirstVisPos() + nScroll; 186 } 187 else if( nNewPos > GetLastVisPos() - CSV_SCROLL_DIST - 1L ) 188 { 189 sal_Int32 nScroll = (GetFirstVisPos() < GetMaxPosOffset()) ? CSV_SCROLL_DIST : 0; 190 nNewPos = GetLastVisPos() - nScroll - 1; 191 } 192 } 193 return nNewPos; 194 } 195 196 void ScCsvGrid::InitColors() 197 { 198 maBackColor.SetColor( static_cast< sal_uInt32 >( mrColorConfig.GetColorValue( ::svtools::DOCCOLOR ).nColor ) ); 199 maGridColor.SetColor( static_cast< sal_uInt32 >( mrColorConfig.GetColorValue( ::svtools::CALCGRID ).nColor ) ); 200 maGridPBColor.SetColor( static_cast< sal_uInt32 >( mrColorConfig.GetColorValue( ::svtools::CALCPAGEBREAK ).nColor ) ); 201 maAppBackColor.SetColor( static_cast< sal_uInt32 >( mrColorConfig.GetColorValue( ::svtools::APPBACKGROUND ).nColor ) ); 202 maTextColor.SetColor( static_cast< sal_uInt32 >( mrColorConfig.GetColorValue( ::svtools::FONTCOLOR ).nColor ) ); 203 204 const StyleSettings& rSett = GetSettings().GetStyleSettings(); 205 maHeaderBackColor = rSett.GetFaceColor(); 206 maHeaderGridColor = rSett.GetDarkShadowColor(); 207 maHeaderTextColor = rSett.GetButtonTextColor(); 208 maSelectColor = rSett.GetActiveColor(); 209 210 InvalidateGfx(); 211 } 212 213 void ScCsvGrid::InitFonts() 214 { 215 maMonoFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_ENGLISH_US, 0 ); 216 maMonoFont.SetSize( Size( maMonoFont.GetSize().Width(), maHeaderFont.GetSize().Height() ) ); 217 218 /* *** Set edit engine defaults *** 219 maMonoFont for Latin script, smaller default font for Asian and Complex script. */ 220 221 // get default fonts 222 SvxFontItem aLatinItem( EE_CHAR_FONTINFO ); 223 SvxFontItem aAsianItem( EE_CHAR_FONTINFO_CJK ); 224 SvxFontItem aComplexItem( EE_CHAR_FONTINFO_CTL ); 225 ::GetDefaultFonts( aLatinItem, aAsianItem, aComplexItem ); 226 227 // create item set for defaults 228 SfxItemSet aDefSet( mpEditEngine->GetEmptyItemSet() ); 229 EditEngine::SetFontInfoInItemSet( aDefSet, maMonoFont ); 230 aDefSet.Put( aAsianItem ); 231 aDefSet.Put( aComplexItem ); 232 233 // set Asian/Complex font size to height of character in Latin font 234 sal_uLong nFontHt = static_cast< sal_uLong >( maMonoFont.GetSize().Height() ); 235 aDefSet.Put( SvxFontHeightItem( nFontHt, 100, EE_CHAR_FONTHEIGHT_CJK ) ); 236 aDefSet.Put( SvxFontHeightItem( nFontHt, 100, EE_CHAR_FONTHEIGHT_CTL ) ); 237 238 // copy other items from default font 239 const SfxPoolItem& rWeightItem = aDefSet.Get( EE_CHAR_WEIGHT ); 240 aDefSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK ); 241 aDefSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL ); 242 const SfxPoolItem& rItalicItem = aDefSet.Get( EE_CHAR_ITALIC ); 243 aDefSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK ); 244 aDefSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL ); 245 const SfxPoolItem& rLangItem = aDefSet.Get( EE_CHAR_LANGUAGE ); 246 aDefSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK ); 247 aDefSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL ); 248 249 mpEditEngine->SetDefaults( aDefSet ); 250 InvalidateGfx(); 251 } 252 253 void ScCsvGrid::InitSizeData() 254 { 255 maWinSize = GetSizePixel(); 256 maBackgrDev.SetOutputSizePixel( maWinSize ); 257 maGridDev.SetOutputSizePixel( maWinSize ); 258 InvalidateGfx(); 259 } 260 261 262 // split handling ------------------------------------------------------------- 263 264 void ScCsvGrid::InsertSplit( sal_Int32 nPos ) 265 { 266 if( ImplInsertSplit( nPos ) ) 267 { 268 DisableRepaint(); 269 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 270 Execute( CSVCMD_UPDATECELLTEXTS ); 271 sal_uInt32 nColIx = GetColumnFromPos( nPos ); 272 ImplDrawColumn( nColIx - 1 ); 273 ImplDrawColumn( nColIx ); 274 ValidateGfx(); // performance: do not redraw all columns 275 EnableRepaint(); 276 } 277 } 278 279 void ScCsvGrid::RemoveSplit( sal_Int32 nPos ) 280 { 281 if( ImplRemoveSplit( nPos ) ) 282 { 283 DisableRepaint(); 284 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 285 Execute( CSVCMD_UPDATECELLTEXTS ); 286 ImplDrawColumn( GetColumnFromPos( nPos ) ); 287 ValidateGfx(); // performance: do not redraw all columns 288 EnableRepaint(); 289 } 290 } 291 292 void ScCsvGrid::MoveSplit( sal_Int32 nPos, sal_Int32 nNewPos ) 293 { 294 sal_uInt32 nColIx = GetColumnFromPos( nPos ); 295 if( nColIx != CSV_COLUMN_INVALID ) 296 { 297 DisableRepaint(); 298 if( (GetColumnPos( nColIx - 1 ) < nNewPos) && (nNewPos < GetColumnPos( nColIx + 1 )) ) 299 { 300 // move a split in the range between 2 others -> keep selection state of both columns 301 maSplits.Remove( nPos ); 302 maSplits.Insert( nNewPos ); 303 Execute( CSVCMD_UPDATECELLTEXTS ); 304 ImplDrawColumn( nColIx - 1 ); 305 ImplDrawColumn( nColIx ); 306 ValidateGfx(); // performance: do not redraw all columns 307 AccSendTableUpdateEvent( nColIx - 1, nColIx ); 308 } 309 else 310 { 311 ImplRemoveSplit( nPos ); 312 ImplInsertSplit( nNewPos ); 313 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 314 Execute( CSVCMD_UPDATECELLTEXTS ); 315 } 316 EnableRepaint(); 317 } 318 } 319 320 void ScCsvGrid::RemoveAllSplits() 321 { 322 DisableRepaint(); 323 ImplClearSplits(); 324 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 325 Execute( CSVCMD_UPDATECELLTEXTS ); 326 EnableRepaint(); 327 } 328 329 void ScCsvGrid::SetSplits( const ScCsvSplits& rSplits ) 330 { 331 DisableRepaint(); 332 ImplClearSplits(); 333 sal_uInt32 nCount = rSplits.Count(); 334 for( sal_uInt32 nIx = 0; nIx < nCount; ++nIx ) 335 maSplits.Insert( rSplits[ nIx ] ); 336 maColStates.clear(); 337 maColStates.resize( maSplits.Count() - 1 ); 338 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 339 Execute( CSVCMD_UPDATECELLTEXTS ); 340 EnableRepaint(); 341 } 342 343 bool ScCsvGrid::ImplInsertSplit( sal_Int32 nPos ) 344 { 345 sal_uInt32 nColIx = GetColumnFromPos( nPos ); 346 bool bRet = (nColIx < GetColumnCount()) && maSplits.Insert( nPos ); 347 if( bRet ) 348 { 349 ScCsvColState aState( GetColumnType( nColIx ) ); 350 aState.Select( IsSelected( nColIx ) && IsSelected( nColIx + 1 ) ); 351 maColStates.insert( maColStates.begin() + nColIx + 1, aState ); 352 AccSendInsertColumnEvent( nColIx + 1, nColIx + 1 ); 353 AccSendTableUpdateEvent( nColIx, nColIx ); 354 } 355 return bRet; 356 } 357 358 bool ScCsvGrid::ImplRemoveSplit( sal_Int32 nPos ) 359 { 360 bool bRet = maSplits.Remove( nPos ); 361 if( bRet ) 362 { 363 sal_uInt32 nColIx = GetColumnFromPos( nPos ); 364 bool bSel = IsSelected( nColIx ) || IsSelected( nColIx + 1 ); 365 maColStates.erase( maColStates.begin() + nColIx + 1 ); 366 maColStates[ nColIx ].Select( bSel ); 367 AccSendRemoveColumnEvent( nColIx + 1, nColIx + 1 ); 368 AccSendTableUpdateEvent( nColIx, nColIx ); 369 } 370 return bRet; 371 } 372 373 void ScCsvGrid::ImplClearSplits() 374 { 375 sal_uInt32 nColumns = GetColumnCount(); 376 maSplits.Clear(); 377 maSplits.Insert( 0 ); 378 maSplits.Insert( GetPosCount() ); 379 maColStates.resize( 1 ); 380 InvalidateGfx(); 381 AccSendRemoveColumnEvent( 1, nColumns - 1 ); 382 } 383 384 // columns/column types ------------------------------------------------------- 385 386 sal_uInt32 ScCsvGrid::GetFirstVisColumn() const 387 { 388 return GetColumnFromPos( GetFirstVisPos() ); 389 } 390 391 sal_uInt32 ScCsvGrid::GetLastVisColumn() const 392 { 393 return GetColumnFromPos( Min( GetLastVisPos(), GetPosCount() ) - 1 ); 394 } 395 396 bool ScCsvGrid::IsValidColumn( sal_uInt32 nColIndex ) const 397 { 398 return nColIndex < GetColumnCount(); 399 } 400 401 bool ScCsvGrid::IsVisibleColumn( sal_uInt32 nColIndex ) const 402 { 403 return IsValidColumn( nColIndex ) && 404 (GetColumnPos( nColIndex ) < GetLastVisPos()) && 405 (GetFirstVisPos() < GetColumnPos( nColIndex + 1 )); 406 } 407 408 sal_Int32 ScCsvGrid::GetColumnX( sal_uInt32 nColIndex ) const 409 { 410 return GetX( GetColumnPos( nColIndex ) ); 411 } 412 413 sal_uInt32 ScCsvGrid::GetColumnFromX( sal_Int32 nX ) const 414 { 415 sal_Int32 nPos = (nX - GetFirstX()) / GetCharWidth() + GetFirstVisPos(); 416 return ((GetFirstVisPos() <= nPos) && (nPos <= GetLastVisPos())) ? 417 GetColumnFromPos( nPos ) : CSV_COLUMN_INVALID; 418 } 419 420 sal_uInt32 ScCsvGrid::GetColumnFromPos( sal_Int32 nPos ) const 421 { 422 return maSplits.UpperBound( nPos ); 423 } 424 425 sal_Int32 ScCsvGrid::GetColumnWidth( sal_uInt32 nColIndex ) const 426 { 427 return IsValidColumn( nColIndex ) ? (GetColumnPos( nColIndex + 1 ) - GetColumnPos( nColIndex )) : 0; 428 } 429 430 void ScCsvGrid::SetColumnStates( const ScCsvColStateVec& rStates ) 431 { 432 maColStates = rStates; 433 maColStates.resize( maSplits.Count() - 1 ); 434 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 435 AccSendTableUpdateEvent( 0, GetColumnCount(), false ); 436 AccSendSelectionEvent(); 437 } 438 439 sal_Int32 ScCsvGrid::GetColumnType( sal_uInt32 nColIndex ) const 440 { 441 return IsValidColumn( nColIndex ) ? maColStates[ nColIndex ].mnType : CSV_TYPE_NOSELECTION; 442 } 443 444 void ScCsvGrid::SetColumnType( sal_uInt32 nColIndex, sal_Int32 nColType ) 445 { 446 if( IsValidColumn( nColIndex ) ) 447 { 448 maColStates[ nColIndex ].mnType = nColType; 449 AccSendTableUpdateEvent( nColIndex, nColIndex, false ); 450 } 451 } 452 453 sal_Int32 ScCsvGrid::GetSelColumnType() const 454 { 455 sal_uInt32 nColIx = GetFirstSelected(); 456 if( nColIx == CSV_COLUMN_INVALID ) 457 return CSV_TYPE_NOSELECTION; 458 459 sal_Int32 nType = GetColumnType( nColIx ); 460 while( (nColIx != CSV_COLUMN_INVALID) && (nType != CSV_TYPE_MULTI) ) 461 { 462 if( nType != GetColumnType( nColIx ) ) 463 nType = CSV_TYPE_MULTI; 464 nColIx = GetNextSelected( nColIx ); 465 } 466 return nType; 467 } 468 469 void ScCsvGrid::SetSelColumnType( sal_Int32 nType ) 470 { 471 if( (nType != CSV_TYPE_MULTI) && (nType != CSV_TYPE_NOSELECTION) ) 472 { 473 for( sal_uInt32 nColIx = GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = GetNextSelected( nColIx ) ) 474 SetColumnType( nColIx, nType ); 475 Repaint( true ); 476 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 477 } 478 } 479 480 void ScCsvGrid::SetTypeNames( const StringVec& rTypeNames ) 481 { 482 DBG_ASSERT( !rTypeNames.empty(), "ScCsvGrid::SetTypeNames - vector is empty" ); 483 maTypeNames = rTypeNames; 484 Repaint( true ); 485 486 maPopup.Clear(); 487 sal_uInt32 nCount = maTypeNames.size(); 488 sal_uInt32 nIx; 489 sal_uInt16 nItemId; 490 for( nIx = 0, nItemId = 1; nIx < nCount; ++nIx, ++nItemId ) 491 maPopup.InsertItem( nItemId, maTypeNames[ nIx ] ); 492 493 ::std::for_each( maColStates.begin(), maColStates.end(), Func_SetType( CSV_TYPE_DEFAULT ) ); 494 } 495 496 const String& ScCsvGrid::GetColumnTypeName( sal_uInt32 nColIndex ) const 497 { 498 sal_uInt32 nTypeIx = static_cast< sal_uInt32 >( GetColumnType( nColIndex ) ); 499 return (nTypeIx < maTypeNames.size()) ? maTypeNames[ nTypeIx ] : EMPTY_STRING; 500 } 501 502 sal_uInt8 lcl_GetExtColumnType( sal_Int32 nIntType ) 503 { 504 static sal_uInt8 pExtTypes[] = 505 { SC_COL_STANDARD, SC_COL_TEXT, SC_COL_DMY, SC_COL_MDY, SC_COL_YMD, SC_COL_ENGLISH, SC_COL_SKIP }; 506 static sal_Int32 nExtTypeCount = sizeof( pExtTypes ) / sizeof( *pExtTypes ); 507 return pExtTypes[ ((0 <= nIntType) && (nIntType < nExtTypeCount)) ? nIntType : 0 ]; 508 } 509 510 void ScCsvGrid::FillColumnDataSep( ScAsciiOptions& rOptions ) const 511 { 512 sal_uInt32 nCount = GetColumnCount(); 513 ScCsvExpDataVec aDataVec; 514 515 for( sal_uInt32 nColIx = 0; nColIx < nCount; ++nColIx ) 516 { 517 if( GetColumnType( nColIx ) != CSV_TYPE_DEFAULT ) 518 // 1-based column index 519 aDataVec.push_back( ScCsvExpData( 520 static_cast< xub_StrLen >( nColIx + 1 ), 521 lcl_GetExtColumnType( GetColumnType( nColIx ) ) ) ); 522 } 523 rOptions.SetColumnInfo( aDataVec ); 524 } 525 526 void ScCsvGrid::FillColumnDataFix( ScAsciiOptions& rOptions ) const 527 { 528 sal_uInt32 nCount = Min( GetColumnCount(), static_cast<sal_uInt32>(MAXCOLCOUNT) ); 529 ScCsvExpDataVec aDataVec( nCount + 1 ); 530 531 for( sal_uInt32 nColIx = 0; nColIx < nCount; ++nColIx ) 532 { 533 ScCsvExpData& rData = aDataVec[ nColIx ]; 534 rData.mnIndex = static_cast< xub_StrLen >( 535 Min( static_cast< sal_Int32 >( STRING_MAXLEN ), GetColumnPos( nColIx ) ) ); 536 rData.mnType = lcl_GetExtColumnType( GetColumnType( nColIx ) ); 537 } 538 aDataVec[ nCount ].mnIndex = STRING_MAXLEN; 539 aDataVec[ nCount ].mnType = SC_COL_SKIP; 540 rOptions.SetColumnInfo( aDataVec ); 541 } 542 543 void ScCsvGrid::ScrollVertRel( ScMoveMode eDir ) 544 { 545 sal_Int32 nLine = GetFirstVisLine(); 546 switch( eDir ) 547 { 548 case MOVE_PREV: --nLine; break; 549 case MOVE_NEXT: ++nLine; break; 550 case MOVE_FIRST: nLine = 0; break; 551 case MOVE_LAST: nLine = GetMaxLineOffset(); break; 552 case MOVE_PREVPAGE: nLine -= GetVisLineCount() - 2; break; 553 case MOVE_NEXTPAGE: nLine += GetVisLineCount() - 2; break; 554 default: 555 { 556 // added to avoid warnings 557 } 558 } 559 Execute( CSVCMD_SETLINEOFFSET, nLine ); 560 } 561 562 void ScCsvGrid::ExecutePopup( const Point& rPos ) 563 { 564 sal_uInt16 nItemId = maPopup.Execute( this, rPos ); 565 if( nItemId ) // 0 = cancelled 566 Execute( CSVCMD_SETCOLUMNTYPE, maPopup.GetItemPos( nItemId ) ); 567 } 568 569 570 // selection handling --------------------------------------------------------- 571 572 bool ScCsvGrid::IsSelected( sal_uInt32 nColIndex ) const 573 { 574 return IsValidColumn( nColIndex ) && maColStates[ nColIndex ].IsSelected(); 575 } 576 577 sal_uInt32 ScCsvGrid::GetFirstSelected() const 578 { 579 return IsSelected( 0 ) ? 0 : GetNextSelected( 0 ); 580 } 581 582 sal_uInt32 ScCsvGrid::GetNextSelected( sal_uInt32 nFromIndex ) const 583 { 584 sal_uInt32 nColCount = GetColumnCount(); 585 for( sal_uInt32 nColIx = nFromIndex + 1; nColIx < nColCount; ++nColIx ) 586 if( IsSelected( nColIx ) ) 587 return nColIx; 588 return CSV_COLUMN_INVALID; 589 } 590 591 void ScCsvGrid::Select( sal_uInt32 nColIndex, bool bSelect ) 592 { 593 if( IsValidColumn( nColIndex ) ) 594 { 595 maColStates[ nColIndex ].Select( bSelect ); 596 ImplDrawColumnSelection( nColIndex ); 597 Repaint(); 598 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 599 if( bSelect ) 600 mnRecentSelCol = nColIndex; 601 AccSendSelectionEvent(); 602 } 603 } 604 605 void ScCsvGrid::ToggleSelect( sal_uInt32 nColIndex ) 606 { 607 Select( nColIndex, !IsSelected( nColIndex ) ); 608 } 609 610 void ScCsvGrid::SelectRange( sal_uInt32 nColIndex1, sal_uInt32 nColIndex2, bool bSelect ) 611 { 612 if( nColIndex1 == CSV_COLUMN_INVALID ) 613 Select( nColIndex2 ); 614 else if( nColIndex2 == CSV_COLUMN_INVALID ) 615 Select( nColIndex1 ); 616 else if( nColIndex1 > nColIndex2 ) 617 { 618 SelectRange( nColIndex2, nColIndex1, bSelect ); 619 if( bSelect ) 620 mnRecentSelCol = nColIndex1; 621 } 622 else if( IsValidColumn( nColIndex1 ) && IsValidColumn( nColIndex2 ) ) 623 { 624 for( sal_uInt32 nColIx = nColIndex1; nColIx <= nColIndex2; ++nColIx ) 625 { 626 maColStates[ nColIx ].Select( bSelect ); 627 ImplDrawColumnSelection( nColIx ); 628 } 629 Repaint(); 630 Execute( CSVCMD_EXPORTCOLUMNTYPE ); 631 if( bSelect ) 632 mnRecentSelCol = nColIndex1; 633 AccSendSelectionEvent(); 634 } 635 } 636 637 void ScCsvGrid::SelectAll( bool bSelect ) 638 { 639 SelectRange( 0, GetColumnCount() - 1, bSelect ); 640 } 641 642 void ScCsvGrid::MoveCursor( sal_uInt32 nColIndex ) 643 { 644 DisableRepaint(); 645 if( IsValidColumn( nColIndex ) ) 646 { 647 sal_Int32 nPosBeg = GetColumnPos( nColIndex ); 648 sal_Int32 nPosEnd = GetColumnPos( nColIndex + 1 ); 649 sal_Int32 nMinPos = Max( nPosBeg - CSV_SCROLL_DIST, sal_Int32( 0 ) ); 650 sal_Int32 nMaxPos = Min( nPosEnd - GetVisPosCount() + CSV_SCROLL_DIST + sal_Int32( 1 ), nMinPos ); 651 if( nPosBeg - CSV_SCROLL_DIST + 1 <= GetFirstVisPos() ) 652 Execute( CSVCMD_SETPOSOFFSET, nMinPos ); 653 else if( nPosEnd + CSV_SCROLL_DIST >= GetLastVisPos() ) 654 Execute( CSVCMD_SETPOSOFFSET, nMaxPos ); 655 } 656 Execute( CSVCMD_MOVEGRIDCURSOR, GetColumnPos( nColIndex ) ); 657 EnableRepaint(); 658 } 659 660 void ScCsvGrid::MoveCursorRel( ScMoveMode eDir ) 661 { 662 if( GetFocusColumn() != CSV_COLUMN_INVALID ) 663 { 664 switch( eDir ) 665 { 666 case MOVE_FIRST: 667 MoveCursor( 0 ); 668 break; 669 case MOVE_LAST: 670 MoveCursor( GetColumnCount() - 1 ); 671 break; 672 case MOVE_PREV: 673 if( GetFocusColumn() > 0 ) 674 MoveCursor( GetFocusColumn() - 1 ); 675 break; 676 case MOVE_NEXT: 677 if( GetFocusColumn() < GetColumnCount() - 1 ) 678 MoveCursor( GetFocusColumn() + 1 ); 679 break; 680 default: 681 { 682 // added to avoid warnings 683 } 684 } 685 } 686 } 687 688 void ScCsvGrid::ImplClearSelection() 689 { 690 ::std::for_each( maColStates.begin(), maColStates.end(), Func_Select( false ) ); 691 ImplDrawGridDev(); 692 } 693 694 void ScCsvGrid::DoSelectAction( sal_uInt32 nColIndex, sal_uInt16 nModifier ) 695 { 696 if( !(nModifier & KEY_MOD1) ) 697 ImplClearSelection(); 698 if( nModifier & KEY_SHIFT ) // SHIFT always expands 699 SelectRange( mnRecentSelCol, nColIndex ); 700 else if( !(nModifier & KEY_MOD1) ) // no SHIFT/CTRL always selects 1 column 701 Select( nColIndex ); 702 else if( IsTracking() ) // CTRL in tracking does not toggle 703 Select( nColIndex, mbMTSelecting ); 704 else // CTRL only toggles 705 ToggleSelect( nColIndex ); 706 Execute( CSVCMD_MOVEGRIDCURSOR, GetColumnPos( nColIndex ) ); 707 } 708 709 710 // cell contents -------------------------------------------------------------- 711 712 void ScCsvGrid::ImplSetTextLineSep( 713 sal_Int32 nLine, const String& rTextLine, 714 const String& rSepChars, sal_Unicode cTextSep, bool bMergeSep ) 715 { 716 if( nLine < GetFirstVisLine() ) return; 717 718 sal_uInt32 nLineIx = nLine - GetFirstVisLine(); 719 while( maTexts.size() <= nLineIx ) 720 maTexts.push_back( StringVec() ); 721 StringVec& rStrVec = maTexts[ nLineIx ]; 722 rStrVec.clear(); 723 724 // scan for separators 725 String aCellText; 726 const sal_Unicode* pSepChars = rSepChars.GetBuffer(); 727 const sal_Unicode* pChar = rTextLine.GetBuffer(); 728 sal_uInt32 nColIx = 0; 729 730 while( *pChar && (nColIx < sal::static_int_cast<sal_uInt32>(CSV_MAXCOLCOUNT)) ) 731 { 732 // scan for next cell text 733 bool bIsQuoted = false; 734 pChar = ScImportExport::ScanNextFieldFromString( pChar, aCellText, cTextSep, pSepChars, bMergeSep, bIsQuoted ); 735 736 // update column width 737 sal_Int32 nWidth = Max( CSV_MINCOLWIDTH, aCellText.Len() + sal_Int32( 1 ) ); 738 if( IsValidColumn( nColIx ) ) 739 { 740 // expand existing column 741 sal_Int32 nDiff = nWidth - GetColumnWidth( nColIx ); 742 if( nDiff > 0 ) 743 { 744 Execute( CSVCMD_SETPOSCOUNT, GetPosCount() + nDiff ); 745 for( sal_uInt32 nSplitIx = GetColumnCount() - 1; nSplitIx > nColIx; --nSplitIx ) 746 { 747 sal_Int32 nPos = maSplits[ nSplitIx ]; 748 maSplits.Remove( nPos ); 749 maSplits.Insert( nPos + nDiff ); 750 } 751 } 752 } 753 else 754 { 755 // append new column 756 sal_Int32 nLastPos = GetPosCount(); 757 Execute( CSVCMD_SETPOSCOUNT, nLastPos + nWidth ); 758 ImplInsertSplit( nLastPos ); 759 } 760 761 if( aCellText.Len() <= CSV_MAXSTRLEN ) 762 rStrVec.push_back( aCellText ); 763 else 764 rStrVec.push_back( aCellText.Copy( 0, CSV_MAXSTRLEN ) ); 765 ++nColIx; 766 } 767 InvalidateGfx(); 768 } 769 770 void ScCsvGrid::ImplSetTextLineFix( sal_Int32 nLine, const String& rTextLine ) 771 { 772 if( nLine < GetFirstVisLine() ) return; 773 774 sal_Int32 nChars = rTextLine.Len(); 775 if( nChars > GetPosCount() ) 776 Execute( CSVCMD_SETPOSCOUNT, nChars ); 777 778 sal_uInt32 nLineIx = nLine - GetFirstVisLine(); 779 while( maTexts.size() <= nLineIx ) 780 maTexts.push_back( StringVec() ); 781 782 StringVec& rStrVec = maTexts[ nLineIx ]; 783 rStrVec.clear(); 784 sal_uInt32 nColCount = GetColumnCount(); 785 xub_StrLen nStrLen = rTextLine.Len(); 786 xub_StrLen nStrIx = 0; 787 for( sal_uInt32 nColIx = 0; (nColIx < nColCount) && (nStrIx < nStrLen); ++nColIx ) 788 { 789 xub_StrLen nColWidth = static_cast< xub_StrLen >( GetColumnWidth( nColIx ) ); 790 rStrVec.push_back( rTextLine.Copy( nStrIx, Max( nColWidth, CSV_MAXSTRLEN ) ) ); 791 nStrIx = sal::static_int_cast<xub_StrLen>( nStrIx + nColWidth ); 792 } 793 InvalidateGfx(); 794 } 795 796 const String& ScCsvGrid::GetCellText( sal_uInt32 nColIndex, sal_Int32 nLine ) const 797 { 798 if( nLine < GetFirstVisLine() ) return EMPTY_STRING; 799 800 sal_uInt32 nLineIx = nLine - GetFirstVisLine(); 801 if( nLineIx >= maTexts.size() ) return EMPTY_STRING; 802 803 const StringVec& rStrVec = maTexts[ nLineIx ]; 804 if( nColIndex >= rStrVec.size() ) return EMPTY_STRING; 805 806 return rStrVec[ nColIndex ]; 807 } 808 809 810 // event handling ------------------------------------------------------------- 811 812 void ScCsvGrid::Resize() 813 { 814 ScCsvControl::Resize(); 815 InitSizeData(); 816 Execute( CSVCMD_UPDATECELLTEXTS ); 817 } 818 819 void ScCsvGrid::GetFocus() 820 { 821 ScCsvControl::GetFocus(); 822 Execute( CSVCMD_MOVEGRIDCURSOR, GetNoScrollCol( GetGridCursorPos() ) ); 823 Repaint(); 824 } 825 826 void ScCsvGrid::LoseFocus() 827 { 828 ScCsvControl::LoseFocus(); 829 Repaint(); 830 } 831 832 void ScCsvGrid::MouseButtonDown( const MouseEvent& rMEvt ) 833 { 834 DisableRepaint(); 835 if( !HasFocus() ) 836 GrabFocus(); 837 838 Point aPos( rMEvt.GetPosPixel() ); 839 sal_uInt32 nColIx = GetColumnFromX( aPos.X() ); 840 841 if( rMEvt.IsLeft() ) 842 { 843 if( (GetFirstX() > aPos.X()) || (aPos.X() > GetLastX()) ) // in header column 844 { 845 if( aPos.Y() <= GetHdrHeight() ) 846 SelectAll(); 847 } 848 else if( IsValidColumn( nColIx ) ) 849 { 850 DoSelectAction( nColIx, rMEvt.GetModifier() ); 851 mnMTCurrCol = nColIx; 852 mbMTSelecting = IsSelected( nColIx ); 853 StartTracking( STARTTRACK_BUTTONREPEAT ); 854 } 855 } 856 EnableRepaint(); 857 } 858 859 void ScCsvGrid::Tracking( const TrackingEvent& rTEvt ) 860 { 861 if( rTEvt.IsTrackingEnded() || rTEvt.IsTrackingRepeat() ) 862 { 863 DisableRepaint(); 864 const MouseEvent& rMEvt = rTEvt.GetMouseEvent(); 865 866 sal_Int32 nPos = (rMEvt.GetPosPixel().X() - GetFirstX()) / GetCharWidth() + GetFirstVisPos(); 867 // on mouse tracking: keep position valid 868 nPos = Max( Min( nPos, GetPosCount() - sal_Int32( 1 ) ), sal_Int32( 0 ) ); 869 Execute( CSVCMD_MAKEPOSVISIBLE, nPos ); 870 871 sal_uInt32 nColIx = GetColumnFromPos( nPos ); 872 if( mnMTCurrCol != nColIx ) 873 { 874 DoSelectAction( nColIx, rMEvt.GetModifier() ); 875 mnMTCurrCol = nColIx; 876 } 877 EnableRepaint(); 878 } 879 } 880 881 void ScCsvGrid::KeyInput( const KeyEvent& rKEvt ) 882 { 883 const KeyCode& rKCode = rKEvt.GetKeyCode(); 884 sal_uInt16 nCode = rKCode.GetCode(); 885 bool bShift = rKCode.IsShift() == sal_True; 886 bool bMod1 = rKCode.IsMod1() == sal_True; 887 888 if( !rKCode.IsMod2() ) 889 { 890 ScMoveMode eHDir = GetHorzDirection( nCode, !bMod1 ); 891 ScMoveMode eVDir = GetVertDirection( nCode, bMod1 ); 892 893 if( eHDir != MOVE_NONE ) 894 { 895 DisableRepaint(); 896 MoveCursorRel( eHDir ); 897 if( !bMod1 ) 898 ImplClearSelection(); 899 if( bShift ) 900 SelectRange( mnRecentSelCol, GetFocusColumn() ); 901 else if( !bMod1 ) 902 Select( GetFocusColumn() ); 903 EnableRepaint(); 904 } 905 else if( eVDir != MOVE_NONE ) 906 ScrollVertRel( eVDir ); 907 else if( nCode == KEY_SPACE ) 908 { 909 if( !bMod1 ) 910 ImplClearSelection(); 911 if( bShift ) 912 SelectRange( mnRecentSelCol, GetFocusColumn() ); 913 else if( bMod1 ) 914 ToggleSelect( GetFocusColumn() ); 915 else 916 Select( GetFocusColumn() ); 917 } 918 else if( !bShift && bMod1 ) 919 { 920 if( nCode == KEY_A ) 921 SelectAll(); 922 else if( (KEY_1 <= nCode) && (nCode <= KEY_9) ) 923 { 924 sal_uInt32 nType = nCode - KEY_1; 925 if( nType < maTypeNames.size() ) 926 Execute( CSVCMD_SETCOLUMNTYPE, nType ); 927 } 928 } 929 } 930 931 if( rKCode.GetGroup() != KEYGROUP_CURSOR ) 932 ScCsvControl::KeyInput( rKEvt ); 933 } 934 935 void ScCsvGrid::Command( const CommandEvent& rCEvt ) 936 { 937 switch( rCEvt.GetCommand() ) 938 { 939 case COMMAND_CONTEXTMENU: 940 { 941 if( rCEvt.IsMouseEvent() ) 942 { 943 Point aPos( rCEvt.GetMousePosPixel() ); 944 sal_uInt32 nColIx = GetColumnFromX( aPos.X() ); 945 if( IsValidColumn( nColIx ) && (GetFirstX() <= aPos.X()) && (aPos.X() <= GetLastX()) ) 946 { 947 if( !IsSelected( nColIx ) ) 948 DoSelectAction( nColIx, 0 ); // focus & select 949 ExecutePopup( aPos ); 950 } 951 } 952 else 953 { 954 sal_uInt32 nColIx = GetFocusColumn(); 955 if( !IsSelected( nColIx ) ) 956 Select( nColIx ); 957 sal_Int32 nX1 = Max( GetColumnX( nColIx ), GetFirstX() ); 958 sal_Int32 nX2 = Min( GetColumnX( nColIx + 1 ), GetWidth() ); 959 ExecutePopup( Point( (nX1 + nX2) / 2, GetHeight() / 2 ) ); 960 } 961 } 962 break; 963 case COMMAND_WHEEL: 964 { 965 Point aPoint; 966 Rectangle aRect( aPoint, maWinSize ); 967 if( aRect.IsInside( rCEvt.GetMousePosPixel() ) ) 968 { 969 const CommandWheelData* pData = rCEvt.GetWheelData(); 970 if( pData && (pData->GetMode() == COMMAND_WHEEL_SCROLL) && !pData->IsHorz() ) 971 Execute( CSVCMD_SETLINEOFFSET, GetFirstVisLine() - pData->GetNotchDelta() ); 972 } 973 } 974 break; 975 default: 976 ScCsvControl::Command( rCEvt ); 977 } 978 } 979 980 void ScCsvGrid::DataChanged( const DataChangedEvent& rDCEvt ) 981 { 982 if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 983 { 984 InitColors(); 985 InitFonts(); 986 UpdateLayoutData(); 987 Execute( CSVCMD_UPDATECELLTEXTS ); 988 } 989 ScCsvControl::DataChanged( rDCEvt ); 990 } 991 992 void ScCsvGrid::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ) 993 { 994 InitColors(); 995 Repaint(); 996 } 997 998 999 // painting ------------------------------------------------------------------- 1000 1001 void ScCsvGrid::Paint( const Rectangle& ) 1002 { 1003 Repaint(); 1004 } 1005 1006 void ScCsvGrid::ImplRedraw() 1007 { 1008 if( IsVisible() ) 1009 { 1010 if( !IsValidGfx() ) 1011 { 1012 ValidateGfx(); 1013 ImplDrawBackgrDev(); 1014 ImplDrawGridDev(); 1015 } 1016 DrawOutDev( Point(), maWinSize, Point(), maWinSize, maGridDev ); 1017 ImplDrawTrackingRect( GetFocusColumn() ); 1018 } 1019 } 1020 1021 EditEngine* ScCsvGrid::GetEditEngine() 1022 { 1023 return mpEditEngine.get(); 1024 } 1025 1026 void ScCsvGrid::ImplSetColumnClipRegion( OutputDevice& rOutDev, sal_uInt32 nColIndex ) 1027 { 1028 rOutDev.SetClipRegion( Region( Rectangle( 1029 Max( GetColumnX( nColIndex ), GetFirstX() ) + 1, 0, 1030 Min( GetColumnX( nColIndex + 1 ), GetLastX() ), GetHeight() - 1 ) ) ); 1031 } 1032 1033 void ScCsvGrid::ImplDrawColumnHeader( OutputDevice& rOutDev, sal_uInt32 nColIndex, Color aFillColor ) 1034 { 1035 sal_Int32 nX1 = GetColumnX( nColIndex ) + 1; 1036 sal_Int32 nX2 = GetColumnX( nColIndex + 1 ); 1037 sal_Int32 nHdrHt = GetHdrHeight(); 1038 1039 rOutDev.SetLineColor(); 1040 rOutDev.SetFillColor( aFillColor ); 1041 rOutDev.DrawRect( Rectangle( nX1, 0, nX2, nHdrHt ) ); 1042 1043 rOutDev.SetFont( maHeaderFont ); 1044 rOutDev.SetTextColor( maHeaderTextColor ); 1045 rOutDev.SetTextFillColor(); 1046 rOutDev.DrawText( Point( nX1 + 1, 0 ), GetColumnTypeName( nColIndex ) ); 1047 1048 rOutDev.SetLineColor( maHeaderGridColor ); 1049 rOutDev.DrawLine( Point( nX1, nHdrHt ), Point( nX2, nHdrHt ) ); 1050 rOutDev.DrawLine( Point( nX2, 0 ), Point( nX2, nHdrHt ) ); 1051 } 1052 1053 void ScCsvGrid::ImplDrawCellText( const Point& rPos, const String& rText ) 1054 { 1055 String aPlainText( rText ); 1056 aPlainText.SearchAndReplaceAll( '\t', ' ' ); 1057 aPlainText.SearchAndReplaceAll( '\n', ' ' ); 1058 mpEditEngine->SetPaperSize( maEdEngSize ); 1059 1060 /* #i60296# If string contains mixed script types, the space character 1061 U+0020 may be drawn with a wrong width (from non-fixed-width Asian or 1062 Complex font). Now we draw every non-space portion separately. */ 1063 xub_StrLen nTokenCount = aPlainText.GetTokenCount( ' ' ); 1064 xub_StrLen nCharIx = 0; 1065 for( xub_StrLen nToken = 0; nToken < nTokenCount; ++nToken ) 1066 { 1067 xub_StrLen nBeginIx = nCharIx; 1068 String aToken = aPlainText.GetToken( 0, ' ', nCharIx ); 1069 if( aToken.Len() > 0 ) 1070 { 1071 sal_Int32 nX = rPos.X() + GetCharWidth() * nBeginIx; 1072 mpEditEngine->SetText( aToken ); 1073 mpEditEngine->Draw( &maBackgrDev, Point( nX, rPos.Y() ) ); 1074 } 1075 } 1076 1077 nCharIx = 0; 1078 while( (nCharIx = rText.Search( '\t', nCharIx )) != STRING_NOTFOUND ) 1079 { 1080 sal_Int32 nX1 = rPos.X() + GetCharWidth() * nCharIx; 1081 sal_Int32 nX2 = nX1 + GetCharWidth() - 2; 1082 sal_Int32 nY = rPos.Y() + GetLineHeight() / 2; 1083 Color aColor( maTextColor ); 1084 maBackgrDev.SetLineColor( aColor ); 1085 maBackgrDev.DrawLine( Point( nX1, nY ), Point( nX2, nY ) ); 1086 maBackgrDev.DrawLine( Point( nX2 - 2, nY - 2 ), Point( nX2, nY ) ); 1087 maBackgrDev.DrawLine( Point( nX2 - 2, nY + 2 ), Point( nX2, nY ) ); 1088 ++nCharIx; 1089 } 1090 nCharIx = 0; 1091 while( (nCharIx = rText.Search( '\n', nCharIx )) != STRING_NOTFOUND ) 1092 { 1093 sal_Int32 nX1 = rPos.X() + GetCharWidth() * nCharIx; 1094 sal_Int32 nX2 = nX1 + GetCharWidth() - 2; 1095 sal_Int32 nY = rPos.Y() + GetLineHeight() / 2; 1096 Color aColor( maTextColor ); 1097 maBackgrDev.SetLineColor( aColor ); 1098 maBackgrDev.DrawLine( Point( nX1, nY ), Point( nX2, nY ) ); 1099 maBackgrDev.DrawLine( Point( nX1 + 2, nY - 2 ), Point( nX1, nY ) ); 1100 maBackgrDev.DrawLine( Point( nX1 + 2, nY + 2 ), Point( nX1, nY ) ); 1101 maBackgrDev.DrawLine( Point( nX2, nY - 2 ), Point( nX2, nY ) ); 1102 ++nCharIx; 1103 } 1104 } 1105 1106 void ScCsvGrid::ImplDrawFirstLineSep( bool bSet ) 1107 { 1108 if( IsVisibleLine( mnFirstImpLine ) && (mnFirstImpLine != GetFirstVisLine() ) ) 1109 { 1110 sal_Int32 nY = GetY( mnFirstImpLine ); 1111 sal_Int32 nX = Min( GetColumnX( GetLastVisColumn() + 1 ), GetLastX() ); 1112 maBackgrDev.SetLineColor( bSet ? maGridPBColor : maGridColor ); 1113 maBackgrDev.DrawLine( Point( GetFirstX() + 1, nY ), Point( nX, nY ) ); 1114 } 1115 } 1116 1117 void ScCsvGrid::ImplDrawColumnBackgr( sal_uInt32 nColIndex ) 1118 { 1119 if( !IsVisibleColumn( nColIndex ) ) 1120 return; 1121 1122 ImplSetColumnClipRegion( maBackgrDev, nColIndex ); 1123 1124 // grid 1125 maBackgrDev.SetLineColor(); 1126 maBackgrDev.SetFillColor( maBackColor ); 1127 sal_Int32 nX1 = GetColumnX( nColIndex ) + 1; 1128 sal_Int32 nX2 = GetColumnX( nColIndex + 1 ); 1129 sal_Int32 nY2 = GetY( GetLastVisLine() + 1 ); 1130 sal_Int32 nHdrHt = GetHdrHeight(); 1131 Rectangle aRect( nX1, nHdrHt, nX2, nY2 ); 1132 maBackgrDev.DrawRect( aRect ); 1133 maBackgrDev.SetLineColor( maGridColor ); 1134 maBackgrDev.DrawGrid( aRect, Size( 1, GetLineHeight() ), GRID_HORZLINES ); 1135 maBackgrDev.DrawLine( Point( nX2, nHdrHt ), Point( nX2, nY2 ) ); 1136 ImplDrawFirstLineSep( true ); 1137 1138 // cell texts 1139 mpEditEngine->SetDefaultItem( SvxColorItem( maTextColor, EE_CHAR_COLOR ) ); 1140 size_t nLineCount = ::std::min( static_cast< size_t >( GetLastVisLine() - GetFirstVisLine() + 1 ), maTexts.size() ); 1141 // #i67432# cut string to avoid edit engine performance problems with very large strings 1142 sal_Int32 nFirstVisPos = ::std::max( GetColumnPos( nColIndex ), GetFirstVisPos() ); 1143 sal_Int32 nLastVisPos = ::std::min( GetColumnPos( nColIndex + 1 ), GetLastVisPos() ); 1144 xub_StrLen nStrPos = static_cast< xub_StrLen >( nFirstVisPos - GetColumnPos( nColIndex ) ); 1145 xub_StrLen nStrLen = static_cast< xub_StrLen >( nLastVisPos - nFirstVisPos + 1 ); 1146 sal_Int32 nStrX = GetX( nFirstVisPos ); 1147 for( size_t nLine = 0; nLine < nLineCount; ++nLine ) 1148 { 1149 StringVec& rStrVec = maTexts[ nLine ]; 1150 if( (nColIndex < rStrVec.size()) && (rStrVec[ nColIndex ].Len() > nStrPos) ) 1151 { 1152 String aText( rStrVec[ nColIndex ], nStrPos, nStrLen ); 1153 ImplDrawCellText( Point( nStrX, GetY( GetFirstVisLine() + nLine ) ), aText ); 1154 } 1155 } 1156 1157 // header 1158 ImplDrawColumnHeader( maBackgrDev, nColIndex, maHeaderBackColor ); 1159 1160 maBackgrDev.SetClipRegion(); 1161 } 1162 1163 void ScCsvGrid::ImplDrawRowHeaders() 1164 { 1165 maBackgrDev.SetLineColor(); 1166 maBackgrDev.SetFillColor( maAppBackColor ); 1167 Point aPoint( GetHdrX(), 0 ); 1168 Rectangle aRect( aPoint, Size( GetHdrWidth() + 1, GetHeight() ) ); 1169 maBackgrDev.DrawRect( aRect ); 1170 1171 maBackgrDev.SetFillColor( maHeaderBackColor ); 1172 aRect.Bottom() = GetY( GetLastVisLine() + 1 ); 1173 maBackgrDev.DrawRect( aRect ); 1174 1175 // line numbers 1176 maBackgrDev.SetFont( maHeaderFont ); 1177 maBackgrDev.SetTextColor( maHeaderTextColor ); 1178 maBackgrDev.SetTextFillColor(); 1179 sal_Int32 nLastLine = GetLastVisLine(); 1180 for( sal_Int32 nLine = GetFirstVisLine(); nLine <= nLastLine; ++nLine ) 1181 { 1182 String aText( String::CreateFromInt32( nLine + 1 ) ); 1183 sal_Int32 nX = GetHdrX() + (GetHdrWidth() - maBackgrDev.GetTextWidth( aText )) / 2; 1184 maBackgrDev.DrawText( Point( nX, GetY( nLine ) ), aText ); 1185 } 1186 1187 // grid 1188 maBackgrDev.SetLineColor( maHeaderGridColor ); 1189 if( IsRTL() ) 1190 { 1191 maBackgrDev.DrawLine( Point( 0, 0 ), Point( 0, GetHeight() - 1 ) ); 1192 maBackgrDev.DrawLine( aRect.TopLeft(), aRect.BottomLeft() ); 1193 } 1194 else 1195 maBackgrDev.DrawLine( aRect.TopRight(), aRect.BottomRight() ); 1196 aRect.Top() = GetHdrHeight(); 1197 maBackgrDev.DrawGrid( aRect, Size( 1, GetLineHeight() ), GRID_HORZLINES ); 1198 } 1199 1200 void ScCsvGrid::ImplDrawBackgrDev() 1201 { 1202 maBackgrDev.SetLineColor(); 1203 maBackgrDev.SetFillColor( maAppBackColor ); 1204 maBackgrDev.DrawRect( Rectangle( 1205 Point( GetFirstX() + 1, 0 ), Size( GetWidth() - GetHdrWidth(), GetHeight() ) ) ); 1206 1207 sal_uInt32 nLastCol = GetLastVisColumn(); 1208 for( sal_uInt32 nColIx = GetFirstVisColumn(); nColIx <= nLastCol; ++nColIx ) 1209 ImplDrawColumnBackgr( nColIx ); 1210 1211 ImplDrawRowHeaders(); 1212 } 1213 1214 void ScCsvGrid::ImplDrawColumnSelection( sal_uInt32 nColIndex ) 1215 { 1216 ImplInvertCursor( GetRulerCursorPos() ); 1217 ImplSetColumnClipRegion( maGridDev, nColIndex ); 1218 maGridDev.DrawOutDev( Point(), maWinSize, Point(), maWinSize, maBackgrDev ); 1219 1220 if( IsSelected( nColIndex ) ) 1221 { 1222 sal_Int32 nX1 = GetColumnX( nColIndex ) + 1; 1223 sal_Int32 nX2 = GetColumnX( nColIndex + 1 ); 1224 1225 // header 1226 Rectangle aRect( nX1, 0, nX2, GetHdrHeight() ); 1227 maGridDev.SetLineColor(); 1228 if( maHeaderBackColor.IsDark() ) 1229 // redraw with light gray background in dark mode 1230 ImplDrawColumnHeader( maGridDev, nColIndex, COL_LIGHTGRAY ); 1231 else 1232 { 1233 // use transparent active color 1234 maGridDev.SetFillColor( maSelectColor ); 1235 maGridDev.DrawTransparent( PolyPolygon( Polygon( aRect ) ), CSV_HDR_TRANSPARENCY ); 1236 } 1237 1238 // column selection 1239 aRect = Rectangle( nX1, GetHdrHeight() + 1, nX2, GetY( GetLastVisLine() + 1 ) - 1 ); 1240 ImplInvertRect( maGridDev, aRect ); 1241 } 1242 1243 maGridDev.SetClipRegion(); 1244 ImplInvertCursor( GetRulerCursorPos() ); 1245 } 1246 1247 void ScCsvGrid::ImplDrawGridDev() 1248 { 1249 maGridDev.DrawOutDev( Point(), maWinSize, Point(), maWinSize, maBackgrDev ); 1250 sal_uInt32 nLastCol = GetLastVisColumn(); 1251 for( sal_uInt32 nColIx = GetFirstVisColumn(); nColIx <= nLastCol; ++nColIx ) 1252 ImplDrawColumnSelection( nColIx ); 1253 } 1254 1255 void ScCsvGrid::ImplDrawColumn( sal_uInt32 nColIndex ) 1256 { 1257 ImplDrawColumnBackgr( nColIndex ); 1258 ImplDrawColumnSelection( nColIndex ); 1259 } 1260 1261 void ScCsvGrid::ImplDrawHorzScrolled( sal_Int32 nOldPos ) 1262 { 1263 sal_Int32 nPos = GetFirstVisPos(); 1264 if( !IsValidGfx() || (nPos == nOldPos) ) 1265 return; 1266 if( Abs( nPos - nOldPos ) > GetVisPosCount() / 2 ) 1267 { 1268 ImplDrawBackgrDev(); 1269 ImplDrawGridDev(); 1270 return; 1271 } 1272 1273 Point aSrc, aDest; 1274 sal_uInt32 nFirstColIx, nLastColIx; 1275 if( nPos < nOldPos ) 1276 { 1277 aSrc = Point( GetFirstX() + 1, 0 ); 1278 aDest = Point( GetFirstX() + GetCharWidth() * (nOldPos - nPos) + 1, 0 ); 1279 nFirstColIx = GetColumnFromPos( nPos ); 1280 nLastColIx = GetColumnFromPos( nOldPos ); 1281 } 1282 else 1283 { 1284 aSrc = Point( GetFirstX() + GetCharWidth() * (nPos - nOldPos) + 1, 0 ); 1285 aDest = Point( GetFirstX() + 1, 0 ); 1286 nFirstColIx = GetColumnFromPos( Min( nOldPos + GetVisPosCount(), GetPosCount() ) - 1 ); 1287 nLastColIx = GetColumnFromPos( Min( nPos + GetVisPosCount(), GetPosCount() ) - 1 ); 1288 } 1289 1290 ImplInvertCursor( GetRulerCursorPos() + (nPos - nOldPos) ); 1291 Rectangle aRectangle( GetFirstX(), 0, GetLastX(), GetHeight() - 1 ); 1292 Region aClipReg( aRectangle ); 1293 maBackgrDev.SetClipRegion( aClipReg ); 1294 maBackgrDev.CopyArea( aDest, aSrc, maWinSize ); 1295 maBackgrDev.SetClipRegion(); 1296 maGridDev.SetClipRegion( aClipReg ); 1297 maGridDev.CopyArea( aDest, aSrc, maWinSize ); 1298 maGridDev.SetClipRegion(); 1299 ImplInvertCursor( GetRulerCursorPos() ); 1300 1301 for( sal_uInt32 nColIx = nFirstColIx; nColIx <= nLastColIx; ++nColIx ) 1302 ImplDrawColumn( nColIx ); 1303 1304 sal_Int32 nLastX = GetX( GetPosCount() ) + 1; 1305 if( nLastX <= GetLastX() ) 1306 { 1307 Rectangle aRect( nLastX, 0, GetLastX(), GetHeight() - 1 ); 1308 maBackgrDev.SetLineColor(); 1309 maBackgrDev.SetFillColor( maAppBackColor ); 1310 maBackgrDev.DrawRect( aRect ); 1311 maGridDev.SetLineColor(); 1312 maGridDev.SetFillColor( maAppBackColor ); 1313 maGridDev.DrawRect( aRect ); 1314 } 1315 } 1316 1317 void ScCsvGrid::ImplInvertCursor( sal_Int32 nPos ) 1318 { 1319 if( IsVisibleSplitPos( nPos ) ) 1320 { 1321 sal_Int32 nX = GetX( nPos ) - 1; 1322 Rectangle aRect( Point( nX, 0 ), Size( 3, GetHdrHeight() ) ); 1323 ImplInvertRect( maGridDev, aRect ); 1324 aRect.Top() = GetHdrHeight() + 1; 1325 aRect.Bottom() = GetY( GetLastVisLine() + 1 ); 1326 ImplInvertRect( maGridDev, aRect ); 1327 } 1328 } 1329 1330 void ScCsvGrid::ImplDrawTrackingRect( sal_uInt32 nColIndex ) 1331 { 1332 if( HasFocus() && IsVisibleColumn( nColIndex ) ) 1333 { 1334 sal_Int32 nX1 = Max( GetColumnX( nColIndex ), GetFirstX() ) + 1; 1335 sal_Int32 nX2 = Min( GetColumnX( nColIndex + 1 ) - sal_Int32( 1 ), GetLastX() ); 1336 sal_Int32 nY2 = Min( GetY( GetLastVisLine() + 1 ), GetHeight() ) - 1; 1337 InvertTracking( Rectangle( nX1, 0, nX2, nY2 ), SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); 1338 } 1339 } 1340 1341 1342 // accessibility ============================================================== 1343 1344 ScAccessibleCsvControl* ScCsvGrid::ImplCreateAccessible() 1345 { 1346 return new ScAccessibleCsvGrid( *this ); 1347 } 1348 1349 1350 // ============================================================================ 1351 1352