xref: /trunk/main/sc/source/ui/dbgui/csvruler.cxx (revision cdf0e10c)
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