1
0
Fork 0
libreoffice/svx/source/dialog/pagectrl.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

397 lines
13 KiB
C++

/* -*- 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 <memory>
#include <editeng/frmdir.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/outdev.hxx>
#include <vcl/settings.hxx>
#include <tools/fract.hxx>
#include <svx/pageitem.hxx>
#include <svx/pagectrl.hxx>
#include <algorithm>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#define CELL_WIDTH 1600L
#define CELL_HEIGHT 800L
SvxPageWindow::SvxPageWindow() :
nTop(0),
nBottom(0),
nLeft(0),
nRight(0),
bResetBackground(false),
bFrameDirection(false),
nFrameDirection(SvxFrameDirection::Horizontal_LR_TB),
nHdLeft(0),
nHdRight(0),
nHdDist(0),
nHdHeight(0),
nFtLeft(0),
nFtRight(0),
nFtDist(0),
nFtHeight(0),
bFooter(false),
bHeader(false),
bTable(false),
bHorz(false),
bVert(false),
eUsage(SvxPageUsage::All)
{
}
SvxPageWindow::~SvxPageWindow()
{
}
void SvxPageWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
{
rRenderContext.Push(vcl::PushFlags::MAPMODE);
rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
Fraction aXScale(aWinSize.Width(), std::max(aSize.Width() * 2 + aSize.Width() / 8, tools::Long(1)));
Fraction aYScale(aWinSize.Height(), std::max(aSize.Height(), tools::Long(1)));
MapMode aMapMode(rRenderContext.GetMapMode());
if(aYScale < aXScale)
{
aMapMode.SetScaleX(aYScale);
aMapMode.SetScaleY(aYScale);
}
else
{
aMapMode.SetScaleX(aXScale);
aMapMode.SetScaleY(aXScale);
}
rRenderContext.SetMapMode(aMapMode);
Size aSz(rRenderContext.PixelToLogic(GetOutputSizePixel()));
tools::Long nYPos = (aSz.Height() - aSize.Height()) / 2;
if (eUsage == SvxPageUsage::All)
{
// all pages are equal -> draw one page
if (aSize.Width() > aSize.Height())
{
// Draw Landscape page of the same size
Fraction aX = aMapMode.GetScaleX();
Fraction aY = aMapMode.GetScaleY();
Fraction a2(1.5);
aX *= a2;
aY *= a2;
aMapMode.SetScaleX(aX);
aMapMode.SetScaleY(aY);
rRenderContext.SetMapMode(aMapMode);
aSz = rRenderContext.PixelToLogic(GetOutputSizePixel());
nYPos = (aSz.Height() - aSize.Height()) / 2;
tools::Long nXPos = (aSz.Width() - aSize.Width()) / 2;
DrawPage(rRenderContext, Point(nXPos,nYPos),true,true);
}
else
// Portrait
DrawPage(rRenderContext, Point((aSz.Width() - aSize.Width()) / 2,nYPos),true,true);
}
else
{
// Left and right page are different -> draw two pages if possible
DrawPage(rRenderContext, Point(0, nYPos), false,
eUsage == SvxPageUsage::Left || eUsage == SvxPageUsage::All || eUsage == SvxPageUsage::Mirror);
DrawPage(rRenderContext, Point(aSize.Width() + aSize.Width() / 8, nYPos), true,
eUsage == SvxPageUsage::Right || eUsage == SvxPageUsage::All || eUsage == SvxPageUsage::Mirror);
}
rRenderContext.Pop();
}
void SvxPageWindow::DrawPage(vcl::RenderContext& rRenderContext, const Point& rOrg, const bool bSecond, const bool bEnabled)
{
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
const Color& rFieldColor = rStyleSettings.GetFieldColor();
const Color& rFieldTextColor = rStyleSettings.GetFieldTextColor();
const Color& rDisableColor = rStyleSettings.GetDisableColor();
const Color& rDlgColor = rStyleSettings.GetDialogColor();
// background
if (!bSecond || bResetBackground)
{
rRenderContext.SetLineColor(COL_TRANSPARENT);
rRenderContext.SetFillColor(rDlgColor);
Size winSize(rRenderContext.GetOutputSize());
rRenderContext.DrawRect(tools::Rectangle(Point(0,0), winSize));
if (bResetBackground)
bResetBackground = false;
}
rRenderContext.SetLineColor(rFieldTextColor);
// Shadow
Size aTempSize = aSize;
// Page
if (!bEnabled)
{
rRenderContext.SetFillColor(rDisableColor);
rRenderContext.DrawRect(tools::Rectangle(rOrg, aTempSize));
return;
}
rRenderContext.SetFillColor(rFieldColor);
rRenderContext.DrawRect(tools::Rectangle(rOrg, aTempSize));
tools::Long nL = nLeft;
tools::Long nR = nRight;
if (eUsage == SvxPageUsage::Mirror && !bSecond)
{
// turn for mirrored
nL = nRight;
nR = nLeft;
}
tools::Rectangle aRect;
aRect.SetLeft( rOrg.X() + nL );
aRect.SetRight( rOrg.X() + aTempSize.Width() - nR );
aRect.SetTop( rOrg.Y() + nTop );
aRect.SetBottom( rOrg.Y() + aTempSize.Height() - nBottom );
tools::Rectangle aHdRect(aRect);
tools::Rectangle aFtRect(aRect);
if (bHeader || bFooter)
{
// Header and/or footer used
const Color aLineColor(rRenderContext.GetLineColor());
// draw PageFill first and on the whole page, no outline
rRenderContext.SetLineColor();
drawFillAttributes(rRenderContext, maPageFillAttributes, aRect, aRect);
rRenderContext.SetLineColor(aLineColor);
if (bHeader)
{
// show headers if possible
aHdRect.AdjustLeft(nHdLeft );
aHdRect.AdjustRight( -nHdRight );
aHdRect.SetBottom( aRect.Top() + nHdHeight );
aRect.AdjustTop(nHdHeight + nHdDist );
// draw header over PageFill, plus outline
drawFillAttributes(rRenderContext, maHeaderFillAttributes, aHdRect, aHdRect);
}
if (bFooter)
{
// show footer if possible
aFtRect.AdjustLeft(nFtLeft );
aFtRect.AdjustRight( -nFtRight );
aFtRect.SetTop( aRect.Bottom() - nFtHeight );
aRect.AdjustBottom( -(nFtHeight + nFtDist) );
// draw footer over PageFill, plus outline
drawFillAttributes(rRenderContext, maFooterFillAttributes, aFtRect, aFtRect);
}
// draw page's reduced outline, only outline
drawFillAttributes(rRenderContext, drawinglayer::attribute::SdrAllFillAttributesHelperPtr(), aRect, aRect);
}
else
{
// draw PageFill and outline
drawFillAttributes(rRenderContext, maPageFillAttributes, aRect, aRect);
}
if (bFrameDirection && !bTable)
{
Point aPos;
vcl::Font aFont(rRenderContext.GetFont());
const Size aSaveSize = aFont.GetFontSize();
Size aDrawSize(0,aRect.GetHeight() / 6);
aFont.SetFontSize(aDrawSize);
rRenderContext.SetFont(aFont);
OUString sText(u"ABC"_ustr);
Point aMove(1, rRenderContext.GetTextHeight());
sal_Unicode cArrow = 0x2193;
tools::Long nAWidth = rRenderContext.GetTextWidth(sText.copy(0,1));
switch (nFrameDirection)
{
case SvxFrameDirection::Horizontal_LR_TB:
aPos = aRect.TopLeft();
aPos.AdjustX(rRenderContext.PixelToLogic(Point(1,1)).X() );
aMove.setY( 0 );
cArrow = 0x2192;
break;
case SvxFrameDirection::Horizontal_RL_TB:
aPos = aRect.TopRight();
aPos.AdjustX( -nAWidth );
aMove.setY( 0 );
aMove.setX( aMove.X() * -1 );
cArrow = 0x2190;
break;
case SvxFrameDirection::Vertical_LR_TB:
aPos = aRect.TopLeft();
aPos.AdjustX(rRenderContext.PixelToLogic(Point(1,1)).X() );
aMove.setX( 0 );
break;
case SvxFrameDirection::Vertical_RL_TB:
aPos = aRect.TopRight();
aPos.AdjustX( -nAWidth );
aMove.setX( 0 );
break;
default: break;
}
sText += OUStringChar(cArrow);
for (sal_Int32 i = 0; i < sText.getLength(); i++)
{
OUString sDraw(sText.copy(i,1));
tools::Long nHDiff = 0;
tools::Long nCharWidth = rRenderContext.GetTextWidth(sDraw);
bool bHorizontal = 0 == aMove.Y();
if (!bHorizontal)
{
nHDiff = (nAWidth - nCharWidth) / 2;
aPos.AdjustX(nHDiff );
}
rRenderContext.DrawText(aPos,sDraw);
if (bHorizontal)
{
aPos.AdjustX(aMove.X() < 0 ? -nCharWidth : nCharWidth );
}
else
{
aPos.AdjustX( -nHDiff );
aPos.AdjustY(aMove.Y() );
}
}
aFont.SetFontSize(aSaveSize);
rRenderContext.SetFont(aFont);
}
if (!bTable)
return;
// Paint Table, if necessary center it
rRenderContext.SetLineColor(COL_LIGHTGRAY);
tools::Long nW = aRect.GetWidth();
tools::Long nH = aRect.GetHeight();
tools::Long const nTW = CELL_WIDTH * 3;
tools::Long const nTH = CELL_HEIGHT * 3;
tools::Long _nLeft = bHorz ? aRect.Left() + ((nW - nTW) / 2) : aRect.Left();
tools::Long _nTop = bVert ? aRect.Top() + ((nH - nTH) / 2) : aRect.Top();
tools::Rectangle aCellRect(Point(_nLeft, _nTop),Size(CELL_WIDTH, CELL_HEIGHT));
for (sal_uInt16 i = 0; i < 3; ++i)
{
aCellRect.SetLeft( _nLeft );
aCellRect.SetRight( _nLeft + CELL_WIDTH );
if(i > 0)
aCellRect.Move(0,CELL_HEIGHT);
for (sal_uInt16 j = 0; j < 3; ++j)
{
if (j > 0)
aCellRect.Move(CELL_WIDTH,0);
rRenderContext.DrawRect(aCellRect);
}
}
}
void SvxPageWindow::drawFillAttributes(vcl::RenderContext& rRenderContext,
const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
const tools::Rectangle& rPaintRange,
const tools::Rectangle& rDefineRange)
{
const basegfx::B2DRange aPaintRange = vcl::unotools::b2DRectangleFromRectangle(rPaintRange);
if(aPaintRange.isEmpty() ||
basegfx::fTools::equalZero(aPaintRange.getWidth()) ||
basegfx::fTools::equalZero(aPaintRange.getHeight()))
return;
const basegfx::B2DRange aDefineRange = vcl::unotools::b2DRectangleFromRectangle(rDefineRange);
// prepare primitive sequence
drawinglayer::primitive2d::Primitive2DContainer aSequence;
// create fill geometry if there is something to fill
if (rFillAttributes && rFillAttributes->isUsed())
{
aSequence = rFillAttributes->getPrimitive2DSequence(aPaintRange, aDefineRange);
}
// create line geometry if a LineColor is set at the target device
if (rRenderContext.IsLineColor())
{
const drawinglayer::primitive2d::Primitive2DReference xOutline(
new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
basegfx::utils::createPolygonFromRect(aPaintRange), rRenderContext.GetLineColor().getBColor()));
aSequence.push_back(xOutline);
}
// draw that if we have something to draw
if (aSequence.empty())
return;
drawinglayer::geometry::ViewInformation2D aViewInformation2D;
aViewInformation2D.setViewTransformation(rRenderContext.GetViewTransformation());
aViewInformation2D.setViewport(aPaintRange);
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, aViewInformation2D));
pProcessor->process(aSequence);
}
void SvxPageWindow::EnableFrameDirection(bool bEnable)
{
bFrameDirection = bEnable;
}
void SvxPageWindow::SetFrameDirection(SvxFrameDirection nDirection)
{
nFrameDirection = nDirection;
}
void SvxPageWindow::ResetBackground()
{
bResetBackground = true;
}
void SvxPageWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
{
CustomWidgetController::SetDrawingArea(pDrawingArea);
OutputDevice& rRefDevice = pDrawingArea->get_ref_device();
// Count in Twips by default
rRefDevice.Push(vcl::PushFlags::MAPMODE);
rRefDevice.SetMapMode(MapMode(MapUnit::MapTwip));
aWinSize = rRefDevice.LogicToPixel(Size(75, 46), MapMode(MapUnit::MapAppFont));
pDrawingArea->set_size_request(aWinSize.Width(), aWinSize.Height());
aWinSize.AdjustHeight( -4 );
aWinSize.AdjustWidth( -4 );
aWinSize = rRefDevice.PixelToLogic(aWinSize);
rRefDevice.Pop();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */