summaryrefslogtreecommitdiffstats
path: root/sw/source/ui/table/autoformatpreview.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/ui/table/autoformatpreview.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/ui/table/autoformatpreview.cxx')
-rw-r--r--sw/source/ui/table/autoformatpreview.cxx465
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: */