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