1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <scitems.hxx>
21 #include <editeng/boxitem.hxx>
22 #include <editeng/brushitem.hxx>
23 #include <editeng/contouritem.hxx>
24 #include <editeng/colritem.hxx>
25 #include <editeng/crossedoutitem.hxx>
26 #include <editeng/fontitem.hxx>
27 #include <editeng/justifyitem.hxx>
28 #include <editeng/lineitem.hxx>
29 #include <editeng/postitem.hxx>
30 #include <editeng/shdditem.hxx>
31 #include <editeng/udlnitem.hxx>
32 #include <editeng/wghtitem.hxx>
33 #include <o3tl/unit_conversion.hxx>
34 #include <osl/diagnose.h>
35 #include <svl/numformat.hxx>
36 #include <svtools/scriptedtext.hxx>
37 #include <svx/framelink.hxx>
38 #include <vcl/settings.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/virdev.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <drawinglayer/processor2d/processor2dtools.hxx>
43 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
45 #include <strings.hrc>
46 #include <zforauto.hxx>
48 #include <autoform.hxx>
49 #include <autofmt.hxx>
50 #include <scresid.hxx>
51 #include <document.hxx>
52 #include <viewdata.hxx>
53 #include <svtools/colorcfg.hxx>
56 #define FRAME_OFFSET 4
60 ScAutoFmtPreview::ScAutoFmtPreview()
64 , aStrJan(ScResId(STR_JAN
))
65 , aStrFeb(ScResId(STR_FEB
))
66 , aStrMar(ScResId(STR_MAR
))
67 , aStrNorth(ScResId(STR_NORTH
))
68 , aStrMid(ScResId(STR_MID
))
69 , aStrSouth(ScResId(STR_SOUTH
))
70 , aStrSum(ScResId(STR_SUM
))
71 , pNumFmt(new SvNumberFormatter(::comphelper::getProcessComponentContext(), ScGlobal::eLnge
))
76 void ScAutoFmtPreview::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
78 aVD
.disposeAndReset(VclPtr
<VirtualDevice
>::Create(pDrawingArea
->get_ref_device()));
79 CustomWidgetController::SetDrawingArea(pDrawingArea
);
82 void ScAutoFmtPreview::Resize()
84 Size
aSize(GetOutputSizePixel());
85 aPrvSize
= Size(aSize
.Width() - 6, aSize
.Height() - 30);
86 mnLabelColWidth
= (aPrvSize
.Width() - 4) / 4 - 12;
87 mnDataColWidth1
= (aPrvSize
.Width() - 4 - 2 * mnLabelColWidth
) / 3;
88 mnDataColWidth2
= (aPrvSize
.Width() - 4 - 2 * mnLabelColWidth
) / 4;
89 mnRowHeight
= (aPrvSize
.Height() - 4) / 5;
90 NotifyChange(pCurData
);
93 ScAutoFmtPreview::~ScAutoFmtPreview()
97 static void lcl_SetFontProperties(
99 const SvxFontItem
& rFontItem
,
100 const SvxWeightItem
& rWeightItem
,
101 const SvxPostureItem
& rPostureItem
)
103 rFont
.SetFamily ( rFontItem
.GetFamily() );
104 rFont
.SetFamilyName ( rFontItem
.GetFamilyName() );
105 rFont
.SetStyleName ( rFontItem
.GetStyleName() );
106 rFont
.SetCharSet ( rFontItem
.GetCharSet() );
107 rFont
.SetPitch ( rFontItem
.GetPitch() );
108 rFont
.SetWeight ( rWeightItem
.GetValue() );
109 rFont
.SetItalic ( rPostureItem
.GetValue() );
112 void ScAutoFmtPreview::MakeFonts(vcl::RenderContext
const& rRenderContext
, sal_uInt16 nIndex
, vcl::Font
& rFont
, vcl::Font
& rCJKFont
, vcl::Font
& rCTLFont
)
117 rFont
= rCJKFont
= rCTLFont
= rRenderContext
.GetFont();
118 Size
aFontSize(rFont
.GetFontSize().Width(), 10 * rRenderContext
.GetDPIScaleFactor());
120 const SvxFontItem
* pFontItem
= pCurData
->GetItem( nIndex
, ATTR_FONT
);
121 const SvxWeightItem
* pWeightItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_WEIGHT
);
122 const SvxPostureItem
* pPostureItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_POSTURE
);
123 const SvxFontItem
* pCJKFontItem
= pCurData
->GetItem( nIndex
, ATTR_CJK_FONT
);
124 const SvxWeightItem
* pCJKWeightItem
= pCurData
->GetItem( nIndex
, ATTR_CJK_FONT_WEIGHT
);
125 const SvxPostureItem
* pCJKPostureItem
= pCurData
->GetItem( nIndex
, ATTR_CJK_FONT_POSTURE
);
126 const SvxFontItem
* pCTLFontItem
= pCurData
->GetItem( nIndex
, ATTR_CTL_FONT
);
127 const SvxWeightItem
* pCTLWeightItem
= pCurData
->GetItem( nIndex
, ATTR_CTL_FONT_WEIGHT
);
128 const SvxPostureItem
* pCTLPostureItem
= pCurData
->GetItem( nIndex
, ATTR_CTL_FONT_POSTURE
);
129 const SvxUnderlineItem
* pUnderlineItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_UNDERLINE
);
130 const SvxOverlineItem
* pOverlineItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_OVERLINE
);
131 const SvxCrossedOutItem
* pCrossedOutItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_CROSSEDOUT
);
132 const SvxContourItem
* pContourItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_CONTOUR
);
133 const SvxShadowedItem
* pShadowedItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_SHADOWED
);
134 const SvxColorItem
* pColorItem
= pCurData
->GetItem( nIndex
, ATTR_FONT_COLOR
);
136 lcl_SetFontProperties( rFont
, *pFontItem
, *pWeightItem
, *pPostureItem
);
137 lcl_SetFontProperties( rCJKFont
, *pCJKFontItem
, *pCJKWeightItem
, *pCJKPostureItem
);
138 lcl_SetFontProperties( rCTLFont
, *pCTLFontItem
, *pCTLWeightItem
, *pCTLPostureItem
);
140 Color
aColor( pColorItem
->GetValue() );
141 if( aColor
== COL_TRANSPARENT
)
142 aColor
= Application::GetSettings().GetStyleSettings().GetWindowTextColor();
144 #define SETONALLFONTS( MethodName, Value ) \
145 rFont.MethodName( Value ); rCJKFont.MethodName( Value ); rCTLFont.MethodName( Value );
147 SETONALLFONTS( SetUnderline
, pUnderlineItem
->GetValue() )
148 SETONALLFONTS( SetOverline
, pOverlineItem
->GetValue() )
149 SETONALLFONTS( SetStrikeout
, pCrossedOutItem
->GetValue() )
150 SETONALLFONTS( SetOutline
, pContourItem
->GetValue() )
151 SETONALLFONTS( SetShadow
, pShadowedItem
->GetValue() )
152 SETONALLFONTS( SetColor
, aColor
)
153 SETONALLFONTS( SetFontSize
, aFontSize
)
154 SETONALLFONTS( SetTransparent
, true )
159 sal_uInt16
ScAutoFmtPreview::GetFormatIndex( size_t nCol
, size_t nRow
) const
161 static const sal_uInt16 pnFmtMap
[] =
169 return pnFmtMap
[ maArray
.GetCellIndex( nCol
, nRow
, mbRTL
) ];
172 const SvxBoxItem
& ScAutoFmtPreview::GetBoxItem( size_t nCol
, size_t nRow
) const
174 assert(pCurData
&& "ScAutoFmtPreview::GetBoxItem - no format data found");
175 return * pCurData
->GetItem( GetFormatIndex( nCol
, nRow
), ATTR_BORDER
);
178 const SvxLineItem
& ScAutoFmtPreview::GetDiagItem( size_t nCol
, size_t nRow
, bool bTLBR
) const
180 assert(pCurData
&& "ScAutoFmtPreview::GetDiagItem - no format data found");
181 return * pCurData
->GetItem( GetFormatIndex( nCol
, nRow
), bTLBR
? ATTR_BORDER_TLBR
: ATTR_BORDER_BLTR
);
184 void ScAutoFmtPreview::DrawString(vcl::RenderContext
& rRenderContext
, size_t nCol
, size_t nRow
)
191 // Emit the cell text
194 bool bNumFormat
= pCurData
->GetIncludeValueFormat();
197 const Color
* pDummy
= nullptr;
198 sal_uInt16 nIndex
= static_cast<sal_uInt16
>(maArray
.GetCellIndex(nCol
, nRow
, mbRTL
));
202 case 1: cellString
= aStrJan
; break;
203 case 2: cellString
= aStrFeb
; break;
204 case 3: cellString
= aStrMar
; break;
205 case 5: cellString
= aStrNorth
; break;
206 case 10: cellString
= aStrMid
; break;
207 case 15: cellString
= aStrSouth
; break;
209 case 20: cellString
= aStrSum
; break;
214 case 18: nVal
= nIndex
;
218 case 7: nVal
= nIndex
;
223 case 13: nVal
= nIndex
;
224 nNum
= 12 == nIndex
? 10 : 9;
227 case 9: nVal
= 21; nNum
= 7; goto mknum
;
228 case 14: nVal
= 36; nNum
= 11; goto mknum
;
229 case 19: nVal
= 51; nNum
= 7; goto mknum
;
230 case 21: nVal
= 33; nNum
= 13; goto mknum
;
231 case 22: nVal
= 36; nNum
= 14; goto mknum
;
232 case 23: nVal
= 39; nNum
= 13; goto mknum
;
233 case 24: nVal
= 108; nNum
= 15;
237 ScNumFormatAbbrev
& rNumFormat
= const_cast<ScNumFormatAbbrev
&>(pCurData
->GetNumFormat(sal_uInt16(nNum
)));
238 nNum
= rNumFormat
.GetFormatIndex(*pNumFmt
);
242 pNumFmt
->GetOutputString(nVal
, nNum
, cellString
, &pDummy
);
246 if (cellString
.isEmpty())
250 sal_uInt16 nFmtIndex
= GetFormatIndex( nCol
, nRow
);
251 const basegfx::B2DRange
cellRange(maArray
.GetCellRange( nCol
, nRow
));
252 Point
aPos(basegfx::fround
<tools::Long
>(cellRange
.getMinX()), basegfx::fround
<tools::Long
>(cellRange
.getMinY()));
253 sal_uInt16 nRightX
= 0;
254 bool bJustify
= pCurData
->GetIncludeJustify();
255 SvxCellHorJustify eJustification
;
257 SvtScriptedTextHelper
aScriptedText(rRenderContext
);
261 eJustification
= mbRTL
? SvxCellHorJustify::Right
: bJustify
?
262 pCurData
->GetItem(nFmtIndex
, ATTR_HOR_JUSTIFY
)->GetValue() :
263 SvxCellHorJustify::Standard
;
265 if (pCurData
->GetIncludeFont())
267 vcl::Font aFont
, aCJKFont
, aCTLFont
;
270 MakeFonts(rRenderContext
, nFmtIndex
, aFont
, aCJKFont
, aCTLFont
);
272 theMaxStrSize
= Size(basegfx::fround
<tools::Long
>(cellRange
.getWidth()), basegfx::fround
<tools::Long
>(cellRange
.getHeight()));
273 theMaxStrSize
.AdjustWidth( -(FRAME_OFFSET
) );
274 theMaxStrSize
.AdjustHeight( -(FRAME_OFFSET
) );
276 aScriptedText
.SetFonts( &aFont
, &aCJKFont
, &aCTLFont
);
277 aScriptedText
.SetText(cellString
, xBreakIter
);
278 aStrSize
= aScriptedText
.GetTextSize();
280 if (theMaxStrSize
.Height() < aStrSize
.Height())
282 // if the string does not fit in the row using this font,
283 // the default font is used
284 aScriptedText
.SetDefaultFont();
285 aStrSize
= aScriptedText
.GetTextSize();
287 while((theMaxStrSize
.Width() <= aStrSize
.Width()) && (cellString
.getLength() > 1))
289 if( eJustification
== SvxCellHorJustify::Right
)
290 cellString
= cellString
.copy(1);
292 cellString
= cellString
.copy(0, cellString
.getLength() - 1 );
294 aScriptedText
.SetText( cellString
, xBreakIter
);
295 aStrSize
= aScriptedText
.GetTextSize();
300 aScriptedText
.SetDefaultFont();
301 aScriptedText
.SetText( cellString
, xBreakIter
);
302 aStrSize
= aScriptedText
.GetTextSize();
305 nRightX
= sal_uInt16(basegfx::fround(cellRange
.getWidth()) - aStrSize
.Width() - FRAME_OFFSET
);
307 // vertical (always center):
309 aPos
.AdjustY((mnRowHeight
- static_cast<sal_uInt16
>(aStrSize
.Height())) / 2 );
313 if (eJustification
!= SvxCellHorJustify::Standard
)
315 sal_uInt16 nHorPos
= sal_uInt16((basegfx::fround(cellRange
.getWidth())-aStrSize
.Width()) / 2);
316 //sal_uInt16 nHorPos = sal_uInt16((basegfx::fround(cellRange.getWidth())-aStrSize.Width()) / 2);
318 switch (eJustification
)
320 case SvxCellHorJustify::Left
:
321 aPos
.AdjustX(FRAME_OFFSET
);
323 case SvxCellHorJustify::Right
:
324 aPos
.AdjustX(nRightX
);
326 case SvxCellHorJustify::Block
:
327 case SvxCellHorJustify::Repeat
:
328 case SvxCellHorJustify::Center
:
329 aPos
.AdjustX(nHorPos
);
331 // coverity[dead_error_line] - following conditions exist to avoid compiler warning
332 case SvxCellHorJustify::Standard
:
334 // Standard is not handled here
341 // Standard justification
343 if (nCol
== 0 || nRow
== 0)
345 // Text label to the left or sum left adjusted
346 aPos
.AdjustX(FRAME_OFFSET
);
350 // Numbers/Dates right adjusted
351 aPos
.AdjustX(nRightX
);
354 aScriptedText
.DrawText(aPos
);
359 void ScAutoFmtPreview::DrawBackground(vcl::RenderContext
& rRenderContext
)
364 for(size_t nRow
= 0; nRow
< 5; ++nRow
)
366 for(size_t nCol
= 0; nCol
< 5; ++nCol
)
368 const SvxBrushItem
* pItem
=
369 pCurData
->GetItem( GetFormatIndex( nCol
, nRow
), ATTR_BACKGROUND
);
371 rRenderContext
.Push( vcl::PushFlags::LINECOLOR
| vcl::PushFlags::FILLCOLOR
);
372 rRenderContext
.SetLineColor();
373 rRenderContext
.SetFillColor( pItem
->GetColor() );
375 const basegfx::B2DRange
aCellRange(maArray
.GetCellRange( nCol
, nRow
));
376 rRenderContext
.DrawRect(
378 basegfx::fround
<tools::Long
>(aCellRange
.getMinX()), basegfx::fround
<tools::Long
>(aCellRange
.getMinY()),
379 basegfx::fround
<tools::Long
>(aCellRange
.getMaxX()), basegfx::fround
<tools::Long
>(aCellRange
.getMaxY())));
381 rRenderContext
.Pop();
386 void ScAutoFmtPreview::PaintCells(vcl::RenderContext
& rRenderContext
)
392 if (pCurData
->GetIncludeBackground())
393 DrawBackground(rRenderContext
);
396 for(size_t nRow
= 0; nRow
< 5; ++nRow
)
397 for(size_t nCol
= 0; nCol
< 5; ++nCol
)
398 DrawString(rRenderContext
, nCol
, nRow
);
401 if (!pCurData
->GetIncludeFrame())
404 const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D
;
405 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor2D(
406 drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
408 aNewViewInformation2D
));
410 pProcessor2D
->process(maArray
.CreateB2DPrimitiveArray());
411 pProcessor2D
.reset();
414 void ScAutoFmtPreview::Init()
416 maArray
.Initialize( 5, 5 );
421 CalcCellArray( false );
425 void ScAutoFmtPreview::DetectRTL(const ScViewData
& rViewData
)
427 SCTAB nCurrentTab
= rViewData
.GetTabNo();
428 ScDocument
& rDoc
= rViewData
.GetDocument();
429 mbRTL
= rDoc
.IsLayoutRTL(nCurrentTab
);
430 xBreakIter
= rDoc
.GetBreakIterator();
433 void ScAutoFmtPreview::CalcCellArray( bool bFitWidthP
)
435 maArray
.SetXOffset( 2 );
436 maArray
.SetAllColWidths( bFitWidthP
? mnDataColWidth2
: mnDataColWidth1
);
437 maArray
.SetColWidth( 0, mnLabelColWidth
);
438 maArray
.SetColWidth( 4, mnLabelColWidth
);
440 maArray
.SetYOffset( 2 );
441 maArray
.SetAllRowHeights( mnRowHeight
);
443 aPrvSize
.setWidth( maArray
.GetWidth() + 4 );
444 aPrvSize
.setHeight( maArray
.GetHeight() + 4 );
447 static void lclSetStyleFromBorder( svx::frame::Style
& rStyle
, const ::editeng::SvxBorderLine
* pBorder
)
449 rStyle
.Set(pBorder
, o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::pt
), 5);
452 void ScAutoFmtPreview::CalcLineMap()
457 for( size_t nRow
= 0; nRow
< 5; ++nRow
)
459 for( size_t nCol
= 0; nCol
< 5; ++nCol
)
461 svx::frame::Style aStyle
;
463 const SvxBoxItem
& rItem
= GetBoxItem( nCol
, nRow
);
464 lclSetStyleFromBorder( aStyle
, rItem
.GetLeft() );
465 maArray
.SetCellStyleLeft( nCol
, nRow
, aStyle
);
466 lclSetStyleFromBorder( aStyle
, rItem
.GetRight() );
467 maArray
.SetCellStyleRight( nCol
, nRow
, aStyle
);
468 lclSetStyleFromBorder( aStyle
, rItem
.GetTop() );
469 maArray
.SetCellStyleTop( nCol
, nRow
, aStyle
);
470 lclSetStyleFromBorder( aStyle
, rItem
.GetBottom() );
471 maArray
.SetCellStyleBottom( nCol
, nRow
, aStyle
);
473 lclSetStyleFromBorder( aStyle
, GetDiagItem( nCol
, nRow
, true ).GetLine() );
474 maArray
.SetCellStyleTLBR( nCol
, nRow
, aStyle
);
475 lclSetStyleFromBorder( aStyle
, GetDiagItem( nCol
, nRow
, false ).GetLine() );
476 maArray
.SetCellStyleBLTR( nCol
, nRow
, aStyle
);
481 void ScAutoFmtPreview::NotifyChange( ScAutoFormatData
* pNewData
)
486 bFitWidth
= pNewData
->GetIncludeWidthHeight();
489 CalcCellArray( bFitWidth
);
495 void ScAutoFmtPreview::DoPaint(vcl::RenderContext
& rRenderContext
)
497 rRenderContext
.Push(vcl::PushFlags::ALL
);
498 DrawModeFlags nOldDrawMode
= aVD
->GetDrawMode();
500 Size
aWndSize(GetOutputSizePixel());
501 vcl::Font
aFont(aVD
->GetFont());
502 const Color
& aBackCol
= ScModule::get()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR
).nColor
;
503 tools::Rectangle
aRect(Point(), aWndSize
);
505 aFont
.SetTransparent( true );
508 aVD
->SetFillColor(aBackCol
);
509 aVD
->SetOutputSize(aWndSize
);
510 aVD
->DrawRect(aRect
);
514 rRenderContext
.SetLineColor();
515 rRenderContext
.SetFillColor(aBackCol
);
516 rRenderContext
.DrawRect(aRect
);
518 Point
aPos((aWndSize
.Width() - aPrvSize
.Width()) / 2, (aWndSize
.Height() - aPrvSize
.Height()) / 2);
519 if (AllSettings::GetLayoutRTL())
520 aPos
.setX( -aPos
.X() );
521 rRenderContext
.DrawOutDev(aPos
, aWndSize
, Point(), aWndSize
, *aVD
);
522 aVD
->SetDrawMode(nOldDrawMode
);
523 rRenderContext
.Pop();
526 void ScAutoFmtPreview::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
528 DoPaint(rRenderContext
);
531 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */