1
0
Fork 0
libreoffice/sc/source/ui/dbgui/csvtablebox.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

378 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <csvtablebox.hxx>
#include <vcl/settings.hxx>
ScCsvTableBox::ScCsvTableBox(weld::Builder& rBuilder)
: mxRuler(new ScCsvRuler(maData, this))
, mxGrid(new ScCsvGrid(maData, rBuilder.weld_menu(u"popup"_ustr), this))
, mxScroll(rBuilder.weld_scrolled_window(u"scrolledwindow"_ustr, true))
, mxRulerWeld(new weld::CustomWeld(rBuilder, u"csvruler"_ustr, *mxRuler))
, mxGridWeld(new weld::CustomWeld(rBuilder, u"csvgrid"_ustr, *mxGrid))
, maEndScrollIdle("ScCsvTableBox maEndScrollIdle")
{
const OutputDevice& rRefDev = mxGrid->GetDrawingArea()->get_ref_device();
Size aSize(rRefDev.approximate_digit_width() * 67,
rRefDev.GetTextHeight() * 10);
// this needs to be larger than the ScCsvGrid initial size to get it
// to stretch to fit, see ScCsvGrid::SetDrawingArea
mxScroll->set_size_request(aSize.Width(), aSize.Height());
mbFixedMode = false;
mnFixedWidth = 1;
Link<ScCsvControl&,void> aLink = LINK( this, ScCsvTableBox, CsvCmdHdl );
mxRuler->SetCmdHdl( aLink );
mxGrid->SetCmdHdl( aLink );
mxScroll->connect_hadjustment_changed(LINK(this, ScCsvTableBox, HScrollHdl));
mxScroll->connect_vadjustment_changed(LINK(this, ScCsvTableBox, VScrollHdl));
maEndScrollIdle.SetPriority(TaskPriority::LOWEST);
maEndScrollIdle.SetInvokeHandler(LINK(this,ScCsvTableBox,ScrollEndHdl));
InitControls();
}
ScCsvTableBox::~ScCsvTableBox()
{
}
// common table box handling --------------------------------------------------
void ScCsvTableBox::Refresh()
{
mxGrid->DisableRepaint();
mxGrid->Execute( CSVCMD_SETLINEOFFSET, 0 );
if (mbFixedMode)
{
mxGrid->Execute( CSVCMD_SETPOSCOUNT, mnFixedWidth );
mxGrid->SetSplits( mxRuler->GetSplits() );
mxGrid->SetColumnStates( std::vector(maFixColStates) );
}
else
{
mxGrid->Execute( CSVCMD_SETPOSCOUNT, 1 );
mxGrid->Execute( CSVCMD_NEWCELLTEXTS );
mxGrid->SetColumnStates( std::vector(maSepColStates) );
}
InitControls();
mxGrid->EnableRepaint();
}
void ScCsvTableBox::SetSeparatorsMode()
{
if( !mbFixedMode )
return;
// rescue data for fixed width mode
mnFixedWidth = mxGrid->GetPosCount();
maFixColStates = mxGrid->GetColumnStates();
// switch to separators mode
mbFixedMode = false;
// reset and reinitialize controls
Refresh();
}
void ScCsvTableBox::SetFixedWidthMode()
{
if( mbFixedMode )
return;
// rescue data for separators mode
maSepColStates = mxGrid->GetColumnStates();
// switch to fixed width mode
mbFixedMode = true;
// reset and reinitialize controls
Refresh();
}
void ScCsvTableBox::Init()
{
mxGrid->Init();
}
void ScCsvTableBox::InitControls()
{
mxGrid->UpdateLayoutData();
mxGrid->Show();
if (mbFixedMode)
mxRuler->Show();
else
mxRuler->Hide();
Size aWinSize = mxGrid->GetOutputSizePixel();
maData.mnWinWidth = aWinSize.Width();
maData.mnWinHeight = aWinSize.Height();
// scrollbars always visible
InitHScrollBar();
// scrollbars always visible
InitVScrollBar();
// let the controls self-adjust to visible area
mxGrid->Execute( CSVCMD_SETPOSOFFSET, mxGrid->GetFirstVisPos() );
mxGrid->Execute( CSVCMD_SETLINEOFFSET, mxGrid->GetFirstVisLine() );
}
void ScCsvTableBox::InitHScrollBar()
{
int nLower = 0;
int nValue = mxGrid->GetFirstVisPos();
int nUpper = mxGrid->GetPosCount() + 2;
int nPageSize = mxGrid->GetVisPosCount();
// Undo scrollbar RTL
if (AllSettings::GetLayoutRTL())
nValue = nUpper - (nValue - nLower + nPageSize);
mxScroll->hadjustment_configure(nValue, nLower, nUpper,
1, mxGrid->GetVisPosCount() * 3 / 4,
nPageSize);
}
void ScCsvTableBox::InitVScrollBar()
{
mxScroll->vadjustment_configure(mxGrid->GetFirstVisLine(), 0, mxGrid->GetLineCount() + 1,
1, mxGrid->GetVisLineCount() - 2,
mxGrid->GetVisLineCount());
}
void ScCsvTableBox::MakePosVisible( sal_Int32 nPos )
{
if( (0 <= nPos) && (nPos < mxGrid->GetPosCount()) )
{
if( nPos - CSV_SCROLL_DIST + 1 <= mxGrid->GetFirstVisPos() )
mxGrid->Execute( CSVCMD_SETPOSOFFSET, nPos - CSV_SCROLL_DIST );
else if( nPos + CSV_SCROLL_DIST >= mxGrid->GetLastVisPos() )
mxGrid->Execute( CSVCMD_SETPOSOFFSET, nPos - mxGrid->GetVisPosCount() + CSV_SCROLL_DIST );
}
}
// cell contents --------------------------------------------------------------
void ScCsvTableBox::SetUniStrings(
const OUString* pTextLines, const OUString& rSepChars,
sal_Unicode cTextSep, bool bMergeSep, bool bRemoveSpace )
{
// assuming that pTextLines is a string array with size CSV_PREVIEW_LINES
// -> will be dynamic sometime
mxGrid->DisableRepaint();
sal_Int32 nEndLine = mxGrid->GetFirstVisLine() + CSV_PREVIEW_LINES;
const OUString* pString = pTextLines;
for( sal_Int32 nLine = mxGrid->GetFirstVisLine(); nLine < nEndLine; ++nLine, ++pString )
{
if( mbFixedMode )
mxGrid->ImplSetTextLineFix( nLine, *pString );
else
mxGrid->ImplSetTextLineSep( nLine, *pString, rSepChars, cTextSep, bMergeSep, bRemoveSpace );
}
mxGrid->EnableRepaint();
}
// column settings ------------------------------------------------------------
void ScCsvTableBox::InitTypes(const weld::ComboBox& rListBox)
{
const sal_Int32 nTypeCount = rListBox.get_count();
std::vector<OUString> aTypeNames( nTypeCount );
for( sal_Int32 nIndex = 0; nIndex < nTypeCount; ++nIndex )
aTypeNames[ nIndex ] = rListBox.get_text( nIndex );
mxGrid->SetTypeNames( std::move(aTypeNames) );
}
void ScCsvTableBox::FillColumnData( ScAsciiOptions& rOptions ) const
{
if( mbFixedMode )
mxGrid->FillColumnDataFix( rOptions );
else
mxGrid->FillColumnDataSep( rOptions );
}
// event handling -------------------------------------------------------------
IMPL_LINK( ScCsvTableBox, CsvCmdHdl, ScCsvControl&, rCtrl, void )
{
const ScCsvCmd& rCmd = rCtrl.GetCmd();
ScCsvCmdType eType = rCmd.GetType();
sal_Int32 nParam1 = rCmd.GetParam1();
sal_Int32 nParam2 = rCmd.GetParam2();
bool bFound = true;
switch( eType )
{
case CSVCMD_REPAINT:
if( !mxGrid->IsNoRepaint() )
{
mxGrid->Invalidate();
mxRuler->Invalidate();
InitHScrollBar();
InitVScrollBar();
}
break;
case CSVCMD_MAKEPOSVISIBLE:
MakePosVisible( nParam1 );
break;
case CSVCMD_NEWCELLTEXTS:
if( mbFixedMode )
mxGrid->Execute( CSVCMD_UPDATECELLTEXTS );
else
{
mxGrid->DisableRepaint();
ScCsvColStateVec aStates( mxGrid->GetColumnStates() );
sal_Int32 nPos = mxGrid->GetFirstVisPos();
mxGrid->Execute( CSVCMD_SETPOSCOUNT, 1 );
mxGrid->Execute( CSVCMD_UPDATECELLTEXTS );
mxGrid->Execute( CSVCMD_SETPOSOFFSET, nPos );
mxGrid->SetColumnStates( std::move(aStates) );
mxGrid->EnableRepaint();
}
break;
case CSVCMD_UPDATECELLTEXTS:
maUpdateTextHdl.Call( *this );
break;
case CSVCMD_SETCOLUMNTYPE:
mxGrid->SetSelColumnType( nParam1 );
break;
case CSVCMD_EXPORTCOLUMNTYPE:
maColTypeHdl.Call( *this );
break;
case CSVCMD_SETFIRSTIMPORTLINE:
mxGrid->SetFirstImportedLine( nParam1 );
break;
case CSVCMD_INSERTSPLIT:
OSL_ENSURE( mbFixedMode, "ScCsvTableBox::CsvCmdHdl::InsertSplit - invalid call" );
if( mxRuler->GetSplitCount() + 1 < sal::static_int_cast<sal_uInt32>(CSV_MAXCOLCOUNT) )
{
mxRuler->InsertSplit( nParam1 );
mxGrid->InsertSplit( nParam1 );
}
break;
case CSVCMD_REMOVESPLIT:
OSL_ENSURE( mbFixedMode, "ScCsvTableBox::CsvCmdHdl::RemoveSplit - invalid call" );
mxRuler->RemoveSplit( nParam1 );
mxGrid->RemoveSplit( nParam1 );
break;
case CSVCMD_TOGGLESPLIT:
mxGrid->Execute( mxRuler->HasSplit( nParam1 ) ? CSVCMD_REMOVESPLIT : CSVCMD_INSERTSPLIT, nParam1 );
break;
case CSVCMD_MOVESPLIT:
OSL_ENSURE( mbFixedMode, "ScCsvTableBox::CsvCmdHdl::MoveSplit - invalid call" );
mxRuler->MoveSplit( nParam1, nParam2 );
mxGrid->MoveSplit( nParam1, nParam2 );
break;
case CSVCMD_REMOVEALLSPLITS:
OSL_ENSURE( mbFixedMode, "ScCsvTableBox::CsvCmdHdl::RemoveAllSplits - invalid call" );
mxRuler->RemoveAllSplits();
mxGrid->RemoveAllSplits();
break;
default:
bFound = false;
}
if( bFound )
return;
const ScCsvLayoutData aOldData( maData );
switch( eType )
{
case CSVCMD_SETPOSCOUNT:
maData.mnPosCount = std::max( nParam1, sal_Int32( 1 ) );
ImplSetPosOffset( mxGrid->GetFirstVisPos() );
break;
case CSVCMD_SETPOSOFFSET:
ImplSetPosOffset( nParam1 );
break;
case CSVCMD_SETHDRWIDTH:
maData.mnHdrWidth = std::max( nParam1, sal_Int32( 0 ) );
ImplSetPosOffset( mxGrid->GetFirstVisPos() );
break;
case CSVCMD_SETCHARWIDTH:
maData.mnCharWidth = std::max( nParam1, sal_Int32( 1 ) );
ImplSetPosOffset( mxGrid->GetFirstVisPos() );
break;
case CSVCMD_SETLINECOUNT:
maData.mnLineCount = std::max( nParam1, sal_Int32( 1 ) );
ImplSetLineOffset( mxGrid->GetFirstVisLine() );
break;
case CSVCMD_SETLINEOFFSET:
ImplSetLineOffset( nParam1 );
break;
case CSVCMD_SETHDRHEIGHT:
maData.mnHdrHeight = std::max( nParam1, sal_Int32( 0 ) );
ImplSetLineOffset( mxGrid->GetFirstVisLine() );
break;
case CSVCMD_SETLINEHEIGHT:
maData.mnLineHeight = std::max( nParam1, sal_Int32( 1 ) );
ImplSetLineOffset( mxGrid->GetFirstVisLine() );
break;
case CSVCMD_MOVERULERCURSOR:
maData.mnPosCursor = mxGrid->IsVisibleSplitPos( nParam1 ) ? nParam1 : CSV_POS_INVALID;
break;
case CSVCMD_MOVEGRIDCURSOR:
maData.mnColCursor = ((0 <= nParam1) && (nParam1 < mxGrid->GetPosCount())) ? nParam1 : CSV_POS_INVALID;
break;
default:
{
// added to avoid warnings
}
}
if( maData != aOldData )
{
mxGrid->DisableRepaint();
mxRuler->ApplyLayout( aOldData );
mxGrid->ApplyLayout( aOldData );
mxGrid->EnableRepaint();
}
}
IMPL_LINK(ScCsvTableBox, HScrollHdl, weld::ScrolledWindow&, rScroll, void)
{
int nLower = 0;
int nValue = rScroll.hadjustment_get_value();
int nUpper = mxGrid->GetPosCount() + 2;
int nPageSize = mxGrid->GetVisPosCount();
// Undo scrollbar RTL
if (AllSettings::GetLayoutRTL())
nValue = nUpper - (nValue - nLower + nPageSize);
mxGrid->Execute(CSVCMD_SETPOSOFFSET, nValue);
maEndScrollIdle.Start();
}
IMPL_LINK(ScCsvTableBox, VScrollHdl, weld::ScrolledWindow&, rScroll, void)
{
mxGrid->Execute(CSVCMD_SETLINEOFFSET, rScroll.vadjustment_get_value());
}
IMPL_LINK_NOARG(ScCsvTableBox, ScrollEndHdl, Timer*, void)
{
if( mxGrid->GetRulerCursorPos() != CSV_POS_INVALID )
mxGrid->Execute( CSVCMD_MOVERULERCURSOR, mxRuler->GetNoScrollPos( mxGrid->GetRulerCursorPos() ) );
if( mxGrid->GetGridCursorPos() != CSV_POS_INVALID )
mxGrid->Execute( CSVCMD_MOVEGRIDCURSOR, mxGrid->GetNoScrollCol( mxGrid->GetGridCursorPos() ) );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */