tdf#164420 Fix unselected Check/Radio buttons not following themes in GTK
[LibreOffice.git] / sw / source / ui / table / autoformatpreview.cxx
blobcb999155cc8197ad3f20cb80d4846f30ee1afdea
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <editeng/adjustitem.hxx>
21 #include <editeng/boxitem.hxx>
22 #include <editeng/brushitem.hxx>
23 #include <editeng/crossedoutitem.hxx>
24 #include <editeng/colritem.hxx>
25 #include <editeng/contouritem.hxx>
26 #include <editeng/fontitem.hxx>
27 #include <editeng/postitem.hxx>
28 #include <editeng/shdditem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/wghtitem.hxx>
31 #include <vcl/settings.hxx>
32 #include <com/sun/star/i18n/BreakIterator.hpp>
33 #include <comphelper/processfactory.hxx>
34 #include <svtools/scriptedtext.hxx>
35 #include <svx/framelink.hxx>
36 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
37 #include <drawinglayer/processor2d/processor2dtools.hxx>
38 #include <strings.hrc>
39 #include <svtools/colorcfg.hxx>
40 #include <swmodule.hxx>
42 #include <autoformatpreview.hxx>
44 #define FRAME_OFFSET 4
46 AutoFormatPreview::AutoFormatPreview()
47 : maCurrentData(OUString())
48 , mbFitWidth(false)
49 , mbRTL(false)
50 , maStringJan(SwResId(STR_JAN))
51 , maStringFeb(SwResId(STR_FEB))
52 , maStringMar(SwResId(STR_MAR))
53 , maStringNorth(SwResId(STR_NORTH))
54 , maStringMid(SwResId(STR_MID))
55 , maStringSouth(SwResId(STR_SOUTH))
56 , maStringSum(SwResId(STR_SUM))
58 const uno::Reference<uno::XComponentContext>& xContext
59 = comphelper::getProcessComponentContext();
60 m_xBreak = i18n::BreakIterator::create(xContext);
61 mxNumFormat.reset(new SvNumberFormatter(xContext, LANGUAGE_SYSTEM));
63 Init();
66 void AutoFormatPreview::Resize()
68 Size aSize = GetOutputSizePixel();
69 maPreviousSize = Size(aSize.Width() - 6, aSize.Height() - 30);
70 mnLabelColumnWidth = (maPreviousSize.Width() - 4) / 4 - 12;
71 mnDataColumnWidth1 = (maPreviousSize.Width() - 4 - 2 * mnLabelColumnWidth) / 3;
72 mnDataColumnWidth2 = (maPreviousSize.Width() - 4 - 2 * mnLabelColumnWidth) / 4;
73 mnRowHeight = (maPreviousSize.Height() - 4) / 5;
74 NotifyChange(maCurrentData);
77 void AutoFormatPreview::DetectRTL(SwWrtShell const* pWrtShell)
79 if (!pWrtShell->IsCursorInTable()) // We haven't created the table yet
80 mbRTL = AllSettings::GetLayoutRTL();
81 else
82 mbRTL = pWrtShell->IsTableRightToLeft();
85 static void lcl_SetFontProperties(vcl::Font& rFont, const SvxFontItem& rFontItem,
86 const SvxWeightItem& rWeightItem,
87 const SvxPostureItem& rPostureItem)
89 rFont.SetFamily(rFontItem.GetFamily());
90 rFont.SetFamilyName(rFontItem.GetFamilyName());
91 rFont.SetStyleName(rFontItem.GetStyleName());
92 rFont.SetCharSet(rFontItem.GetCharSet());
93 rFont.SetPitch(rFontItem.GetPitch());
94 rFont.SetWeight(rWeightItem.GetValue());
95 rFont.SetItalic(rPostureItem.GetValue());
98 #define SETONALLFONTS(MethodName, Value) \
99 rFont.MethodName(Value); \
100 rCJKFont.MethodName(Value); \
101 rCTLFont.MethodName(Value);
103 void AutoFormatPreview::MakeFonts(vcl::RenderContext const& rRenderContext, sal_uInt8 nIndex,
104 vcl::Font& rFont, vcl::Font& rCJKFont, vcl::Font& rCTLFont)
106 const SwBoxAutoFormat& rBoxFormat = maCurrentData.GetBoxFormat(nIndex);
108 rFont = rCJKFont = rCTLFont = rRenderContext.GetFont();
109 Size aFontSize(rFont.GetFontSize().Width(), 10 * rRenderContext.GetDPIScaleFactor());
111 lcl_SetFontProperties(rFont, rBoxFormat.GetFont(), rBoxFormat.GetWeight(),
112 rBoxFormat.GetPosture());
113 lcl_SetFontProperties(rCJKFont, rBoxFormat.GetCJKFont(), rBoxFormat.GetCJKWeight(),
114 rBoxFormat.GetCJKPosture());
115 lcl_SetFontProperties(rCTLFont, rBoxFormat.GetCTLFont(), rBoxFormat.GetCTLWeight(),
116 rBoxFormat.GetCTLPosture());
118 SETONALLFONTS(SetUnderline, rBoxFormat.GetUnderline().GetValue());
119 SETONALLFONTS(SetOverline, rBoxFormat.GetOverline().GetValue());
120 SETONALLFONTS(SetStrikeout, rBoxFormat.GetCrossedOut().GetValue());
121 SETONALLFONTS(SetOutline, rBoxFormat.GetContour().GetValue());
122 SETONALLFONTS(SetShadow, rBoxFormat.GetShadowed().GetValue());
123 SETONALLFONTS(SetColor, rBoxFormat.GetColor().GetValue());
124 SETONALLFONTS(SetFontSize, aFontSize);
125 SETONALLFONTS(SetTransparent, true);
128 sal_uInt8 AutoFormatPreview::GetFormatIndex(size_t nCol, size_t nRow) const
130 static const sal_uInt8 pnFormatMap[]
131 = { 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 };
132 return pnFormatMap[maArray.GetCellIndex(nCol, nRow, mbRTL)];
135 void AutoFormatPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCol, size_t nRow)
137 // Output of the cell text:
138 sal_uLong nNum;
139 double nVal;
140 OUString cellString;
141 sal_uInt8 nIndex = static_cast<sal_uInt8>(maArray.GetCellIndex(nCol, nRow, mbRTL));
143 switch (nIndex)
145 case 1:
146 cellString = maStringJan;
147 break;
148 case 2:
149 cellString = maStringFeb;
150 break;
151 case 3:
152 cellString = maStringMar;
153 break;
154 case 5:
155 cellString = maStringNorth;
156 break;
157 case 10:
158 cellString = maStringMid;
159 break;
160 case 15:
161 cellString = maStringSouth;
162 break;
163 case 4:
164 case 20:
165 cellString = maStringSum;
166 break;
167 case 6:
168 case 8:
169 case 16:
170 case 18:
171 nVal = nIndex;
172 nNum = 5;
173 goto MAKENUMSTR;
174 case 17:
175 case 7:
176 nVal = nIndex;
177 nNum = 6;
178 goto MAKENUMSTR;
179 case 11:
180 case 12:
181 case 13:
182 nVal = nIndex;
183 nNum = 12 == nIndex ? 10 : 9;
184 goto MAKENUMSTR;
185 case 9:
186 nVal = 21;
187 nNum = 7;
188 goto MAKENUMSTR;
189 case 14:
190 nVal = 36;
191 nNum = 11;
192 goto MAKENUMSTR;
193 case 19:
194 nVal = 51;
195 nNum = 7;
196 goto MAKENUMSTR;
197 case 21:
198 nVal = 33;
199 nNum = 13;
200 goto MAKENUMSTR;
201 case 22:
202 nVal = 36;
203 nNum = 14;
204 goto MAKENUMSTR;
205 case 23:
206 nVal = 39;
207 nNum = 13;
208 goto MAKENUMSTR;
209 case 24:
210 nVal = 108;
211 nNum = 15;
212 goto MAKENUMSTR;
214 MAKENUMSTR:
215 if (maCurrentData.IsValueFormat())
217 OUString sFormat;
218 LanguageType eLng, eSys;
219 maCurrentData.GetBoxFormat(sal_uInt8(nNum)).GetValueFormat(sFormat, eLng, eSys);
221 SvNumFormatType nType;
222 bool bNew;
223 sal_Int32 nCheckPos;
224 sal_uInt32 nKey = mxNumFormat->GetIndexPuttingAndConverting(sFormat, eLng, eSys,
225 nType, bNew, nCheckPos);
226 const Color* pDummy;
227 mxNumFormat->GetOutputString(nVal, nKey, cellString, &pDummy);
229 else
230 cellString = OUString::number(sal_Int32(nVal));
231 break;
234 if (cellString.isEmpty())
235 return;
237 SvtScriptedTextHelper aScriptedText(rRenderContext);
238 Size aStrSize;
239 sal_uInt8 nFormatIndex = GetFormatIndex(nCol, nRow);
240 const basegfx::B2DRange aCellRange(maArray.GetCellRange(nCol, nRow));
241 const tools::Rectangle cellRect(basegfx::fround<tools::Long>(aCellRange.getMinX()),
242 basegfx::fround<tools::Long>(aCellRange.getMinY()),
243 basegfx::fround<tools::Long>(aCellRange.getMaxX()),
244 basegfx::fround<tools::Long>(aCellRange.getMaxY()));
245 Point aPos = cellRect.TopLeft();
246 tools::Long nRightX = 0;
248 Size theMaxStrSize(cellRect.GetWidth() - FRAME_OFFSET, cellRect.GetHeight() - FRAME_OFFSET);
249 if (maCurrentData.IsFont())
251 vcl::Font aFont, aCJKFont, aCTLFont;
252 MakeFonts(rRenderContext, nFormatIndex, aFont, aCJKFont, aCTLFont);
253 aScriptedText.SetFonts(&aFont, &aCJKFont, &aCTLFont);
255 else
256 aScriptedText.SetDefaultFont();
258 aScriptedText.SetText(cellString, m_xBreak);
259 aStrSize = aScriptedText.GetTextSize();
261 if (maCurrentData.IsFont() && theMaxStrSize.Height() < aStrSize.Height())
263 // If the string in this font does not
264 // fit into the cell, the standard font
265 // is taken again:
266 aScriptedText.SetDefaultFont();
267 aStrSize = aScriptedText.GetTextSize();
270 while (theMaxStrSize.Width() <= aStrSize.Width() && cellString.getLength() > 1)
272 cellString = cellString.copy(0, cellString.getLength() - 1);
273 aScriptedText.SetText(cellString, m_xBreak);
274 aStrSize = aScriptedText.GetTextSize();
277 nRightX = cellRect.GetWidth() - aStrSize.Width() - FRAME_OFFSET;
279 // vertical (always centering):
280 aPos.AdjustY((mnRowHeight - aStrSize.Height()) / 2);
282 // horizontal
283 if (mbRTL)
284 aPos.AdjustX(nRightX);
285 else if (maCurrentData.IsJustify())
287 const SvxAdjustItem& rAdj = maCurrentData.GetBoxFormat(nFormatIndex).GetAdjust();
288 switch (rAdj.GetAdjust())
290 case SvxAdjust::Left:
291 aPos.AdjustX(FRAME_OFFSET);
292 break;
293 case SvxAdjust::Right:
294 aPos.AdjustX(nRightX);
295 break;
296 default:
297 aPos.AdjustX((cellRect.GetWidth() - aStrSize.Width()) / 2);
298 break;
301 else
303 // Standard align:
304 if (nCol == 0 || nIndex == 4)
306 // Text-Label left or sum left aligned
307 aPos.AdjustX(FRAME_OFFSET);
309 else
311 // numbers/dates right aligned
312 aPos.AdjustX(nRightX);
316 aScriptedText.DrawText(aPos);
319 void AutoFormatPreview::DrawBackground(vcl::RenderContext& rRenderContext)
321 for (size_t nRow = 0; nRow < 5; ++nRow)
323 for (size_t nCol = 0; nCol < 5; ++nCol)
325 SvxBrushItem aBrushItem(
326 maCurrentData.GetBoxFormat(GetFormatIndex(nCol, nRow)).GetBackground());
328 rRenderContext.Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
329 rRenderContext.SetLineColor();
330 rRenderContext.SetFillColor(aBrushItem.GetColor());
331 const basegfx::B2DRange aCellRange(maArray.GetCellRange(nCol, nRow));
332 rRenderContext.DrawRect(
333 tools::Rectangle(basegfx::fround<tools::Long>(aCellRange.getMinX()),
334 basegfx::fround<tools::Long>(aCellRange.getMinY()),
335 basegfx::fround<tools::Long>(aCellRange.getMaxX()),
336 basegfx::fround<tools::Long>(aCellRange.getMaxY())));
337 rRenderContext.Pop();
342 void AutoFormatPreview::PaintCells(vcl::RenderContext& rRenderContext)
344 // 1) background
345 if (maCurrentData.IsBackground())
346 DrawBackground(rRenderContext);
348 // 2) values
349 for (size_t nRow = 0; nRow < 5; ++nRow)
350 for (size_t nCol = 0; nCol < 5; ++nCol)
351 DrawString(rRenderContext, nCol, nRow);
353 // 3) border
354 if (!maCurrentData.IsFrame())
355 return;
357 const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
358 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
359 drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(rRenderContext,
360 aNewViewInformation2D));
362 if (pProcessor2D)
364 pProcessor2D->process(maArray.CreateB2DPrimitiveArray());
365 pProcessor2D.reset();
369 void AutoFormatPreview::Init()
371 maArray.Initialize(5, 5);
372 mnLabelColumnWidth = 0;
373 mnDataColumnWidth1 = 0;
374 mnDataColumnWidth2 = 0;
375 mnRowHeight = 0;
376 CalcCellArray(false);
377 CalcLineMap();
380 void AutoFormatPreview::CalcCellArray(bool _bFitWidth)
382 maArray.SetAllColWidths(_bFitWidth ? mnDataColumnWidth2 : mnDataColumnWidth1);
383 maArray.SetColWidth(0, mnLabelColumnWidth);
384 maArray.SetColWidth(4, mnLabelColumnWidth);
386 maArray.SetAllRowHeights(mnRowHeight);
388 maPreviousSize.setWidth(maArray.GetWidth() + 4);
389 maPreviousSize.setHeight(maArray.GetHeight() + 4);
392 static void lclSetStyleFromBorder(svx::frame::Style& rStyle,
393 const ::editeng::SvxBorderLine* pBorder)
395 rStyle.Set(pBorder, 0.05, 5);
398 void AutoFormatPreview::CalcLineMap()
400 for (size_t nRow = 0; nRow < 5; ++nRow)
402 for (size_t nCol = 0; nCol < 5; ++nCol)
404 svx::frame::Style aStyle;
406 const SvxBoxItem& rItem
407 = maCurrentData.GetBoxFormat(GetFormatIndex(nCol, nRow)).GetBox();
408 lclSetStyleFromBorder(aStyle, rItem.GetLeft());
409 maArray.SetCellStyleLeft(nCol, nRow, aStyle);
410 lclSetStyleFromBorder(aStyle, rItem.GetRight());
411 maArray.SetCellStyleRight(nCol, nRow, aStyle);
412 lclSetStyleFromBorder(aStyle, rItem.GetTop());
413 maArray.SetCellStyleTop(nCol, nRow, aStyle);
414 lclSetStyleFromBorder(aStyle, rItem.GetBottom());
415 maArray.SetCellStyleBottom(nCol, nRow, aStyle);
417 // FIXME - uncomment to draw diagonal borders
418 // lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, true ).GetLine() );
419 // maArray.SetCellStyleTLBR( nCol, nRow, aStyle );
420 // lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, false ).GetLine() );
421 // maArray.SetCellStyleBLTR( nCol, nRow, aStyle );
426 void AutoFormatPreview::NotifyChange(const SwTableAutoFormat& rNewData)
428 maCurrentData = rNewData;
429 mbFitWidth = maCurrentData.IsJustify(); // true; //???
430 CalcCellArray(mbFitWidth);
431 CalcLineMap();
432 Invalidate();
435 void AutoFormatPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
437 rRenderContext.Push(vcl::PushFlags::ALL);
439 const Color& rWinColor
440 = SwModule::get()->GetColorConfig().GetColorValue(::svtools::DOCCOLOR).nColor;
441 rRenderContext.SetBackground(Wallpaper(rWinColor));
442 rRenderContext.Erase();
444 DrawModeFlags nOldDrawMode = rRenderContext.GetDrawMode();
445 if (rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode())
446 rRenderContext.SetDrawMode(DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill
447 | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient);
449 Size theWndSize = rRenderContext.GetOutputSizePixel();
451 vcl::Font aFont(rRenderContext.GetFont());
452 aFont.SetTransparent(true);
453 rRenderContext.SetFont(aFont);
455 // Draw the Frame
456 Color oldColor = rRenderContext.GetLineColor();
457 rRenderContext.SetLineColor();
458 rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), theWndSize));
459 rRenderContext.SetLineColor(oldColor);
461 // Center the preview
462 maArray.SetXOffset(2 + (theWndSize.Width() - maPreviousSize.Width()) / 2);
463 maArray.SetYOffset(2 + (theWndSize.Height() - maPreviousSize.Height()) / 2);
464 // Draw cells on virtual device
465 PaintCells(rRenderContext);
467 rRenderContext.SetDrawMode(nOldDrawMode);
468 rRenderContext.Pop();
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */