diff options
Diffstat (limited to 'sw/source/ui/table/autoformatpreview.cxx')
-rw-r--r-- | sw/source/ui/table/autoformatpreview.cxx | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/sw/source/ui/table/autoformatpreview.cxx b/sw/source/ui/table/autoformatpreview.cxx new file mode 100644 index 000000000..b524532d9 --- /dev/null +++ b/sw/source/ui/table/autoformatpreview.cxx @@ -0,0 +1,465 @@ +/* -*- 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 <editeng/adjustitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/contouritem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <vcl/settings.hxx> +#include <com/sun/star/i18n/BreakIterator.hpp> +#include <comphelper/processfactory.hxx> +#include <svtools/scriptedtext.hxx> +#include <svx/framelink.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/processor2d/processor2dtools.hxx> +#include <strings.hrc> + +#include <autoformatpreview.hxx> + +#define FRAME_OFFSET 4 + +AutoFormatPreview::AutoFormatPreview() + : maCurrentData(OUString()) + , mbFitWidth(false) + , mbRTL(false) + , maStringJan(SwResId(STR_JAN)) + , maStringFeb(SwResId(STR_FEB)) + , maStringMar(SwResId(STR_MAR)) + , maStringNorth(SwResId(STR_NORTH)) + , maStringMid(SwResId(STR_MID)) + , maStringSouth(SwResId(STR_SOUTH)) + , maStringSum(SwResId(STR_SUM)) +{ + uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext(); + m_xBreak = i18n::BreakIterator::create(xContext); + mxNumFormat.reset(new SvNumberFormatter(xContext, LANGUAGE_SYSTEM)); + + Init(); +} + +void AutoFormatPreview::Resize() +{ + Size aSize = GetOutputSizePixel(); + maPreviousSize = Size(aSize.Width() - 6, aSize.Height() - 30); + mnLabelColumnWidth = (maPreviousSize.Width() - 4) / 4 - 12; + mnDataColumnWidth1 = (maPreviousSize.Width() - 4 - 2 * mnLabelColumnWidth) / 3; + mnDataColumnWidth2 = (maPreviousSize.Width() - 4 - 2 * mnLabelColumnWidth) / 4; + mnRowHeight = (maPreviousSize.Height() - 4) / 5; + NotifyChange(maCurrentData); +} + +void AutoFormatPreview::DetectRTL(SwWrtShell const* pWrtShell) +{ + if (!pWrtShell->IsCursorInTable()) // We haven't created the table yet + mbRTL = AllSettings::GetLayoutRTL(); + else + mbRTL = pWrtShell->IsTableRightToLeft(); +} + +static void lcl_SetFontProperties(vcl::Font& rFont, const SvxFontItem& rFontItem, + const SvxWeightItem& rWeightItem, + const SvxPostureItem& rPostureItem) +{ + rFont.SetFamily(rFontItem.GetFamily()); + rFont.SetFamilyName(rFontItem.GetFamilyName()); + rFont.SetStyleName(rFontItem.GetStyleName()); + rFont.SetCharSet(rFontItem.GetCharSet()); + rFont.SetPitch(rFontItem.GetPitch()); + rFont.SetWeight(rWeightItem.GetValue()); + rFont.SetItalic(rPostureItem.GetValue()); +} + +#define SETONALLFONTS(MethodName, Value) \ + rFont.MethodName(Value); \ + rCJKFont.MethodName(Value); \ + rCTLFont.MethodName(Value); + +void AutoFormatPreview::MakeFonts(vcl::RenderContext const& rRenderContext, sal_uInt8 nIndex, + vcl::Font& rFont, vcl::Font& rCJKFont, vcl::Font& rCTLFont) +{ + const SwBoxAutoFormat& rBoxFormat = maCurrentData.GetBoxFormat(nIndex); + + rFont = rCJKFont = rCTLFont = rRenderContext.GetFont(); + Size aFontSize(rFont.GetFontSize().Width(), 10 * rRenderContext.GetDPIScaleFactor()); + + lcl_SetFontProperties(rFont, rBoxFormat.GetFont(), rBoxFormat.GetWeight(), + rBoxFormat.GetPosture()); + lcl_SetFontProperties(rCJKFont, rBoxFormat.GetCJKFont(), rBoxFormat.GetCJKWeight(), + rBoxFormat.GetCJKPosture()); + lcl_SetFontProperties(rCTLFont, rBoxFormat.GetCTLFont(), rBoxFormat.GetCTLWeight(), + rBoxFormat.GetCTLPosture()); + + SETONALLFONTS(SetUnderline, rBoxFormat.GetUnderline().GetValue()); + SETONALLFONTS(SetOverline, rBoxFormat.GetOverline().GetValue()); + SETONALLFONTS(SetStrikeout, rBoxFormat.GetCrossedOut().GetValue()); + SETONALLFONTS(SetOutline, rBoxFormat.GetContour().GetValue()); + SETONALLFONTS(SetShadow, rBoxFormat.GetShadowed().GetValue()); + SETONALLFONTS(SetColor, rBoxFormat.GetColor().GetValue()); + SETONALLFONTS(SetFontSize, aFontSize); + SETONALLFONTS(SetTransparent, true); +} + +sal_uInt8 AutoFormatPreview::GetFormatIndex(size_t nCol, size_t nRow) const +{ + static const sal_uInt8 pnFormatMap[] + = { 0, 1, 2, 1, 3, 4, 5, 6, 5, 7, 8, 9, 10, 9, 11, 4, 5, 6, 5, 7, 12, 13, 14, 13, 15 }; + return pnFormatMap[maArray.GetCellIndex(nCol, nRow, mbRTL)]; +} + +void AutoFormatPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCol, size_t nRow) +{ + // Output of the cell text: + sal_uLong nNum; + double nVal; + OUString cellString; + sal_uInt8 nIndex = static_cast<sal_uInt8>(maArray.GetCellIndex(nCol, nRow, mbRTL)); + + switch (nIndex) + { + case 1: + cellString = maStringJan; + break; + case 2: + cellString = maStringFeb; + break; + case 3: + cellString = maStringMar; + break; + case 5: + cellString = maStringNorth; + break; + case 10: + cellString = maStringMid; + break; + case 15: + cellString = maStringSouth; + break; + case 4: + case 20: + cellString = maStringSum; + break; + case 6: + case 8: + case 16: + case 18: + nVal = nIndex; + nNum = 5; + goto MAKENUMSTR; + case 17: + case 7: + nVal = nIndex; + nNum = 6; + goto MAKENUMSTR; + case 11: + case 12: + case 13: + nVal = nIndex; + nNum = 12 == nIndex ? 10 : 9; + goto MAKENUMSTR; + case 9: + nVal = 21; + nNum = 7; + goto MAKENUMSTR; + case 14: + nVal = 36; + nNum = 11; + goto MAKENUMSTR; + case 19: + nVal = 51; + nNum = 7; + goto MAKENUMSTR; + case 21: + nVal = 33; + nNum = 13; + goto MAKENUMSTR; + case 22: + nVal = 36; + nNum = 14; + goto MAKENUMSTR; + case 23: + nVal = 39; + nNum = 13; + goto MAKENUMSTR; + case 24: + nVal = 108; + nNum = 15; + goto MAKENUMSTR; + + MAKENUMSTR: + if (maCurrentData.IsValueFormat()) + { + OUString sFormat; + LanguageType eLng, eSys; + maCurrentData.GetBoxFormat(sal_uInt8(nNum)).GetValueFormat(sFormat, eLng, eSys); + + SvNumFormatType nType; + bool bNew; + sal_Int32 nCheckPos; + sal_uInt32 nKey = mxNumFormat->GetIndexPuttingAndConverting(sFormat, eLng, eSys, + nType, bNew, nCheckPos); + Color* pDummy; + mxNumFormat->GetOutputString(nVal, nKey, cellString, &pDummy); + } + else + cellString = OUString::number(sal_Int32(nVal)); + break; + } + + if (cellString.isEmpty()) + return; + + SvtScriptedTextHelper aScriptedText(rRenderContext); + Size aStrSize; + sal_uInt8 nFormatIndex = GetFormatIndex(nCol, nRow); + const basegfx::B2DRange aCellRange(maArray.GetCellRange(nCol, nRow, true)); + const tools::Rectangle cellRect( + basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()), + basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY())); + Point aPos = cellRect.TopLeft(); + long nRightX = 0; + + Size theMaxStrSize(cellRect.GetWidth() - FRAME_OFFSET, cellRect.GetHeight() - FRAME_OFFSET); + if (maCurrentData.IsFont()) + { + vcl::Font aFont, aCJKFont, aCTLFont; + MakeFonts(rRenderContext, nFormatIndex, aFont, aCJKFont, aCTLFont); + aScriptedText.SetFonts(&aFont, &aCJKFont, &aCTLFont); + } + else + aScriptedText.SetDefaultFont(); + + aScriptedText.SetText(cellString, m_xBreak); + aStrSize = aScriptedText.GetTextSize(); + + if (maCurrentData.IsFont() && theMaxStrSize.Height() < aStrSize.Height()) + { + // If the string in this font does not + // fit into the cell, the standard font + // is taken again: + aScriptedText.SetDefaultFont(); + aStrSize = aScriptedText.GetTextSize(); + } + + while (theMaxStrSize.Width() <= aStrSize.Width() && cellString.getLength() > 1) + { + cellString = cellString.copy(0, cellString.getLength() - 1); + aScriptedText.SetText(cellString, m_xBreak); + aStrSize = aScriptedText.GetTextSize(); + } + + nRightX = cellRect.GetWidth() - aStrSize.Width() - FRAME_OFFSET; + + // vertical (always centering): + aPos.AdjustY((mnRowHeight - aStrSize.Height()) / 2); + + // horizontal + if (mbRTL) + aPos.AdjustX(nRightX); + else if (maCurrentData.IsJustify()) + { + const SvxAdjustItem& rAdj = maCurrentData.GetBoxFormat(nFormatIndex).GetAdjust(); + switch (rAdj.GetAdjust()) + { + case SvxAdjust::Left: + aPos.AdjustX(FRAME_OFFSET); + break; + case SvxAdjust::Right: + aPos.AdjustX(nRightX); + break; + default: + aPos.AdjustX((cellRect.GetWidth() - aStrSize.Width()) / 2); + break; + } + } + else + { + // Standard align: + if (nCol == 0 || nIndex == 4) + { + // Text-Label left or sum left aligned + aPos.AdjustX(FRAME_OFFSET); + } + else + { + // numbers/dates right aligned + aPos.AdjustX(nRightX); + } + } + + aScriptedText.DrawText(aPos); +} + +void AutoFormatPreview::DrawBackground(vcl::RenderContext& rRenderContext) +{ + for (size_t nRow = 0; nRow < 5; ++nRow) + { + for (size_t nCol = 0; nCol < 5; ++nCol) + { + SvxBrushItem aBrushItem( + maCurrentData.GetBoxFormat(GetFormatIndex(nCol, nRow)).GetBackground()); + + rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR); + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(aBrushItem.GetColor()); + const basegfx::B2DRange aCellRange(maArray.GetCellRange(nCol, nRow, true)); + rRenderContext.DrawRect(tools::Rectangle( + basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()), + basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()))); + rRenderContext.Pop(); + } + } +} + +void AutoFormatPreview::PaintCells(vcl::RenderContext& rRenderContext) +{ + // 1) background + if (maCurrentData.IsBackground()) + DrawBackground(rRenderContext); + + // 2) values + for (size_t nRow = 0; nRow < 5; ++nRow) + for (size_t nCol = 0; nCol < 5; ++nCol) + DrawString(rRenderContext, nCol, nRow); + + // 3) border + if (maCurrentData.IsFrame()) + { + const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D; + std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D( + drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice( + rRenderContext, aNewViewInformation2D)); + + if (pProcessor2D) + { + pProcessor2D->process(maArray.CreateB2DPrimitiveArray()); + pProcessor2D.reset(); + } + } +} + +void AutoFormatPreview::Init() +{ + maArray.Initialize(5, 5); + mnLabelColumnWidth = 0; + mnDataColumnWidth1 = 0; + mnDataColumnWidth2 = 0; + mnRowHeight = 0; + CalcCellArray(false); + CalcLineMap(); +} + +void AutoFormatPreview::CalcCellArray(bool _bFitWidth) +{ + maArray.SetAllColWidths(_bFitWidth ? mnDataColumnWidth2 : mnDataColumnWidth1); + maArray.SetColWidth(0, mnLabelColumnWidth); + maArray.SetColWidth(4, mnLabelColumnWidth); + + maArray.SetAllRowHeights(mnRowHeight); + + maPreviousSize.setWidth(maArray.GetWidth() + 4); + maPreviousSize.setHeight(maArray.GetHeight() + 4); +} + +static void lclSetStyleFromBorder(svx::frame::Style& rStyle, + const ::editeng::SvxBorderLine* pBorder) +{ + rStyle.Set(pBorder, 0.05, 5); +} + +void AutoFormatPreview::CalcLineMap() +{ + for (size_t nRow = 0; nRow < 5; ++nRow) + { + for (size_t nCol = 0; nCol < 5; ++nCol) + { + svx::frame::Style aStyle; + + const SvxBoxItem& rItem + = maCurrentData.GetBoxFormat(GetFormatIndex(nCol, nRow)).GetBox(); + lclSetStyleFromBorder(aStyle, rItem.GetLeft()); + maArray.SetCellStyleLeft(nCol, nRow, aStyle); + lclSetStyleFromBorder(aStyle, rItem.GetRight()); + maArray.SetCellStyleRight(nCol, nRow, aStyle); + lclSetStyleFromBorder(aStyle, rItem.GetTop()); + maArray.SetCellStyleTop(nCol, nRow, aStyle); + lclSetStyleFromBorder(aStyle, rItem.GetBottom()); + maArray.SetCellStyleBottom(nCol, nRow, aStyle); + + // FIXME - uncomment to draw diagonal borders + // lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, true ).GetLine() ); + // maArray.SetCellStyleTLBR( nCol, nRow, aStyle ); + // lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, false ).GetLine() ); + // maArray.SetCellStyleBLTR( nCol, nRow, aStyle ); + } + } +} + +void AutoFormatPreview::NotifyChange(const SwTableAutoFormat& rNewData) +{ + maCurrentData = rNewData; + mbFitWidth = maCurrentData.IsJustify(); // true; //??? + CalcCellArray(mbFitWidth); + CalcLineMap(); + Invalidate(); +} + +void AutoFormatPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + rRenderContext.Push(PushFlags::ALL); + + DrawModeFlags nOldDrawMode = rRenderContext.GetDrawMode(); + if (rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode()) + rRenderContext.SetDrawMode(DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill + | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient); + + Size theWndSize = rRenderContext.GetOutputSizePixel(); + + vcl::Font aFont(rRenderContext.GetFont()); + aFont.SetTransparent(true); + + rRenderContext.SetFont(aFont); + rRenderContext.SetLineColor(); + const Color& rWinColor = rRenderContext.GetSettings().GetStyleSettings().GetWindowColor(); + rRenderContext.SetBackground(Wallpaper(rWinColor)); + rRenderContext.SetFillColor(rWinColor); + + // Draw the Frame + Color oldColor = rRenderContext.GetLineColor(); + rRenderContext.SetLineColor(); + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), theWndSize)); + rRenderContext.SetLineColor(oldColor); + + // Center the preview + maArray.SetXOffset(2 + (theWndSize.Width() - maPreviousSize.Width()) / 2); + maArray.SetYOffset(2 + (theWndSize.Height() - maPreviousSize.Height()) / 2); + // Draw cells on virtual device + PaintCells(rRenderContext); + + rRenderContext.SetDrawMode(nOldDrawMode); + rRenderContext.Pop(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |