cui/source/inc/numpages.hxx | 2 cui/source/tabpages/numpages.cxx | 353 -------------------------- include/svx/numberingpreview.hxx | 17 - sc/source/ui/inc/viewfunc.hxx | 7 sc/source/ui/view/viewfunc.cxx | 402 ++++++++++++++++++------------ sd/source/ui/inc/BulletAndPositionDlg.hxx | 2 svx/source/dialog/pagenumberlistbox.cxx | 385 ++++++++++++++++++++++++++++ 7 files changed, 643 insertions(+), 525 deletions(-)
New commits: commit b39c6082aa975ed8e5696c3dc24c3025ed07bbb6 Author: codewithvk <vivek.jav...@collabora.com> AuthorDate: Thu Jan 11 10:27:27 2024 +0530 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Wed Jan 31 10:33:48 2024 +0100 Implement Async AutoCorrectQuery Dialogs for Formula Check in calc Key changes include: 1. Decomposition into Four Methods: The core logic of formula processing `ScViewFunc::EnterData` has been divided into four distinct methods: `parseAndCorrectFormula`, `runAutoCorrectQueryAsync`, `finalizeFormulaProcessing`, and `performAutoFormatAndUpdate`. This modular approach improves code readability and maintainability. 2. Introduction of `FormulaProcessingContext` Struct: To manage the complexities of asynchronous behavior and parameter passing, a new struct `FormulaProcessingContext` has been introduced. It acts as a central state holder, ensuring parameter persistence throughout the asynchronous operations and avoiding scope-related errors. 3. Recursive Dependency and Loop Replacement: The methods `parseAndCorrectFormula` and `runAutoCorrectQueryAsync` are interdependent and recursively call each other. This recursive strategy effectively replaces the previous `do while` loop in the code, streamlining the process of formula correction. 4. Asynchronous Dialog Invocation: The `runAutoCorrectQueryAsync` method now handles the asynchronous triggering of AutoCorrectQuery dialogs. This change significantly improves the user experience by preventing UI freezes during formula processing. Overall, this commit achieves the goal of making AutoCorrectQuery dialogs asynchronous while refactoring `ScViewFunc::EnterData` for better code structure and performance. Signed-off-by: codewithvk <vivek.jav...@collabora.com> Change-Id: If159b98d54c0eaed41789eca7913a929b1e19c1c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162740 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index 117cd407bbd8..82d202b2df8e 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -345,6 +345,10 @@ public: void OnLOKInsertDeleteRow(SCROW nStartRow, tools::Long nOffset); void OnLOKSetWidthOrHeight(SCCOLROW nStart, bool bWidth); + bool TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrChanged ); + void DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab, + bool bAttrChanged ); + // Internal helper functions protected: static void UpdateLineAttrs( ::editeng::SvxBorderLine& rLine, @@ -381,9 +385,6 @@ private: sal_uInt16 GetOptimalColWidth( SCCOL nCol, SCTAB nTab, bool bFormula ); void StartFormatArea(); - bool TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrChanged ); - void DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab, - bool bAttrChanged ); void MarkAndJumpToRanges(const ScRangeList& rRanges); void CopyAutoSpellData( FillDir eDir, SCCOL nStartCol, SCROW nStartRow, diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index a6d28ecbc37b..ed5de281b5bc 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -136,6 +136,46 @@ ScViewFunc::~ScViewFunc() namespace { +struct FormulaProcessingContext +{ + std::shared_ptr<ScAddress> aPos; + std::shared_ptr<ScCompiler> aComp; + std::shared_ptr<ScDocShellModificator> aModificator; + std::shared_ptr<ScTokenArray> pArr; + std::shared_ptr<ScTokenArray> pArrFirst; + + const EditTextObject* pData; + ScMarkData aMark; + ScViewFunc& rViewFunc; + + OUString aCorrectedFormula; + OUString aFormula; + OUString aString; + + SCCOL nCol; + SCROW nRow; + SCTAB nTab; + + bool bMatrixExpand; + bool bNumFmtChanged; + bool bRecord; + + ScViewData& GetViewData() const + { + return rViewFunc.GetViewData(); + } + + ScDocFunc& GetDocFunc() const + { + return GetViewData().GetDocFunc(); + } + + ScDocument& GetDoc() const + { + return GetViewData().GetDocument(); + } +}; + void collectUIInformation(std::map<OUString, OUString>&& aParameters, const OUString& rAction) { EventDescription aDescription; @@ -358,7 +398,7 @@ static bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode ) namespace HelperNotifyChanges { - static void NotifyIfChangesListeners(const ScDocShell &rDocShell, ScMarkData& rMark, + static void NotifyIfChangesListeners(const ScDocShell &rDocShell, const ScMarkData& rMark, SCCOL nCol, SCROW nRow, const OUString& rType = "cell-change") { ScModelObj* pModelObj = rDocShell.GetModel(); @@ -398,134 +438,41 @@ namespace } }; } - -// actual functions - -// input - undo OK -void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, - const OUString& rString, - const EditTextObject* pData, - bool bMatrixExpand ) +namespace { - ScDocument& rDoc = GetViewData().GetDocument(); - ScMarkData rMark(GetViewData().GetMarkData()); - bool bRecord = rDoc.IsUndoEnabled(); - SCTAB i; + void runAutoCorrectQueryAsync(std::shared_ptr<FormulaProcessingContext> context); - ScDocShell* pDocSh = GetViewData().GetDocShell(); - ScDocFunc &rFunc = GetViewData().GetDocFunc(); - ScDocShellModificator aModificator( *pDocSh ); - - ScEditableTester aTester( rDoc, nCol,nRow, nCol,nRow, rMark ); - if (!aTester.IsEditable()) + void performAutoFormatAndUpdate(std::u16string_view rString, const ScMarkData& rMark, SCCOL nCol, + SCROW nRow, SCTAB nTab, bool bNumFmtChanged, bool bRecord, + const std::shared_ptr<ScDocShellModificator>& pModificator, + ScViewFunc& rViewFunc) { - ErrorMessage(aTester.GetMessageId()); - PaintArea(nCol, nRow, nCol, nRow); // possibly the edit-engine is still painted there - return; - } + bool bAutoFormat = rViewFunc.TestFormatArea(nCol, nRow, nTab, bNumFmtChanged); - if ( bRecord ) - rFunc.EnterListAction( STR_UNDO_ENTERDATA ); + if (bAutoFormat) + rViewFunc.DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged); - bool bFormula = false; + ScViewData& rViewData = rViewFunc.GetViewData(); + ScDocShell* pDocSh = rViewData.GetDocShell(); + pDocSh->UpdateOle(rViewData); - // do not check formula if it is a text cell - sal_uInt32 format = rDoc.GetNumberFormat( nCol, nRow, nTab ); - SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); - // a single '=' character is handled as string (needed for special filters) - if ( pFormatter->GetType(format) != SvNumFormatType::TEXT && rString.getLength() > 1 ) - { - if ( rString[0] == '=' ) + const OUString aType(rString.empty() ? u"delete-content" : u"cell-change"); + HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow, aType); + + if (bRecord) { - // handle as formula - bFormula = true; + ScDocFunc &rFunc = rViewData.GetDocFunc(); + rFunc.EndListAction(); } - else if ( rString[0] == '+' || rString[0] == '-' ) - { - // if there is more than one leading '+' or '-' character, remove the additional ones - sal_Int32 nIndex = 1; - sal_Int32 nLen = rString.getLength(); - while ( nIndex < nLen && ( rString[ nIndex ] == '+' || rString[ nIndex ] == '-' ) ) - { - ++nIndex; - } - OUString aString = rString.replaceAt( 1, nIndex - 1, u"" ); - // if the remaining part without the leading '+' or '-' character - // is non-empty and not a number, handle as formula - if ( aString.getLength() > 1 ) - { - double fNumber = 0; - if ( !pFormatter->IsNumberFormat( aString, format, fNumber ) ) - { - bFormula = true; - } - } - } + pModificator->SetDocumentModified(); + ScDocument& rDoc = rViewData.GetDocument(); + lcl_PostRepaintCondFormat(rDoc.GetCondFormat(nCol, nRow, nTab), pDocSh); + lcl_PostRepaintSparkLine(rDoc.GetSparklineList(nTab), ScRange(nCol, nRow, nTab), pDocSh); } - bool bNumFmtChanged = false; - if ( bFormula ) - { // formula, compile with autoCorrection - i = rMark.GetFirstSelected(); - ScAddress aPos( nCol, nRow, i ); - ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar(), true, false ); -//2do: enable/disable autoCorrection via calcoptions - aComp.SetAutoCorrection( true ); - if ( rString[0] == '+' || rString[0] == '-' ) - { - aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK ); - } - OUString aFormula( rString ); - std::unique_ptr< ScTokenArray > pArr; - bool bAgain; - do - { - bAgain = false; - bool bAddEqual = false; - pArr = aComp.CompileString( aFormula ); - bool bCorrected = aComp.IsCorrected(); - std::unique_ptr< ScTokenArray > pArrFirst; - if ( bCorrected ) - { // try to parse with first parser-correction - pArrFirst = std::move( pArr ); - pArr = aComp.CompileString( aComp.GetCorrectedFormula() ); - } - if ( pArr->GetCodeError() == FormulaError::NONE ) - { - bAddEqual = true; - aComp.CompileTokenArray(); - bCorrected |= aComp.IsCorrected(); - } - if ( bCorrected ) - { - OUString aCorrectedFormula; - if ( bAddEqual ) - { - aCorrectedFormula = "=" + aComp.GetCorrectedFormula(); - } - else - aCorrectedFormula = aComp.GetCorrectedFormula(); - short nResult; - if ( aCorrectedFormula.getLength() == 1 ) - nResult = RET_NO; // empty formula, just '=' - else - { - AutoCorrectQuery aQueryBox(GetViewData().GetDialogParent(), aCorrectedFormula); - nResult = aQueryBox.run(); - } - if ( nResult == RET_YES ) - { - aFormula = aCorrectedFormula; - bAgain = true; - } - else - { - if ( pArrFirst ) - pArr = std::move( pArrFirst ); - } - } - } while ( bAgain ); + void finalizeFormulaProcessing(std::shared_ptr<FormulaProcessingContext> context) + { // to be used in multiple tabs, the formula must be compiled anew // via ScFormulaCell copy-ctor because of RangeNames, // the same code-array for all cells is not possible. @@ -533,7 +480,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, // cells and the error be set explicitly, so that // via FormulaCell copy-ctor and Interpreter it will be, when possible, // ironed out again, too intelligent... e.g.: =1)) - FormulaError nError = pArr->GetCodeError(); + FormulaError nError = context->pArr->GetCodeError(); if ( nError == FormulaError::NONE ) { // update list of recent functions with all functions that @@ -543,8 +490,8 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, ScAppOptions aAppOpt = pScMod->GetAppOptions(); bool bOptChanged = false; - formula::FormulaToken** ppToken = pArr->GetArray(); - sal_uInt16 nTokens = pArr->GetLen(); + formula::FormulaToken** ppToken = context->pArr->GetArray(); + sal_uInt16 nTokens = context->pArr->GetLen(); sal_uInt16 nLevel = 0; for (sal_uInt16 nTP=0; nTP<nTokens; nTP++) { @@ -564,53 +511,55 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, pScMod->SetAppOptions(aAppOpt); } - if (bMatrixExpand) + if (context->bMatrixExpand) { // If the outer function/operator returns an array/matrix then // enter a matrix formula. ScViewFunc::EnterMatrix() takes care // of selection/mark of the result dimensions or preselected // mark. If the user wanted less or a single cell then should // mark such prior to entering the formula. - const formula::FormulaToken* pToken = pArr->LastRPNToken(); + const formula::FormulaToken* pToken = context->pArr->LastRPNToken(); if (pToken && (formula::FormulaCompiler::IsMatrixFunction( pToken->GetOpCode()) || pToken->IsInForceArray())) { // Discard this (still empty here) Undo action, // EnterMatrix() will create its own. - if (bRecord) - rFunc.EndListAction(); + if (context->bRecord) + context->GetDocFunc().EndListAction(); // Use corrected formula string. - EnterMatrix( aFormula, rDoc.GetGrammar()); + context->rViewFunc.EnterMatrix( context->aFormula, context->GetDoc().GetGrammar()); return; } } } - ScFormulaCell aCell(rDoc, aPos, std::move( pArr ), formula::FormulaGrammar::GRAM_DEFAULT, ScMatrixMode::NONE); + ScFormulaCell aCell(context->GetDoc(), *context->aPos, std::move(*context->pArr), formula::FormulaGrammar::GRAM_DEFAULT, ScMatrixMode::NONE); - for (const auto& rTab : rMark) + SCTAB i; + SvNumberFormatter* pFormatter = context->GetDoc().GetFormatTable(); + for (const auto& rTab : context->aMark) { i = rTab; - aPos.SetTab( i ); - const sal_uInt32 nIndex = rDoc.GetAttr( - nCol, nRow, i, ATTR_VALUE_FORMAT )->GetValue(); + context->aPos->SetTab( i ); + const sal_uInt32 nIndex = context->GetDoc().GetAttr( + context->nCol, context->nRow, i, ATTR_VALUE_FORMAT )->GetValue(); const SvNumFormatType nType = pFormatter->GetType( nIndex); if (nType == SvNumFormatType::TEXT || - ((rString[0] == '+' || rString[0] == '-') && nError != FormulaError::NONE && rString == aFormula)) + ((context->aString[0] == '+' || context->aString[0] == '-') && nError != FormulaError::NONE && context->aString == context->aFormula)) { - if ( pData ) + if ( context->pData ) { - // A clone of pData will be stored in the cell. - rFunc.SetEditCell(aPos, *pData, true); + // A clone of context->pData will be stored in the cell. + context->GetDocFunc().SetEditCell(*(context->aPos), *context->pData, true); } else - rFunc.SetStringCell(aPos, aFormula, true); + context->GetDocFunc().SetStringCell(*(context->aPos), context->aFormula, true); } else { - ScFormulaCell* pCell = new ScFormulaCell( aCell, rDoc, aPos ); + ScFormulaCell* pCell = new ScFormulaCell( aCell, context->GetDoc(), *(context->aPos) ); if ( nError != FormulaError::NONE ) { pCell->GetCode()->DelRPN(); @@ -627,17 +576,166 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const SvNumberformat* pEntry = pFormatter->GetEntry( nIndex); const LanguageType nLang = (pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge); const sal_uInt32 nFormat = pFormatter->GetStandardFormat( SvNumFormatType::NUMBER, nLang); - ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); + ScPatternAttr aPattern(context->GetDoc().getCellAttributeHelper()); aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nFormat)); - ScMarkData aMark(rDoc.GetSheetLimits()); + ScMarkData aMark(context->GetDoc().GetSheetLimits()); aMark.SelectTable( i, true); - aMark.SetMarkArea( ScRange( aPos)); - rFunc.ApplyAttributes( aMark, aPattern, false); - bNumFmtChanged = true; + aMark.SetMarkArea( ScRange( *(context->aPos))); + context->GetDocFunc().ApplyAttributes( aMark, aPattern, false); + context->bNumFmtChanged = true; } - rFunc.SetFormulaCell(aPos, pCell, true); + context->GetDocFunc().SetFormulaCell(*(context->aPos), pCell, true); } } + + performAutoFormatAndUpdate(context->aString, context->aMark, context->nCol, + context->nRow, context->nTab, context->bNumFmtChanged, + context->bRecord, context->aModificator, context->rViewFunc); + } + + void parseAndCorrectFormula(std::shared_ptr<FormulaProcessingContext> context) + { + bool bAddEqual = false; + context->pArr = context->aComp->CompileString(context->aFormula); + bool bCorrected = context->aComp->IsCorrected(); + + if (bCorrected) { + context->pArrFirst = context->pArr; + context->pArr = context->aComp->CompileString(context->aComp->GetCorrectedFormula()); + } + + if (context->pArr->GetCodeError() == FormulaError::NONE) { + bAddEqual = true; + context->aComp->CompileTokenArray(); + bCorrected |= context->aComp->IsCorrected(); + } + + if (bCorrected) { + context->aCorrectedFormula = bAddEqual ? "=" + context->aComp->GetCorrectedFormula() + : context->aComp->GetCorrectedFormula(); + if (context->aCorrectedFormula.getLength() == 1) { + // empty formula, just '=' + if (context->pArrFirst) + context->pArr = context->pArrFirst; + } + else + { + runAutoCorrectQueryAsync(context); + return; + } + } + finalizeFormulaProcessing(context); + } + + void runAutoCorrectQueryAsync(std::shared_ptr<FormulaProcessingContext> context) + { + auto aQueryBox = std::make_shared<AutoCorrectQuery>(context->GetViewData().GetDialogParent(), context->aCorrectedFormula); + weld::DialogController::runAsync(aQueryBox, [context] (int nResult) + { + if (nResult == RET_YES) { + context->aFormula = context->aCorrectedFormula; + parseAndCorrectFormula(context); + } else { + if (context->pArrFirst) + context->pArr = context->pArrFirst; + + finalizeFormulaProcessing(context); + } + }); + } +} + +// actual functions + +// input - undo OK +void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, + const OUString& rString, + const EditTextObject* pData, + bool bMatrixExpand ) +{ + ScDocument& rDoc = GetViewData().GetDocument(); + ScMarkData rMark(GetViewData().GetMarkData()); + bool bRecord = rDoc.IsUndoEnabled(); + SCTAB i; + + ScDocShell* pDocSh = GetViewData().GetDocShell(); + ScDocFunc &rFunc = GetViewData().GetDocFunc(); + std::shared_ptr<ScDocShellModificator> xModificator = std::make_shared<ScDocShellModificator>(*pDocSh); + + ScEditableTester aTester( rDoc, nCol,nRow, nCol,nRow, rMark ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + PaintArea(nCol, nRow, nCol, nRow); // possibly the edit-engine is still painted there + return; + } + + if ( bRecord ) + rFunc.EnterListAction( STR_UNDO_ENTERDATA ); + + bool bFormula = false; + + // do not check formula if it is a text cell + sal_uInt32 format = rDoc.GetNumberFormat( nCol, nRow, nTab ); + SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); + // a single '=' character is handled as string (needed for special filters) + if ( pFormatter->GetType(format) != SvNumFormatType::TEXT && rString.getLength() > 1 ) + { + if ( rString[0] == '=' ) + { + // handle as formula + bFormula = true; + } + else if ( rString[0] == '+' || rString[0] == '-' ) + { + // if there is more than one leading '+' or '-' character, remove the additional ones + sal_Int32 nIndex = 1; + sal_Int32 nLen = rString.getLength(); + while ( nIndex < nLen && ( rString[ nIndex ] == '+' || rString[ nIndex ] == '-' ) ) + { + ++nIndex; + } + OUString aString = rString.replaceAt( 1, nIndex - 1, u"" ); + + // if the remaining part without the leading '+' or '-' character + // is non-empty and not a number, handle as formula + if ( aString.getLength() > 1 ) + { + double fNumber = 0; + if ( !pFormatter->IsNumberFormat( aString, format, fNumber ) ) + { + bFormula = true; + } + } + } + } + + bool bNumFmtChanged = false; + if ( bFormula ) + { // formula, compile with autoCorrection + i = rMark.GetFirstSelected(); + auto aPosPtr = std::make_shared<ScAddress>(nCol, nRow, i); + auto aCompPtr = std::make_shared<ScCompiler>(rDoc, *aPosPtr, rDoc.GetGrammar(), true, false); + + //2do: enable/disable autoCorrection via calcoptions + aCompPtr->SetAutoCorrection( true ); + if ( rString[0] == '+' || rString[0] == '-' ) + { + aCompPtr->SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK ); + } + + OUString aFormula( rString ); + std::shared_ptr< ScTokenArray > pArr; + + FormulaProcessingContext context_instance{ + aPosPtr, aCompPtr, xModificator, pArr, nullptr, pData, + rMark, *this, OUString(), aFormula, rString, nCol, + nRow, nTab, bMatrixExpand, bNumFmtChanged, bRecord + }; + + std::shared_ptr<FormulaProcessingContext> context = std::make_shared<FormulaProcessingContext>(context_instance); + + parseAndCorrectFormula(context); } else { @@ -666,24 +764,8 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, bNumFmtChanged = true; } } + performAutoFormatAndUpdate(rString, rMark, nCol, nRow, nTab, bNumFmtChanged, bRecord, xModificator, *this); } - - bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged); - - if (bAutoFormat) - DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged); - - pDocSh->UpdateOle(GetViewData()); - - const OUString aType(rString.isEmpty() ? u"delete-content" : u"cell-change"); - HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow, aType); - - if ( bRecord ) - rFunc.EndListAction(); - - aModificator.SetDocumentModified(); - lcl_PostRepaintCondFormat( rDoc.GetCondFormat( nCol, nRow, nTab ), pDocSh ); - lcl_PostRepaintSparkLine(rDoc.GetSparklineList(nTab), ScRange(nCol, nRow, nTab), pDocSh); } // enter value in single cell (on nTab only) commit a830a34d6d21656d00996c002b0dedf37b7545c0 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Jan 30 11:54:18 2024 +0000 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Wed Jan 31 10:33:37 2024 +0100 move SvxNumberingPreview out of cui the point of cui was to have no headers, so move this SvxNumberingPreview out of cui and into svx Change-Id: I83edbcdc8d8b95dbea734bdef4a93f6ec8ee50e6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162748 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/cui/source/inc/numpages.hxx b/cui/source/inc/numpages.hxx index d693b9e0324f..ec7b72ac71fb 100644 --- a/cui/source/inc/numpages.hxx +++ b/cui/source/inc/numpages.hxx @@ -25,9 +25,9 @@ #include <editeng/numdef.hxx> #include <editeng/svxenum.hxx> #include <svtools/ctrlbox.hxx> +#include <svx/numberingpreview.hxx> #include <vcl/customweld.hxx> #include <vcl/timer.hxx> -#include <cui/numberingpreview.hxx> #define MN_GALLERY_ENTRY 100 diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx index caf44cb7ecfd..7fbe8b393608 100644 --- a/cui/source/tabpages/numpages.cxx +++ b/cui/source/tabpages/numpages.cxx @@ -2151,359 +2151,6 @@ void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::Entry* pEdit) SetModified(); } -static tools::Long lcl_DrawGraphic(VirtualDevice& rVDev, const SvxNumberFormat &rFmt, tools::Long nXStart, - tools::Long nYMiddle, tools::Long nDivision) -{ - const SvxBrushItem* pBrushItem = rFmt.GetBrush(); - tools::Long nRet = 0; - if(pBrushItem) - { - const Graphic* pGrf = pBrushItem->GetGraphic(); - if(pGrf) - { - Size aGSize( rFmt.GetGraphicSize() ); - aGSize.setWidth( aGSize.Width() / nDivision ); - nRet = aGSize.Width(); - aGSize.setHeight( aGSize.Height() / nDivision ); - pGrf->Draw(rVDev, Point(nXStart,nYMiddle - ( aGSize.Height() / 2) ), - rVDev.PixelToLogic( aGSize ) ); - } - } - return nRet; - -} - -static tools::Long lcl_DrawBullet(VirtualDevice* pVDev, - const SvxNumberFormat& rFmt, tools::Long nXStart, - tools::Long nYStart, const Size& rSize) -{ - vcl::Font aTmpFont(pVDev->GetFont()); - - // via Uno it's possible that no font has been set! - vcl::Font aFont(rFmt.GetBulletFont() ? *rFmt.GetBulletFont() : aTmpFont); - Size aTmpSize(rSize); - aTmpSize.setWidth( aTmpSize.Width() * ( rFmt.GetBulletRelSize()) ); - aTmpSize.setWidth( aTmpSize.Width() / 100 ) ; - aTmpSize.setHeight( aTmpSize.Height() * ( rFmt.GetBulletRelSize()) ); - aTmpSize.setHeight( aTmpSize.Height() / 100 ) ; - // in case of a height of zero it is drawn in original height - if(!aTmpSize.Height()) - aTmpSize.setHeight( 1 ); - aFont.SetFontSize(aTmpSize); - aFont.SetTransparent(true); - Color aBulletColor = rFmt.GetBulletColor(); - if (aBulletColor == COL_AUTO) - aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - else if (pVDev->GetBackgroundColor().IsDark() == aBulletColor.IsDark()) - aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - aFont.SetColor(aBulletColor); - pVDev->SetFont( aFont ); - sal_UCS4 cChar = rFmt.GetBulletChar(); - OUString aText(&cChar, 1); - tools::Long nY = nYStart; - nY -= ((aTmpSize.Height() - rSize.Height())/ 2); - pVDev->DrawText( Point(nXStart, nY), aText ); - tools::Long nRet = pVDev->GetTextWidth(aText); - - pVDev->SetFont(aTmpFont); - return nRet; -} - -SvxNumberingPreview::SvxNumberingPreview() - : pActNum(nullptr) - , bPosition(false) - , nActLevel(SAL_MAX_UINT16) -{ -} - -// paint preview of numeration -void SvxNumberingPreview::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& /*rRect*/) -{ - Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel())); - - // Use default document and font colors to create preview - const Color aBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor; - const Color aTextColor = svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; - - ScopedVclPtrInstance<VirtualDevice> pVDev(rRenderContext); - pVDev->EnableRTL(rRenderContext.IsRTLEnabled()); - pVDev->SetMapMode(rRenderContext.GetMapMode()); - pVDev->SetOutputSize(aSize); - - Color aLineColor(COL_LIGHTGRAY); - if (aLineColor == aBackColor) - aLineColor.Invert(); - pVDev->SetLineColor(aLineColor); - pVDev->SetFillColor(aBackColor); - pVDev->SetBackground(Wallpaper(aBackColor)); - pVDev->DrawWallpaper(pVDev->GetOutputRectPixel(), pVDev->GetBackground()); - - if (pActNum) - { - tools::Long nWidthRelation = 30; // chapter dialog - - // height per level - tools::Long nXStep = aSize.Width() / (pActNum->GetLevelCount() > 1 ? 3 * pActNum->GetLevelCount() : 3); - if (pActNum->GetLevelCount() < 10) - nXStep /= 2; - tools::Long nYStart = 4; - // the whole height mustn't be used for a single level - tools::Long nYStep = (aSize.Height() - 6)/ (pActNum->GetLevelCount() > 1 ? pActNum->GetLevelCount() : 5); - - aStdFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, MsLangId::getConfiguredSystemLanguage(), GetDefaultFontFlags::OnlyOne); - aStdFont.SetColor(aTextColor); - aStdFont.SetFillColor(aBackColor); - - tools::Long nFontHeight = nYStep * 6 / 10; - if (bPosition) - nFontHeight = nYStep * 15 / 10; - aStdFont.SetFontSize(Size( 0, nFontHeight )); - - SvxNodeNum aNum; - sal_uInt16 nPreNum = pActNum->GetLevel(0).GetStart(); - - if (bPosition) - { - // When bPosition == true, draw the preview used in the Writer's "Position" tab - // This is not used in Impress/Draw - - tools::Long nLineHeight = nFontHeight * 8 / 7; - sal_uInt8 nStart = 0; - while (!(nActLevel & (1<<nStart))) - { - nStart++; - } - if (nStart) - nStart--; - sal_uInt8 nEnd = std::min(sal_uInt8(nStart + 3), sal_uInt8(pActNum->GetLevelCount())); - for (sal_uInt8 nLevel = nStart; nLevel < nEnd; ++nLevel) - { - const SvxNumberFormat &rFmt = pActNum->GetLevel(nLevel); - aNum.GetLevelVal()[nLevel] = rFmt.GetStart(); - - tools::Long nXStart( 0 ); - short nTextOffset( 0 ); - tools::Long nNumberXPos( 0 ); - if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) - { - nXStart = rFmt.GetAbsLSpace() / nWidthRelation; - nTextOffset = rFmt.GetCharTextDistance() / nWidthRelation; - nNumberXPos = nXStart; - tools::Long nFirstLineOffset = (-rFmt.GetFirstLineOffset()) / nWidthRelation; - - if (nFirstLineOffset <= nNumberXPos) - nNumberXPos = nNumberXPos - nFirstLineOffset; - else - nNumberXPos = 0; - // in draw this is valid - if (nTextOffset < 0) - nNumberXPos = nNumberXPos + nTextOffset; - } - else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) - { - const tools::Long nTmpNumberXPos((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent() ) / nWidthRelation); - if (nTmpNumberXPos < 0) - { - nNumberXPos = 0; - } - else - { - nNumberXPos = nTmpNumberXPos; - } - } - - tools::Long nBulletWidth = 0; - if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() &(~LINK_TOKEN))) - { - tools::Long nYMiddle = nYStart + ( nFontHeight / 2 ); - nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawGraphic(*pVDev, rFmt, nNumberXPos, nYMiddle, nWidthRelation) : 0; - } - else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) - { - nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawBullet(pVDev.get(), rFmt, nNumberXPos, nYStart, aStdFont.GetFontSize()) : 0; - } - else - { - pVDev->SetFont(aStdFont); - aNum.SetLevel(nLevel); - if (pActNum->IsContinuousNumbering()) - aNum.GetLevelVal()[nLevel] = nPreNum; - OUString aText(pActNum->MakeNumString( aNum )); - vcl::Font aSaveFont = pVDev->GetFont(); - vcl::Font aColorFont(aSaveFont); - Color aTmpBulletColor = rFmt.GetBulletColor(); - if (aTmpBulletColor == COL_AUTO) - aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - else if (pVDev->GetBackgroundColor().IsDark() == aTmpBulletColor.IsDark()) - aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - aColorFont.SetColor(aTmpBulletColor); - pVDev->SetFont(aColorFont); - pVDev->DrawText(Point(nNumberXPos, nYStart), aText); - pVDev->SetFont(aSaveFont); - nBulletWidth = pVDev->GetTextWidth(aText); - nPreNum++; - } - if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT && - rFmt.GetLabelFollowedBy() == SvxNumberFormat::SPACE ) - { - pVDev->SetFont(aStdFont); - OUString aText(' '); - pVDev->DrawText( Point(nNumberXPos, nYStart), aText ); - nBulletWidth = nBulletWidth + pVDev->GetTextWidth(aText); - } - - tools::Long nTextXPos( 0 ); - if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) - { - nTextXPos = nXStart; - if (nTextOffset < 0) - nTextXPos = nTextXPos + nTextOffset; - if (nNumberXPos + nBulletWidth + nTextOffset > nTextXPos) - nTextXPos = nNumberXPos + nBulletWidth + nTextOffset; - } - else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) - { - switch (rFmt.GetLabelFollowedBy()) - { - case SvxNumberFormat::LISTTAB: - { - nTextXPos = rFmt.GetListtabPos() / nWidthRelation; - if (nTextXPos < nNumberXPos + nBulletWidth) - { - nTextXPos = nNumberXPos + nBulletWidth; - } - } - break; - case SvxNumberFormat::SPACE: - case SvxNumberFormat::NOTHING: - case SvxNumberFormat::NEWLINE: - { - nTextXPos = nNumberXPos + nBulletWidth; - } - break; - } - - nXStart = rFmt.GetIndentAt() / nWidthRelation; - } - - ::tools::Rectangle aRect1(Point(nTextXPos, nYStart + nFontHeight / 2), Size(aSize.Width() / 2, 2)); - pVDev->SetFillColor(aBackColor); - pVDev->DrawRect(aRect1); - - ::tools::Rectangle aRect2(Point(nXStart, nYStart + nLineHeight + nFontHeight / 2 ), Size(aSize.Width() / 2, 2)); - pVDev->DrawRect(aRect2); - nYStart += 2 * nLineHeight; - } - } - else - { - // When bPosition == false, draw the preview used in Writer's "Customize" tab - // and in Impress' "Bullets and Numbering" dialog - - //#i5153# painting gray or black rectangles as 'normal' numbering text - tools::Long nWidth = pVDev->GetTextWidth("Preview"); - tools::Long nTextHeight = pVDev->GetTextHeight(); - tools::Long nRectHeight = nTextHeight * 2 / 3; - tools::Long nTopOffset = nTextHeight - nRectHeight; - Color aSelRectColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - - for (sal_uInt16 nLevel = 0; nLevel < pActNum->GetLevelCount(); ++nLevel, nYStart = nYStart + nYStep) - { - const SvxNumberFormat &rFmt = pActNum->GetLevel(nLevel); - aNum.GetLevelVal()[ nLevel ] = rFmt.GetStart(); - tools::Long nXStart( 0 ); - pVDev->SetFillColor( aBackColor ); - - if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) - { - nXStart = rFmt.GetAbsLSpace() / nWidthRelation; - } - else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) - { - const tools::Long nTmpXStart((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent() ) / nWidthRelation); - if (nTmpXStart < 0) - { - nXStart = 0; - } - else - { - nXStart = nTmpXStart; - } - } - nXStart /= 2; - nXStart += 2; - tools::Long nTextOffset = 2 * nXStep; - if (SVX_NUM_BITMAP == (rFmt.GetNumberingType()&(~LINK_TOKEN))) - { - if (rFmt.IsShowSymbol()) - { - tools::Long nYMiddle = nYStart + ( nFontHeight / 2 ); - nTextOffset = lcl_DrawGraphic(*pVDev, rFmt, nXStart, nYMiddle, nWidthRelation); - nTextOffset = nTextOffset + nXStep; - } - } - else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) - { - if (rFmt.IsShowSymbol()) - { - nTextOffset = lcl_DrawBullet(pVDev.get(), rFmt, nXStart, nYStart, aStdFont.GetFontSize()); - nTextOffset = nTextOffset + nXStep; - } - } - else - { - vcl::Font aFont(aStdFont); - Size aTmpSize(aStdFont.GetFontSize()); - if(pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE)) - { - aTmpSize.setWidth( aTmpSize.Width() * ( rFmt.GetBulletRelSize()) ); - aTmpSize.setWidth( aTmpSize.Width() / 100 ) ; - aTmpSize.setHeight( aTmpSize.Height() * ( rFmt.GetBulletRelSize()) ); - aTmpSize.setHeight( aTmpSize.Height() / 100 ) ; - } - if(!aTmpSize.Height()) - aTmpSize.setHeight( 1 ); - aFont.SetFontSize(aTmpSize); - Color aTmpBulletColor = rFmt.GetBulletColor(); - if (aTmpBulletColor == COL_AUTO) - aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - else if (pVDev->GetBackgroundColor().IsDark() == aTmpBulletColor.IsDark()) - aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; - aFont.SetColor(aTmpBulletColor); - pVDev->SetFont(aFont); - aNum.SetLevel( nLevel ); - if (pActNum->IsContinuousNumbering()) - aNum.GetLevelVal()[nLevel] = nPreNum; - OUString aText(pActNum->MakeNumString(aNum)); - tools::Long nY = nYStart; - nY -= (pVDev->GetTextHeight() - nTextHeight - pVDev->GetFontMetric().GetDescent()); - pVDev->DrawText(Point(nXStart, nY), aText); - nTextOffset = pVDev->GetTextWidth(aText); - nTextOffset = nTextOffset + nXStep; - nPreNum++; - pVDev->SetFont(aStdFont); - } - //#i5153# the selected rectangle(s) should be black - if (0 != (nActLevel & (1<<nLevel))) - { - pVDev->SetFillColor( aSelRectColor ); - pVDev->SetLineColor( aSelRectColor ); - } - else - { - //#i5153# unselected levels are gray - pVDev->SetFillColor( aLineColor ); - pVDev->SetLineColor( aLineColor ); - } - ::tools::Rectangle aRect1(Point(nXStart + nTextOffset, nYStart + nTopOffset), Size(nWidth, nRectHeight)); - pVDev->DrawRect(aRect1); - } - } - } - rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *pVDev); -} - - //See uiconfig/swriter/ui/outlinepositionpage.ui for effectively a duplicate //dialog to this one, except with a different preview window impl. //TODO, determine if SwNumPositionTabPage and SvxNumPositionTabPage can be diff --git a/include/cui/numberingpreview.hxx b/include/svx/numberingpreview.hxx similarity index 52% rename from include/cui/numberingpreview.hxx rename to include/svx/numberingpreview.hxx index 8a7883522bf0..ac2285c1c643 100644 --- a/include/cui/numberingpreview.hxx +++ b/include/svx/numberingpreview.hxx @@ -1,12 +1,19 @@ -#ifndef INCLUDED_CUI_NUMBERINGPREVIEW_HXX -#define INCLUDED_CUI_NUMBERINGPREVIEW_HXX +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ +#pragma once -#include <cui/cuidllapi.h> +#include <svx/svxdllapi.h> #include <editeng/numitem.hxx> #include <vcl/customweld.hxx> /// Provides the preview to show how looks bullet or numbering format before the apply. -class CUI_DLLPUBLIC SvxNumberingPreview final : public weld::CustomWidgetController +class SVXCORE_DLLPUBLIC SvxNumberingPreview final : public weld::CustomWidgetController { const SvxNumRule* pActNum; vcl::Font aStdFont; @@ -28,4 +35,4 @@ public: void SetLevel(sal_uInt16 nSet) { nActLevel = nSet; } }; -#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sd/source/ui/inc/BulletAndPositionDlg.hxx b/sd/source/ui/inc/BulletAndPositionDlg.hxx index 35a35412bce0..9d1393f13919 100644 --- a/sd/source/ui/inc/BulletAndPositionDlg.hxx +++ b/sd/source/ui/inc/BulletAndPositionDlg.hxx @@ -26,7 +26,7 @@ #include <editeng/svxenum.hxx> #include <vcl/weld.hxx> #include "View.hxx" -#include <cui/numberingpreview.hxx> +#include <svx/numberingpreview.hxx> #define MN_GALLERY_ENTRY 100 diff --git a/svx/source/dialog/pagenumberlistbox.cxx b/svx/source/dialog/pagenumberlistbox.cxx index 076da12e123e..1b53e1d26350 100644 --- a/svx/source/dialog/pagenumberlistbox.cxx +++ b/svx/source/dialog/pagenumberlistbox.cxx @@ -17,12 +17,20 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <editeng/brushitem.hxx> +#include <editeng/numitem.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <svtools/colorcfg.hxx> #include <svx/dialmgr.hxx> +#include <svx/numberingpreview.hxx> #include <svx/pagenumberlistbox.hxx> -#include <editeng/numitem.hxx> -#include <com/sun/star/style/NumberingType.hpp> +#include <vcl/graph.hxx> +#include <vcl/metric.hxx> +#include <vcl/virdev.hxx> #include <numberingtype.hrc> +#include <com/sun/star/style/NumberingType.hpp> + SvxPageNumberListBox::SvxPageNumberListBox(std::unique_ptr<weld::ComboBox> pControl) : m_xControl(std::move(pControl)) { @@ -49,4 +57,377 @@ SvxPageNumberListBox::SvxPageNumberListBox(std::unique_ptr<weld::ComboBox> pCont } } +SvxNumberingPreview::SvxNumberingPreview() + : pActNum(nullptr) + , bPosition(false) + , nActLevel(SAL_MAX_UINT16) +{ +} + +static tools::Long lcl_DrawGraphic(VirtualDevice& rVDev, const SvxNumberFormat& rFmt, + tools::Long nXStart, tools::Long nYMiddle, tools::Long nDivision) +{ + const SvxBrushItem* pBrushItem = rFmt.GetBrush(); + tools::Long nRet = 0; + if (pBrushItem) + { + const Graphic* pGrf = pBrushItem->GetGraphic(); + if (pGrf) + { + Size aGSize(rFmt.GetGraphicSize()); + aGSize.setWidth(aGSize.Width() / nDivision); + nRet = aGSize.Width(); + aGSize.setHeight(aGSize.Height() / nDivision); + pGrf->Draw(rVDev, Point(nXStart, nYMiddle - (aGSize.Height() / 2)), + rVDev.PixelToLogic(aGSize)); + } + } + return nRet; +} + +static tools::Long lcl_DrawBullet(VirtualDevice* pVDev, const SvxNumberFormat& rFmt, + tools::Long nXStart, tools::Long nYStart, const Size& rSize) +{ + vcl::Font aTmpFont(pVDev->GetFont()); + + // via Uno it's possible that no font has been set! + vcl::Font aFont(rFmt.GetBulletFont() ? *rFmt.GetBulletFont() : aTmpFont); + Size aTmpSize(rSize); + aTmpSize.setWidth(aTmpSize.Width() * (rFmt.GetBulletRelSize())); + aTmpSize.setWidth(aTmpSize.Width() / 100); + aTmpSize.setHeight(aTmpSize.Height() * (rFmt.GetBulletRelSize())); + aTmpSize.setHeight(aTmpSize.Height() / 100); + // in case of a height of zero it is drawn in original height + if (!aTmpSize.Height()) + aTmpSize.setHeight(1); + aFont.SetFontSize(aTmpSize); + aFont.SetTransparent(true); + Color aBulletColor = rFmt.GetBulletColor(); + if (aBulletColor == COL_AUTO) + aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + else if (pVDev->GetBackgroundColor().IsDark() == aBulletColor.IsDark()) + aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + aFont.SetColor(aBulletColor); + pVDev->SetFont(aFont); + sal_UCS4 cChar = rFmt.GetBulletChar(); + OUString aText(&cChar, 1); + tools::Long nY = nYStart; + nY -= ((aTmpSize.Height() - rSize.Height()) / 2); + pVDev->DrawText(Point(nXStart, nY), aText); + tools::Long nRet = pVDev->GetTextWidth(aText); + + pVDev->SetFont(aTmpFont); + return nRet; +} + +// paint preview of numeration +void SvxNumberingPreview::Paint(vcl::RenderContext& rRenderContext, + const ::tools::Rectangle& /*rRect*/) +{ + Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel())); + + // Use default document and font colors to create preview + const Color aBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor; + const Color aTextColor = svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + + ScopedVclPtrInstance<VirtualDevice> pVDev(rRenderContext); + pVDev->EnableRTL(rRenderContext.IsRTLEnabled()); + pVDev->SetMapMode(rRenderContext.GetMapMode()); + pVDev->SetOutputSize(aSize); + + Color aLineColor(COL_LIGHTGRAY); + if (aLineColor == aBackColor) + aLineColor.Invert(); + pVDev->SetLineColor(aLineColor); + pVDev->SetFillColor(aBackColor); + pVDev->SetBackground(Wallpaper(aBackColor)); + pVDev->DrawWallpaper(pVDev->GetOutputRectPixel(), pVDev->GetBackground()); + + if (pActNum) + { + tools::Long nWidthRelation = 30; // chapter dialog + + // height per level + tools::Long nXStep + = aSize.Width() / (pActNum->GetLevelCount() > 1 ? 3 * pActNum->GetLevelCount() : 3); + if (pActNum->GetLevelCount() < 10) + nXStep /= 2; + tools::Long nYStart = 4; + // the whole height mustn't be used for a single level + tools::Long nYStep + = (aSize.Height() - 6) / (pActNum->GetLevelCount() > 1 ? pActNum->GetLevelCount() : 5); + + aStdFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, + MsLangId::getConfiguredSystemLanguage(), + GetDefaultFontFlags::OnlyOne); + aStdFont.SetColor(aTextColor); + aStdFont.SetFillColor(aBackColor); + + tools::Long nFontHeight = nYStep * 6 / 10; + if (bPosition) + nFontHeight = nYStep * 15 / 10; + aStdFont.SetFontSize(Size(0, nFontHeight)); + + SvxNodeNum aNum; + sal_uInt16 nPreNum = pActNum->GetLevel(0).GetStart(); + + if (bPosition) + { + // When bPosition == true, draw the preview used in the Writer's "Position" tab + // This is not used in Impress/Draw + + tools::Long nLineHeight = nFontHeight * 8 / 7; + sal_uInt8 nStart = 0; + while (!(nActLevel & (1 << nStart))) + { + nStart++; + } + if (nStart) + nStart--; + sal_uInt8 nEnd = std::min(sal_uInt8(nStart + 3), sal_uInt8(pActNum->GetLevelCount())); + for (sal_uInt8 nLevel = nStart; nLevel < nEnd; ++nLevel) + { + const SvxNumberFormat& rFmt = pActNum->GetLevel(nLevel); + aNum.GetLevelVal()[nLevel] = rFmt.GetStart(); + + tools::Long nXStart(0); + short nTextOffset(0); + tools::Long nNumberXPos(0); + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nXStart = rFmt.GetAbsLSpace() / nWidthRelation; + nTextOffset = rFmt.GetCharTextDistance() / nWidthRelation; + nNumberXPos = nXStart; + tools::Long nFirstLineOffset = (-rFmt.GetFirstLineOffset()) / nWidthRelation; + + if (nFirstLineOffset <= nNumberXPos) + nNumberXPos = nNumberXPos - nFirstLineOffset; + else + nNumberXPos = 0; + // in draw this is valid + if (nTextOffset < 0) + nNumberXPos = nNumberXPos + nTextOffset; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + const tools::Long nTmpNumberXPos( + (rFmt.GetIndentAt() + rFmt.GetFirstLineIndent()) / nWidthRelation); + if (nTmpNumberXPos < 0) + { + nNumberXPos = 0; + } + else + { + nNumberXPos = nTmpNumberXPos; + } + } + + tools::Long nBulletWidth = 0; + if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() & (~LINK_TOKEN))) + { + tools::Long nYMiddle = nYStart + (nFontHeight / 2); + nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawGraphic(*pVDev, rFmt, nNumberXPos, + nYMiddle, nWidthRelation) + : 0; + } + else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) + { + nBulletWidth = rFmt.IsShowSymbol() + ? lcl_DrawBullet(pVDev.get(), rFmt, nNumberXPos, nYStart, + aStdFont.GetFontSize()) + : 0; + } + else + { + pVDev->SetFont(aStdFont); + aNum.SetLevel(nLevel); + if (pActNum->IsContinuousNumbering()) + aNum.GetLevelVal()[nLevel] = nPreNum; + OUString aText(pActNum->MakeNumString(aNum)); + vcl::Font aSaveFont = pVDev->GetFont(); + vcl::Font aColorFont(aSaveFont); + Color aTmpBulletColor = rFmt.GetBulletColor(); + if (aTmpBulletColor == COL_AUTO) + aTmpBulletColor + = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + else if (pVDev->GetBackgroundColor().IsDark() == aTmpBulletColor.IsDark()) + aTmpBulletColor + = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + aColorFont.SetColor(aTmpBulletColor); + pVDev->SetFont(aColorFont); + pVDev->DrawText(Point(nNumberXPos, nYStart), aText); + pVDev->SetFont(aSaveFont); + nBulletWidth = pVDev->GetTextWidth(aText); + nPreNum++; + } + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT + && rFmt.GetLabelFollowedBy() == SvxNumberFormat::SPACE) + { + pVDev->SetFont(aStdFont); + OUString aText(' '); + pVDev->DrawText(Point(nNumberXPos, nYStart), aText); + nBulletWidth = nBulletWidth + pVDev->GetTextWidth(aText); + } + + tools::Long nTextXPos(0); + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nTextXPos = nXStart; + if (nTextOffset < 0) + nTextXPos = nTextXPos + nTextOffset; + if (nNumberXPos + nBulletWidth + nTextOffset > nTextXPos) + nTextXPos = nNumberXPos + nBulletWidth + nTextOffset; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + switch (rFmt.GetLabelFollowedBy()) + { + case SvxNumberFormat::LISTTAB: + { + nTextXPos = rFmt.GetListtabPos() / nWidthRelation; + if (nTextXPos < nNumberXPos + nBulletWidth) + { + nTextXPos = nNumberXPos + nBulletWidth; + } + } + break; + case SvxNumberFormat::SPACE: + case SvxNumberFormat::NOTHING: + case SvxNumberFormat::NEWLINE: + { + nTextXPos = nNumberXPos + nBulletWidth; + } + break; + } + + nXStart = rFmt.GetIndentAt() / nWidthRelation; + } + + ::tools::Rectangle aRect1(Point(nTextXPos, nYStart + nFontHeight / 2), + Size(aSize.Width() / 2, 2)); + pVDev->SetFillColor(aBackColor); + pVDev->DrawRect(aRect1); + + ::tools::Rectangle aRect2(Point(nXStart, nYStart + nLineHeight + nFontHeight / 2), + Size(aSize.Width() / 2, 2)); + pVDev->DrawRect(aRect2); + nYStart += 2 * nLineHeight; + } + } + else + { + // When bPosition == false, draw the preview used in Writer's "Customize" tab + // and in Impress' "Bullets and Numbering" dialog + + //#i5153# painting gray or black rectangles as 'normal' numbering text + tools::Long nWidth = pVDev->GetTextWidth("Preview"); + tools::Long nTextHeight = pVDev->GetTextHeight(); + tools::Long nRectHeight = nTextHeight * 2 / 3; + tools::Long nTopOffset = nTextHeight - nRectHeight; + Color aSelRectColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + + for (sal_uInt16 nLevel = 0; nLevel < pActNum->GetLevelCount(); + ++nLevel, nYStart = nYStart + nYStep) + { + const SvxNumberFormat& rFmt = pActNum->GetLevel(nLevel); + aNum.GetLevelVal()[nLevel] = rFmt.GetStart(); + tools::Long nXStart(0); + pVDev->SetFillColor(aBackColor); + + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nXStart = rFmt.GetAbsLSpace() / nWidthRelation; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + const tools::Long nTmpXStart((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent()) + / nWidthRelation); + if (nTmpXStart < 0) + { + nXStart = 0; + } + else + { + nXStart = nTmpXStart; + } + } + nXStart /= 2; + nXStart += 2; + tools::Long nTextOffset = 2 * nXStep; + if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() & (~LINK_TOKEN))) + { + if (rFmt.IsShowSymbol()) + { + tools::Long nYMiddle = nYStart + (nFontHeight / 2); + nTextOffset + = lcl_DrawGraphic(*pVDev, rFmt, nXStart, nYMiddle, nWidthRelation); + nTextOffset = nTextOffset + nXStep; + } + } + else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) + { + if (rFmt.IsShowSymbol()) + { + nTextOffset = lcl_DrawBullet(pVDev.get(), rFmt, nXStart, nYStart, + aStdFont.GetFontSize()); + nTextOffset = nTextOffset + nXStep; + } + } + else + { + vcl::Font aFont(aStdFont); + Size aTmpSize(aStdFont.GetFontSize()); + if (pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE)) + { + aTmpSize.setWidth(aTmpSize.Width() * (rFmt.GetBulletRelSize())); + aTmpSize.setWidth(aTmpSize.Width() / 100); + aTmpSize.setHeight(aTmpSize.Height() * (rFmt.GetBulletRelSize())); + aTmpSize.setHeight(aTmpSize.Height() / 100); + } + if (!aTmpSize.Height()) + aTmpSize.setHeight(1); + aFont.SetFontSize(aTmpSize); + Color aTmpBulletColor = rFmt.GetBulletColor(); + if (aTmpBulletColor == COL_AUTO) + aTmpBulletColor + = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + else if (pVDev->GetBackgroundColor().IsDark() == aTmpBulletColor.IsDark()) + aTmpBulletColor + = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK; + aFont.SetColor(aTmpBulletColor); + pVDev->SetFont(aFont); + aNum.SetLevel(nLevel); + if (pActNum->IsContinuousNumbering()) + aNum.GetLevelVal()[nLevel] = nPreNum; + OUString aText(pActNum->MakeNumString(aNum)); + tools::Long nY = nYStart; + nY -= (pVDev->GetTextHeight() - nTextHeight + - pVDev->GetFontMetric().GetDescent()); + pVDev->DrawText(Point(nXStart, nY), aText); + nTextOffset = pVDev->GetTextWidth(aText); + nTextOffset = nTextOffset + nXStep; + nPreNum++; + pVDev->SetFont(aStdFont); + } + //#i5153# the selected rectangle(s) should be black + if (0 != (nActLevel & (1 << nLevel))) + { + pVDev->SetFillColor(aSelRectColor); + pVDev->SetLineColor(aSelRectColor); + } + else + { + //#i5153# unselected levels are gray + pVDev->SetFillColor(aLineColor); + pVDev->SetLineColor(aLineColor); + } + ::tools::Rectangle aRect1(Point(nXStart + nTextOffset, nYStart + nTopOffset), + Size(nWidth, nRectHeight)); + pVDev->DrawRect(aRect1); + } + } + } + rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *pVDev); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */