bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / dbgui / csvgrid.cxx
blobe1595b12c821c203ffae69f78e3fd79581323e61
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "csvgrid.hxx"
22 #include <algorithm>
23 #include <memory>
25 #include <comphelper/string.hxx>
26 #include <svtools/colorcfg.hxx>
27 #include <svl/smplhint.hxx>
28 #include <sal/macros.h>
29 #include <tools/poly.hxx>
30 #include "scmod.hxx"
31 #include "asciiopt.hxx"
32 #include "impex.hxx"
33 #include "AccessibleCsvControl.hxx"
35 // *** edit engine ***
36 #include "scitems.hxx"
37 #include <editeng/eeitem.hxx>
40 #include <editeng/colritem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/fontitem.hxx>
43 #include <svl/itemset.hxx>
44 #include "editutil.hxx"
45 // *** edit engine ***
48 // ============================================================================
50 struct Func_SetType
52 sal_Int32 mnType;
53 inline Func_SetType( sal_Int32 nType ) : mnType( nType ) {}
54 inline void operator()( ScCsvColState& rState ) const
55 { rState.mnType = mnType; }
58 struct Func_Select
60 bool mbSelect;
61 inline Func_Select( bool bSelect ) : mbSelect( bSelect ) {}
62 inline void operator()( ScCsvColState& rState ) const
63 { rState.Select( mbSelect ); }
67 // ============================================================================
69 ScCsvGrid::ScCsvGrid( ScCsvControl& rParent ) :
70 ScCsvControl( rParent ),
71 mpColorConfig( 0 ),
72 mpEditEngine( new ScEditEngineDefaulter( EditEngine::CreatePool(), true ) ),
73 maHeaderFont( GetFont() ),
74 maColStates( 1 ),
75 maTypeNames( 1 ),
76 mnFirstImpLine( 0 ),
77 mnRecentSelCol( CSV_COLUMN_INVALID )
79 mpEditEngine->SetRefDevice( &maBackgrDev );
80 mpEditEngine->SetRefMapMode( MapMode( MAP_PIXEL ) );
81 maEdEngSize = mpEditEngine->GetPaperSize();
83 maPopup.SetMenuFlags( maPopup.GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
85 EnableRTL( false ); // RTL
86 InitFonts();
87 ImplClearSplits();
90 ScCsvGrid::~ScCsvGrid()
92 OSL_ENSURE(mpColorConfig, "the object hasn't been initialized properly");
93 if (mpColorConfig)
94 mpColorConfig->RemoveListener(this);
97 void
98 ScCsvGrid::Init()
100 OSL_PRECOND(!mpColorConfig, "the object has already been initialized");
101 mpColorConfig = &SC_MOD()->GetColorConfig();
102 InitColors();
103 mpColorConfig->AddListener(this);
106 // common grid handling -------------------------------------------------------
108 void ScCsvGrid::UpdateLayoutData()
110 DisableRepaint();
111 SetFont( maMonoFont );
112 Execute( CSVCMD_SETCHARWIDTH, GetTextWidth( OUString( 'X' ) ) );
113 Execute( CSVCMD_SETLINEHEIGHT, GetTextHeight() + 1 );
114 SetFont( maHeaderFont );
115 Execute( CSVCMD_SETHDRHEIGHT, GetTextHeight() + 1 );
116 UpdateOffsetX();
117 EnableRepaint();
120 void ScCsvGrid::UpdateOffsetX()
122 sal_Int32 nLastLine = GetLastVisLine() + 1;
123 sal_Int32 nDigits = 2;
124 while( nLastLine /= 10 ) ++nDigits;
125 nDigits = std::max( nDigits, sal_Int32( 3 ) );
126 Execute( CSVCMD_SETHDRWIDTH, GetTextWidth( OUString( '0' ) ) * nDigits );
129 void ScCsvGrid::ApplyLayout( const ScCsvLayoutData& rOldData )
131 ScCsvDiff nDiff = GetLayoutData().GetDiff( rOldData );
132 if( nDiff == CSV_DIFF_EQUAL ) return;
134 DisableRepaint();
136 if( nDiff & CSV_DIFF_RULERCURSOR )
138 ImplInvertCursor( rOldData.mnPosCursor );
139 ImplInvertCursor( GetRulerCursorPos() );
142 if( nDiff & CSV_DIFF_POSCOUNT )
144 if( GetPosCount() < rOldData.mnPosCount )
146 SelectAll( false );
147 maSplits.RemoveRange( GetPosCount(), rOldData.mnPosCount );
149 else
150 maSplits.Remove( rOldData.mnPosCount );
151 maSplits.Insert( GetPosCount() );
152 maColStates.resize( maSplits.Count() - 1 );
155 if( nDiff & CSV_DIFF_LINEOFFSET )
157 Execute( CSVCMD_UPDATECELLTEXTS );
158 UpdateOffsetX();
161 ScCsvDiff nHVDiff = nDiff & (CSV_DIFF_HORIZONTAL | CSV_DIFF_VERTICAL);
162 if( nHVDiff == CSV_DIFF_POSOFFSET )
163 ImplDrawHorzScrolled( rOldData.mnPosOffset );
164 else if( nHVDiff != CSV_DIFF_EQUAL )
165 InvalidateGfx();
167 EnableRepaint();
169 if( nDiff & (CSV_DIFF_POSOFFSET | CSV_DIFF_LINEOFFSET) )
170 AccSendVisibleEvent();
173 void ScCsvGrid::SetFirstImportedLine( sal_Int32 nLine )
175 ImplDrawFirstLineSep( false );
176 mnFirstImpLine = nLine;
177 ImplDrawFirstLineSep( true );
178 ImplDrawGridDev();
179 Repaint();
182 sal_Int32 ScCsvGrid::GetNoScrollCol( sal_Int32 nPos ) const
184 sal_Int32 nNewPos = nPos;
185 if( nNewPos != CSV_POS_INVALID )
187 if( nNewPos < GetFirstVisPos() + CSV_SCROLL_DIST )
189 sal_Int32 nScroll = (GetFirstVisPos() > 0) ? CSV_SCROLL_DIST : 0;
190 nNewPos = GetFirstVisPos() + nScroll;
192 else if( nNewPos > GetLastVisPos() - CSV_SCROLL_DIST - 1L )
194 sal_Int32 nScroll = (GetFirstVisPos() < GetMaxPosOffset()) ? CSV_SCROLL_DIST : 0;
195 nNewPos = GetLastVisPos() - nScroll - 1;
198 return nNewPos;
201 void ScCsvGrid::InitColors()
203 OSL_PRECOND(mpColorConfig, "the object hasn't been initialized properly");
204 if ( !mpColorConfig )
205 return;
206 maBackColor.SetColor( static_cast< sal_uInt32 >( mpColorConfig->GetColorValue( ::svtools::DOCCOLOR ).nColor ) );
207 maGridColor.SetColor( static_cast< sal_uInt32 >( mpColorConfig->GetColorValue( ::svtools::CALCGRID ).nColor ) );
208 maGridPBColor.SetColor( static_cast< sal_uInt32 >( mpColorConfig->GetColorValue( ::svtools::CALCPAGEBREAK ).nColor ) );
209 maAppBackColor.SetColor( static_cast< sal_uInt32 >( mpColorConfig->GetColorValue( ::svtools::APPBACKGROUND ).nColor ) );
210 maTextColor.SetColor( static_cast< sal_uInt32 >( mpColorConfig->GetColorValue( ::svtools::FONTCOLOR ).nColor ) );
212 const StyleSettings& rSett = GetSettings().GetStyleSettings();
213 maHeaderBackColor = rSett.GetFaceColor();
214 maHeaderGridColor = rSett.GetDarkShadowColor();
215 maHeaderTextColor = rSett.GetButtonTextColor();
216 maSelectColor = rSett.GetActiveColor();
218 InvalidateGfx();
221 void ScCsvGrid::InitFonts()
223 maMonoFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_ENGLISH_US, 0 );
224 maMonoFont.SetSize( Size( maMonoFont.GetSize().Width(), maHeaderFont.GetSize().Height() ) );
226 /* *** Set edit engine defaults ***
227 maMonoFont for Latin script, smaller default font for Asian and Complex script. */
229 // get default fonts
230 SvxFontItem aLatinItem( EE_CHAR_FONTINFO );
231 SvxFontItem aAsianItem( EE_CHAR_FONTINFO_CJK );
232 SvxFontItem aComplexItem( EE_CHAR_FONTINFO_CTL );
233 ::GetDefaultFonts( aLatinItem, aAsianItem, aComplexItem );
235 // create item set for defaults
236 SfxItemSet aDefSet( mpEditEngine->GetEmptyItemSet() );
237 EditEngine::SetFontInfoInItemSet( aDefSet, maMonoFont );
238 aDefSet.Put( aAsianItem );
239 aDefSet.Put( aComplexItem );
241 // set Asian/Complex font size to height of character in Latin font
242 sal_uLong nFontHt = static_cast< sal_uLong >( maMonoFont.GetSize().Height() );
243 aDefSet.Put( SvxFontHeightItem( nFontHt, 100, EE_CHAR_FONTHEIGHT_CJK ) );
244 aDefSet.Put( SvxFontHeightItem( nFontHt, 100, EE_CHAR_FONTHEIGHT_CTL ) );
246 // copy other items from default font
247 const SfxPoolItem& rWeightItem = aDefSet.Get( EE_CHAR_WEIGHT );
248 aDefSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK );
249 aDefSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL );
250 const SfxPoolItem& rItalicItem = aDefSet.Get( EE_CHAR_ITALIC );
251 aDefSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK );
252 aDefSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL );
253 const SfxPoolItem& rLangItem = aDefSet.Get( EE_CHAR_LANGUAGE );
254 aDefSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK );
255 aDefSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL );
257 mpEditEngine->SetDefaults( aDefSet );
258 InvalidateGfx();
261 void ScCsvGrid::InitSizeData()
263 maWinSize = GetSizePixel();
264 maBackgrDev.SetOutputSizePixel( maWinSize );
265 maGridDev.SetOutputSizePixel( maWinSize );
266 InvalidateGfx();
270 // split handling -------------------------------------------------------------
272 void ScCsvGrid::InsertSplit( sal_Int32 nPos )
274 if( ImplInsertSplit( nPos ) )
276 DisableRepaint();
277 Execute( CSVCMD_EXPORTCOLUMNTYPE );
278 Execute( CSVCMD_UPDATECELLTEXTS );
279 sal_uInt32 nColIx = GetColumnFromPos( nPos );
280 ImplDrawColumn( nColIx - 1 );
281 ImplDrawColumn( nColIx );
282 ValidateGfx(); // performance: do not redraw all columns
283 EnableRepaint();
287 void ScCsvGrid::RemoveSplit( sal_Int32 nPos )
289 if( ImplRemoveSplit( nPos ) )
291 DisableRepaint();
292 Execute( CSVCMD_EXPORTCOLUMNTYPE );
293 Execute( CSVCMD_UPDATECELLTEXTS );
294 ImplDrawColumn( GetColumnFromPos( nPos ) );
295 ValidateGfx(); // performance: do not redraw all columns
296 EnableRepaint();
300 void ScCsvGrid::MoveSplit( sal_Int32 nPos, sal_Int32 nNewPos )
302 sal_uInt32 nColIx = GetColumnFromPos( nPos );
303 if( nColIx != CSV_COLUMN_INVALID )
305 DisableRepaint();
306 if( (GetColumnPos( nColIx - 1 ) < nNewPos) && (nNewPos < GetColumnPos( nColIx + 1 )) )
308 // move a split in the range between 2 others -> keep selection state of both columns
309 maSplits.Remove( nPos );
310 maSplits.Insert( nNewPos );
311 Execute( CSVCMD_UPDATECELLTEXTS );
312 ImplDrawColumn( nColIx - 1 );
313 ImplDrawColumn( nColIx );
314 ValidateGfx(); // performance: do not redraw all columns
315 AccSendTableUpdateEvent( nColIx - 1, nColIx );
317 else
319 ImplRemoveSplit( nPos );
320 ImplInsertSplit( nNewPos );
321 Execute( CSVCMD_EXPORTCOLUMNTYPE );
322 Execute( CSVCMD_UPDATECELLTEXTS );
324 EnableRepaint();
328 void ScCsvGrid::RemoveAllSplits()
330 DisableRepaint();
331 ImplClearSplits();
332 Execute( CSVCMD_EXPORTCOLUMNTYPE );
333 Execute( CSVCMD_UPDATECELLTEXTS );
334 EnableRepaint();
337 void ScCsvGrid::SetSplits( const ScCsvSplits& rSplits )
339 DisableRepaint();
340 ImplClearSplits();
341 sal_uInt32 nCount = rSplits.Count();
342 for( sal_uInt32 nIx = 0; nIx < nCount; ++nIx )
343 maSplits.Insert( rSplits[ nIx ] );
344 maColStates.clear();
345 maColStates.resize( maSplits.Count() - 1 );
346 Execute( CSVCMD_EXPORTCOLUMNTYPE );
347 Execute( CSVCMD_UPDATECELLTEXTS );
348 EnableRepaint();
351 bool ScCsvGrid::ImplInsertSplit( sal_Int32 nPos )
353 sal_uInt32 nColIx = GetColumnFromPos( nPos );
354 bool bRet = (nColIx < GetColumnCount()) && maSplits.Insert( nPos );
355 if( bRet )
357 ScCsvColState aState( GetColumnType( nColIx ) );
358 aState.Select( IsSelected( nColIx ) && IsSelected( nColIx + 1 ) );
359 maColStates.insert( maColStates.begin() + nColIx + 1, aState );
360 AccSendInsertColumnEvent( nColIx + 1, nColIx + 1 );
361 AccSendTableUpdateEvent( nColIx, nColIx );
363 return bRet;
366 bool ScCsvGrid::ImplRemoveSplit( sal_Int32 nPos )
368 bool bRet = maSplits.Remove( nPos );
369 if( bRet )
371 sal_uInt32 nColIx = GetColumnFromPos( nPos );
372 bool bSel = IsSelected( nColIx ) || IsSelected( nColIx + 1 );
373 maColStates.erase( maColStates.begin() + nColIx + 1 );
374 maColStates[ nColIx ].Select( bSel );
375 AccSendRemoveColumnEvent( nColIx + 1, nColIx + 1 );
376 AccSendTableUpdateEvent( nColIx, nColIx );
378 return bRet;
381 void ScCsvGrid::ImplClearSplits()
383 sal_uInt32 nColumns = GetColumnCount();
384 maSplits.Clear();
385 maSplits.Insert( 0 );
386 maSplits.Insert( GetPosCount() );
387 maColStates.resize( 1 );
388 InvalidateGfx();
389 AccSendRemoveColumnEvent( 1, nColumns - 1 );
392 // columns/column types -------------------------------------------------------
394 sal_uInt32 ScCsvGrid::GetFirstVisColumn() const
396 return GetColumnFromPos( GetFirstVisPos() );
399 sal_uInt32 ScCsvGrid::GetLastVisColumn() const
401 return GetColumnFromPos( std::min( GetLastVisPos(), GetPosCount() ) - 1 );
404 bool ScCsvGrid::IsValidColumn( sal_uInt32 nColIndex ) const
406 return nColIndex < GetColumnCount();
409 bool ScCsvGrid::IsVisibleColumn( sal_uInt32 nColIndex ) const
411 return IsValidColumn( nColIndex ) &&
412 (GetColumnPos( nColIndex ) < GetLastVisPos()) &&
413 (GetFirstVisPos() < GetColumnPos( nColIndex + 1 ));
416 sal_Int32 ScCsvGrid::GetColumnX( sal_uInt32 nColIndex ) const
418 return GetX( GetColumnPos( nColIndex ) );
421 sal_uInt32 ScCsvGrid::GetColumnFromX( sal_Int32 nX ) const
423 sal_Int32 nPos = (nX - GetFirstX()) / GetCharWidth() + GetFirstVisPos();
424 return ((GetFirstVisPos() <= nPos) && (nPos <= GetLastVisPos())) ?
425 GetColumnFromPos( nPos ) : CSV_COLUMN_INVALID;
428 sal_uInt32 ScCsvGrid::GetColumnFromPos( sal_Int32 nPos ) const
430 return maSplits.UpperBound( nPos );
433 sal_Int32 ScCsvGrid::GetColumnWidth( sal_uInt32 nColIndex ) const
435 return IsValidColumn( nColIndex ) ? (GetColumnPos( nColIndex + 1 ) - GetColumnPos( nColIndex )) : 0;
438 void ScCsvGrid::SetColumnStates( const ScCsvColStateVec& rStates )
440 maColStates = rStates;
441 maColStates.resize( maSplits.Count() - 1 );
442 Execute( CSVCMD_EXPORTCOLUMNTYPE );
443 AccSendTableUpdateEvent( 0, GetColumnCount(), false );
444 AccSendSelectionEvent();
447 sal_Int32 ScCsvGrid::GetColumnType( sal_uInt32 nColIndex ) const
449 return IsValidColumn( nColIndex ) ? maColStates[ nColIndex ].mnType : CSV_TYPE_NOSELECTION;
452 void ScCsvGrid::SetColumnType( sal_uInt32 nColIndex, sal_Int32 nColType )
454 if( IsValidColumn( nColIndex ) )
456 maColStates[ nColIndex ].mnType = nColType;
457 AccSendTableUpdateEvent( nColIndex, nColIndex, false );
461 sal_Int32 ScCsvGrid::GetSelColumnType() const
463 sal_uInt32 nColIx = GetFirstSelected();
464 if( nColIx == CSV_COLUMN_INVALID )
465 return CSV_TYPE_NOSELECTION;
467 sal_Int32 nType = GetColumnType( nColIx );
468 while( (nColIx != CSV_COLUMN_INVALID) && (nType != CSV_TYPE_MULTI) )
470 if( nType != GetColumnType( nColIx ) )
471 nType = CSV_TYPE_MULTI;
472 nColIx = GetNextSelected( nColIx );
474 return nType;
477 void ScCsvGrid::SetSelColumnType( sal_Int32 nType )
479 if( (nType != CSV_TYPE_MULTI) && (nType != CSV_TYPE_NOSELECTION) )
481 for( sal_uInt32 nColIx = GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = GetNextSelected( nColIx ) )
482 SetColumnType( nColIx, nType );
483 Repaint( true );
484 Execute( CSVCMD_EXPORTCOLUMNTYPE );
488 void ScCsvGrid::SetTypeNames( const StringVec& rTypeNames )
490 OSL_ENSURE( !rTypeNames.empty(), "ScCsvGrid::SetTypeNames - vector is empty" );
491 maTypeNames = rTypeNames;
492 Repaint( true );
494 maPopup.Clear();
495 sal_uInt32 nCount = maTypeNames.size();
496 sal_uInt32 nIx;
497 sal_uInt16 nItemId;
498 for( nIx = 0, nItemId = 1; nIx < nCount; ++nIx, ++nItemId )
499 maPopup.InsertItem( nItemId, maTypeNames[ nIx ] );
501 ::std::for_each( maColStates.begin(), maColStates.end(), Func_SetType( CSV_TYPE_DEFAULT ) );
504 const String& ScCsvGrid::GetColumnTypeName( sal_uInt32 nColIndex ) const
506 sal_uInt32 nTypeIx = static_cast< sal_uInt32 >( GetColumnType( nColIndex ) );
507 return (nTypeIx < maTypeNames.size()) ? maTypeNames[ nTypeIx ] : EMPTY_STRING;
510 static sal_uInt8 lcl_GetExtColumnType( sal_Int32 nIntType )
512 static sal_uInt8 pExtTypes[] =
513 { SC_COL_STANDARD, SC_COL_TEXT, SC_COL_DMY, SC_COL_MDY, SC_COL_YMD, SC_COL_ENGLISH, SC_COL_SKIP };
514 static sal_Int32 nExtTypeCount = SAL_N_ELEMENTS(pExtTypes);
515 return pExtTypes[ ((0 <= nIntType) && (nIntType < nExtTypeCount)) ? nIntType : 0 ];
518 void ScCsvGrid::FillColumnDataSep( ScAsciiOptions& rOptions ) const
520 sal_uInt32 nCount = GetColumnCount();
521 ScCsvExpDataVec aDataVec;
523 for( sal_uInt32 nColIx = 0; nColIx < nCount; ++nColIx )
525 if( GetColumnType( nColIx ) != CSV_TYPE_DEFAULT )
526 // 1-based column index
527 aDataVec.push_back( ScCsvExpData(
528 static_cast< sal_Int32 >( nColIx + 1 ),
529 lcl_GetExtColumnType( GetColumnType( nColIx ) ) ) );
531 rOptions.SetColumnInfo( aDataVec );
534 void ScCsvGrid::FillColumnDataFix( ScAsciiOptions& rOptions ) const
536 sal_uInt32 nCount = std::min( GetColumnCount(), static_cast<sal_uInt32>(MAXCOLCOUNT) );
537 ScCsvExpDataVec aDataVec( nCount + 1 );
539 for( sal_uInt32 nColIx = 0; nColIx < nCount; ++nColIx )
541 ScCsvExpData& rData = aDataVec[ nColIx ];
542 rData.mnIndex = static_cast< sal_Int32 >( GetColumnPos( nColIx ) );
543 rData.mnType = lcl_GetExtColumnType( GetColumnType( nColIx ) );
545 aDataVec[ nCount ].mnIndex = SAL_MAX_INT32;
546 aDataVec[ nCount ].mnType = SC_COL_SKIP;
547 rOptions.SetColumnInfo( aDataVec );
550 void ScCsvGrid::ScrollVertRel( ScMoveMode eDir )
552 sal_Int32 nLine = GetFirstVisLine();
553 switch( eDir )
555 case MOVE_PREV: --nLine; break;
556 case MOVE_NEXT: ++nLine; break;
557 case MOVE_FIRST: nLine = 0; break;
558 case MOVE_LAST: nLine = GetMaxLineOffset(); break;
559 case MOVE_PREVPAGE: nLine -= GetVisLineCount() - 2; break;
560 case MOVE_NEXTPAGE: nLine += GetVisLineCount() - 2; break;
561 default:
563 // added to avoid warnings
566 Execute( CSVCMD_SETLINEOFFSET, nLine );
569 void ScCsvGrid::ExecutePopup( const Point& rPos )
571 sal_uInt16 nItemId = maPopup.Execute( this, rPos );
572 if( nItemId ) // 0 = cancelled
573 Execute( CSVCMD_SETCOLUMNTYPE, maPopup.GetItemPos( nItemId ) );
577 // selection handling ---------------------------------------------------------
579 bool ScCsvGrid::IsSelected( sal_uInt32 nColIndex ) const
581 return IsValidColumn( nColIndex ) && maColStates[ nColIndex ].IsSelected();
584 sal_uInt32 ScCsvGrid::GetFirstSelected() const
586 return IsSelected( 0 ) ? 0 : GetNextSelected( 0 );
589 sal_uInt32 ScCsvGrid::GetNextSelected( sal_uInt32 nFromIndex ) const
591 sal_uInt32 nColCount = GetColumnCount();
592 for( sal_uInt32 nColIx = nFromIndex + 1; nColIx < nColCount; ++nColIx )
593 if( IsSelected( nColIx ) )
594 return nColIx;
595 return CSV_COLUMN_INVALID;
598 void ScCsvGrid::Select( sal_uInt32 nColIndex, bool bSelect )
600 if( IsValidColumn( nColIndex ) )
602 maColStates[ nColIndex ].Select( bSelect );
603 ImplDrawColumnSelection( nColIndex );
604 Repaint();
605 Execute( CSVCMD_EXPORTCOLUMNTYPE );
606 if( bSelect )
607 mnRecentSelCol = nColIndex;
608 AccSendSelectionEvent();
612 void ScCsvGrid::ToggleSelect( sal_uInt32 nColIndex )
614 Select( nColIndex, !IsSelected( nColIndex ) );
617 void ScCsvGrid::SelectRange( sal_uInt32 nColIndex1, sal_uInt32 nColIndex2, bool bSelect )
619 if( nColIndex1 == CSV_COLUMN_INVALID )
620 Select( nColIndex2 );
621 else if( nColIndex2 == CSV_COLUMN_INVALID )
622 Select( nColIndex1 );
623 else if( nColIndex1 > nColIndex2 )
625 SelectRange( nColIndex2, nColIndex1, bSelect );
626 if( bSelect )
627 mnRecentSelCol = nColIndex1;
629 else if( IsValidColumn( nColIndex1 ) && IsValidColumn( nColIndex2 ) )
631 for( sal_uInt32 nColIx = nColIndex1; nColIx <= nColIndex2; ++nColIx )
633 maColStates[ nColIx ].Select( bSelect );
634 ImplDrawColumnSelection( nColIx );
636 Repaint();
637 Execute( CSVCMD_EXPORTCOLUMNTYPE );
638 if( bSelect )
639 mnRecentSelCol = nColIndex1;
640 AccSendSelectionEvent();
644 void ScCsvGrid::SelectAll( bool bSelect )
646 SelectRange( 0, GetColumnCount() - 1, bSelect );
649 void ScCsvGrid::MoveCursor( sal_uInt32 nColIndex )
651 DisableRepaint();
652 if( IsValidColumn( nColIndex ) )
654 sal_Int32 nPosBeg = GetColumnPos( nColIndex );
655 sal_Int32 nPosEnd = GetColumnPos( nColIndex + 1 );
656 sal_Int32 nMinPos = std::max( nPosBeg - CSV_SCROLL_DIST, sal_Int32( 0 ) );
657 sal_Int32 nMaxPos = std::min( nPosEnd - GetVisPosCount() + CSV_SCROLL_DIST + sal_Int32( 1 ), nMinPos );
658 if( nPosBeg - CSV_SCROLL_DIST + 1 <= GetFirstVisPos() )
659 Execute( CSVCMD_SETPOSOFFSET, nMinPos );
660 else if( nPosEnd + CSV_SCROLL_DIST >= GetLastVisPos() )
661 Execute( CSVCMD_SETPOSOFFSET, nMaxPos );
663 Execute( CSVCMD_MOVEGRIDCURSOR, GetColumnPos( nColIndex ) );
664 EnableRepaint();
667 void ScCsvGrid::MoveCursorRel( ScMoveMode eDir )
669 if( GetFocusColumn() != CSV_COLUMN_INVALID )
671 switch( eDir )
673 case MOVE_FIRST:
674 MoveCursor( 0 );
675 break;
676 case MOVE_LAST:
677 MoveCursor( GetColumnCount() - 1 );
678 break;
679 case MOVE_PREV:
680 if( GetFocusColumn() > 0 )
681 MoveCursor( GetFocusColumn() - 1 );
682 break;
683 case MOVE_NEXT:
684 if( GetFocusColumn() < GetColumnCount() - 1 )
685 MoveCursor( GetFocusColumn() + 1 );
686 break;
687 default:
689 // added to avoid warnings
695 void ScCsvGrid::ImplClearSelection()
697 ::std::for_each( maColStates.begin(), maColStates.end(), Func_Select( false ) );
698 ImplDrawGridDev();
701 void ScCsvGrid::DoSelectAction( sal_uInt32 nColIndex, sal_uInt16 nModifier )
703 if( !(nModifier & KEY_MOD1) )
704 ImplClearSelection();
705 if( nModifier & KEY_SHIFT ) // SHIFT always expands
706 SelectRange( mnRecentSelCol, nColIndex );
707 else if( !(nModifier & KEY_MOD1) ) // no SHIFT/CTRL always selects 1 column
708 Select( nColIndex );
709 else if( IsTracking() ) // CTRL in tracking does not toggle
710 Select( nColIndex, mbMTSelecting );
711 else // CTRL only toggles
712 ToggleSelect( nColIndex );
713 Execute( CSVCMD_MOVEGRIDCURSOR, GetColumnPos( nColIndex ) );
717 // cell contents --------------------------------------------------------------
719 void ScCsvGrid::ImplSetTextLineSep(
720 sal_Int32 nLine, const OUString& rTextLine,
721 const String& rSepChars, sal_Unicode cTextSep, bool bMergeSep )
723 if( nLine < GetFirstVisLine() ) return;
725 sal_uInt32 nLineIx = nLine - GetFirstVisLine();
726 while( maTexts.size() <= nLineIx )
727 maTexts.push_back( StringVec() );
728 StringVec& rStrVec = maTexts[ nLineIx ];
729 rStrVec.clear();
731 // scan for separators
732 String aCellText;
733 const sal_Unicode* pSepChars = rSepChars.GetBuffer();
734 const sal_Unicode* pChar = rTextLine.getStr();
735 sal_uInt32 nColIx = 0;
737 while( *pChar && (nColIx < sal::static_int_cast<sal_uInt32>(CSV_MAXCOLCOUNT)) )
739 // scan for next cell text
740 bool bIsQuoted = false;
741 bool bOverflowCell = false;
742 pChar = ScImportExport::ScanNextFieldFromString( pChar, aCellText,
743 cTextSep, pSepChars, bMergeSep, bIsQuoted, bOverflowCell );
744 /* TODO: signal overflow somewhere in UI */
746 // update column width
747 sal_Int32 nWidth = std::max( CSV_MINCOLWIDTH, aCellText.Len() + sal_Int32( 1 ) );
748 if( IsValidColumn( nColIx ) )
750 // expand existing column
751 sal_Int32 nDiff = nWidth - GetColumnWidth( nColIx );
752 if( nDiff > 0 )
754 Execute( CSVCMD_SETPOSCOUNT, GetPosCount() + nDiff );
755 for( sal_uInt32 nSplitIx = GetColumnCount() - 1; nSplitIx > nColIx; --nSplitIx )
757 sal_Int32 nPos = maSplits[ nSplitIx ];
758 maSplits.Remove( nPos );
759 maSplits.Insert( nPos + nDiff );
763 else
765 // append new column
766 sal_Int32 nLastPos = GetPosCount();
767 Execute( CSVCMD_SETPOSCOUNT, nLastPos + nWidth );
768 ImplInsertSplit( nLastPos );
771 if( aCellText.Len() <= CSV_MAXSTRLEN )
772 rStrVec.push_back( aCellText );
773 else
774 rStrVec.push_back( aCellText.Copy( 0, CSV_MAXSTRLEN ) );
775 ++nColIx;
777 InvalidateGfx();
780 void ScCsvGrid::ImplSetTextLineFix( sal_Int32 nLine, const OUString& rTextLine )
782 if( nLine < GetFirstVisLine() ) return;
784 sal_Int32 nChars = rTextLine.getLength();
785 if( nChars > GetPosCount() )
786 Execute( CSVCMD_SETPOSCOUNT, nChars );
788 sal_uInt32 nLineIx = nLine - GetFirstVisLine();
789 while( maTexts.size() <= nLineIx )
790 maTexts.push_back( StringVec() );
792 StringVec& rStrVec = maTexts[ nLineIx ];
793 rStrVec.clear();
794 sal_uInt32 nColCount = GetColumnCount();
795 sal_Int32 nStrLen = rTextLine.getLength();
796 sal_Int32 nStrIx = 0;
797 for( sal_uInt32 nColIx = 0; (nColIx < nColCount) && (nStrIx < nStrLen); ++nColIx )
799 sal_Int32 nColWidth = GetColumnWidth( nColIx );
800 sal_Int32 nLen = std::min( std::min( nColWidth, static_cast<sal_Int32>(CSV_MAXSTRLEN) ), nStrLen - nStrIx);
801 rStrVec.push_back( rTextLine.copy( nStrIx, nLen ) );
802 nStrIx = nStrIx + nColWidth;
804 InvalidateGfx();
807 const String& ScCsvGrid::GetCellText( sal_uInt32 nColIndex, sal_Int32 nLine ) const
809 if( nLine < GetFirstVisLine() ) return EMPTY_STRING;
811 sal_uInt32 nLineIx = nLine - GetFirstVisLine();
812 if( nLineIx >= maTexts.size() ) return EMPTY_STRING;
814 const StringVec& rStrVec = maTexts[ nLineIx ];
815 if( nColIndex >= rStrVec.size() ) return EMPTY_STRING;
817 return rStrVec[ nColIndex ];
821 // event handling -------------------------------------------------------------
823 void ScCsvGrid::Resize()
825 ScCsvControl::Resize();
826 InitSizeData();
827 Execute( CSVCMD_UPDATECELLTEXTS );
830 void ScCsvGrid::GetFocus()
832 ScCsvControl::GetFocus();
833 Execute( CSVCMD_MOVEGRIDCURSOR, GetNoScrollCol( GetGridCursorPos() ) );
834 Repaint();
837 void ScCsvGrid::LoseFocus()
839 ScCsvControl::LoseFocus();
840 Repaint();
843 void ScCsvGrid::MouseButtonDown( const MouseEvent& rMEvt )
845 DisableRepaint();
846 if( !HasFocus() )
847 GrabFocus();
849 Point aPos( rMEvt.GetPosPixel() );
850 sal_uInt32 nColIx = GetColumnFromX( aPos.X() );
852 if( rMEvt.IsLeft() )
854 if( (GetFirstX() > aPos.X()) || (aPos.X() > GetLastX()) ) // in header column
856 if( aPos.Y() <= GetHdrHeight() )
857 SelectAll();
859 else if( IsValidColumn( nColIx ) )
861 DoSelectAction( nColIx, rMEvt.GetModifier() );
862 mnMTCurrCol = nColIx;
863 mbMTSelecting = IsSelected( nColIx );
864 StartTracking( STARTTRACK_BUTTONREPEAT );
867 EnableRepaint();
870 void ScCsvGrid::Tracking( const TrackingEvent& rTEvt )
872 if( rTEvt.IsTrackingEnded() || rTEvt.IsTrackingRepeat() )
874 DisableRepaint();
875 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
877 sal_Int32 nPos = (rMEvt.GetPosPixel().X() - GetFirstX()) / GetCharWidth() + GetFirstVisPos();
878 // on mouse tracking: keep position valid
879 nPos = std::max( std::min( nPos, GetPosCount() - sal_Int32( 1 ) ), sal_Int32( 0 ) );
880 Execute( CSVCMD_MAKEPOSVISIBLE, nPos );
882 sal_uInt32 nColIx = GetColumnFromPos( nPos );
883 if( mnMTCurrCol != nColIx )
885 DoSelectAction( nColIx, rMEvt.GetModifier() );
886 mnMTCurrCol = nColIx;
888 EnableRepaint();
892 void ScCsvGrid::KeyInput( const KeyEvent& rKEvt )
894 const KeyCode& rKCode = rKEvt.GetKeyCode();
895 sal_uInt16 nCode = rKCode.GetCode();
896 bool bShift = rKCode.IsShift() == sal_True;
897 bool bMod1 = rKCode.IsMod1() == sal_True;
899 if( !rKCode.IsMod2() )
901 ScMoveMode eHDir = GetHorzDirection( nCode, !bMod1 );
902 ScMoveMode eVDir = GetVertDirection( nCode, bMod1 );
904 if( eHDir != MOVE_NONE )
906 DisableRepaint();
907 MoveCursorRel( eHDir );
908 if( !bMod1 )
909 ImplClearSelection();
910 if( bShift )
911 SelectRange( mnRecentSelCol, GetFocusColumn() );
912 else if( !bMod1 )
913 Select( GetFocusColumn() );
914 EnableRepaint();
916 else if( eVDir != MOVE_NONE )
917 ScrollVertRel( eVDir );
918 else if( nCode == KEY_SPACE )
920 if( !bMod1 )
921 ImplClearSelection();
922 if( bShift )
923 SelectRange( mnRecentSelCol, GetFocusColumn() );
924 else if( bMod1 )
925 ToggleSelect( GetFocusColumn() );
926 else
927 Select( GetFocusColumn() );
929 else if( !bShift && bMod1 )
931 if( nCode == KEY_A )
932 SelectAll();
933 else if( (KEY_1 <= nCode) && (nCode <= KEY_9) )
935 sal_uInt32 nType = nCode - KEY_1;
936 if( nType < maTypeNames.size() )
937 Execute( CSVCMD_SETCOLUMNTYPE, nType );
942 if( rKCode.GetGroup() != KEYGROUP_CURSOR )
943 ScCsvControl::KeyInput( rKEvt );
946 void ScCsvGrid::Command( const CommandEvent& rCEvt )
948 switch( rCEvt.GetCommand() )
950 case COMMAND_CONTEXTMENU:
952 if( rCEvt.IsMouseEvent() )
954 Point aPos( rCEvt.GetMousePosPixel() );
955 sal_uInt32 nColIx = GetColumnFromX( aPos.X() );
956 if( IsValidColumn( nColIx ) && (GetFirstX() <= aPos.X()) && (aPos.X() <= GetLastX()) )
958 if( !IsSelected( nColIx ) )
959 DoSelectAction( nColIx, 0 ); // focus & select
960 ExecutePopup( aPos );
963 else
965 sal_uInt32 nColIx = GetFocusColumn();
966 if( !IsSelected( nColIx ) )
967 Select( nColIx );
968 sal_Int32 nX1 = std::max( GetColumnX( nColIx ), GetFirstX() );
969 sal_Int32 nX2 = std::min( GetColumnX( nColIx + 1 ), GetWidth() );
970 ExecutePopup( Point( (nX1 + nX2) / 2, GetHeight() / 2 ) );
973 break;
974 case COMMAND_WHEEL:
976 Point aPoint;
977 Rectangle aRect( aPoint, maWinSize );
978 if( aRect.IsInside( rCEvt.GetMousePosPixel() ) )
980 const CommandWheelData* pData = rCEvt.GetWheelData();
981 if( pData && (pData->GetMode() == COMMAND_WHEEL_SCROLL) && !pData->IsHorz() )
982 Execute( CSVCMD_SETLINEOFFSET, GetFirstVisLine() - pData->GetNotchDelta() );
985 break;
986 default:
987 ScCsvControl::Command( rCEvt );
991 void ScCsvGrid::DataChanged( const DataChangedEvent& rDCEvt )
993 if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
995 InitColors();
996 InitFonts();
997 UpdateLayoutData();
998 Execute( CSVCMD_UPDATECELLTEXTS );
1000 ScCsvControl::DataChanged( rDCEvt );
1003 void ScCsvGrid::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 )
1005 InitColors();
1006 Repaint();
1010 // painting -------------------------------------------------------------------
1012 void ScCsvGrid::Paint( const Rectangle& )
1014 Repaint();
1017 void ScCsvGrid::ImplRedraw()
1019 if( IsVisible() )
1021 if( !IsValidGfx() )
1023 ValidateGfx();
1024 ImplDrawBackgrDev();
1025 ImplDrawGridDev();
1027 DrawOutDev( Point(), maWinSize, Point(), maWinSize, maGridDev );
1028 ImplDrawTrackingRect( GetFocusColumn() );
1032 EditEngine* ScCsvGrid::GetEditEngine()
1034 return mpEditEngine.get();
1037 void ScCsvGrid::ImplSetColumnClipRegion( OutputDevice& rOutDev, sal_uInt32 nColIndex )
1039 rOutDev.SetClipRegion( Region( Rectangle(
1040 std::max( GetColumnX( nColIndex ), GetFirstX() ) + 1, 0,
1041 std::min( GetColumnX( nColIndex + 1 ), GetLastX() ), GetHeight() - 1 ) ) );
1044 void ScCsvGrid::ImplDrawColumnHeader( OutputDevice& rOutDev, sal_uInt32 nColIndex, Color aFillColor )
1046 sal_Int32 nX1 = GetColumnX( nColIndex ) + 1;
1047 sal_Int32 nX2 = GetColumnX( nColIndex + 1 );
1048 sal_Int32 nHdrHt = GetHdrHeight();
1050 rOutDev.SetLineColor();
1051 rOutDev.SetFillColor( aFillColor );
1052 rOutDev.DrawRect( Rectangle( nX1, 0, nX2, nHdrHt ) );
1054 rOutDev.SetFont( maHeaderFont );
1055 rOutDev.SetTextColor( maHeaderTextColor );
1056 rOutDev.SetTextFillColor();
1057 rOutDev.DrawText( Point( nX1 + 1, 0 ), GetColumnTypeName( nColIndex ) );
1059 rOutDev.SetLineColor( maHeaderGridColor );
1060 rOutDev.DrawLine( Point( nX1, nHdrHt ), Point( nX2, nHdrHt ) );
1061 rOutDev.DrawLine( Point( nX2, 0 ), Point( nX2, nHdrHt ) );
1064 void ScCsvGrid::ImplDrawCellText( const Point& rPos, const String& rText )
1066 String aPlainText( rText );
1067 aPlainText.SearchAndReplaceAll( '\t', ' ' );
1068 aPlainText.SearchAndReplaceAll( '\n', ' ' );
1069 mpEditEngine->SetPaperSize( maEdEngSize );
1071 /* #i60296# If string contains mixed script types, the space character
1072 U+0020 may be drawn with a wrong width (from non-fixed-width Asian or
1073 Complex font). Now we draw every non-space portion separately. */
1074 xub_StrLen nTokenCount = comphelper::string::getTokenCount(aPlainText, ' ');
1075 sal_Int32 nCharIxInt = 0;
1076 for( xub_StrLen nToken = 0; nToken < nTokenCount; ++nToken )
1078 sal_Int32 nBeginIx = nCharIxInt;
1079 String aToken = aPlainText.GetToken( 0, ' ', nCharIxInt );
1080 if( aToken.Len() > 0 )
1082 sal_Int32 nX = rPos.X() + GetCharWidth() * nBeginIx;
1083 mpEditEngine->SetText( aToken );
1084 mpEditEngine->Draw( &maBackgrDev, Point( nX, rPos.Y() ) );
1088 xub_StrLen nCharIx = 0;
1089 while( (nCharIx = rText.Search( '\t', nCharIx )) != STRING_NOTFOUND )
1091 sal_Int32 nX1 = rPos.X() + GetCharWidth() * nCharIx;
1092 sal_Int32 nX2 = nX1 + GetCharWidth() - 2;
1093 sal_Int32 nY = rPos.Y() + GetLineHeight() / 2;
1094 Color aColor( maTextColor );
1095 maBackgrDev.SetLineColor( aColor );
1096 maBackgrDev.DrawLine( Point( nX1, nY ), Point( nX2, nY ) );
1097 maBackgrDev.DrawLine( Point( nX2 - 2, nY - 2 ), Point( nX2, nY ) );
1098 maBackgrDev.DrawLine( Point( nX2 - 2, nY + 2 ), Point( nX2, nY ) );
1099 ++nCharIx;
1101 nCharIx = 0;
1102 while( (nCharIx = rText.Search( '\n', nCharIx )) != STRING_NOTFOUND )
1104 sal_Int32 nX1 = rPos.X() + GetCharWidth() * nCharIx;
1105 sal_Int32 nX2 = nX1 + GetCharWidth() - 2;
1106 sal_Int32 nY = rPos.Y() + GetLineHeight() / 2;
1107 Color aColor( maTextColor );
1108 maBackgrDev.SetLineColor( aColor );
1109 maBackgrDev.DrawLine( Point( nX1, nY ), Point( nX2, nY ) );
1110 maBackgrDev.DrawLine( Point( nX1 + 2, nY - 2 ), Point( nX1, nY ) );
1111 maBackgrDev.DrawLine( Point( nX1 + 2, nY + 2 ), Point( nX1, nY ) );
1112 maBackgrDev.DrawLine( Point( nX2, nY - 2 ), Point( nX2, nY ) );
1113 ++nCharIx;
1117 void ScCsvGrid::ImplDrawFirstLineSep( bool bSet )
1119 if( IsVisibleLine( mnFirstImpLine ) && (mnFirstImpLine != GetFirstVisLine() ) )
1121 sal_Int32 nY = GetY( mnFirstImpLine );
1122 sal_Int32 nX = std::min( GetColumnX( GetLastVisColumn() + 1 ), GetLastX() );
1123 maBackgrDev.SetLineColor( bSet ? maGridPBColor : maGridColor );
1124 maBackgrDev.DrawLine( Point( GetFirstX() + 1, nY ), Point( nX, nY ) );
1128 void ScCsvGrid::ImplDrawColumnBackgr( sal_uInt32 nColIndex )
1130 if( !IsVisibleColumn( nColIndex ) )
1131 return;
1133 ImplSetColumnClipRegion( maBackgrDev, nColIndex );
1135 // grid
1136 maBackgrDev.SetLineColor();
1137 maBackgrDev.SetFillColor( maBackColor );
1138 sal_Int32 nX1 = GetColumnX( nColIndex ) + 1;
1139 sal_Int32 nX2 = GetColumnX( nColIndex + 1 );
1140 sal_Int32 nY2 = GetY( GetLastVisLine() + 1 );
1141 sal_Int32 nHdrHt = GetHdrHeight();
1142 Rectangle aRect( nX1, nHdrHt, nX2, nY2 );
1143 maBackgrDev.DrawRect( aRect );
1144 maBackgrDev.SetLineColor( maGridColor );
1145 maBackgrDev.DrawGrid( aRect, Size( 1, GetLineHeight() ), GRID_HORZLINES );
1146 maBackgrDev.DrawLine( Point( nX2, nHdrHt ), Point( nX2, nY2 ) );
1147 ImplDrawFirstLineSep( true );
1149 // cell texts
1150 mpEditEngine->SetDefaultItem( SvxColorItem( maTextColor, EE_CHAR_COLOR ) );
1151 size_t nLineCount = ::std::min( static_cast< size_t >( GetLastVisLine() - GetFirstVisLine() + 1 ), maTexts.size() );
1152 // #i67432# cut string to avoid edit engine performance problems with very large strings
1153 sal_Int32 nFirstVisPos = ::std::max( GetColumnPos( nColIndex ), GetFirstVisPos() );
1154 sal_Int32 nLastVisPos = ::std::min( GetColumnPos( nColIndex + 1 ), GetLastVisPos() );
1155 xub_StrLen nStrPos = static_cast< xub_StrLen >( nFirstVisPos - GetColumnPos( nColIndex ) );
1156 xub_StrLen nStrLen = static_cast< xub_StrLen >( nLastVisPos - nFirstVisPos + 1 );
1157 sal_Int32 nStrX = GetX( nFirstVisPos );
1158 for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1160 StringVec& rStrVec = maTexts[ nLine ];
1161 if( (nColIndex < rStrVec.size()) && (rStrVec[ nColIndex ].Len() > nStrPos) )
1163 String aText( rStrVec[ nColIndex ], nStrPos, nStrLen );
1164 ImplDrawCellText( Point( nStrX, GetY( GetFirstVisLine() + nLine ) ), aText );
1168 // header
1169 ImplDrawColumnHeader( maBackgrDev, nColIndex, maHeaderBackColor );
1171 maBackgrDev.SetClipRegion();
1174 void ScCsvGrid::ImplDrawRowHeaders()
1176 maBackgrDev.SetLineColor();
1177 maBackgrDev.SetFillColor( maAppBackColor );
1178 Point aPoint( GetHdrX(), 0 );
1179 Rectangle aRect( aPoint, Size( GetHdrWidth() + 1, GetHeight() ) );
1180 maBackgrDev.DrawRect( aRect );
1182 maBackgrDev.SetFillColor( maHeaderBackColor );
1183 aRect.Bottom() = GetY( GetLastVisLine() + 1 );
1184 maBackgrDev.DrawRect( aRect );
1186 // line numbers
1187 maBackgrDev.SetFont( maHeaderFont );
1188 maBackgrDev.SetTextColor( maHeaderTextColor );
1189 maBackgrDev.SetTextFillColor();
1190 sal_Int32 nLastLine = GetLastVisLine();
1191 for( sal_Int32 nLine = GetFirstVisLine(); nLine <= nLastLine; ++nLine )
1193 String aText( OUString::number( nLine + 1 ) );
1194 sal_Int32 nX = GetHdrX() + (GetHdrWidth() - maBackgrDev.GetTextWidth( aText )) / 2;
1195 maBackgrDev.DrawText( Point( nX, GetY( nLine ) ), aText );
1198 // grid
1199 maBackgrDev.SetLineColor( maHeaderGridColor );
1200 if( IsRTL() )
1202 maBackgrDev.DrawLine( Point( 0, 0 ), Point( 0, GetHeight() - 1 ) );
1203 maBackgrDev.DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
1205 else
1206 maBackgrDev.DrawLine( aRect.TopRight(), aRect.BottomRight() );
1207 aRect.Top() = GetHdrHeight();
1208 maBackgrDev.DrawGrid( aRect, Size( 1, GetLineHeight() ), GRID_HORZLINES );
1211 void ScCsvGrid::ImplDrawBackgrDev()
1213 maBackgrDev.SetLineColor();
1214 maBackgrDev.SetFillColor( maAppBackColor );
1215 maBackgrDev.DrawRect( Rectangle(
1216 Point( GetFirstX() + 1, 0 ), Size( GetWidth() - GetHdrWidth(), GetHeight() ) ) );
1218 sal_uInt32 nLastCol = GetLastVisColumn();
1219 if (nLastCol == CSV_COLUMN_INVALID)
1220 return;
1221 for( sal_uInt32 nColIx = GetFirstVisColumn(); nColIx <= nLastCol; ++nColIx )
1222 ImplDrawColumnBackgr( nColIx );
1224 ImplDrawRowHeaders();
1227 void ScCsvGrid::ImplDrawColumnSelection( sal_uInt32 nColIndex )
1229 ImplInvertCursor( GetRulerCursorPos() );
1230 ImplSetColumnClipRegion( maGridDev, nColIndex );
1231 maGridDev.DrawOutDev( Point(), maWinSize, Point(), maWinSize, maBackgrDev );
1233 if( IsSelected( nColIndex ) )
1235 sal_Int32 nX1 = GetColumnX( nColIndex ) + 1;
1236 sal_Int32 nX2 = GetColumnX( nColIndex + 1 );
1238 // header
1239 Rectangle aRect( nX1, 0, nX2, GetHdrHeight() );
1240 maGridDev.SetLineColor();
1241 if( maHeaderBackColor.IsDark() )
1242 // redraw with light gray background in dark mode
1243 ImplDrawColumnHeader( maGridDev, nColIndex, COL_LIGHTGRAY );
1244 else
1246 // use transparent active color
1247 maGridDev.SetFillColor( maSelectColor );
1248 maGridDev.DrawTransparent( PolyPolygon( Polygon( aRect ) ), CSV_HDR_TRANSPARENCY );
1251 // column selection
1252 aRect = Rectangle( nX1, GetHdrHeight() + 1, nX2, GetY( GetLastVisLine() + 1 ) - 1 );
1253 ImplInvertRect( maGridDev, aRect );
1256 maGridDev.SetClipRegion();
1257 ImplInvertCursor( GetRulerCursorPos() );
1260 void ScCsvGrid::ImplDrawGridDev()
1262 maGridDev.DrawOutDev( Point(), maWinSize, Point(), maWinSize, maBackgrDev );
1263 sal_uInt32 nLastCol = GetLastVisColumn();
1264 if (nLastCol == CSV_COLUMN_INVALID)
1265 return;
1266 for( sal_uInt32 nColIx = GetFirstVisColumn(); nColIx <= nLastCol; ++nColIx )
1267 ImplDrawColumnSelection( nColIx );
1270 void ScCsvGrid::ImplDrawColumn( sal_uInt32 nColIndex )
1272 ImplDrawColumnBackgr( nColIndex );
1273 ImplDrawColumnSelection( nColIndex );
1276 void ScCsvGrid::ImplDrawHorzScrolled( sal_Int32 nOldPos )
1278 sal_Int32 nPos = GetFirstVisPos();
1279 if( !IsValidGfx() || (nPos == nOldPos) )
1280 return;
1281 if( std::abs( nPos - nOldPos ) > GetVisPosCount() / 2 )
1283 ImplDrawBackgrDev();
1284 ImplDrawGridDev();
1285 return;
1288 Point aSrc, aDest;
1289 sal_uInt32 nFirstColIx, nLastColIx;
1290 if( nPos < nOldPos )
1292 aSrc = Point( GetFirstX() + 1, 0 );
1293 aDest = Point( GetFirstX() + GetCharWidth() * (nOldPos - nPos) + 1, 0 );
1294 nFirstColIx = GetColumnFromPos( nPos );
1295 nLastColIx = GetColumnFromPos( nOldPos );
1297 else
1299 aSrc = Point( GetFirstX() + GetCharWidth() * (nPos - nOldPos) + 1, 0 );
1300 aDest = Point( GetFirstX() + 1, 0 );
1301 nFirstColIx = GetColumnFromPos( std::min( nOldPos + GetVisPosCount(), GetPosCount() ) - 1 );
1302 nLastColIx = GetColumnFromPos( std::min( nPos + GetVisPosCount(), GetPosCount() ) - 1 );
1305 ImplInvertCursor( GetRulerCursorPos() + (nPos - nOldPos) );
1306 Rectangle aRectangle( GetFirstX(), 0, GetLastX(), GetHeight() - 1 );
1307 Region aClipReg( aRectangle );
1308 maBackgrDev.SetClipRegion( aClipReg );
1309 maBackgrDev.CopyArea( aDest, aSrc, maWinSize );
1310 maBackgrDev.SetClipRegion();
1311 maGridDev.SetClipRegion( aClipReg );
1312 maGridDev.CopyArea( aDest, aSrc, maWinSize );
1313 maGridDev.SetClipRegion();
1314 ImplInvertCursor( GetRulerCursorPos() );
1316 for( sal_uInt32 nColIx = nFirstColIx; nColIx <= nLastColIx; ++nColIx )
1317 ImplDrawColumn( nColIx );
1319 sal_Int32 nLastX = GetX( GetPosCount() ) + 1;
1320 if( nLastX <= GetLastX() )
1322 Rectangle aRect( nLastX, 0, GetLastX(), GetHeight() - 1 );
1323 maBackgrDev.SetLineColor();
1324 maBackgrDev.SetFillColor( maAppBackColor );
1325 maBackgrDev.DrawRect( aRect );
1326 maGridDev.SetLineColor();
1327 maGridDev.SetFillColor( maAppBackColor );
1328 maGridDev.DrawRect( aRect );
1332 void ScCsvGrid::ImplInvertCursor( sal_Int32 nPos )
1334 if( IsVisibleSplitPos( nPos ) )
1336 sal_Int32 nX = GetX( nPos ) - 1;
1337 Rectangle aRect( Point( nX, 0 ), Size( 3, GetHdrHeight() ) );
1338 ImplInvertRect( maGridDev, aRect );
1339 aRect.Top() = GetHdrHeight() + 1;
1340 aRect.Bottom() = GetY( GetLastVisLine() + 1 );
1341 ImplInvertRect( maGridDev, aRect );
1345 void ScCsvGrid::ImplDrawTrackingRect( sal_uInt32 nColIndex )
1347 if( HasFocus() && IsVisibleColumn( nColIndex ) )
1349 sal_Int32 nX1 = std::max( GetColumnX( nColIndex ), GetFirstX() ) + 1;
1350 sal_Int32 nX2 = std::min( GetColumnX( nColIndex + 1 ) - sal_Int32( 1 ), GetLastX() );
1351 sal_Int32 nY2 = std::min( GetY( GetLastVisLine() + 1 ), GetHeight() ) - 1;
1352 InvertTracking( Rectangle( nX1, 0, nX2, nY2 ), SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
1357 // accessibility ==============================================================
1359 ScAccessibleCsvControl* ScCsvGrid::ImplCreateAccessible()
1361 std::auto_ptr<ScAccessibleCsvControl> pControl(new ScAccessibleCsvGrid( *this ));
1362 pControl->Init();
1363 return pControl.release();
1367 // ============================================================================
1369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */