433 lines
19 KiB
C++
433 lines
19 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 <editeng/brushitem.hxx>
|
|
#include <editeng/numitem.hxx>
|
|
#include <i18nlangtag/mslangid.hxx>
|
|
#include <svtools/colorcfg.hxx>
|
|
#include <svx/dialmgr.hxx>
|
|
#include <svx/numberingpreview.hxx>
|
|
#include <svx/pagenumberlistbox.hxx>
|
|
#include <vcl/graph.hxx>
|
|
#include <vcl/metric.hxx>
|
|
#include <vcl/virdev.hxx>
|
|
#include <numberingtype.hrc>
|
|
|
|
#include <com/sun/star/style/NumberingType.hpp>
|
|
|
|
SvxPageNumberListBox::SvxPageNumberListBox(std::unique_ptr<weld::ComboBox> pControl)
|
|
: m_xControl(std::move(pControl))
|
|
{
|
|
m_xControl->set_size_request(150, -1);
|
|
|
|
for (size_t i = 0; i < SAL_N_ELEMENTS(RID_SVXSTRARY_NUMBERINGTYPE); ++i)
|
|
{
|
|
sal_uInt16 nData = RID_SVXSTRARY_NUMBERINGTYPE[i].second;
|
|
switch (nData)
|
|
{
|
|
// String list array is also used in Writer and contains strings
|
|
// for Bullet and Graphics, ignore those here.
|
|
case css::style::NumberingType::CHAR_SPECIAL:
|
|
case css::style::NumberingType::BITMAP:
|
|
case css::style::NumberingType::BITMAP | LINK_TOKEN:
|
|
break;
|
|
default:
|
|
{
|
|
OUString aStr = SvxResId(RID_SVXSTRARY_NUMBERINGTYPE[i].first);
|
|
m_xControl->append(OUString::number(nData), aStr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SvxNumberingPreview::SvxNumberingPreview()
|
|
: m_pActNum(nullptr)
|
|
, m_bPosition(false)
|
|
, m_nActLevel(SAL_MAX_UINT16)
|
|
{
|
|
}
|
|
|
|
static tools::Long lcl_DrawGraphic(VirtualDevice& rVDev, const SvxNumberFormat& rFmt,
|
|
tools::Long nXStart, tools::Long nYMiddle, tools::Long nDivision)
|
|
{
|
|
const SvxBrushItem* pBrushItem = rFmt.GetBrush();
|
|
tools::Long nRet = 0;
|
|
if (pBrushItem)
|
|
{
|
|
const Graphic* pGrf = pBrushItem->GetGraphic();
|
|
if (pGrf)
|
|
{
|
|
Size aGSize(rFmt.GetGraphicSize());
|
|
aGSize.setWidth(aGSize.Width() / nDivision);
|
|
nRet = aGSize.Width();
|
|
aGSize.setHeight(aGSize.Height() / nDivision);
|
|
pGrf->Draw(rVDev, Point(nXStart, nYMiddle - (aGSize.Height() / 2)),
|
|
rVDev.PixelToLogic(aGSize));
|
|
}
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
static tools::Long lcl_DrawBullet(VirtualDevice* pVDev, const SvxNumberFormat& rFmt,
|
|
tools::Long nXStart, tools::Long nYStart, const Size& rSize)
|
|
{
|
|
vcl::Font aTmpFont(pVDev->GetFont());
|
|
|
|
// via Uno it's possible that no font has been set!
|
|
vcl::Font aFont(rFmt.GetBulletFont() ? *rFmt.GetBulletFont() : aTmpFont);
|
|
Size aTmpSize(rSize);
|
|
aTmpSize.setWidth(aTmpSize.Width() * (rFmt.GetBulletRelSize()));
|
|
aTmpSize.setWidth(aTmpSize.Width() / 100);
|
|
aTmpSize.setHeight(aTmpSize.Height() * (rFmt.GetBulletRelSize()));
|
|
aTmpSize.setHeight(aTmpSize.Height() / 100);
|
|
// in case of a height of zero it is drawn in original height
|
|
if (!aTmpSize.Height())
|
|
aTmpSize.setHeight(1);
|
|
aFont.SetFontSize(aTmpSize);
|
|
aFont.SetTransparent(true);
|
|
Color aBulletColor = rFmt.GetBulletColor();
|
|
if (aBulletColor == COL_AUTO)
|
|
aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
else if (pVDev->GetBackgroundColor().IsDark() == aBulletColor.IsDark())
|
|
aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
aFont.SetColor(aBulletColor);
|
|
pVDev->SetFont(aFont);
|
|
sal_UCS4 cChar = rFmt.GetBulletChar();
|
|
OUString aText(&cChar, 1);
|
|
tools::Long nY = nYStart;
|
|
nY -= ((aTmpSize.Height() - rSize.Height()) / 2);
|
|
pVDev->DrawText(Point(nXStart, nY), aText);
|
|
tools::Long nRet = pVDev->GetTextWidth(aText);
|
|
|
|
pVDev->SetFont(aTmpFont);
|
|
return nRet;
|
|
}
|
|
|
|
// paint preview of numeration
|
|
void SvxNumberingPreview::Paint(vcl::RenderContext& rRenderContext,
|
|
const ::tools::Rectangle& /*rRect*/)
|
|
{
|
|
Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
|
|
|
|
// Use default document and font colors to create preview
|
|
const Color aBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
|
|
const Color aTextColor = svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
|
|
|
|
ScopedVclPtrInstance<VirtualDevice> pVDev(rRenderContext);
|
|
pVDev->EnableRTL(rRenderContext.IsRTLEnabled());
|
|
pVDev->SetMapMode(rRenderContext.GetMapMode());
|
|
pVDev->SetOutputSize(aSize);
|
|
|
|
Color aLineColor(COL_LIGHTGRAY);
|
|
if (aLineColor == aBackColor)
|
|
aLineColor.Invert();
|
|
pVDev->SetLineColor(aLineColor);
|
|
pVDev->SetFillColor(aBackColor);
|
|
pVDev->SetBackground(Wallpaper(aBackColor));
|
|
pVDev->DrawWallpaper(pVDev->GetOutputRectPixel(), pVDev->GetBackground());
|
|
|
|
if (m_pActNum)
|
|
{
|
|
tools::Long nWidthRelation = 30; // chapter dialog
|
|
|
|
// height per level
|
|
tools::Long nXStep
|
|
= aSize.Width() / (m_pActNum->GetLevelCount() > 1 ? 3 * m_pActNum->GetLevelCount() : 3);
|
|
if (m_pActNum->GetLevelCount() < 10)
|
|
nXStep /= 2;
|
|
tools::Long nYStart = 4;
|
|
// the whole height mustn't be used for a single level
|
|
tools::Long nYStep = (aSize.Height() - 6)
|
|
/ (m_pActNum->GetLevelCount() > 1 ? m_pActNum->GetLevelCount() : 5);
|
|
|
|
m_aStdFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS,
|
|
MsLangId::getConfiguredSystemLanguage(),
|
|
GetDefaultFontFlags::OnlyOne);
|
|
m_aStdFont.SetColor(aTextColor);
|
|
m_aStdFont.SetFillColor(aBackColor);
|
|
|
|
tools::Long nFontHeight = nYStep * 6 / 10;
|
|
if (m_bPosition)
|
|
nFontHeight = nYStep * 15 / 10;
|
|
m_aStdFont.SetFontSize(Size(0, nFontHeight));
|
|
|
|
SvxNodeNum aNum;
|
|
sal_uInt16 nPreNum = m_pActNum->GetLevel(0).GetStart();
|
|
|
|
if (m_bPosition)
|
|
{
|
|
// When bPosition == true, draw the preview used in the Writer's "Position" tab
|
|
// This is not used in Impress/Draw
|
|
|
|
tools::Long nLineHeight = nFontHeight * 8 / 7;
|
|
sal_uInt8 nStart = 0;
|
|
while (!(m_nActLevel & (1 << nStart)))
|
|
{
|
|
nStart++;
|
|
}
|
|
if (nStart)
|
|
nStart--;
|
|
sal_uInt8 nEnd = std::min(sal_uInt8(nStart + 3), sal_uInt8(m_pActNum->GetLevelCount()));
|
|
for (sal_uInt8 nLevel = nStart; nLevel < nEnd; ++nLevel)
|
|
{
|
|
const SvxNumberFormat& rFmt = m_pActNum->GetLevel(nLevel);
|
|
aNum.GetLevelVal()[nLevel] = rFmt.GetStart();
|
|
|
|
tools::Long nXStart(0);
|
|
short nTextOffset(0);
|
|
tools::Long nNumberXPos(0);
|
|
if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
|
|
{
|
|
nXStart = rFmt.GetAbsLSpace() / nWidthRelation;
|
|
nTextOffset = rFmt.GetCharTextDistance() / nWidthRelation;
|
|
nNumberXPos = nXStart;
|
|
tools::Long nFirstLineOffset = (-rFmt.GetFirstLineOffset()) / nWidthRelation;
|
|
|
|
if (nFirstLineOffset <= nNumberXPos)
|
|
nNumberXPos = nNumberXPos - nFirstLineOffset;
|
|
else
|
|
nNumberXPos = 0;
|
|
// in draw this is valid
|
|
if (nTextOffset < 0)
|
|
nNumberXPos = nNumberXPos + nTextOffset;
|
|
}
|
|
else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
|
|
{
|
|
const tools::Long nTmpNumberXPos(
|
|
(rFmt.GetIndentAt() + rFmt.GetFirstLineIndent()) / nWidthRelation);
|
|
if (nTmpNumberXPos < 0)
|
|
{
|
|
nNumberXPos = 0;
|
|
}
|
|
else
|
|
{
|
|
nNumberXPos = nTmpNumberXPos;
|
|
}
|
|
}
|
|
|
|
tools::Long nBulletWidth = 0;
|
|
if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() & (~LINK_TOKEN)))
|
|
{
|
|
tools::Long nYMiddle = nYStart + (nFontHeight / 2);
|
|
nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawGraphic(*pVDev, rFmt, nNumberXPos,
|
|
nYMiddle, nWidthRelation)
|
|
: 0;
|
|
}
|
|
else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType())
|
|
{
|
|
nBulletWidth = rFmt.IsShowSymbol()
|
|
? lcl_DrawBullet(pVDev.get(), rFmt, nNumberXPos, nYStart,
|
|
m_aStdFont.GetFontSize())
|
|
: 0;
|
|
}
|
|
else
|
|
{
|
|
pVDev->SetFont(m_aStdFont);
|
|
aNum.SetLevel(nLevel);
|
|
if (m_pActNum->IsContinuousNumbering())
|
|
aNum.GetLevelVal()[nLevel] = nPreNum;
|
|
OUString aText(m_pActNum->MakeNumString(aNum));
|
|
vcl::Font aSaveFont = pVDev->GetFont();
|
|
vcl::Font aColorFont(aSaveFont);
|
|
Color aTmpBulletColor = rFmt.GetBulletColor();
|
|
if (aTmpBulletColor == COL_AUTO)
|
|
aTmpBulletColor
|
|
= pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
else if (pVDev->GetBackgroundColor().IsDark() == aTmpBulletColor.IsDark())
|
|
aTmpBulletColor
|
|
= pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
aColorFont.SetColor(aTmpBulletColor);
|
|
pVDev->SetFont(aColorFont);
|
|
pVDev->DrawText(Point(nNumberXPos, nYStart), aText);
|
|
pVDev->SetFont(aSaveFont);
|
|
nBulletWidth = pVDev->GetTextWidth(aText);
|
|
nPreNum++;
|
|
}
|
|
if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
|
|
&& rFmt.GetLabelFollowedBy() == SvxNumberFormat::SPACE)
|
|
{
|
|
pVDev->SetFont(m_aStdFont);
|
|
OUString aText(' ');
|
|
pVDev->DrawText(Point(nNumberXPos, nYStart), aText);
|
|
nBulletWidth = nBulletWidth + pVDev->GetTextWidth(aText);
|
|
}
|
|
|
|
tools::Long nTextXPos(0);
|
|
if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
|
|
{
|
|
nTextXPos = nXStart;
|
|
if (nTextOffset < 0)
|
|
nTextXPos = nTextXPos + nTextOffset;
|
|
if (nNumberXPos + nBulletWidth + nTextOffset > nTextXPos)
|
|
nTextXPos = nNumberXPos + nBulletWidth + nTextOffset;
|
|
}
|
|
else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
|
|
{
|
|
switch (rFmt.GetLabelFollowedBy())
|
|
{
|
|
case SvxNumberFormat::LISTTAB:
|
|
{
|
|
nTextXPos = rFmt.GetListtabPos() / nWidthRelation;
|
|
if (nTextXPos < nNumberXPos + nBulletWidth)
|
|
{
|
|
nTextXPos = nNumberXPos + nBulletWidth;
|
|
}
|
|
}
|
|
break;
|
|
case SvxNumberFormat::SPACE:
|
|
case SvxNumberFormat::NOTHING:
|
|
case SvxNumberFormat::NEWLINE:
|
|
{
|
|
nTextXPos = nNumberXPos + nBulletWidth;
|
|
}
|
|
break;
|
|
}
|
|
|
|
nXStart = rFmt.GetIndentAt() / nWidthRelation;
|
|
}
|
|
|
|
::tools::Rectangle aRect1(Point(nTextXPos, nYStart + nFontHeight / 2),
|
|
Size(aSize.Width() / 2, 2));
|
|
pVDev->SetFillColor(aBackColor);
|
|
pVDev->DrawRect(aRect1);
|
|
|
|
::tools::Rectangle aRect2(Point(nXStart, nYStart + nLineHeight + nFontHeight / 2),
|
|
Size(aSize.Width() / 2, 2));
|
|
pVDev->DrawRect(aRect2);
|
|
nYStart += 2 * nLineHeight;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// When bPosition == false, draw the preview used in Writer's "Customize" tab
|
|
// and in Impress' "Bullets and Numbering" dialog
|
|
|
|
//#i5153# painting gray or black rectangles as 'normal' numbering text
|
|
tools::Long nWidth = pVDev->GetTextWidth(u"Preview"_ustr);
|
|
tools::Long nTextHeight = pVDev->GetTextHeight();
|
|
tools::Long nRectHeight = nTextHeight * 2 / 3;
|
|
tools::Long nTopOffset = nTextHeight - nRectHeight;
|
|
Color aSelRectColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
|
|
for (sal_uInt16 nLevel = 0; nLevel < m_pActNum->GetLevelCount();
|
|
++nLevel, nYStart = nYStart + nYStep)
|
|
{
|
|
const SvxNumberFormat& rFmt = m_pActNum->GetLevel(nLevel);
|
|
aNum.GetLevelVal()[nLevel] = rFmt.GetStart();
|
|
tools::Long nXStart(0);
|
|
pVDev->SetFillColor(aBackColor);
|
|
|
|
if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
|
|
{
|
|
nXStart = rFmt.GetAbsLSpace() / nWidthRelation;
|
|
}
|
|
else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
|
|
{
|
|
const tools::Long nTmpXStart((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent())
|
|
/ nWidthRelation);
|
|
if (nTmpXStart < 0)
|
|
{
|
|
nXStart = 0;
|
|
}
|
|
else
|
|
{
|
|
nXStart = nTmpXStart;
|
|
}
|
|
}
|
|
nXStart /= 2;
|
|
nXStart += 2;
|
|
tools::Long nTextOffset = 2 * nXStep;
|
|
if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() & (~LINK_TOKEN)))
|
|
{
|
|
if (rFmt.IsShowSymbol())
|
|
{
|
|
tools::Long nYMiddle = nYStart + (nFontHeight / 2);
|
|
nTextOffset
|
|
= lcl_DrawGraphic(*pVDev, rFmt, nXStart, nYMiddle, nWidthRelation);
|
|
nTextOffset = nTextOffset + nXStep;
|
|
}
|
|
}
|
|
else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType())
|
|
{
|
|
if (rFmt.IsShowSymbol())
|
|
{
|
|
nTextOffset = lcl_DrawBullet(pVDev.get(), rFmt, nXStart, nYStart,
|
|
m_aStdFont.GetFontSize());
|
|
nTextOffset = nTextOffset + nXStep;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vcl::Font aFont(m_aStdFont);
|
|
Size aTmpSize(m_aStdFont.GetFontSize());
|
|
if (m_pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE))
|
|
{
|
|
aTmpSize.setWidth(aTmpSize.Width() * (rFmt.GetBulletRelSize()));
|
|
aTmpSize.setWidth(aTmpSize.Width() / 100);
|
|
aTmpSize.setHeight(aTmpSize.Height() * (rFmt.GetBulletRelSize()));
|
|
aTmpSize.setHeight(aTmpSize.Height() / 100);
|
|
}
|
|
if (!aTmpSize.Height())
|
|
aTmpSize.setHeight(1);
|
|
aFont.SetFontSize(aTmpSize);
|
|
Color aTmpBulletColor = rFmt.GetBulletColor();
|
|
if (aTmpBulletColor == COL_AUTO)
|
|
aTmpBulletColor
|
|
= pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
else if (pVDev->GetBackgroundColor().IsDark() == aTmpBulletColor.IsDark())
|
|
aTmpBulletColor
|
|
= pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : COL_BLACK;
|
|
aFont.SetColor(aTmpBulletColor);
|
|
pVDev->SetFont(aFont);
|
|
aNum.SetLevel(nLevel);
|
|
if (m_pActNum->IsContinuousNumbering())
|
|
aNum.GetLevelVal()[nLevel] = nPreNum;
|
|
OUString aText(m_pActNum->MakeNumString(aNum));
|
|
tools::Long nY = nYStart;
|
|
nY -= (pVDev->GetTextHeight() - nTextHeight
|
|
- pVDev->GetFontMetric().GetDescent());
|
|
pVDev->DrawText(Point(nXStart, nY), aText);
|
|
nTextOffset = pVDev->GetTextWidth(aText);
|
|
nTextOffset = nTextOffset + nXStep;
|
|
nPreNum++;
|
|
pVDev->SetFont(m_aStdFont);
|
|
}
|
|
//#i5153# the selected rectangle(s) should be black
|
|
if (0 != (m_nActLevel & (1 << nLevel)))
|
|
{
|
|
pVDev->SetFillColor(aSelRectColor);
|
|
pVDev->SetLineColor(aSelRectColor);
|
|
}
|
|
else
|
|
{
|
|
//#i5153# unselected levels are gray
|
|
pVDev->SetFillColor(aLineColor);
|
|
pVDev->SetLineColor(aLineColor);
|
|
}
|
|
::tools::Rectangle aRect1(Point(nXStart + nTextOffset, nYStart + nTopOffset),
|
|
Size(nWidth, nRectHeight));
|
|
pVDev->DrawRect(aRect1);
|
|
}
|
|
}
|
|
}
|
|
rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *pVDev);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|