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 .
21 #include <editeng/frmdir.hxx>
22 #include <vcl/canvastools.hxx>
23 #include <vcl/outdev.hxx>
24 #include <vcl/settings.hxx>
25 #include <tools/fract.hxx>
26 #include <svx/pageitem.hxx>
27 #include <svx/pagectrl.hxx>
29 #include <basegfx/matrix/b2dhommatrix.hxx>
30 #include <drawinglayer/geometry/viewinformation2d.hxx>
31 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
32 #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
33 #include <drawinglayer/processor2d/processor2dtools.hxx>
34 #include <basegfx/polygon/b2dpolygontools.hxx>
36 #define CELL_WIDTH 1600L
37 #define CELL_HEIGHT 800L
39 SvxPageWindow::SvxPageWindow() :
44 bResetBackground(false),
45 bFrameDirection(false),
46 nFrameDirection(SvxFrameDirection::Horizontal_LR_TB
),
60 eUsage(SvxPageUsage::All
)
64 SvxPageWindow::~SvxPageWindow()
68 void SvxPageWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
70 rRenderContext
.Push(vcl::PushFlags::MAPMODE
);
71 rRenderContext
.SetMapMode(MapMode(MapUnit::MapTwip
));
73 Fraction
aXScale(aWinSize
.Width(), std::max(aSize
.Width() * 2 + aSize
.Width() / 8, tools::Long(1)));
74 Fraction
aYScale(aWinSize
.Height(), std::max(aSize
.Height(), tools::Long(1)));
75 MapMode
aMapMode(rRenderContext
.GetMapMode());
79 aMapMode
.SetScaleX(aYScale
);
80 aMapMode
.SetScaleY(aYScale
);
84 aMapMode
.SetScaleX(aXScale
);
85 aMapMode
.SetScaleY(aXScale
);
87 rRenderContext
.SetMapMode(aMapMode
);
88 Size
aSz(rRenderContext
.PixelToLogic(GetOutputSizePixel()));
89 tools::Long nYPos
= (aSz
.Height() - aSize
.Height()) / 2;
91 if (eUsage
== SvxPageUsage::All
)
93 // all pages are equal -> draw one page
94 if (aSize
.Width() > aSize
.Height())
96 // Draw Landscape page of the same size
97 Fraction aX
= aMapMode
.GetScaleX();
98 Fraction aY
= aMapMode
.GetScaleY();
102 aMapMode
.SetScaleX(aX
);
103 aMapMode
.SetScaleY(aY
);
104 rRenderContext
.SetMapMode(aMapMode
);
105 aSz
= rRenderContext
.PixelToLogic(GetOutputSizePixel());
106 nYPos
= (aSz
.Height() - aSize
.Height()) / 2;
107 tools::Long nXPos
= (aSz
.Width() - aSize
.Width()) / 2;
108 DrawPage(rRenderContext
, Point(nXPos
,nYPos
),true,true);
112 DrawPage(rRenderContext
, Point((aSz
.Width() - aSize
.Width()) / 2,nYPos
),true,true);
116 // Left and right page are different -> draw two pages if possible
117 DrawPage(rRenderContext
, Point(0, nYPos
), false,
118 eUsage
== SvxPageUsage::Left
|| eUsage
== SvxPageUsage::All
|| eUsage
== SvxPageUsage::Mirror
);
119 DrawPage(rRenderContext
, Point(aSize
.Width() + aSize
.Width() / 8, nYPos
), true,
120 eUsage
== SvxPageUsage::Right
|| eUsage
== SvxPageUsage::All
|| eUsage
== SvxPageUsage::Mirror
);
122 rRenderContext
.Pop();
125 void SvxPageWindow::DrawPage(vcl::RenderContext
& rRenderContext
, const Point
& rOrg
, const bool bSecond
, const bool bEnabled
)
127 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
128 const Color
& rFieldColor
= rStyleSettings
.GetFieldColor();
129 const Color
& rFieldTextColor
= rStyleSettings
.GetFieldTextColor();
130 const Color
& rDisableColor
= rStyleSettings
.GetDisableColor();
131 const Color
& rDlgColor
= rStyleSettings
.GetDialogColor();
134 if (!bSecond
|| bResetBackground
)
136 rRenderContext
.SetLineColor(COL_TRANSPARENT
);
137 rRenderContext
.SetFillColor(rDlgColor
);
138 Size
winSize(rRenderContext
.GetOutputSize());
139 rRenderContext
.DrawRect(tools::Rectangle(Point(0,0), winSize
));
141 if (bResetBackground
)
142 bResetBackground
= false;
144 rRenderContext
.SetLineColor(rFieldTextColor
);
147 Size aTempSize
= aSize
;
152 rRenderContext
.SetFillColor(rDisableColor
);
153 rRenderContext
.DrawRect(tools::Rectangle(rOrg
, aTempSize
));
156 rRenderContext
.SetFillColor(rFieldColor
);
157 rRenderContext
.DrawRect(tools::Rectangle(rOrg
, aTempSize
));
159 tools::Long nL
= nLeft
;
160 tools::Long nR
= nRight
;
162 if (eUsage
== SvxPageUsage::Mirror
&& !bSecond
)
169 tools::Rectangle aRect
;
171 aRect
.SetLeft( rOrg
.X() + nL
);
172 aRect
.SetRight( rOrg
.X() + aTempSize
.Width() - nR
);
173 aRect
.SetTop( rOrg
.Y() + nTop
);
174 aRect
.SetBottom( rOrg
.Y() + aTempSize
.Height() - nBottom
);
176 tools::Rectangle
aHdRect(aRect
);
177 tools::Rectangle
aFtRect(aRect
);
179 if (bHeader
|| bFooter
)
181 // Header and/or footer used
182 const Color
aLineColor(rRenderContext
.GetLineColor());
184 // draw PageFill first and on the whole page, no outline
185 rRenderContext
.SetLineColor();
186 drawFillAttributes(rRenderContext
, maPageFillAttributes
, aRect
, aRect
);
187 rRenderContext
.SetLineColor(aLineColor
);
191 // show headers if possible
192 aHdRect
.AdjustLeft(nHdLeft
);
193 aHdRect
.AdjustRight( -nHdRight
);
194 aHdRect
.SetBottom( aRect
.Top() + nHdHeight
);
195 aRect
.AdjustTop(nHdHeight
+ nHdDist
);
197 // draw header over PageFill, plus outline
198 drawFillAttributes(rRenderContext
, maHeaderFillAttributes
, aHdRect
, aHdRect
);
203 // show footer if possible
204 aFtRect
.AdjustLeft(nFtLeft
);
205 aFtRect
.AdjustRight( -nFtRight
);
206 aFtRect
.SetTop( aRect
.Bottom() - nFtHeight
);
207 aRect
.AdjustBottom( -(nFtHeight
+ nFtDist
) );
209 // draw footer over PageFill, plus outline
210 drawFillAttributes(rRenderContext
, maFooterFillAttributes
, aFtRect
, aFtRect
);
213 // draw page's reduced outline, only outline
214 drawFillAttributes(rRenderContext
, drawinglayer::attribute::SdrAllFillAttributesHelperPtr(), aRect
, aRect
);
218 // draw PageFill and outline
219 drawFillAttributes(rRenderContext
, maPageFillAttributes
, aRect
, aRect
);
222 if (bFrameDirection
&& !bTable
)
225 vcl::Font
aFont(rRenderContext
.GetFont());
226 const Size aSaveSize
= aFont
.GetFontSize();
227 Size
aDrawSize(0,aRect
.GetHeight() / 6);
228 aFont
.SetFontSize(aDrawSize
);
229 rRenderContext
.SetFont(aFont
);
230 OUString
sText(u
"ABC"_ustr
);
231 Point
aMove(1, rRenderContext
.GetTextHeight());
232 sal_Unicode cArrow
= 0x2193;
233 tools::Long nAWidth
= rRenderContext
.GetTextWidth(sText
.copy(0,1));
234 switch (nFrameDirection
)
236 case SvxFrameDirection::Horizontal_LR_TB
:
237 aPos
= aRect
.TopLeft();
238 aPos
.AdjustX(rRenderContext
.PixelToLogic(Point(1,1)).X() );
242 case SvxFrameDirection::Horizontal_RL_TB
:
243 aPos
= aRect
.TopRight();
244 aPos
.AdjustX( -nAWidth
);
246 aMove
.setX( aMove
.X() * -1 );
249 case SvxFrameDirection::Vertical_LR_TB
:
250 aPos
= aRect
.TopLeft();
251 aPos
.AdjustX(rRenderContext
.PixelToLogic(Point(1,1)).X() );
254 case SvxFrameDirection::Vertical_RL_TB
:
255 aPos
= aRect
.TopRight();
256 aPos
.AdjustX( -nAWidth
);
261 sText
+= OUStringChar(cArrow
);
262 for (sal_Int32 i
= 0; i
< sText
.getLength(); i
++)
264 OUString
sDraw(sText
.copy(i
,1));
265 tools::Long nHDiff
= 0;
266 tools::Long nCharWidth
= rRenderContext
.GetTextWidth(sDraw
);
267 bool bHorizontal
= 0 == aMove
.Y();
270 nHDiff
= (nAWidth
- nCharWidth
) / 2;
271 aPos
.AdjustX(nHDiff
);
273 rRenderContext
.DrawText(aPos
,sDraw
);
276 aPos
.AdjustX(aMove
.X() < 0 ? -nCharWidth
: nCharWidth
);
280 aPos
.AdjustX( -nHDiff
);
281 aPos
.AdjustY(aMove
.Y() );
284 aFont
.SetFontSize(aSaveSize
);
285 rRenderContext
.SetFont(aFont
);
291 // Paint Table, if necessary center it
292 rRenderContext
.SetLineColor(COL_LIGHTGRAY
);
294 tools::Long nW
= aRect
.GetWidth();
295 tools::Long nH
= aRect
.GetHeight();
296 tools::Long
const nTW
= CELL_WIDTH
* 3;
297 tools::Long
const nTH
= CELL_HEIGHT
* 3;
298 tools::Long _nLeft
= bHorz
? aRect
.Left() + ((nW
- nTW
) / 2) : aRect
.Left();
299 tools::Long _nTop
= bVert
? aRect
.Top() + ((nH
- nTH
) / 2) : aRect
.Top();
300 tools::Rectangle
aCellRect(Point(_nLeft
, _nTop
),Size(CELL_WIDTH
, CELL_HEIGHT
));
302 for (sal_uInt16 i
= 0; i
< 3; ++i
)
304 aCellRect
.SetLeft( _nLeft
);
305 aCellRect
.SetRight( _nLeft
+ CELL_WIDTH
);
307 aCellRect
.Move(0,CELL_HEIGHT
);
309 for (sal_uInt16 j
= 0; j
< 3; ++j
)
312 aCellRect
.Move(CELL_WIDTH
,0);
313 rRenderContext
.DrawRect(aCellRect
);
318 void SvxPageWindow::drawFillAttributes(vcl::RenderContext
& rRenderContext
,
319 const drawinglayer::attribute::SdrAllFillAttributesHelperPtr
& rFillAttributes
,
320 const tools::Rectangle
& rPaintRange
,
321 const tools::Rectangle
& rDefineRange
)
323 const basegfx::B2DRange aPaintRange
= vcl::unotools::b2DRectangleFromRectangle(rPaintRange
);
325 if(aPaintRange
.isEmpty() ||
326 basegfx::fTools::equalZero(aPaintRange
.getWidth()) ||
327 basegfx::fTools::equalZero(aPaintRange
.getHeight()))
330 const basegfx::B2DRange aDefineRange
= vcl::unotools::b2DRectangleFromRectangle(rDefineRange
);
332 // prepare primitive sequence
333 drawinglayer::primitive2d::Primitive2DContainer aSequence
;
335 // create fill geometry if there is something to fill
336 if (rFillAttributes
&& rFillAttributes
->isUsed())
338 aSequence
= rFillAttributes
->getPrimitive2DSequence(aPaintRange
, aDefineRange
);
341 // create line geometry if a LineColor is set at the target device
342 if (rRenderContext
.IsLineColor())
344 const drawinglayer::primitive2d::Primitive2DReference
xOutline(
345 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
346 basegfx::utils::createPolygonFromRect(aPaintRange
), rRenderContext
.GetLineColor().getBColor()));
348 aSequence
.push_back(xOutline
);
351 // draw that if we have something to draw
352 if (aSequence
.empty())
355 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
356 aViewInformation2D
.setViewTransformation(rRenderContext
.GetViewTransformation());
357 aViewInformation2D
.setViewport(aPaintRange
);
359 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor(
360 drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext
, aViewInformation2D
));
361 pProcessor
->process(aSequence
);
364 void SvxPageWindow::EnableFrameDirection(bool bEnable
)
366 bFrameDirection
= bEnable
;
369 void SvxPageWindow::SetFrameDirection(SvxFrameDirection nDirection
)
371 nFrameDirection
= nDirection
;
374 void SvxPageWindow::ResetBackground()
376 bResetBackground
= true;
379 void SvxPageWindow::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
381 CustomWidgetController::SetDrawingArea(pDrawingArea
);
383 OutputDevice
& rRefDevice
= pDrawingArea
->get_ref_device();
384 // Count in Twips by default
385 rRefDevice
.Push(vcl::PushFlags::MAPMODE
);
386 rRefDevice
.SetMapMode(MapMode(MapUnit::MapTwip
));
387 aWinSize
= rRefDevice
.LogicToPixel(Size(75, 46), MapMode(MapUnit::MapAppFont
));
388 pDrawingArea
->set_size_request(aWinSize
.Width(), aWinSize
.Height());
390 aWinSize
.AdjustHeight( -4 );
391 aWinSize
.AdjustWidth( -4 );
393 aWinSize
= rRefDevice
.PixelToLogic(aWinSize
);
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */