diff options
Diffstat (limited to 'sc/source/ui/dbgui/csvtablebox.cxx')
-rw-r--r-- | sc/source/ui/dbgui/csvtablebox.cxx | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/sc/source/ui/dbgui/csvtablebox.cxx b/sc/source/ui/dbgui/csvtablebox.cxx new file mode 100644 index 000000000..10dba1b81 --- /dev/null +++ b/sc/source/ui/dbgui/csvtablebox.cxx @@ -0,0 +1,369 @@ +/* -*- 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("popup"), this)) + , mxScroll(rBuilder.weld_scrolled_window("scrolledwindow", true)) + , mxRulerWeld(new weld::CustomWeld(rBuilder, "csvruler", *mxRuler)) + , mxGridWeld(new weld::CustomWeld(rBuilder, "csvgrid", *mxGrid)) + , maEndScrollIdle("ScCsvTableBox maEndScrollIdle") +{ + Size aSize(mxScroll->get_approximate_digit_width() * 67, + mxScroll->get_text_height() * 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::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 + mxGrid->DisableRepaint(); + mxGrid->Execute( CSVCMD_SETLINEOFFSET, 0 ); + mxGrid->Execute( CSVCMD_SETPOSCOUNT, 1 ); + mxGrid->Execute( CSVCMD_NEWCELLTEXTS ); + mxGrid->SetColumnStates( std::vector(maSepColStates) ); + InitControls(); + mxGrid->EnableRepaint(); +} + +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 + mxGrid->DisableRepaint(); + mxGrid->Execute( CSVCMD_SETLINEOFFSET, 0 ); + mxGrid->Execute( CSVCMD_SETPOSCOUNT, mnFixedWidth ); + mxGrid->SetSplits( mxRuler->GetSplits() ); + mxGrid->SetColumnStates( std::vector(maFixColStates) ); + InitControls(); + mxGrid->EnableRepaint(); +} + +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: */ |