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 <csvtablebox.hxx>
21 #include <vcl/settings.hxx>
23 ScCsvTableBox::ScCsvTableBox(weld::Builder
& rBuilder
)
24 : mxRuler(new ScCsvRuler(maData
, this))
25 , mxGrid(new ScCsvGrid(maData
, rBuilder
.weld_menu(u
"popup"_ustr
), this))
26 , mxScroll(rBuilder
.weld_scrolled_window(u
"scrolledwindow"_ustr
, true))
27 , mxRulerWeld(new weld::CustomWeld(rBuilder
, u
"csvruler"_ustr
, *mxRuler
))
28 , mxGridWeld(new weld::CustomWeld(rBuilder
, u
"csvgrid"_ustr
, *mxGrid
))
29 , maEndScrollIdle("ScCsvTableBox maEndScrollIdle")
31 const OutputDevice
& rRefDev
= mxGrid
->GetDrawingArea()->get_ref_device();
32 Size
aSize(rRefDev
.approximate_digit_width() * 67,
33 rRefDev
.GetTextHeight() * 10);
34 // this needs to be larger than the ScCsvGrid initial size to get it
35 // to stretch to fit, see ScCsvGrid::SetDrawingArea
36 mxScroll
->set_size_request(aSize
.Width(), aSize
.Height());
41 Link
<ScCsvControl
&,void> aLink
= LINK( this, ScCsvTableBox
, CsvCmdHdl
);
42 mxRuler
->SetCmdHdl( aLink
);
43 mxGrid
->SetCmdHdl( aLink
);
45 mxScroll
->connect_hadjustment_changed(LINK(this, ScCsvTableBox
, HScrollHdl
));
46 mxScroll
->connect_vadjustment_changed(LINK(this, ScCsvTableBox
, VScrollHdl
));
48 maEndScrollIdle
.SetPriority(TaskPriority::LOWEST
);
49 maEndScrollIdle
.SetInvokeHandler(LINK(this,ScCsvTableBox
,ScrollEndHdl
));
54 ScCsvTableBox::~ScCsvTableBox()
58 // common table box handling --------------------------------------------------
60 void ScCsvTableBox::Refresh()
62 mxGrid
->DisableRepaint();
63 mxGrid
->Execute( CSVCMD_SETLINEOFFSET
, 0 );
66 mxGrid
->Execute( CSVCMD_SETPOSCOUNT
, mnFixedWidth
);
67 mxGrid
->SetSplits( mxRuler
->GetSplits() );
68 mxGrid
->SetColumnStates( std::vector(maFixColStates
) );
72 mxGrid
->Execute( CSVCMD_SETPOSCOUNT
, 1 );
73 mxGrid
->Execute( CSVCMD_NEWCELLTEXTS
);
74 mxGrid
->SetColumnStates( std::vector(maSepColStates
) );
77 mxGrid
->EnableRepaint();
80 void ScCsvTableBox::SetSeparatorsMode()
85 // rescue data for fixed width mode
86 mnFixedWidth
= mxGrid
->GetPosCount();
87 maFixColStates
= mxGrid
->GetColumnStates();
88 // switch to separators mode
90 // reset and reinitialize controls
94 void ScCsvTableBox::SetFixedWidthMode()
99 // rescue data for separators mode
100 maSepColStates
= mxGrid
->GetColumnStates();
101 // switch to fixed width mode
103 // reset and reinitialize controls
107 void ScCsvTableBox::Init()
112 void ScCsvTableBox::InitControls()
114 mxGrid
->UpdateLayoutData();
122 Size aWinSize
= mxGrid
->GetOutputSizePixel();
123 maData
.mnWinWidth
= aWinSize
.Width();
124 maData
.mnWinHeight
= aWinSize
.Height();
126 // scrollbars always visible
129 // scrollbars always visible
132 // let the controls self-adjust to visible area
133 mxGrid
->Execute( CSVCMD_SETPOSOFFSET
, mxGrid
->GetFirstVisPos() );
134 mxGrid
->Execute( CSVCMD_SETLINEOFFSET
, mxGrid
->GetFirstVisLine() );
137 void ScCsvTableBox::InitHScrollBar()
140 int nValue
= mxGrid
->GetFirstVisPos();
141 int nUpper
= mxGrid
->GetPosCount() + 2;
142 int nPageSize
= mxGrid
->GetVisPosCount();
144 // Undo scrollbar RTL
145 if (AllSettings::GetLayoutRTL())
146 nValue
= nUpper
- (nValue
- nLower
+ nPageSize
);
148 mxScroll
->hadjustment_configure(nValue
, nLower
, nUpper
,
149 1, mxGrid
->GetVisPosCount() * 3 / 4,
153 void ScCsvTableBox::InitVScrollBar()
155 mxScroll
->vadjustment_configure(mxGrid
->GetFirstVisLine(), 0, mxGrid
->GetLineCount() + 1,
156 1, mxGrid
->GetVisLineCount() - 2,
157 mxGrid
->GetVisLineCount());
160 void ScCsvTableBox::MakePosVisible( sal_Int32 nPos
)
162 if( (0 <= nPos
) && (nPos
< mxGrid
->GetPosCount()) )
164 if( nPos
- CSV_SCROLL_DIST
+ 1 <= mxGrid
->GetFirstVisPos() )
165 mxGrid
->Execute( CSVCMD_SETPOSOFFSET
, nPos
- CSV_SCROLL_DIST
);
166 else if( nPos
+ CSV_SCROLL_DIST
>= mxGrid
->GetLastVisPos() )
167 mxGrid
->Execute( CSVCMD_SETPOSOFFSET
, nPos
- mxGrid
->GetVisPosCount() + CSV_SCROLL_DIST
);
171 // cell contents --------------------------------------------------------------
173 void ScCsvTableBox::SetUniStrings(
174 const OUString
* pTextLines
, const OUString
& rSepChars
,
175 sal_Unicode cTextSep
, bool bMergeSep
, bool bRemoveSpace
)
177 // assuming that pTextLines is a string array with size CSV_PREVIEW_LINES
178 // -> will be dynamic sometime
179 mxGrid
->DisableRepaint();
180 sal_Int32 nEndLine
= mxGrid
->GetFirstVisLine() + CSV_PREVIEW_LINES
;
181 const OUString
* pString
= pTextLines
;
182 for( sal_Int32 nLine
= mxGrid
->GetFirstVisLine(); nLine
< nEndLine
; ++nLine
, ++pString
)
185 mxGrid
->ImplSetTextLineFix( nLine
, *pString
);
187 mxGrid
->ImplSetTextLineSep( nLine
, *pString
, rSepChars
, cTextSep
, bMergeSep
, bRemoveSpace
);
189 mxGrid
->EnableRepaint();
192 // column settings ------------------------------------------------------------
194 void ScCsvTableBox::InitTypes(const weld::ComboBox
& rListBox
)
196 const sal_Int32 nTypeCount
= rListBox
.get_count();
197 std::vector
<OUString
> aTypeNames( nTypeCount
);
198 for( sal_Int32 nIndex
= 0; nIndex
< nTypeCount
; ++nIndex
)
199 aTypeNames
[ nIndex
] = rListBox
.get_text( nIndex
);
200 mxGrid
->SetTypeNames( std::move(aTypeNames
) );
203 void ScCsvTableBox::FillColumnData( ScAsciiOptions
& rOptions
) const
206 mxGrid
->FillColumnDataFix( rOptions
);
208 mxGrid
->FillColumnDataSep( rOptions
);
211 // event handling -------------------------------------------------------------
213 IMPL_LINK( ScCsvTableBox
, CsvCmdHdl
, ScCsvControl
&, rCtrl
, void )
215 const ScCsvCmd
& rCmd
= rCtrl
.GetCmd();
216 ScCsvCmdType eType
= rCmd
.GetType();
217 sal_Int32 nParam1
= rCmd
.GetParam1();
218 sal_Int32 nParam2
= rCmd
.GetParam2();
224 if( !mxGrid
->IsNoRepaint() )
226 mxGrid
->Invalidate();
227 mxRuler
->Invalidate();
232 case CSVCMD_MAKEPOSVISIBLE
:
233 MakePosVisible( nParam1
);
236 case CSVCMD_NEWCELLTEXTS
:
238 mxGrid
->Execute( CSVCMD_UPDATECELLTEXTS
);
241 mxGrid
->DisableRepaint();
242 ScCsvColStateVec
aStates( mxGrid
->GetColumnStates() );
243 sal_Int32 nPos
= mxGrid
->GetFirstVisPos();
244 mxGrid
->Execute( CSVCMD_SETPOSCOUNT
, 1 );
245 mxGrid
->Execute( CSVCMD_UPDATECELLTEXTS
);
246 mxGrid
->Execute( CSVCMD_SETPOSOFFSET
, nPos
);
247 mxGrid
->SetColumnStates( std::move(aStates
) );
248 mxGrid
->EnableRepaint();
251 case CSVCMD_UPDATECELLTEXTS
:
252 maUpdateTextHdl
.Call( *this );
254 case CSVCMD_SETCOLUMNTYPE
:
255 mxGrid
->SetSelColumnType( nParam1
);
257 case CSVCMD_EXPORTCOLUMNTYPE
:
258 maColTypeHdl
.Call( *this );
260 case CSVCMD_SETFIRSTIMPORTLINE
:
261 mxGrid
->SetFirstImportedLine( nParam1
);
264 case CSVCMD_INSERTSPLIT
:
265 OSL_ENSURE( mbFixedMode
, "ScCsvTableBox::CsvCmdHdl::InsertSplit - invalid call" );
266 if( mxRuler
->GetSplitCount() + 1 < sal::static_int_cast
<sal_uInt32
>(CSV_MAXCOLCOUNT
) )
268 mxRuler
->InsertSplit( nParam1
);
269 mxGrid
->InsertSplit( nParam1
);
272 case CSVCMD_REMOVESPLIT
:
273 OSL_ENSURE( mbFixedMode
, "ScCsvTableBox::CsvCmdHdl::RemoveSplit - invalid call" );
274 mxRuler
->RemoveSplit( nParam1
);
275 mxGrid
->RemoveSplit( nParam1
);
277 case CSVCMD_TOGGLESPLIT
:
278 mxGrid
->Execute( mxRuler
->HasSplit( nParam1
) ? CSVCMD_REMOVESPLIT
: CSVCMD_INSERTSPLIT
, nParam1
);
280 case CSVCMD_MOVESPLIT
:
281 OSL_ENSURE( mbFixedMode
, "ScCsvTableBox::CsvCmdHdl::MoveSplit - invalid call" );
282 mxRuler
->MoveSplit( nParam1
, nParam2
);
283 mxGrid
->MoveSplit( nParam1
, nParam2
);
285 case CSVCMD_REMOVEALLSPLITS
:
286 OSL_ENSURE( mbFixedMode
, "ScCsvTableBox::CsvCmdHdl::RemoveAllSplits - invalid call" );
287 mxRuler
->RemoveAllSplits();
288 mxGrid
->RemoveAllSplits();
296 const ScCsvLayoutData
aOldData( maData
);
299 case CSVCMD_SETPOSCOUNT
:
300 maData
.mnPosCount
= std::max( nParam1
, sal_Int32( 1 ) );
301 ImplSetPosOffset( mxGrid
->GetFirstVisPos() );
303 case CSVCMD_SETPOSOFFSET
:
304 ImplSetPosOffset( nParam1
);
306 case CSVCMD_SETHDRWIDTH
:
307 maData
.mnHdrWidth
= std::max( nParam1
, sal_Int32( 0 ) );
308 ImplSetPosOffset( mxGrid
->GetFirstVisPos() );
310 case CSVCMD_SETCHARWIDTH
:
311 maData
.mnCharWidth
= std::max( nParam1
, sal_Int32( 1 ) );
312 ImplSetPosOffset( mxGrid
->GetFirstVisPos() );
314 case CSVCMD_SETLINECOUNT
:
315 maData
.mnLineCount
= std::max( nParam1
, sal_Int32( 1 ) );
316 ImplSetLineOffset( mxGrid
->GetFirstVisLine() );
318 case CSVCMD_SETLINEOFFSET
:
319 ImplSetLineOffset( nParam1
);
321 case CSVCMD_SETHDRHEIGHT
:
322 maData
.mnHdrHeight
= std::max( nParam1
, sal_Int32( 0 ) );
323 ImplSetLineOffset( mxGrid
->GetFirstVisLine() );
325 case CSVCMD_SETLINEHEIGHT
:
326 maData
.mnLineHeight
= std::max( nParam1
, sal_Int32( 1 ) );
327 ImplSetLineOffset( mxGrid
->GetFirstVisLine() );
329 case CSVCMD_MOVERULERCURSOR
:
330 maData
.mnPosCursor
= mxGrid
->IsVisibleSplitPos( nParam1
) ? nParam1
: CSV_POS_INVALID
;
332 case CSVCMD_MOVEGRIDCURSOR
:
333 maData
.mnColCursor
= ((0 <= nParam1
) && (nParam1
< mxGrid
->GetPosCount())) ? nParam1
: CSV_POS_INVALID
;
337 // added to avoid warnings
341 if( maData
!= aOldData
)
343 mxGrid
->DisableRepaint();
344 mxRuler
->ApplyLayout( aOldData
);
345 mxGrid
->ApplyLayout( aOldData
);
346 mxGrid
->EnableRepaint();
350 IMPL_LINK(ScCsvTableBox
, HScrollHdl
, weld::ScrolledWindow
&, rScroll
, void)
353 int nValue
= rScroll
.hadjustment_get_value();
354 int nUpper
= mxGrid
->GetPosCount() + 2;
355 int nPageSize
= mxGrid
->GetVisPosCount();
357 // Undo scrollbar RTL
358 if (AllSettings::GetLayoutRTL())
359 nValue
= nUpper
- (nValue
- nLower
+ nPageSize
);
361 mxGrid
->Execute(CSVCMD_SETPOSOFFSET
, nValue
);
362 maEndScrollIdle
.Start();
365 IMPL_LINK(ScCsvTableBox
, VScrollHdl
, weld::ScrolledWindow
&, rScroll
, void)
367 mxGrid
->Execute(CSVCMD_SETLINEOFFSET
, rScroll
.vadjustment_get_value());
370 IMPL_LINK_NOARG(ScCsvTableBox
, ScrollEndHdl
, Timer
*, void)
372 if( mxGrid
->GetRulerCursorPos() != CSV_POS_INVALID
)
373 mxGrid
->Execute( CSVCMD_MOVERULERCURSOR
, mxRuler
->GetNoScrollPos( mxGrid
->GetRulerCursorPos() ) );
374 if( mxGrid
->GetGridCursorPos() != CSV_POS_INVALID
)
375 mxGrid
->Execute( CSVCMD_MOVEGRIDCURSOR
, mxGrid
->GetNoScrollCol( mxGrid
->GetGridCursorPos() ) );
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */