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