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