1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 // ============================================================================ 33 #include "csvruler.hxx" 34 #include "AccessibleCsvControl.hxx" 35 36 37 #include <optutil.hxx> 38 #include <com/sun/star/uno/Any.hxx> 39 #include <com/sun/star/uno/Sequence.hxx> 40 #include "miscuno.hxx" 41 42 using namespace rtl; 43 using namespace com::sun::star::uno; 44 45 46 47 // ============================================================================ 48 #define SEP_PATH "Office.Calc/Dialogs/CSVImport" 49 #define FIXED_WIDTH_LIST "FixedWidthList" 50 51 52 // ============================================================================ 53 54 static void load_FixedWidthList(ScCsvSplits &aSplits) 55 { 56 String sSplits; 57 OUString sFixedWidthLists; 58 59 Sequence<Any>aValues; 60 const Any *pProperties; 61 Sequence<OUString> aNames(1); 62 OUString* pNames = aNames.getArray(); 63 ScLinkConfigItem aItem( OUString::createFromAscii( SEP_PATH ) ); 64 65 pNames[0] = OUString::createFromAscii( FIXED_WIDTH_LIST ); 66 aValues = aItem.GetProperties( aNames ); 67 pProperties = aValues.getConstArray(); 68 69 if( pProperties[0].hasValue() ) 70 { 71 aSplits.Clear(); 72 pProperties[0] >>= sFixedWidthLists; 73 74 sSplits = String( sFixedWidthLists ); 75 76 // String ends with a semi-colon so there is no 'int' after the last one. 77 xub_StrLen n = sSplits.GetTokenCount() - 1; 78 for (xub_StrLen i = 0; i < n; ++i) 79 aSplits.Insert( sSplits.GetToken(i).ToInt32() ); 80 } 81 } 82 static void save_FixedWidthList(ScCsvSplits aSplits) 83 { 84 String sSplits; 85 // Create a semi-colon separated string to save the splits 86 sal_uInt32 n = aSplits.Count(); 87 for (sal_uInt32 i = 0; i < n; ++i) 88 { 89 sSplits.Append( String::CreateFromInt32( aSplits[i] ) ); 90 sSplits.Append((char)';'); 91 } 92 93 OUString sFixedWidthLists = OUString( sSplits ); 94 Sequence<Any> aValues; 95 Any *pProperties; 96 Sequence<OUString> aNames(1); 97 OUString* pNames = aNames.getArray(); 98 ScLinkConfigItem aItem( OUString::createFromAscii( SEP_PATH ) ); 99 100 pNames[0] = OUString::createFromAscii( FIXED_WIDTH_LIST ); 101 aValues = aItem.GetProperties( aNames ); 102 pProperties = aValues.getArray(); 103 pProperties[0] <<= sFixedWidthLists; 104 105 aItem.PutProperties(aNames, aValues); 106 } 107 108 ScCsvRuler::ScCsvRuler( ScCsvControl& rParent ) : 109 ScCsvControl( rParent ), 110 mnPosCursorLast( 1 ) 111 { 112 EnableRTL( false ); // #107812# RTL 113 InitColors(); 114 InitSizeData(); 115 maBackgrDev.SetFont( GetFont() ); 116 maRulerDev.SetFont( GetFont() ); 117 118 load_FixedWidthList( maSplits ); 119 } 120 121 ScCsvRuler::~ScCsvRuler() 122 { 123 save_FixedWidthList( maSplits ); 124 } 125 126 127 // common ruler handling ------------------------------------------------------ 128 129 void ScCsvRuler::SetPosSizePixel( 130 long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) 131 { 132 if( nFlags & WINDOW_POSSIZE_HEIGHT ) 133 nHeight = GetTextHeight() + mnSplitSize + 2; 134 ScCsvControl::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); 135 } 136 137 void ScCsvRuler::ApplyLayout( const ScCsvLayoutData& rOldData ) 138 { 139 ScCsvDiff nDiff = GetLayoutData().GetDiff( rOldData ) & (CSV_DIFF_HORIZONTAL | CSV_DIFF_RULERCURSOR); 140 if( nDiff == CSV_DIFF_EQUAL ) return; 141 142 DisableRepaint(); 143 if( nDiff & CSV_DIFF_HORIZONTAL ) 144 { 145 InitSizeData(); 146 if( GetRulerCursorPos() >= GetPosCount() ) 147 MoveCursor( GetPosCount() - 1 ); 148 } 149 if( nDiff & CSV_DIFF_RULERCURSOR ) 150 { 151 ImplInvertCursor( rOldData.mnPosCursor ); 152 ImplInvertCursor( GetRulerCursorPos() ); 153 } 154 EnableRepaint(); 155 156 if( nDiff & CSV_DIFF_POSOFFSET ) 157 AccSendVisibleEvent(); 158 } 159 160 void ScCsvRuler::InitColors() 161 { 162 const StyleSettings& rSett = GetSettings().GetStyleSettings(); 163 maBackColor = rSett.GetFaceColor(); 164 maActiveColor = rSett.GetWindowColor(); 165 maTextColor = rSett.GetLabelTextColor(); 166 maSplitColor = maBackColor.IsDark() ? maTextColor : Color( COL_LIGHTRED ); 167 InvalidateGfx(); 168 } 169 170 void ScCsvRuler::InitSizeData() 171 { 172 maWinSize = GetSizePixel(); 173 174 mnSplitSize = (GetCharWidth() * 3 / 5) | 1; // make an odd number 175 176 sal_Int32 nActiveWidth = Min( GetWidth() - GetHdrWidth(), GetPosCount() * GetCharWidth() ); 177 sal_Int32 nActiveHeight = GetTextHeight(); 178 179 maActiveRect.SetPos( Point( GetFirstX(), (GetHeight() - nActiveHeight - 1) / 2 ) ); 180 maActiveRect.SetSize( Size( nActiveWidth, nActiveHeight ) ); 181 182 maBackgrDev.SetOutputSizePixel( maWinSize ); 183 maRulerDev.SetOutputSizePixel( maWinSize ); 184 185 InvalidateGfx(); 186 } 187 188 void ScCsvRuler::MoveCursor( sal_Int32 nPos, bool bScroll ) 189 { 190 DisableRepaint(); 191 if( bScroll ) 192 Execute( CSVCMD_MAKEPOSVISIBLE, nPos ); 193 Execute( CSVCMD_MOVERULERCURSOR, IsVisibleSplitPos( nPos ) ? nPos : CSV_POS_INVALID ); 194 EnableRepaint(); 195 AccSendCaretEvent(); 196 } 197 198 void ScCsvRuler::MoveCursorRel( ScMoveMode eDir ) 199 { 200 if( GetRulerCursorPos() != CSV_POS_INVALID ) 201 { 202 switch( eDir ) 203 { 204 case MOVE_FIRST: 205 MoveCursor( 1 ); 206 break; 207 case MOVE_LAST: 208 MoveCursor( GetPosCount() - 1 ); 209 break; 210 case MOVE_PREV: 211 if( GetRulerCursorPos() > 1 ) 212 MoveCursor( GetRulerCursorPos() - 1 ); 213 break; 214 case MOVE_NEXT: 215 if( GetRulerCursorPos() < GetPosCount() - 1 ) 216 MoveCursor( GetRulerCursorPos() + 1 ); 217 break; 218 default: 219 { 220 // added to avoid warnings 221 } 222 } 223 } 224 } 225 226 void ScCsvRuler::MoveCursorToSplit( ScMoveMode eDir ) 227 { 228 if( GetRulerCursorPos() != CSV_POS_INVALID ) 229 { 230 sal_uInt32 nIndex = CSV_VEC_NOTFOUND; 231 switch( eDir ) 232 { 233 case MOVE_FIRST: nIndex = maSplits.LowerBound( 0 ); break; 234 case MOVE_LAST: nIndex = maSplits.UpperBound( GetPosCount() ); break; 235 case MOVE_PREV: nIndex = maSplits.UpperBound( GetRulerCursorPos() - 1 ); break; 236 case MOVE_NEXT: nIndex = maSplits.LowerBound( GetRulerCursorPos() + 1 ); break; 237 default: 238 { 239 // added to avoid warnings 240 } 241 } 242 sal_Int32 nPos = maSplits[ nIndex ]; 243 if( nPos != CSV_POS_INVALID ) 244 MoveCursor( nPos ); 245 } 246 } 247 248 void ScCsvRuler::ScrollVertRel( ScMoveMode eDir ) 249 { 250 sal_Int32 nLine = GetFirstVisLine(); 251 switch( eDir ) 252 { 253 case MOVE_PREV: --nLine; break; 254 case MOVE_NEXT: ++nLine; break; 255 case MOVE_PREVPAGE: nLine -= GetVisLineCount() - 1; break; 256 case MOVE_NEXTPAGE: nLine += GetVisLineCount() - 1; break; 257 default: 258 { 259 // added to avoid warnings 260 } 261 } 262 Execute( CSVCMD_SETLINEOFFSET, nLine ); 263 } 264 265 266 // split handling ------------------------------------------------------------- 267 268 sal_Int32 ScCsvRuler::GetNoScrollPos( sal_Int32 nPos ) const 269 { 270 sal_Int32 nNewPos = nPos; 271 if( nNewPos != CSV_POS_INVALID ) 272 { 273 if( nNewPos < GetFirstVisPos() + CSV_SCROLL_DIST ) 274 { 275 sal_Int32 nScroll = (GetFirstVisPos() > 0) ? CSV_SCROLL_DIST : 0; 276 nNewPos = Max( nPos, GetFirstVisPos() + nScroll ); 277 } 278 else if( nNewPos > GetLastVisPos() - CSV_SCROLL_DIST - 1L ) 279 { 280 sal_Int32 nScroll = (GetFirstVisPos() < GetMaxPosOffset()) ? CSV_SCROLL_DIST : 0; 281 nNewPos = Min( nNewPos, GetLastVisPos() - nScroll - sal_Int32( 1 ) ); 282 } 283 } 284 return nNewPos; 285 } 286 287 void ScCsvRuler::InsertSplit( sal_Int32 nPos ) 288 { 289 if( maSplits.Insert( nPos ) ) 290 { 291 ImplDrawSplit( nPos ); 292 Repaint(); 293 } 294 } 295 296 void ScCsvRuler::RemoveSplit( sal_Int32 nPos ) 297 { 298 if( maSplits.Remove( nPos ) ) 299 { 300 ImplEraseSplit( nPos ); 301 Repaint(); 302 } 303 } 304 305 void ScCsvRuler::MoveSplit( sal_Int32 nPos, sal_Int32 nNewPos ) 306 { 307 bool bRemove = maSplits.Remove( nPos ); 308 bool bInsert = maSplits.Insert( nNewPos ); 309 if( bRemove || bInsert ) 310 { 311 ImplEraseSplit( nPos ); 312 ImplDrawSplit( nNewPos ); 313 Repaint(); 314 } 315 } 316 317 void ScCsvRuler::RemoveAllSplits() 318 { 319 maSplits.Clear(); 320 Repaint( true ); 321 } 322 323 sal_Int32 ScCsvRuler::FindEmptyPos( sal_Int32 nPos, ScMoveMode eDir ) const 324 { 325 sal_Int32 nNewPos = nPos; 326 if( nNewPos != CSV_POS_INVALID ) 327 { 328 switch( eDir ) 329 { 330 case MOVE_FIRST: 331 nNewPos = Min( nPos, FindEmptyPos( 0, MOVE_NEXT ) ); 332 break; 333 case MOVE_LAST: 334 nNewPos = Max( nPos, FindEmptyPos( GetPosCount(), MOVE_PREV ) ); 335 break; 336 case MOVE_PREV: 337 while( HasSplit( --nNewPos ) ) ; 338 break; 339 case MOVE_NEXT: 340 while( HasSplit( ++nNewPos ) ) ; 341 break; 342 default: 343 { 344 // added to avoid warnings 345 } 346 } 347 } 348 return IsValidSplitPos( nNewPos ) ? nNewPos : CSV_POS_INVALID; 349 } 350 351 void ScCsvRuler::MoveCurrSplit( sal_Int32 nNewPos ) 352 { 353 DisableRepaint(); 354 Execute( CSVCMD_MOVESPLIT, GetRulerCursorPos(), nNewPos ); 355 MoveCursor( nNewPos ); 356 EnableRepaint(); 357 } 358 359 void ScCsvRuler::MoveCurrSplitRel( ScMoveMode eDir ) 360 { 361 if( HasSplit( GetRulerCursorPos() ) ) 362 { 363 sal_Int32 nNewPos = FindEmptyPos( GetRulerCursorPos(), eDir ); 364 if( nNewPos != CSV_POS_INVALID ) 365 MoveCurrSplit( nNewPos ); 366 } 367 } 368 369 370 // event handling ------------------------------------------------------------- 371 372 void ScCsvRuler::Resize() 373 { 374 ScCsvControl::Resize(); 375 InitSizeData(); 376 Repaint(); 377 } 378 379 void ScCsvRuler::GetFocus() 380 { 381 ScCsvControl::GetFocus(); 382 DisableRepaint(); 383 if( GetRulerCursorPos() == CSV_POS_INVALID ) 384 MoveCursor( GetNoScrollPos( mnPosCursorLast ) ); 385 EnableRepaint(); 386 } 387 388 void ScCsvRuler::LoseFocus() 389 { 390 ScCsvControl::LoseFocus(); 391 mnPosCursorLast = GetRulerCursorPos(); 392 MoveCursor( CSV_POS_INVALID ); 393 } 394 395 void ScCsvRuler::DataChanged( const DataChangedEvent& rDCEvt ) 396 { 397 if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 398 { 399 InitColors(); 400 Repaint(); 401 } 402 ScCsvControl::DataChanged( rDCEvt ); 403 } 404 405 void ScCsvRuler::MouseButtonDown( const MouseEvent& rMEvt ) 406 { 407 DisableRepaint(); 408 if( !HasFocus() ) 409 GrabFocus(); 410 if( rMEvt.IsLeft() ) 411 { 412 sal_Int32 nPos = GetPosFromX( rMEvt.GetPosPixel().X() ); 413 if( IsVisibleSplitPos( nPos ) ) 414 StartMouseTracking( nPos ); 415 ImplSetMousePointer( nPos ); 416 } 417 EnableRepaint(); 418 } 419 420 void ScCsvRuler::MouseMove( const MouseEvent& rMEvt ) 421 { 422 if( !rMEvt.IsModifierChanged() ) 423 { 424 sal_Int32 nPos = GetPosFromX( rMEvt.GetPosPixel().X() ); 425 if( IsTracking() ) 426 { 427 // on mouse tracking: keep position valid 428 nPos = Max( Min( nPos, GetPosCount() - sal_Int32( 1 ) ), sal_Int32( 1 ) ); 429 MoveMouseTracking( nPos ); 430 } 431 else 432 { 433 Point aPoint; 434 Rectangle aRect( aPoint, maWinSize ); 435 if( !IsVisibleSplitPos( nPos ) || !aRect.IsInside( rMEvt.GetPosPixel() ) ) 436 // if focused, keep old cursor position for key input 437 nPos = HasFocus() ? GetRulerCursorPos() : CSV_POS_INVALID; 438 MoveCursor( nPos, false ); 439 } 440 ImplSetMousePointer( nPos ); 441 } 442 } 443 444 void ScCsvRuler::Tracking( const TrackingEvent& rTEvt ) 445 { 446 if( rTEvt.IsTrackingEnded() || rTEvt.IsTrackingRepeat() ) 447 MouseMove( rTEvt.GetMouseEvent() ); 448 if( rTEvt.IsTrackingEnded() ) 449 EndMouseTracking( !rTEvt.IsTrackingCanceled() ); 450 } 451 452 void ScCsvRuler::KeyInput( const KeyEvent& rKEvt ) 453 { 454 const KeyCode& rKCode = rKEvt.GetKeyCode(); 455 sal_uInt16 nCode = rKCode.GetCode(); 456 bool bNoMod = !rKCode.GetModifier(); 457 bool bShift = (rKCode.GetModifier() == KEY_SHIFT); 458 bool bJump = (rKCode.GetModifier() == KEY_MOD1); 459 bool bMove = (rKCode.GetModifier() == (KEY_MOD1 | KEY_SHIFT)); 460 461 ScMoveMode eHDir = GetHorzDirection( nCode, true ); 462 ScMoveMode eVDir = GetVertDirection( nCode, false ); 463 464 if( bNoMod ) 465 { 466 if( eHDir != MOVE_NONE ) 467 MoveCursorRel( eHDir ); 468 else if( eVDir != MOVE_NONE ) 469 ScrollVertRel( eVDir ); 470 else switch( nCode ) 471 { 472 case KEY_SPACE: Execute( CSVCMD_TOGGLESPLIT, GetRulerCursorPos() ); break; 473 case KEY_INSERT: Execute( CSVCMD_INSERTSPLIT, GetRulerCursorPos() ); break; 474 case KEY_DELETE: Execute( CSVCMD_REMOVESPLIT, GetRulerCursorPos() ); break; 475 } 476 } 477 else if( bJump && (eHDir != MOVE_NONE) ) 478 MoveCursorToSplit( eHDir ); 479 else if( bMove && (eHDir != MOVE_NONE) ) 480 MoveCurrSplitRel( eHDir ); 481 else if( bShift && (nCode == KEY_DELETE) ) 482 Execute( CSVCMD_REMOVEALLSPLITS ); 483 484 if( rKCode.GetGroup() != KEYGROUP_CURSOR ) 485 ScCsvControl::KeyInput( rKEvt ); 486 } 487 488 void ScCsvRuler::StartMouseTracking( sal_Int32 nPos ) 489 { 490 mnPosMTStart = mnPosMTCurr = nPos; 491 mbPosMTMoved = false; 492 maOldSplits = maSplits; 493 Execute( CSVCMD_INSERTSPLIT, nPos ); 494 if( HasSplit( nPos ) ) 495 StartTracking( STARTTRACK_BUTTONREPEAT ); 496 } 497 498 void ScCsvRuler::MoveMouseTracking( sal_Int32 nPos ) 499 { 500 if( mnPosMTCurr != nPos ) 501 { 502 DisableRepaint(); 503 MoveCursor( nPos ); 504 if( (mnPosMTCurr != mnPosMTStart) && maOldSplits.HasSplit( mnPosMTCurr ) ) 505 Execute( CSVCMD_INSERTSPLIT, nPos ); 506 else 507 Execute( CSVCMD_MOVESPLIT, mnPosMTCurr, nPos ); 508 mnPosMTCurr = nPos; 509 mbPosMTMoved = true; 510 EnableRepaint(); 511 } 512 } 513 514 void ScCsvRuler::EndMouseTracking( bool bApply ) 515 { 516 if( bApply ) // tracking finished successfully 517 { 518 // remove on simple click on an existing split 519 if( (mnPosMTCurr == mnPosMTStart) && maOldSplits.HasSplit( mnPosMTCurr ) && !mbPosMTMoved ) 520 Execute( CSVCMD_REMOVESPLIT, mnPosMTCurr ); 521 } 522 else // tracking cancelled 523 { 524 MoveCursor( mnPosMTStart ); 525 // move split to origin 526 if( maOldSplits.HasSplit( mnPosMTStart ) ) 527 MoveMouseTracking( mnPosMTStart ); 528 // remove temporarily inserted split 529 else if( !maOldSplits.HasSplit( mnPosMTCurr ) ) 530 Execute( CSVCMD_REMOVESPLIT, mnPosMTCurr ); 531 } 532 mnPosMTStart = CSV_POS_INVALID; 533 } 534 535 536 // painting ------------------------------------------------------------------- 537 538 void ScCsvRuler::Paint( const Rectangle& ) 539 { 540 Repaint(); 541 } 542 543 void ScCsvRuler::ImplRedraw() 544 { 545 if( IsVisible() ) 546 { 547 if( !IsValidGfx() ) 548 { 549 ValidateGfx(); 550 ImplDrawBackgrDev(); 551 ImplDrawRulerDev(); 552 } 553 DrawOutDev( Point(), maWinSize, Point(), maWinSize, maRulerDev ); 554 ImplDrawTrackingRect(); 555 } 556 } 557 558 void ScCsvRuler::ImplDrawArea( sal_Int32 nPosX, sal_Int32 nWidth ) 559 { 560 maBackgrDev.SetLineColor(); 561 Rectangle aRect( Point( nPosX, 0 ), Size( nWidth, GetHeight() ) ); 562 maBackgrDev.SetFillColor( maBackColor ); 563 maBackgrDev.DrawRect( aRect ); 564 565 aRect = maActiveRect; 566 aRect.Left() = Max( GetFirstX(), nPosX ); 567 aRect.Right() = Min( Min( GetX( GetPosCount() ), GetLastX() ), nPosX + nWidth - sal_Int32( 1 ) ); 568 if( aRect.Left() <= aRect.Right() ) 569 { 570 maBackgrDev.SetFillColor( maActiveColor ); 571 maBackgrDev.DrawRect( aRect ); 572 } 573 574 maBackgrDev.SetLineColor( maTextColor ); 575 sal_Int32 nY = GetHeight() - 1; 576 maBackgrDev.DrawLine( Point( nPosX, nY ), Point( nPosX + nWidth - 1, nY ) ); 577 } 578 579 void ScCsvRuler::ImplDrawBackgrDev() 580 { 581 ImplDrawArea( 0, GetWidth() ); 582 583 // scale 584 maBackgrDev.SetLineColor( maTextColor ); 585 maBackgrDev.SetFillColor(); 586 sal_Int32 nPos; 587 588 sal_Int32 nFirstPos = Max( GetPosFromX( 0 ) - (sal_Int32)(1L), (sal_Int32)(0L) ); 589 sal_Int32 nLastPos = GetPosFromX( GetWidth() ); 590 sal_Int32 nY = (maActiveRect.Top() + maActiveRect.Bottom()) / 2; 591 for( nPos = nFirstPos; nPos <= nLastPos; ++nPos ) 592 { 593 sal_Int32 nX = GetX( nPos ); 594 if( nPos % 5 ) 595 maBackgrDev.DrawPixel( Point( nX, nY ) ); 596 else 597 maBackgrDev.DrawLine( Point( nX, nY - 1 ), Point( nX, nY + 1 ) ); 598 } 599 600 // texts 601 maBackgrDev.SetTextColor( maTextColor ); 602 maBackgrDev.SetTextFillColor(); 603 for( nPos = ((nFirstPos + 9) / 10) * 10; nPos <= nLastPos; nPos += 10 ) 604 { 605 String aText( String::CreateFromInt32( nPos ) ); 606 sal_Int32 nTextWidth = maBackgrDev.GetTextWidth( aText ); 607 sal_Int32 nTextX = GetX( nPos ) - nTextWidth / 2; 608 ImplDrawArea( nTextX - 1, nTextWidth + 2 ); 609 maBackgrDev.DrawText( Point( nTextX, maActiveRect.Top() ), aText ); 610 } 611 } 612 613 void ScCsvRuler::ImplDrawSplit( sal_Int32 nPos ) 614 { 615 if( IsVisibleSplitPos( nPos ) ) 616 { 617 Point aPos( GetX( nPos ) - mnSplitSize / 2, GetHeight() - mnSplitSize - 2 ); 618 Size aSize( mnSplitSize, mnSplitSize ); 619 maRulerDev.SetLineColor( maTextColor ); 620 maRulerDev.SetFillColor( maSplitColor ); 621 maRulerDev.DrawEllipse( Rectangle( aPos, aSize ) ); 622 maRulerDev.DrawPixel( Point( GetX( nPos ), GetHeight() - 2 ) ); 623 } 624 } 625 626 void ScCsvRuler::ImplEraseSplit( sal_Int32 nPos ) 627 { 628 if( IsVisibleSplitPos( nPos ) ) 629 { 630 ImplInvertCursor( GetRulerCursorPos() ); 631 Point aPos( GetX( nPos ) - mnSplitSize / 2, 0 ); 632 Size aSize( mnSplitSize, GetHeight() ); 633 maRulerDev.DrawOutDev( aPos, aSize, aPos, aSize, maBackgrDev ); 634 ImplInvertCursor( GetRulerCursorPos() ); 635 } 636 } 637 638 void ScCsvRuler::ImplDrawRulerDev() 639 { 640 maRulerDev.DrawOutDev( Point(), maWinSize, Point(), maWinSize, maBackgrDev ); 641 ImplInvertCursor( GetRulerCursorPos() ); 642 643 sal_uInt32 nFirst = maSplits.LowerBound( GetFirstVisPos() ); 644 sal_uInt32 nLast = maSplits.UpperBound( GetLastVisPos() ); 645 if( (nFirst != CSV_VEC_NOTFOUND) && (nLast != CSV_VEC_NOTFOUND) ) 646 for( sal_uInt32 nIndex = nFirst; nIndex <= nLast; ++nIndex ) 647 ImplDrawSplit( GetSplitPos( nIndex ) ); 648 } 649 650 void ScCsvRuler::ImplInvertCursor( sal_Int32 nPos ) 651 { 652 if( IsVisibleSplitPos( nPos ) ) 653 { 654 ImplInvertRect( maRulerDev, Rectangle( Point( GetX( nPos ) - 1, 0 ), Size( 3, GetHeight() - 1 ) ) ); 655 if( HasSplit( nPos ) ) 656 ImplDrawSplit( nPos ); 657 } 658 } 659 660 void ScCsvRuler::ImplDrawTrackingRect() 661 { 662 if( HasFocus() ) 663 InvertTracking( Rectangle( 0, 0, GetWidth() - 1, GetHeight() - 2 ), 664 SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); 665 } 666 667 void ScCsvRuler::ImplSetMousePointer( sal_Int32 nPos ) 668 { 669 SetPointer( Pointer( HasSplit( nPos ) ? POINTER_HSPLIT : POINTER_ARROW ) ); 670 } 671 672 673 // accessibility ============================================================== 674 675 ScAccessibleCsvControl* ScCsvRuler::ImplCreateAccessible() 676 { 677 return new ScAccessibleCsvRuler( *this ); 678 } 679 680 681 // ============================================================================ 682 683