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>
38 #include <vcl/settings.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 ***
50 inline Func_SetType( sal_Int32 nType
) : mnType( nType
) {}
51 inline void operator()( ScCsvColState
& rState
) const
52 { rState
.mnType
= mnType
; }
58 inline Func_Select( bool bSelect
) : mbSelect( bSelect
) {}
59 inline void operator()( ScCsvColState
& rState
) const
60 { rState
.Select( mbSelect
); }
63 ScCsvGrid::ScCsvGrid( ScCsvControl
& rParent
) :
64 ScCsvControl( rParent
),
65 mpBackgrDev( VclPtr
<VirtualDevice
>::Create() ),
66 mpGridDev( VclPtr
<VirtualDevice
>::Create() ),
68 mpEditEngine( new ScEditEngineDefaulter( EditEngine::CreatePool(), true ) ),
69 maHeaderFont( GetFont() ),
73 mnRecentSelCol( CSV_COLUMN_INVALID
),
74 mnMTCurrCol( SAL_MAX_UINT32
),
75 mbMTSelecting( false )
77 mpEditEngine
->SetRefDevice( mpBackgrDev
.get() );
78 mpEditEngine
->SetRefMapMode( MapMode( MAP_PIXEL
) );
79 maEdEngSize
= mpEditEngine
->GetPaperSize();
81 maPopup
.SetMenuFlags( maPopup
.GetMenuFlags() | MenuFlags::NoAutoMnemonics
);
83 EnableRTL( false ); // RTL
88 ScCsvGrid::~ScCsvGrid()
93 void ScCsvGrid::dispose()
95 OSL_ENSURE(mpColorConfig
, "the object hasn't been initialized properly");
97 mpColorConfig
->RemoveListener(this);
98 mpBackgrDev
.disposeAndClear();
99 mpGridDev
.disposeAndClear();
100 ScCsvControl::dispose();
106 OSL_PRECOND(!mpColorConfig
, "the object has already been initialized");
107 mpColorConfig
= &SC_MOD()->GetColorConfig();
109 mpColorConfig
->AddListener(this);
112 // common grid handling -------------------------------------------------------
114 void ScCsvGrid::UpdateLayoutData()
117 SetFont( maMonoFont
);
118 Execute( CSVCMD_SETCHARWIDTH
, GetTextWidth( OUString( 'X' ) ) );
119 Execute( CSVCMD_SETLINEHEIGHT
, GetTextHeight() + 1 );
120 SetFont( maHeaderFont
);
121 Execute( CSVCMD_SETHDRHEIGHT
, GetTextHeight() + 1 );
126 void ScCsvGrid::UpdateOffsetX()
128 sal_Int32 nLastLine
= GetLastVisLine() + 1;
129 sal_Int32 nDigits
= 2;
130 while( nLastLine
/= 10 ) ++nDigits
;
131 nDigits
= std::max( nDigits
, sal_Int32( 3 ) );
132 Execute( CSVCMD_SETHDRWIDTH
, GetTextWidth( OUString( '0' ) ) * nDigits
);
135 void ScCsvGrid::ApplyLayout( const ScCsvLayoutData
& rOldData
)
137 ScCsvDiff nDiff
= GetLayoutData().GetDiff( rOldData
);
138 if( nDiff
== CSV_DIFF_EQUAL
) return;
142 if( nDiff
& CSV_DIFF_RULERCURSOR
)
144 ImplInvertCursor( rOldData
.mnPosCursor
);
145 ImplInvertCursor( GetRulerCursorPos() );
148 if( nDiff
& CSV_DIFF_POSCOUNT
)
150 if( GetPosCount() < rOldData
.mnPosCount
)
153 maSplits
.RemoveRange( GetPosCount(), rOldData
.mnPosCount
);
156 maSplits
.Remove( rOldData
.mnPosCount
);
157 maSplits
.Insert( GetPosCount() );
158 maColStates
.resize( maSplits
.Count() - 1 );
161 if( nDiff
& CSV_DIFF_LINEOFFSET
)
163 Execute( CSVCMD_UPDATECELLTEXTS
);
167 ScCsvDiff nHVDiff
= nDiff
& (CSV_DIFF_HORIZONTAL
| CSV_DIFF_VERTICAL
);
168 if( nHVDiff
== CSV_DIFF_POSOFFSET
)
169 ImplDrawHorzScrolled( rOldData
.mnPosOffset
);
170 else if( nHVDiff
!= CSV_DIFF_EQUAL
)
175 if( nDiff
& (CSV_DIFF_POSOFFSET
| CSV_DIFF_LINEOFFSET
) )
176 AccSendVisibleEvent();
179 void ScCsvGrid::SetFirstImportedLine( sal_Int32 nLine
)
181 ImplDrawFirstLineSep( false );
182 mnFirstImpLine
= nLine
;
183 ImplDrawFirstLineSep( true );
188 sal_Int32
ScCsvGrid::GetNoScrollCol( sal_Int32 nPos
) const
190 sal_Int32 nNewPos
= nPos
;
191 if( nNewPos
!= CSV_POS_INVALID
)
193 if( nNewPos
< GetFirstVisPos() + CSV_SCROLL_DIST
)
195 sal_Int32 nScroll
= (GetFirstVisPos() > 0) ? CSV_SCROLL_DIST
: 0;
196 nNewPos
= GetFirstVisPos() + nScroll
;
198 else if( nNewPos
> GetLastVisPos() - CSV_SCROLL_DIST
- 1L )
200 sal_Int32 nScroll
= (GetFirstVisPos() < GetMaxPosOffset()) ? CSV_SCROLL_DIST
: 0;
201 nNewPos
= GetLastVisPos() - nScroll
- 1;
207 void ScCsvGrid::InitColors()
209 OSL_PRECOND(mpColorConfig
, "the object hasn't been initialized properly");
210 if ( !mpColorConfig
)
212 maBackColor
.SetColor( static_cast< sal_uInt32
>( mpColorConfig
->GetColorValue( ::svtools::DOCCOLOR
).nColor
) );
213 maGridColor
.SetColor( static_cast< sal_uInt32
>( mpColorConfig
->GetColorValue( ::svtools::CALCGRID
).nColor
) );
214 maGridPBColor
.SetColor( static_cast< sal_uInt32
>( mpColorConfig
->GetColorValue( ::svtools::CALCPAGEBREAK
).nColor
) );
215 maAppBackColor
.SetColor( static_cast< sal_uInt32
>( mpColorConfig
->GetColorValue( ::svtools::APPBACKGROUND
).nColor
) );
216 maTextColor
.SetColor( static_cast< sal_uInt32
>( mpColorConfig
->GetColorValue( ::svtools::FONTCOLOR
).nColor
) );
218 const StyleSettings
& rSett
= GetSettings().GetStyleSettings();
219 maHeaderBackColor
= rSett
.GetFaceColor();
220 maHeaderGridColor
= rSett
.GetDarkShadowColor();
221 maHeaderTextColor
= rSett
.GetButtonTextColor();
222 maSelectColor
= rSett
.GetActiveColor();
227 void ScCsvGrid::InitFonts()
229 maMonoFont
= OutputDevice::GetDefaultFont( DefaultFontType::FIXED
, LANGUAGE_ENGLISH_US
, GetDefaultFontFlags::NONE
);
230 maMonoFont
.SetSize( Size( maMonoFont
.GetSize().Width(), maHeaderFont
.GetSize().Height() ) );
232 /* *** Set edit engine defaults ***
233 maMonoFont for Latin script, smaller default font for Asian and Complex script. */
236 SvxFontItem
aLatinItem( EE_CHAR_FONTINFO
);
237 SvxFontItem
aAsianItem( EE_CHAR_FONTINFO_CJK
);
238 SvxFontItem
aComplexItem( EE_CHAR_FONTINFO_CTL
);
239 ::GetDefaultFonts( aLatinItem
, aAsianItem
, aComplexItem
);
241 // create item set for defaults
242 SfxItemSet
aDefSet( mpEditEngine
->GetEmptyItemSet() );
243 EditEngine::SetFontInfoInItemSet( aDefSet
, maMonoFont
);
244 aDefSet
.Put( aAsianItem
);
245 aDefSet
.Put( aComplexItem
);
247 // set Asian/Complex font size to height of character in Latin font
248 sal_uLong nFontHt
= static_cast< sal_uLong
>( maMonoFont
.GetSize().Height() );
249 aDefSet
.Put( SvxFontHeightItem( nFontHt
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
250 aDefSet
.Put( SvxFontHeightItem( nFontHt
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
252 // copy other items from default font
253 const SfxPoolItem
& rWeightItem
= aDefSet
.Get( EE_CHAR_WEIGHT
);
254 aDefSet
.Put( rWeightItem
, EE_CHAR_WEIGHT_CJK
);
255 aDefSet
.Put( rWeightItem
, EE_CHAR_WEIGHT_CTL
);
256 const SfxPoolItem
& rItalicItem
= aDefSet
.Get( EE_CHAR_ITALIC
);
257 aDefSet
.Put( rItalicItem
, EE_CHAR_ITALIC_CJK
);
258 aDefSet
.Put( rItalicItem
, EE_CHAR_ITALIC_CTL
);
259 const SfxPoolItem
& rLangItem
= aDefSet
.Get( EE_CHAR_LANGUAGE
);
260 aDefSet
.Put( rLangItem
, EE_CHAR_LANGUAGE_CJK
);
261 aDefSet
.Put( rLangItem
, EE_CHAR_LANGUAGE_CTL
);
263 mpEditEngine
->SetDefaults( aDefSet
);
267 void ScCsvGrid::InitSizeData()
269 maWinSize
= GetSizePixel();
270 mpBackgrDev
->SetOutputSizePixel( maWinSize
);
271 mpGridDev
->SetOutputSizePixel( maWinSize
);
275 // split handling -------------------------------------------------------------
277 void ScCsvGrid::InsertSplit( sal_Int32 nPos
)
279 if( ImplInsertSplit( nPos
) )
282 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
283 Execute( CSVCMD_UPDATECELLTEXTS
);
284 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
285 ImplDrawColumn( nColIx
- 1 );
286 ImplDrawColumn( nColIx
);
287 ValidateGfx(); // performance: do not redraw all columns
292 void ScCsvGrid::RemoveSplit( sal_Int32 nPos
)
294 if( ImplRemoveSplit( nPos
) )
297 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
298 Execute( CSVCMD_UPDATECELLTEXTS
);
299 ImplDrawColumn( GetColumnFromPos( nPos
) );
300 ValidateGfx(); // performance: do not redraw all columns
305 void ScCsvGrid::MoveSplit( sal_Int32 nPos
, sal_Int32 nNewPos
)
307 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
308 if( nColIx
!= CSV_COLUMN_INVALID
)
311 if( (GetColumnPos( nColIx
- 1 ) < nNewPos
) && (nNewPos
< GetColumnPos( nColIx
+ 1 )) )
313 // move a split in the range between 2 others -> keep selection state of both columns
314 maSplits
.Remove( nPos
);
315 maSplits
.Insert( nNewPos
);
316 Execute( CSVCMD_UPDATECELLTEXTS
);
317 ImplDrawColumn( nColIx
- 1 );
318 ImplDrawColumn( nColIx
);
319 ValidateGfx(); // performance: do not redraw all columns
320 AccSendTableUpdateEvent( nColIx
- 1, nColIx
);
324 ImplRemoveSplit( nPos
);
325 ImplInsertSplit( nNewPos
);
326 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
327 Execute( CSVCMD_UPDATECELLTEXTS
);
333 void ScCsvGrid::RemoveAllSplits()
337 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
338 Execute( CSVCMD_UPDATECELLTEXTS
);
342 void ScCsvGrid::SetSplits( const ScCsvSplits
& rSplits
)
346 sal_uInt32 nCount
= rSplits
.Count();
347 for( sal_uInt32 nIx
= 0; nIx
< nCount
; ++nIx
)
348 maSplits
.Insert( rSplits
[ nIx
] );
350 maColStates
.resize( maSplits
.Count() - 1 );
351 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
352 Execute( CSVCMD_UPDATECELLTEXTS
);
356 bool ScCsvGrid::ImplInsertSplit( sal_Int32 nPos
)
358 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
359 bool bRet
= (nColIx
< GetColumnCount()) && maSplits
.Insert( nPos
);
362 ScCsvColState
aState( GetColumnType( nColIx
) );
363 aState
.Select( IsSelected( nColIx
) && IsSelected( nColIx
+ 1 ) );
364 maColStates
.insert( maColStates
.begin() + nColIx
+ 1, aState
);
365 AccSendInsertColumnEvent( nColIx
+ 1, nColIx
+ 1 );
366 AccSendTableUpdateEvent( nColIx
, nColIx
);
371 bool ScCsvGrid::ImplRemoveSplit( sal_Int32 nPos
)
373 bool bRet
= maSplits
.Remove( nPos
);
376 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
377 bool bSel
= IsSelected( nColIx
) || IsSelected( nColIx
+ 1 );
378 maColStates
.erase( maColStates
.begin() + nColIx
+ 1 );
379 maColStates
[ nColIx
].Select( bSel
);
380 AccSendRemoveColumnEvent( nColIx
+ 1, nColIx
+ 1 );
381 AccSendTableUpdateEvent( nColIx
, nColIx
);
386 void ScCsvGrid::ImplClearSplits()
388 sal_uInt32 nColumns
= GetColumnCount();
390 maSplits
.Insert( 0 );
391 maSplits
.Insert( GetPosCount() );
392 maColStates
.resize( 1 );
394 AccSendRemoveColumnEvent( 1, nColumns
- 1 );
397 // columns/column types -------------------------------------------------------
399 sal_uInt32
ScCsvGrid::GetFirstVisColumn() const
401 return GetColumnFromPos( GetFirstVisPos() );
404 sal_uInt32
ScCsvGrid::GetLastVisColumn() const
406 return GetColumnFromPos( std::min( GetLastVisPos(), GetPosCount() ) - 1 );
409 bool ScCsvGrid::IsValidColumn( sal_uInt32 nColIndex
) const
411 return nColIndex
< GetColumnCount();
414 bool ScCsvGrid::IsVisibleColumn( sal_uInt32 nColIndex
) const
416 return IsValidColumn( nColIndex
) &&
417 (GetColumnPos( nColIndex
) < GetLastVisPos()) &&
418 (GetFirstVisPos() < GetColumnPos( nColIndex
+ 1 ));
421 sal_Int32
ScCsvGrid::GetColumnX( sal_uInt32 nColIndex
) const
423 return GetX( GetColumnPos( nColIndex
) );
426 sal_uInt32
ScCsvGrid::GetColumnFromX( sal_Int32 nX
) const
428 sal_Int32 nPos
= (nX
- GetFirstX()) / GetCharWidth() + GetFirstVisPos();
429 return ((GetFirstVisPos() <= nPos
) && (nPos
<= GetLastVisPos())) ?
430 GetColumnFromPos( nPos
) : CSV_COLUMN_INVALID
;
433 sal_uInt32
ScCsvGrid::GetColumnFromPos( sal_Int32 nPos
) const
435 return maSplits
.UpperBound( nPos
);
438 sal_Int32
ScCsvGrid::GetColumnWidth( sal_uInt32 nColIndex
) const
440 return IsValidColumn( nColIndex
) ? (GetColumnPos( nColIndex
+ 1 ) - GetColumnPos( nColIndex
)) : 0;
443 void ScCsvGrid::SetColumnStates( const ScCsvColStateVec
& rStates
)
445 maColStates
= rStates
;
446 maColStates
.resize( maSplits
.Count() - 1 );
447 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
448 AccSendTableUpdateEvent( 0, GetColumnCount(), false );
449 AccSendSelectionEvent();
452 sal_Int32
ScCsvGrid::GetColumnType( sal_uInt32 nColIndex
) const
454 return IsValidColumn( nColIndex
) ? maColStates
[ nColIndex
].mnType
: CSV_TYPE_NOSELECTION
;
457 void ScCsvGrid::SetColumnType( sal_uInt32 nColIndex
, sal_Int32 nColType
)
459 if( IsValidColumn( nColIndex
) )
461 maColStates
[ nColIndex
].mnType
= nColType
;
462 AccSendTableUpdateEvent( nColIndex
, nColIndex
, false );
466 sal_Int32
ScCsvGrid::GetSelColumnType() const
468 sal_uInt32 nColIx
= GetFirstSelected();
469 if( nColIx
== CSV_COLUMN_INVALID
)
470 return CSV_TYPE_NOSELECTION
;
472 sal_Int32 nType
= GetColumnType( nColIx
);
473 while( (nColIx
!= CSV_COLUMN_INVALID
) && (nType
!= CSV_TYPE_MULTI
) )
475 if( nType
!= GetColumnType( nColIx
) )
476 nType
= CSV_TYPE_MULTI
;
477 nColIx
= GetNextSelected( nColIx
);
482 void ScCsvGrid::SetSelColumnType( sal_Int32 nType
)
484 if( (nType
!= CSV_TYPE_MULTI
) && (nType
!= CSV_TYPE_NOSELECTION
) )
486 for( sal_uInt32 nColIx
= GetFirstSelected(); nColIx
!= CSV_COLUMN_INVALID
; nColIx
= GetNextSelected( nColIx
) )
487 SetColumnType( nColIx
, nType
);
489 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
493 void ScCsvGrid::SetTypeNames( const StringVec
& rTypeNames
)
495 OSL_ENSURE( !rTypeNames
.empty(), "ScCsvGrid::SetTypeNames - vector is empty" );
496 maTypeNames
= rTypeNames
;
500 sal_uInt32 nCount
= maTypeNames
.size();
503 for( nIx
= 0, nItemId
= 1; nIx
< nCount
; ++nIx
, ++nItemId
)
504 maPopup
.InsertItem( nItemId
, maTypeNames
[ nIx
] );
506 ::std::for_each( maColStates
.begin(), maColStates
.end(), Func_SetType( CSV_TYPE_DEFAULT
) );
509 const OUString
& ScCsvGrid::GetColumnTypeName( sal_uInt32 nColIndex
) const
511 sal_uInt32 nTypeIx
= static_cast< sal_uInt32
>( GetColumnType( nColIndex
) );
512 return (nTypeIx
< maTypeNames
.size()) ? maTypeNames
[ nTypeIx
] : EMPTY_OUSTRING
;
515 static sal_uInt8
lcl_GetExtColumnType( sal_Int32 nIntType
)
517 static const sal_uInt8 pExtTypes
[] =
518 { SC_COL_STANDARD
, SC_COL_TEXT
, SC_COL_DMY
, SC_COL_MDY
, SC_COL_YMD
, SC_COL_ENGLISH
, SC_COL_SKIP
};
519 static const sal_Int32 nExtTypeCount
= SAL_N_ELEMENTS(pExtTypes
);
520 return pExtTypes
[ ((0 <= nIntType
) && (nIntType
< nExtTypeCount
)) ? nIntType
: 0 ];
523 void ScCsvGrid::FillColumnDataSep( ScAsciiOptions
& rOptions
) const
525 sal_uInt32 nCount
= GetColumnCount();
526 ScCsvExpDataVec aDataVec
;
528 for( sal_uInt32 nColIx
= 0; nColIx
< nCount
; ++nColIx
)
530 if( GetColumnType( nColIx
) != CSV_TYPE_DEFAULT
)
531 // 1-based column index
532 aDataVec
.push_back( ScCsvExpData(
533 static_cast< sal_Int32
>( nColIx
+ 1 ),
534 lcl_GetExtColumnType( GetColumnType( nColIx
) ) ) );
536 rOptions
.SetColumnInfo( aDataVec
);
539 void ScCsvGrid::FillColumnDataFix( ScAsciiOptions
& rOptions
) const
541 sal_uInt32 nCount
= std::min( GetColumnCount(), static_cast<sal_uInt32
>(MAXCOLCOUNT
) );
542 ScCsvExpDataVec
aDataVec( nCount
+ 1 );
544 for( sal_uInt32 nColIx
= 0; nColIx
< nCount
; ++nColIx
)
546 ScCsvExpData
& rData
= aDataVec
[ nColIx
];
547 rData
.mnIndex
= static_cast< sal_Int32
>( GetColumnPos( nColIx
) );
548 rData
.mnType
= lcl_GetExtColumnType( GetColumnType( nColIx
) );
550 aDataVec
[ nCount
].mnIndex
= SAL_MAX_INT32
;
551 aDataVec
[ nCount
].mnType
= SC_COL_SKIP
;
552 rOptions
.SetColumnInfo( aDataVec
);
555 void ScCsvGrid::ScrollVertRel( ScMoveMode eDir
)
557 sal_Int32 nLine
= GetFirstVisLine();
560 case MOVE_PREV
: --nLine
; break;
561 case MOVE_NEXT
: ++nLine
; break;
562 case MOVE_FIRST
: nLine
= 0; break;
563 case MOVE_LAST
: nLine
= GetMaxLineOffset(); break;
564 case MOVE_PREVPAGE
: nLine
-= GetVisLineCount() - 2; break;
565 case MOVE_NEXTPAGE
: nLine
+= GetVisLineCount() - 2; break;
568 // added to avoid warnings
571 Execute( CSVCMD_SETLINEOFFSET
, nLine
);
574 void ScCsvGrid::ExecutePopup( const Point
& rPos
)
576 sal_uInt16 nItemId
= maPopup
.Execute( this, rPos
);
577 if( nItemId
) // 0 = cancelled
578 Execute( CSVCMD_SETCOLUMNTYPE
, maPopup
.GetItemPos( nItemId
) );
581 // selection handling ---------------------------------------------------------
583 bool ScCsvGrid::IsSelected( sal_uInt32 nColIndex
) const
585 return IsValidColumn( nColIndex
) && maColStates
[ nColIndex
].IsSelected();
588 sal_uInt32
ScCsvGrid::GetFirstSelected() const
590 return IsSelected( 0 ) ? 0 : GetNextSelected( 0 );
593 sal_uInt32
ScCsvGrid::GetNextSelected( sal_uInt32 nFromIndex
) const
595 sal_uInt32 nColCount
= GetColumnCount();
596 for( sal_uInt32 nColIx
= nFromIndex
+ 1; nColIx
< nColCount
; ++nColIx
)
597 if( IsSelected( nColIx
) )
599 return CSV_COLUMN_INVALID
;
602 void ScCsvGrid::Select( sal_uInt32 nColIndex
, bool bSelect
)
604 if( IsValidColumn( nColIndex
) )
606 maColStates
[ nColIndex
].Select( bSelect
);
607 ImplDrawColumnSelection( nColIndex
);
609 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
611 mnRecentSelCol
= nColIndex
;
612 AccSendSelectionEvent();
616 void ScCsvGrid::ToggleSelect( sal_uInt32 nColIndex
)
618 Select( nColIndex
, !IsSelected( nColIndex
) );
621 void ScCsvGrid::SelectRange( sal_uInt32 nColIndex1
, sal_uInt32 nColIndex2
, bool bSelect
)
623 if( nColIndex1
== CSV_COLUMN_INVALID
)
624 Select( nColIndex2
);
625 else if( nColIndex2
== CSV_COLUMN_INVALID
)
626 Select( nColIndex1
);
627 else if( nColIndex1
> nColIndex2
)
629 SelectRange( nColIndex2
, nColIndex1
, bSelect
);
631 mnRecentSelCol
= nColIndex1
;
633 else if( IsValidColumn( nColIndex1
) && IsValidColumn( nColIndex2
) )
635 for( sal_uInt32 nColIx
= nColIndex1
; nColIx
<= nColIndex2
; ++nColIx
)
637 maColStates
[ nColIx
].Select( bSelect
);
638 ImplDrawColumnSelection( nColIx
);
641 Execute( CSVCMD_EXPORTCOLUMNTYPE
);
643 mnRecentSelCol
= nColIndex1
;
644 AccSendSelectionEvent();
648 void ScCsvGrid::SelectAll( bool bSelect
)
650 SelectRange( 0, GetColumnCount() - 1, bSelect
);
653 void ScCsvGrid::MoveCursor( sal_uInt32 nColIndex
)
656 if( IsValidColumn( nColIndex
) )
658 sal_Int32 nPosBeg
= GetColumnPos( nColIndex
);
659 sal_Int32 nPosEnd
= GetColumnPos( nColIndex
+ 1 );
660 sal_Int32 nMinPos
= std::max( nPosBeg
- CSV_SCROLL_DIST
, sal_Int32( 0 ) );
661 sal_Int32 nMaxPos
= std::min( nPosEnd
- GetVisPosCount() + CSV_SCROLL_DIST
+ sal_Int32( 1 ), nMinPos
);
662 if( nPosBeg
- CSV_SCROLL_DIST
+ 1 <= GetFirstVisPos() )
663 Execute( CSVCMD_SETPOSOFFSET
, nMinPos
);
664 else if( nPosEnd
+ CSV_SCROLL_DIST
>= GetLastVisPos() )
665 Execute( CSVCMD_SETPOSOFFSET
, nMaxPos
);
667 Execute( CSVCMD_MOVEGRIDCURSOR
, GetColumnPos( nColIndex
) );
671 void ScCsvGrid::MoveCursorRel( ScMoveMode eDir
)
673 if( GetFocusColumn() != CSV_COLUMN_INVALID
)
681 MoveCursor( GetColumnCount() - 1 );
684 if( GetFocusColumn() > 0 )
685 MoveCursor( GetFocusColumn() - 1 );
688 if( GetFocusColumn() < GetColumnCount() - 1 )
689 MoveCursor( GetFocusColumn() + 1 );
693 // added to avoid warnings
699 void ScCsvGrid::ImplClearSelection()
701 ::std::for_each( maColStates
.begin(), maColStates
.end(), Func_Select( false ) );
705 void ScCsvGrid::DoSelectAction( sal_uInt32 nColIndex
, sal_uInt16 nModifier
)
707 if( !(nModifier
& KEY_MOD1
) )
708 ImplClearSelection();
709 if( nModifier
& KEY_SHIFT
) // SHIFT always expands
710 SelectRange( mnRecentSelCol
, nColIndex
);
711 else if( !(nModifier
& KEY_MOD1
) ) // no SHIFT/CTRL always selects 1 column
713 else if( IsTracking() ) // CTRL in tracking does not toggle
714 Select( nColIndex
, mbMTSelecting
);
715 else // CTRL only toggles
716 ToggleSelect( nColIndex
);
717 Execute( CSVCMD_MOVEGRIDCURSOR
, GetColumnPos( nColIndex
) );
720 // cell contents --------------------------------------------------------------
722 void ScCsvGrid::ImplSetTextLineSep(
723 sal_Int32 nLine
, const OUString
& rTextLine
,
724 const OUString
& rSepChars
, sal_Unicode cTextSep
, bool bMergeSep
)
726 if( nLine
< GetFirstVisLine() ) return;
728 sal_uInt32 nLineIx
= nLine
- GetFirstVisLine();
729 while( maTexts
.size() <= nLineIx
)
730 maTexts
.push_back( StringVec() );
731 StringVec
& rStrVec
= maTexts
[ nLineIx
];
734 // scan for separators
736 const sal_Unicode
* pSepChars
= rSepChars
.getStr();
737 const sal_Unicode
* pChar
= rTextLine
.getStr();
738 sal_uInt32 nColIx
= 0;
740 while( *pChar
&& (nColIx
< sal::static_int_cast
<sal_uInt32
>(CSV_MAXCOLCOUNT
)) )
742 // scan for next cell text
743 bool bIsQuoted
= false;
744 bool bOverflowCell
= false;
745 pChar
= ScImportExport::ScanNextFieldFromString( pChar
, aCellText
,
746 cTextSep
, pSepChars
, bMergeSep
, bIsQuoted
, bOverflowCell
);
747 /* TODO: signal overflow somewhere in UI */
749 // update column width
750 sal_Int32 nWidth
= std::max( CSV_MINCOLWIDTH
, aCellText
.getLength() + 1 );
751 if( IsValidColumn( nColIx
) )
753 // expand existing column
754 sal_Int32 nDiff
= nWidth
- GetColumnWidth( nColIx
);
757 Execute( CSVCMD_SETPOSCOUNT
, GetPosCount() + nDiff
);
758 for( sal_uInt32 nSplitIx
= GetColumnCount() - 1; nSplitIx
> nColIx
; --nSplitIx
)
760 sal_Int32 nPos
= maSplits
[ nSplitIx
];
761 maSplits
.Remove( nPos
);
762 maSplits
.Insert( nPos
+ nDiff
);
769 sal_Int32 nLastPos
= GetPosCount();
770 Execute( CSVCMD_SETPOSCOUNT
, nLastPos
+ nWidth
);
771 ImplInsertSplit( nLastPos
);
774 if( aCellText
.getLength() <= CSV_MAXSTRLEN
)
775 rStrVec
.push_back( aCellText
);
777 rStrVec
.push_back( aCellText
.copy( 0, CSV_MAXSTRLEN
) );
783 void ScCsvGrid::ImplSetTextLineFix( sal_Int32 nLine
, const OUString
& rTextLine
)
785 if( nLine
< GetFirstVisLine() ) return;
787 sal_Int32 nChars
= rTextLine
.getLength();
788 if( nChars
> GetPosCount() )
789 Execute( CSVCMD_SETPOSCOUNT
, nChars
);
791 sal_uInt32 nLineIx
= nLine
- GetFirstVisLine();
792 while( maTexts
.size() <= nLineIx
)
793 maTexts
.push_back( StringVec() );
795 StringVec
& rStrVec
= maTexts
[ nLineIx
];
797 sal_uInt32 nColCount
= GetColumnCount();
798 sal_Int32 nStrLen
= rTextLine
.getLength();
799 sal_Int32 nStrIx
= 0;
800 for( sal_uInt32 nColIx
= 0; (nColIx
< nColCount
) && (nStrIx
< nStrLen
); ++nColIx
)
802 sal_Int32 nColWidth
= GetColumnWidth( nColIx
);
803 sal_Int32 nLen
= std::min( std::min( nColWidth
, static_cast<sal_Int32
>(CSV_MAXSTRLEN
) ), nStrLen
- nStrIx
);
804 rStrVec
.push_back( rTextLine
.copy( nStrIx
, nLen
) );
805 nStrIx
= nStrIx
+ nColWidth
;
810 const OUString
& ScCsvGrid::GetCellText( sal_uInt32 nColIndex
, sal_Int32 nLine
) const
812 if( nLine
< GetFirstVisLine() ) return EMPTY_OUSTRING
;
814 sal_uInt32 nLineIx
= nLine
- GetFirstVisLine();
815 if( nLineIx
>= maTexts
.size() ) return EMPTY_OUSTRING
;
817 const StringVec
& rStrVec
= maTexts
[ nLineIx
];
818 if( nColIndex
>= rStrVec
.size() ) return EMPTY_OUSTRING
;
820 return rStrVec
[ nColIndex
];
823 // event handling -------------------------------------------------------------
825 void ScCsvGrid::Resize()
827 ScCsvControl::Resize();
829 Execute( CSVCMD_UPDATECELLTEXTS
);
832 void ScCsvGrid::GetFocus()
834 ScCsvControl::GetFocus();
835 Execute( CSVCMD_MOVEGRIDCURSOR
, GetNoScrollCol( GetGridCursorPos() ) );
839 void ScCsvGrid::LoseFocus()
841 ScCsvControl::LoseFocus();
845 void ScCsvGrid::MouseButtonDown( const MouseEvent
& rMEvt
)
851 Point
aPos( rMEvt
.GetPosPixel() );
852 sal_uInt32 nColIx
= GetColumnFromX( aPos
.X() );
856 if( (GetFirstX() > aPos
.X()) || (aPos
.X() > GetLastX()) ) // in header column
858 if( aPos
.Y() <= GetHdrHeight() )
861 else if( IsValidColumn( nColIx
) )
863 DoSelectAction( nColIx
, rMEvt
.GetModifier() );
864 mnMTCurrCol
= nColIx
;
865 mbMTSelecting
= IsSelected( nColIx
);
866 StartTracking( STARTTRACK_BUTTONREPEAT
);
872 void ScCsvGrid::Tracking( const TrackingEvent
& rTEvt
)
874 if( rTEvt
.IsTrackingEnded() || rTEvt
.IsTrackingRepeat() )
877 const MouseEvent
& rMEvt
= rTEvt
.GetMouseEvent();
879 sal_Int32 nPos
= (rMEvt
.GetPosPixel().X() - GetFirstX()) / GetCharWidth() + GetFirstVisPos();
880 // on mouse tracking: keep position valid
881 nPos
= std::max( std::min( nPos
, GetPosCount() - sal_Int32( 1 ) ), sal_Int32( 0 ) );
882 Execute( CSVCMD_MAKEPOSVISIBLE
, nPos
);
884 sal_uInt32 nColIx
= GetColumnFromPos( nPos
);
885 if( mnMTCurrCol
!= nColIx
)
887 DoSelectAction( nColIx
, rMEvt
.GetModifier() );
888 mnMTCurrCol
= nColIx
;
894 void ScCsvGrid::KeyInput( const KeyEvent
& rKEvt
)
896 const vcl::KeyCode
& rKCode
= rKEvt
.GetKeyCode();
897 sal_uInt16 nCode
= rKCode
.GetCode();
898 bool bShift
= rKCode
.IsShift();
899 bool bMod1
= rKCode
.IsMod1();
901 if( !rKCode
.IsMod2() )
903 ScMoveMode eHDir
= GetHorzDirection( nCode
, !bMod1
);
904 ScMoveMode eVDir
= GetVertDirection( nCode
, bMod1
);
906 if( eHDir
!= MOVE_NONE
)
909 MoveCursorRel( eHDir
);
911 ImplClearSelection();
913 SelectRange( mnRecentSelCol
, GetFocusColumn() );
915 Select( GetFocusColumn() );
918 else if( eVDir
!= MOVE_NONE
)
919 ScrollVertRel( eVDir
);
920 else if( nCode
== KEY_SPACE
)
923 ImplClearSelection();
925 SelectRange( mnRecentSelCol
, GetFocusColumn() );
927 ToggleSelect( GetFocusColumn() );
929 Select( GetFocusColumn() );
931 else if( !bShift
&& bMod1
)
935 else if( (KEY_1
<= nCode
) && (nCode
<= KEY_9
) )
937 sal_uInt32 nType
= nCode
- KEY_1
;
938 if( nType
< maTypeNames
.size() )
939 Execute( CSVCMD_SETCOLUMNTYPE
, nType
);
944 if( rKCode
.GetGroup() != KEYGROUP_CURSOR
)
945 ScCsvControl::KeyInput( rKEvt
);
948 void ScCsvGrid::Command( const CommandEvent
& rCEvt
)
950 switch( rCEvt
.GetCommand() )
952 case CommandEventId::ContextMenu
:
954 if( rCEvt
.IsMouseEvent() )
956 Point
aPos( rCEvt
.GetMousePosPixel() );
957 sal_uInt32 nColIx
= GetColumnFromX( aPos
.X() );
958 if( IsValidColumn( nColIx
) && (GetFirstX() <= aPos
.X()) && (aPos
.X() <= GetLastX()) )
960 if( !IsSelected( nColIx
) )
961 DoSelectAction( nColIx
, 0 ); // focus & select
962 ExecutePopup( aPos
);
967 sal_uInt32 nColIx
= GetFocusColumn();
968 if( !IsSelected( nColIx
) )
970 sal_Int32 nX1
= std::max( GetColumnX( nColIx
), GetFirstX() );
971 sal_Int32 nX2
= std::min( GetColumnX( nColIx
+ 1 ), GetWidth() );
972 ExecutePopup( Point( (nX1
+ nX2
) / 2, GetHeight() / 2 ) );
976 case CommandEventId::Wheel
:
979 Rectangle
aRect( aPoint
, maWinSize
);
980 if( aRect
.IsInside( rCEvt
.GetMousePosPixel() ) )
982 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
983 if( pData
&& (pData
->GetMode() == CommandWheelMode::SCROLL
) && !pData
->IsHorz() )
984 Execute( CSVCMD_SETLINEOFFSET
, GetFirstVisLine() - pData
->GetNotchDelta() );
989 ScCsvControl::Command( rCEvt
);
993 void ScCsvGrid::DataChanged( const DataChangedEvent
& rDCEvt
)
995 if( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
1000 Execute( CSVCMD_UPDATECELLTEXTS
);
1002 ScCsvControl::DataChanged( rDCEvt
);
1005 void ScCsvGrid::ConfigurationChanged( utl::ConfigurationBroadcaster
*, sal_uInt32
)
1011 // painting -------------------------------------------------------------------
1013 void ScCsvGrid::Paint( vcl::RenderContext
& /*rRenderContext*/, const Rectangle
& )
1018 void ScCsvGrid::ImplRedraw()
1025 ImplDrawBackgrDev();
1028 DrawOutDev( Point(), maWinSize
, Point(), maWinSize
, *mpGridDev
.get() );
1029 ImplDrawTrackingRect( GetFocusColumn() );
1033 EditEngine
* ScCsvGrid::GetEditEngine()
1035 return mpEditEngine
.get();
1038 void ScCsvGrid::ImplSetColumnClipRegion( OutputDevice
& rOutDev
, sal_uInt32 nColIndex
)
1040 rOutDev
.SetClipRegion( vcl::Region( Rectangle(
1041 std::max( GetColumnX( nColIndex
), GetFirstX() ) + 1, 0,
1042 std::min( GetColumnX( nColIndex
+ 1 ), GetLastX() ), GetHeight() - 1 ) ) );
1045 void ScCsvGrid::ImplDrawColumnHeader( OutputDevice
& rOutDev
, sal_uInt32 nColIndex
, Color aFillColor
)
1047 sal_Int32 nX1
= GetColumnX( nColIndex
) + 1;
1048 sal_Int32 nX2
= GetColumnX( nColIndex
+ 1 );
1049 sal_Int32 nHdrHt
= GetHdrHeight();
1051 rOutDev
.SetLineColor();
1052 rOutDev
.SetFillColor( aFillColor
);
1053 rOutDev
.DrawRect( Rectangle( nX1
, 0, nX2
, nHdrHt
) );
1055 rOutDev
.SetFont( maHeaderFont
);
1056 rOutDev
.SetTextColor( maHeaderTextColor
);
1057 rOutDev
.SetTextFillColor();
1058 rOutDev
.DrawText( Point( nX1
+ 1, 0 ), GetColumnTypeName( nColIndex
) );
1060 rOutDev
.SetLineColor( maHeaderGridColor
);
1061 rOutDev
.DrawLine( Point( nX1
, nHdrHt
), Point( nX2
, nHdrHt
) );
1062 rOutDev
.DrawLine( Point( nX2
, 0 ), Point( nX2
, nHdrHt
) );
1065 void ScCsvGrid::ImplDrawCellText( const Point
& rPos
, const OUString
& rText
)
1067 OUString
aPlainText( rText
);
1068 aPlainText
= aPlainText
.replaceAll( "\t", " " );
1069 aPlainText
= aPlainText
.replaceAll( "\n", " " );
1070 mpEditEngine
->SetPaperSize( maEdEngSize
);
1072 /* #i60296# If string contains mixed script types, the space character
1073 U+0020 may be drawn with a wrong width (from non-fixed-width Asian or
1074 Complex font). Now we draw every non-space portion separately. */
1075 sal_Int32 nTokenCount
= comphelper::string::getTokenCount(aPlainText
, ' ');
1076 sal_Int32 nCharIxInt
= 0;
1077 for( sal_Int32 nToken
= 0; nToken
< nTokenCount
; ++nToken
)
1079 sal_Int32 nBeginIx
= nCharIxInt
;
1080 OUString aToken
= aPlainText
.getToken( 0, ' ', nCharIxInt
);
1081 if( !aToken
.isEmpty() )
1083 sal_Int32 nX
= rPos
.X() + GetCharWidth() * nBeginIx
;
1084 mpEditEngine
->SetText( aToken
);
1085 mpEditEngine
->Draw( mpBackgrDev
.get(), Point( nX
, rPos
.Y() ) );
1089 sal_Int32 nCharIx
= 0;
1090 while( (nCharIx
= rText
.indexOf( '\t', nCharIx
)) != -1 )
1092 sal_Int32 nX1
= rPos
.X() + GetCharWidth() * nCharIx
;
1093 sal_Int32 nX2
= nX1
+ GetCharWidth() - 2;
1094 sal_Int32 nY
= rPos
.Y() + GetLineHeight() / 2;
1095 Color
aColor( maTextColor
);
1096 mpBackgrDev
->SetLineColor( aColor
);
1097 mpBackgrDev
->DrawLine( Point( nX1
, nY
), Point( nX2
, nY
) );
1098 mpBackgrDev
->DrawLine( Point( nX2
- 2, nY
- 2 ), Point( nX2
, nY
) );
1099 mpBackgrDev
->DrawLine( Point( nX2
- 2, nY
+ 2 ), Point( nX2
, nY
) );
1103 while( (nCharIx
= rText
.indexOf( '\n', nCharIx
)) != -1 )
1105 sal_Int32 nX1
= rPos
.X() + GetCharWidth() * nCharIx
;
1106 sal_Int32 nX2
= nX1
+ GetCharWidth() - 2;
1107 sal_Int32 nY
= rPos
.Y() + GetLineHeight() / 2;
1108 Color
aColor( maTextColor
);
1109 mpBackgrDev
->SetLineColor( aColor
);
1110 mpBackgrDev
->DrawLine( Point( nX1
, nY
), Point( nX2
, nY
) );
1111 mpBackgrDev
->DrawLine( Point( nX1
+ 2, nY
- 2 ), Point( nX1
, nY
) );
1112 mpBackgrDev
->DrawLine( Point( nX1
+ 2, nY
+ 2 ), Point( nX1
, nY
) );
1113 mpBackgrDev
->DrawLine( Point( nX2
, nY
- 2 ), Point( nX2
, nY
) );
1118 void ScCsvGrid::ImplDrawFirstLineSep( bool bSet
)
1120 if( IsVisibleLine( mnFirstImpLine
) && (mnFirstImpLine
!= GetFirstVisLine() ) )
1122 sal_Int32 nY
= GetY( mnFirstImpLine
);
1123 sal_Int32 nX
= std::min( GetColumnX( GetLastVisColumn() + 1 ), GetLastX() );
1124 mpBackgrDev
->SetLineColor( bSet
? maGridPBColor
: maGridColor
);
1125 mpBackgrDev
->DrawLine( Point( GetFirstX() + 1, nY
), Point( nX
, nY
) );
1129 void ScCsvGrid::ImplDrawColumnBackgr( sal_uInt32 nColIndex
)
1131 if( !IsVisibleColumn( nColIndex
) )
1134 ImplSetColumnClipRegion( *mpBackgrDev
.get(), nColIndex
);
1137 mpBackgrDev
->SetLineColor();
1138 mpBackgrDev
->SetFillColor( maBackColor
);
1139 sal_Int32 nX1
= GetColumnX( nColIndex
) + 1;
1140 sal_Int32 nX2
= GetColumnX( nColIndex
+ 1 );
1141 sal_Int32 nY2
= GetY( GetLastVisLine() + 1 );
1142 sal_Int32 nHdrHt
= GetHdrHeight();
1143 Rectangle
aRect( nX1
, nHdrHt
, nX2
, nY2
);
1144 mpBackgrDev
->DrawRect( aRect
);
1145 mpBackgrDev
->SetLineColor( maGridColor
);
1146 mpBackgrDev
->DrawGrid( aRect
, Size( 1, GetLineHeight() ), DrawGridFlags::HorzLines
);
1147 mpBackgrDev
->DrawLine( Point( nX2
, nHdrHt
), Point( nX2
, nY2
) );
1148 ImplDrawFirstLineSep( true );
1151 mpEditEngine
->SetDefaultItem( SvxColorItem( maTextColor
, EE_CHAR_COLOR
) );
1152 size_t nLineCount
= ::std::min( static_cast< size_t >( GetLastVisLine() - GetFirstVisLine() + 1 ), maTexts
.size() );
1153 // #i67432# cut string to avoid edit engine performance problems with very large strings
1154 sal_Int32 nFirstVisPos
= ::std::max( GetColumnPos( nColIndex
), GetFirstVisPos() );
1155 sal_Int32 nLastVisPos
= ::std::min( GetColumnPos( nColIndex
+ 1 ), GetLastVisPos() );
1156 sal_Int32 nStrPos
= nFirstVisPos
- GetColumnPos( nColIndex
);
1157 sal_Int32 nStrLen
= nLastVisPos
- nFirstVisPos
+ 1;
1158 sal_Int32 nStrX
= GetX( nFirstVisPos
);
1159 for( size_t nLine
= 0; nLine
< nLineCount
; ++nLine
)
1161 StringVec
& rStrVec
= maTexts
[ nLine
];
1162 if( (nColIndex
< rStrVec
.size()) && (rStrVec
[ nColIndex
].getLength() > nStrPos
) )
1164 const OUString
& rStr
= rStrVec
[ nColIndex
];
1165 OUString aText
= rStr
.copy( nStrPos
, ::std::min( nStrLen
, rStr
.getLength() - nStrPos
) );
1166 ImplDrawCellText( Point( nStrX
, GetY( GetFirstVisLine() + nLine
) ), aText
);
1171 ImplDrawColumnHeader( *mpBackgrDev
.get(), nColIndex
, maHeaderBackColor
);
1173 mpBackgrDev
->SetClipRegion();
1176 void ScCsvGrid::ImplDrawRowHeaders()
1178 mpBackgrDev
->SetLineColor();
1179 mpBackgrDev
->SetFillColor( maAppBackColor
);
1180 Point
aPoint( GetHdrX(), 0 );
1181 Rectangle
aRect( aPoint
, Size( GetHdrWidth() + 1, GetHeight() ) );
1182 mpBackgrDev
->DrawRect( aRect
);
1184 mpBackgrDev
->SetFillColor( maHeaderBackColor
);
1185 aRect
.Bottom() = GetY( GetLastVisLine() + 1 );
1186 mpBackgrDev
->DrawRect( aRect
);
1189 mpBackgrDev
->SetFont( maHeaderFont
);
1190 mpBackgrDev
->SetTextColor( maHeaderTextColor
);
1191 mpBackgrDev
->SetTextFillColor();
1192 sal_Int32 nLastLine
= GetLastVisLine();
1193 for( sal_Int32 nLine
= GetFirstVisLine(); nLine
<= nLastLine
; ++nLine
)
1195 OUString
aText( OUString::number( nLine
+ 1 ) );
1196 sal_Int32 nX
= GetHdrX() + (GetHdrWidth() - mpBackgrDev
->GetTextWidth( aText
)) / 2;
1197 mpBackgrDev
->DrawText( Point( nX
, GetY( nLine
) ), aText
);
1201 mpBackgrDev
->SetLineColor( maHeaderGridColor
);
1204 mpBackgrDev
->DrawLine( Point( 0, 0 ), Point( 0, GetHeight() - 1 ) );
1205 mpBackgrDev
->DrawLine( aRect
.TopLeft(), aRect
.BottomLeft() );
1208 mpBackgrDev
->DrawLine( aRect
.TopRight(), aRect
.BottomRight() );
1209 aRect
.Top() = GetHdrHeight();
1210 mpBackgrDev
->DrawGrid( aRect
, Size( 1, GetLineHeight() ), DrawGridFlags::HorzLines
);
1213 void ScCsvGrid::ImplDrawBackgrDev()
1215 mpBackgrDev
->SetLineColor();
1216 mpBackgrDev
->SetFillColor( maAppBackColor
);
1217 mpBackgrDev
->DrawRect( Rectangle(
1218 Point( GetFirstX() + 1, 0 ), Size( GetWidth() - GetHdrWidth(), GetHeight() ) ) );
1220 sal_uInt32 nLastCol
= GetLastVisColumn();
1221 if (nLastCol
== CSV_COLUMN_INVALID
)
1223 for( sal_uInt32 nColIx
= GetFirstVisColumn(); nColIx
<= nLastCol
; ++nColIx
)
1224 ImplDrawColumnBackgr( nColIx
);
1226 ImplDrawRowHeaders();
1229 void ScCsvGrid::ImplDrawColumnSelection( sal_uInt32 nColIndex
)
1231 ImplInvertCursor( GetRulerCursorPos() );
1232 ImplSetColumnClipRegion( *mpGridDev
.get(), nColIndex
);
1233 mpGridDev
->DrawOutDev( Point(), maWinSize
, Point(), maWinSize
, *mpBackgrDev
.get() );
1235 if( IsSelected( nColIndex
) )
1237 sal_Int32 nX1
= GetColumnX( nColIndex
) + 1;
1238 sal_Int32 nX2
= GetColumnX( nColIndex
+ 1 );
1241 Rectangle
aRect( nX1
, 0, nX2
, GetHdrHeight() );
1242 mpGridDev
->SetLineColor();
1243 if( maHeaderBackColor
.IsDark() )
1244 // redraw with light gray background in dark mode
1245 ImplDrawColumnHeader( *mpGridDev
.get(), nColIndex
, COL_LIGHTGRAY
);
1248 // use transparent active color
1249 mpGridDev
->SetFillColor( maSelectColor
);
1250 mpGridDev
->DrawTransparent( tools::PolyPolygon( Polygon( aRect
) ), CSV_HDR_TRANSPARENCY
);
1254 aRect
= Rectangle( nX1
, GetHdrHeight() + 1, nX2
, GetY( GetLastVisLine() + 1 ) - 1 );
1255 ImplInvertRect( *mpGridDev
.get(), aRect
);
1258 mpGridDev
->SetClipRegion();
1259 ImplInvertCursor( GetRulerCursorPos() );
1262 void ScCsvGrid::ImplDrawGridDev()
1264 mpGridDev
->DrawOutDev( Point(), maWinSize
, Point(), maWinSize
, *mpBackgrDev
);
1265 sal_uInt32 nLastCol
= GetLastVisColumn();
1266 if (nLastCol
== CSV_COLUMN_INVALID
)
1268 for( sal_uInt32 nColIx
= GetFirstVisColumn(); nColIx
<= nLastCol
; ++nColIx
)
1269 ImplDrawColumnSelection( nColIx
);
1272 void ScCsvGrid::ImplDrawColumn( sal_uInt32 nColIndex
)
1274 ImplDrawColumnBackgr( nColIndex
);
1275 ImplDrawColumnSelection( nColIndex
);
1278 void ScCsvGrid::ImplDrawHorzScrolled( sal_Int32 nOldPos
)
1280 sal_Int32 nPos
= GetFirstVisPos();
1281 if( !IsValidGfx() || (nPos
== nOldPos
) )
1283 if( std::abs( nPos
- nOldPos
) > GetVisPosCount() / 2 )
1285 ImplDrawBackgrDev();
1291 sal_uInt32 nFirstColIx
, nLastColIx
;
1292 if( nPos
< nOldPos
)
1294 aSrc
= Point( GetFirstX() + 1, 0 );
1295 aDest
= Point( GetFirstX() + GetCharWidth() * (nOldPos
- nPos
) + 1, 0 );
1296 nFirstColIx
= GetColumnFromPos( nPos
);
1297 nLastColIx
= GetColumnFromPos( nOldPos
);
1301 aSrc
= Point( GetFirstX() + GetCharWidth() * (nPos
- nOldPos
) + 1, 0 );
1302 aDest
= Point( GetFirstX() + 1, 0 );
1303 nFirstColIx
= GetColumnFromPos( std::min( nOldPos
+ GetVisPosCount(), GetPosCount() ) - 1 );
1304 nLastColIx
= GetColumnFromPos( std::min( nPos
+ GetVisPosCount(), GetPosCount() ) - 1 );
1307 ImplInvertCursor( GetRulerCursorPos() + (nPos
- nOldPos
) );
1308 Rectangle
aRectangle( GetFirstX(), 0, GetLastX(), GetHeight() - 1 );
1309 vcl::Region
aClipReg( aRectangle
);
1310 mpBackgrDev
->SetClipRegion( aClipReg
);
1311 mpBackgrDev
->CopyArea( aDest
, aSrc
, maWinSize
);
1312 mpBackgrDev
->SetClipRegion();
1313 mpGridDev
->SetClipRegion( aClipReg
);
1314 mpGridDev
->CopyArea( aDest
, aSrc
, maWinSize
);
1315 mpGridDev
->SetClipRegion();
1316 ImplInvertCursor( GetRulerCursorPos() );
1318 for( sal_uInt32 nColIx
= nFirstColIx
; nColIx
<= nLastColIx
; ++nColIx
)
1319 ImplDrawColumn( nColIx
);
1321 sal_Int32 nLastX
= GetX( GetPosCount() ) + 1;
1322 if( nLastX
<= GetLastX() )
1324 Rectangle
aRect( nLastX
, 0, GetLastX(), GetHeight() - 1 );
1325 mpBackgrDev
->SetLineColor();
1326 mpBackgrDev
->SetFillColor( maAppBackColor
);
1327 mpBackgrDev
->DrawRect( aRect
);
1328 mpGridDev
->SetLineColor();
1329 mpGridDev
->SetFillColor( maAppBackColor
);
1330 mpGridDev
->DrawRect( aRect
);
1334 void ScCsvGrid::ImplInvertCursor( sal_Int32 nPos
)
1336 if( IsVisibleSplitPos( nPos
) )
1338 sal_Int32 nX
= GetX( nPos
) - 1;
1339 Rectangle
aRect( Point( nX
, 0 ), Size( 3, GetHdrHeight() ) );
1340 ImplInvertRect( *mpGridDev
.get(), aRect
);
1341 aRect
.Top() = GetHdrHeight() + 1;
1342 aRect
.Bottom() = GetY( GetLastVisLine() + 1 );
1343 ImplInvertRect( *mpGridDev
.get(), aRect
);
1347 void ScCsvGrid::ImplDrawTrackingRect( sal_uInt32 nColIndex
)
1349 if( HasFocus() && IsVisibleColumn( nColIndex
) )
1351 sal_Int32 nX1
= std::max( GetColumnX( nColIndex
), GetFirstX() ) + 1;
1352 sal_Int32 nX2
= std::min( GetColumnX( nColIndex
+ 1 ) - sal_Int32( 1 ), GetLastX() );
1353 sal_Int32 nY2
= std::min( GetY( GetLastVisLine() + 1 ), GetHeight() ) - 1;
1354 InvertTracking( Rectangle( nX1
, 0, nX2
, nY2
), SHOWTRACK_SMALL
| SHOWTRACK_WINDOW
);
1358 // accessibility ==============================================================
1360 ScAccessibleCsvControl
* ScCsvGrid::ImplCreateAccessible()
1362 std::unique_ptr
<ScAccessibleCsvControl
> pControl(new ScAccessibleCsvGrid( *this ));
1364 return pControl
.release();
1367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */