1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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>
31 #include "asciiopt.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 // ============================================================================
53 inline Func_SetType( sal_Int32 nType
) : mnType( nType
) {}
54 inline void operator()( ScCsvColState
& rState
) const
55 { rState
.mnType
= mnType
; }
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
),
72 mpEditEngine( new ScEditEngineDefaulter( EditEngine::CreatePool(), true ) ),
73 maHeaderFont( GetFont() ),
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
90 ScCsvGrid::~ScCsvGrid()
92 OSL_ENSURE(mpColorConfig
, "the object hasn't been initialized properly");
94 mpColorConfig
->RemoveListener(this);
100 OSL_PRECOND(!mpColorConfig
, "the object has already been initialized");
101 mpColorConfig
= &SC_MOD()->GetColorConfig();
103 mpColorConfig
->AddListener(this);
106 // common grid handling -------------------------------------------------------
108 void ScCsvGrid::UpdateLayoutData()
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 );
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;
136 if( nDiff
& CSV_DIFF_RULERCURSOR
)
138 ImplInvertCursor( rOldData
.mnPosCursor
);
139 ImplInvertCursor( GetRulerCursorPos() );
142 if( nDiff
& CSV_DIFF_POSCOUNT
)
144 if( GetPosCount() < rOldData
.mnPosCount
)
147 maSplits
.RemoveRange( GetPosCount(), rOldData
.mnPosCount
);
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
);
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
)
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 );
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;
201 void ScCsvGrid::InitColors()
203 OSL_PRECOND(mpColorConfig
, "the object hasn't been initialized properly");
204 if ( !mpColorConfig
)
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();
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. */
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
);
261 void ScCsvGrid::InitSizeData()
263 maWinSize
= GetSizePixel();
264 maBackgrDev
.SetOutputSizePixel( maWinSize
);
265 maGridDev
.SetOutputSizePixel( maWinSize
);
270 // split handling -------------------------------------------------------------
272 void ScCsvGrid::InsertSplit( sal_Int32 nPos
)
274 if( ImplInsertSplit( nPos
) )
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
287 void ScCsvGrid::RemoveSplit( sal_Int32 nPos
)
289 if( ImplRemoveSplit( nPos
) )
292 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
293 Execute( CSVCMD_UPDATECELLTEXTS
);
294 ImplDrawColumn( GetColumnFromPos( nPos
) );
295 ValidateGfx(); // performance: do not redraw all columns
300 void ScCsvGrid::MoveSplit( sal_Int32 nPos
, sal_Int32 nNewPos
)
302 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
303 if( nColIx
!= CSV_COLUMN_INVALID
)
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
);
319 ImplRemoveSplit( nPos
);
320 ImplInsertSplit( nNewPos
);
321 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
322 Execute( CSVCMD_UPDATECELLTEXTS
);
328 void ScCsvGrid::RemoveAllSplits()
332 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
333 Execute( CSVCMD_UPDATECELLTEXTS
);
337 void ScCsvGrid::SetSplits( const ScCsvSplits
& rSplits
)
341 sal_uInt32 nCount
= rSplits
.Count();
342 for( sal_uInt32 nIx
= 0; nIx
< nCount
; ++nIx
)
343 maSplits
.Insert( rSplits
[ nIx
] );
345 maColStates
.resize( maSplits
.Count() - 1 );
346 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
347 Execute( CSVCMD_UPDATECELLTEXTS
);
351 bool ScCsvGrid::ImplInsertSplit( sal_Int32 nPos
)
353 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
354 bool bRet
= (nColIx
< GetColumnCount()) && maSplits
.Insert( nPos
);
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
);
366 bool ScCsvGrid::ImplRemoveSplit( sal_Int32 nPos
)
368 bool bRet
= maSplits
.Remove( nPos
);
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
);
381 void ScCsvGrid::ImplClearSplits()
383 sal_uInt32 nColumns
= GetColumnCount();
385 maSplits
.Insert( 0 );
386 maSplits
.Insert( GetPosCount() );
387 maColStates
.resize( 1 );
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
);
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
);
484 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
488 void ScCsvGrid::SetTypeNames( const StringVec
& rTypeNames
)
490 OSL_ENSURE( !rTypeNames
.empty(), "ScCsvGrid::SetTypeNames - vector is empty" );
491 maTypeNames
= rTypeNames
;
495 sal_uInt32 nCount
= maTypeNames
.size();
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();
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;
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
) )
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
);
605 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
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
);
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
);
637 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
639 mnRecentSelCol
= nColIndex1
;
640 AccSendSelectionEvent();
644 void ScCsvGrid::SelectAll( bool bSelect
)
646 SelectRange( 0, GetColumnCount() - 1, bSelect
);
649 void ScCsvGrid::MoveCursor( sal_uInt32 nColIndex
)
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
) );
667 void ScCsvGrid::MoveCursorRel( ScMoveMode eDir
)
669 if( GetFocusColumn() != CSV_COLUMN_INVALID
)
677 MoveCursor( GetColumnCount() - 1 );
680 if( GetFocusColumn() > 0 )
681 MoveCursor( GetFocusColumn() - 1 );
684 if( GetFocusColumn() < GetColumnCount() - 1 )
685 MoveCursor( GetFocusColumn() + 1 );
689 // added to avoid warnings
695 void ScCsvGrid::ImplClearSelection()
697 ::std::for_each( maColStates
.begin(), maColStates
.end(), Func_Select( false ) );
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
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
];
731 // scan for separators
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
);
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
);
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
);
774 rStrVec
.push_back( aCellText
.Copy( 0, CSV_MAXSTRLEN
) );
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
];
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
;
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();
827 Execute( CSVCMD_UPDATECELLTEXTS
);
830 void ScCsvGrid::GetFocus()
832 ScCsvControl::GetFocus();
833 Execute( CSVCMD_MOVEGRIDCURSOR
, GetNoScrollCol( GetGridCursorPos() ) );
837 void ScCsvGrid::LoseFocus()
839 ScCsvControl::LoseFocus();
843 void ScCsvGrid::MouseButtonDown( const MouseEvent
& rMEvt
)
849 Point
aPos( rMEvt
.GetPosPixel() );
850 sal_uInt32 nColIx
= GetColumnFromX( aPos
.X() );
854 if( (GetFirstX() > aPos
.X()) || (aPos
.X() > GetLastX()) ) // in header column
856 if( aPos
.Y() <= GetHdrHeight() )
859 else if( IsValidColumn( nColIx
) )
861 DoSelectAction( nColIx
, rMEvt
.GetModifier() );
862 mnMTCurrCol
= nColIx
;
863 mbMTSelecting
= IsSelected( nColIx
);
864 StartTracking( STARTTRACK_BUTTONREPEAT
);
870 void ScCsvGrid::Tracking( const TrackingEvent
& rTEvt
)
872 if( rTEvt
.IsTrackingEnded() || rTEvt
.IsTrackingRepeat() )
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
;
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
)
907 MoveCursorRel( eHDir
);
909 ImplClearSelection();
911 SelectRange( mnRecentSelCol
, GetFocusColumn() );
913 Select( GetFocusColumn() );
916 else if( eVDir
!= MOVE_NONE
)
917 ScrollVertRel( eVDir
);
918 else if( nCode
== KEY_SPACE
)
921 ImplClearSelection();
923 SelectRange( mnRecentSelCol
, GetFocusColumn() );
925 ToggleSelect( GetFocusColumn() );
927 Select( GetFocusColumn() );
929 else if( !bShift
&& bMod1
)
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
);
965 sal_uInt32 nColIx
= GetFocusColumn();
966 if( !IsSelected( 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 ) );
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() );
987 ScCsvControl::Command( rCEvt
);
991 void ScCsvGrid::DataChanged( const DataChangedEvent
& rDCEvt
)
993 if( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
998 Execute( CSVCMD_UPDATECELLTEXTS
);
1000 ScCsvControl::DataChanged( rDCEvt
);
1003 void ScCsvGrid::ConfigurationChanged( utl::ConfigurationBroadcaster
*, sal_uInt32
)
1010 // painting -------------------------------------------------------------------
1012 void ScCsvGrid::Paint( const Rectangle
& )
1017 void ScCsvGrid::ImplRedraw()
1024 ImplDrawBackgrDev();
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
) );
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
) );
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
) )
1133 ImplSetColumnClipRegion( maBackgrDev
, nColIndex
);
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 );
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
);
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
);
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
);
1199 maBackgrDev
.SetLineColor( maHeaderGridColor
);
1202 maBackgrDev
.DrawLine( Point( 0, 0 ), Point( 0, GetHeight() - 1 ) );
1203 maBackgrDev
.DrawLine( aRect
.TopLeft(), aRect
.BottomLeft() );
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
)
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 );
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
);
1246 // use transparent active color
1247 maGridDev
.SetFillColor( maSelectColor
);
1248 maGridDev
.DrawTransparent( PolyPolygon( Polygon( aRect
) ), CSV_HDR_TRANSPARENCY
);
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
)
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
) )
1281 if( std::abs( nPos
- nOldPos
) > GetVisPosCount() / 2 )
1283 ImplDrawBackgrDev();
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
);
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 ));
1363 return pControl
.release();
1367 // ============================================================================
1369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */