/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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 <cstring>
#include <climits>
#include <vcl/commandevent.hxx>
#include <vcl/event.hxx>
#include <vcl/fieldvalues.hxx>
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weldutils.hxx>
#include <svl/eitem.hxx>
#include <svl/rectitem.hxx>
#include <svl/hint.hxx>
#include <sfx2/dispatch.hxx>
#include <svx/strings.hrc>
#include <svx/svxids.hrc>
#include <svx/dialmgr.hxx>
#include <svx/ruler.hxx>
#include <svx/rulritem.hxx>
#include <sfx2/viewsh.hxx>
#include <editeng/editids.hrc>
#include <editeng/tstpitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/protitem.hxx>
#include <osl/diagnose.h>
#include <rtl/math.hxx>
#include <o3tl/string_view.hxx>
#include <svl/itemset.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <tools/json_writer.hxx>
#include <tools/UnitConversion.hxx>
#include <comphelper/lok.hxx>
#include "rlrcitem.hxx"
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <sfx2/viewfrm.hxx>
#include <memory>
using namespace css;
#define CTRL_ITEM_COUNT 14
#define GAP 10
#define OBJECT_BORDER_COUNT 4
#define TAB_GAP 1
#define INDENT_GAP 2
#define INDENT_FIRST_LINE 2
#define INDENT_LEFT_MARGIN 3
#define INDENT_RIGHT_MARGIN 4
#define INDENT_COUNT 3 //without the first two old values
struct SvxRuler_Impl {
std::unique_ptr<sal_uInt16[]> pPercBuf;
std::unique_ptr<sal_uInt16[]> pBlockBuf;
sal_uInt16 nPercSize;
tools::Long nTotalDist;
tools::Long lOldWinPos;
tools::Long lMaxLeftLogic;
tools::Long lMaxRightLogic;
tools::Long lLastLMargin;
tools::Long lLastRMargin;
std::unique_ptr<SvxProtectItem> aProtectItem;
std::unique_ptr<SfxBoolItem> pTextRTLItem;
sal_uInt16 nControllerItems;
sal_uInt16 nIdx;
sal_uInt16 nColLeftPix;
sal_uInt16 nColRightPix; // Pixel values for left / right edge
// For columns; buffered to prevent
// recalculation errors
// May be has to be widen for future values
bool bIsTableRows : 1 ; // mxColumnItem contains table rows instead of columns
//#i24363# tab stops relative to indent
bool bIsTabsRelativeToIndent : 1 ; // Tab stops relative to paragraph indent?
// false means relative to SvxRuler::GetLeftFrameMargin()
SvxRuler_Impl() :
nPercSize(0 ), nTotalDist(0 ),
lOldWinPos(0 ), lMaxLeftLogic(0 ), lMaxRightLogic(0 ),
lLastLMargin(0 ), lLastRMargin(0 ),
aProtectItem(std::make_unique<SvxProtectItem>(SID_RULER_PROTECT)),
nControllerItems(0 ), nIdx(0 ),
nColLeftPix(0 ), nColRightPix(0 ),
bIsTableRows(false ),
bIsTabsRelativeToIndent(true )
{
}
void SetPercSize(sal_uInt16 nSize);
};
static RulerTabData ruler_tab_svx =
{
0 , // DPIScaleFactor to be set
7 , // ruler_tab_width
6 , // ruler_tab_height
0 , // ruler_tab_height2
0 , // ruler_tab_width2
0 , // ruler_tab_cwidth
0 , // ruler_tab_cwidth2
0 , // ruler_tab_cwidth3
0 , // ruler_tab_cwidth4
0 , // ruler_tab_dheight
0 , // ruler_tab_dheight2
0 , // ruler_tab_dwidth
0 , // ruler_tab_dwidth2
0 , // ruler_tab_dwidth3
0 , // ruler_tab_dwidth4
0 // ruler_tab_textoff
};
void SvxRuler_Impl::SetPercSize(sal_uInt16 nSize)
{
if (nSize > nPercSize)
{
nPercSize = nSize;
pPercBuf.reset( new sal_uInt16[nPercSize] );
pBlockBuf.reset( new sal_uInt16[nPercSize] );
}
size_t nSize2 = sizeof (sal_uInt16) * nPercSize;
memset(pPercBuf.get(), 0 , nSize2);
memset(pBlockBuf.get(), 0 , nSize2);
}
// Constructor of the ruler
// SID_ATTR_ULSPACE, SID_ATTR_LRSPACE
// expects as parameter SvxULSpaceItem for page edge
// (either left/right or top/bottom)
// Ruler: SetMargin1, SetMargin2
// SID_RULER_PAGE_POS
// expects as parameter the initial value of the page and page width
// Ruler: SetPagePos
// SID_ATTR_TABSTOP
// expects: SvxTabStopItem
// Ruler: SetTabs
// SID_ATTR_PARA_LRSPACE
// left, right paragraph edge in H-ruler
// Ruler: SetIndents
// SID_RULER_BORDERS
// Table borders, columns
// expects: something like SwTabCols
// Ruler: SetBorders
constexpr tools::Long glMinFrame = 5 ; // minimal frame width in pixels
SvxRuler::SvxRuler(
vcl::Window* pParent, // StarView Parent
vcl::Window* pWin, // Output window: is used for conversion
// logical units <-> pixels
SvxRulerSupportFlags flags, // Display flags, see ruler.hxx
SfxBindings &rBindings, // associated Bindings
WinBits nWinStyle) : // StarView WinBits
Ruler(pParent, nWinStyle),
pCtrlItems(CTRL_ITEM_COUNT),
pEditWin(pWin),
mxRulerImpl(new SvxRuler_Impl),
bAppSetNullOffset(false ), // Is the 0-offset of the ruler set by the application?
lLogicNullOffset(0 ),
lAppNullOffset(LONG_MAX),
lInitialDragPos(0 ),
nFlags(flags),
nDragType(SvxRulerDragFlags::NONE),
nDefTabType(RULER_TAB_LEFT),
nTabCount(0 ),
nTabBufSize(0 ),
lDefTabDist(50 ),
lTabPos(-1 ),
mpBorders(1 ), // due to one column tables
pBindings(&rBindings),
nDragOffset(0 ),
nMaxLeft(0 ),
nMaxRight(0 ),
bValid(false ),
bListening(false ),
bActive(true ),
mbCoarseSnapping(false ),
mbSnapping(true )
{
/* Constructor; Initialize data buffer; controller items are created */
rBindings.EnterRegistrations();
// Create Supported Items
sal_uInt16 i = 0 ;
// Page edges
pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_LR_MIN_MAX, *this , rBindings));
if ((nWinStyle & WB_VSCROLL) == WB_VSCROLL)
{
bHorz = false ;
pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_LONG_ULSPACE, *this , rBindings));
}
else
{
bHorz = true ;
pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_LONG_LRSPACE, *this , rBindings));
}
// Page Position
pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_PAGE_POS, *this , rBindings));
if (nFlags & SvxRulerSupportFlags::TABS)
{
sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
pCtrlItems[i++].reset(new SvxRulerItem(nTabStopId, *this , rBindings));
SetExtraType(RulerExtra::Tab, nDefTabType);
}
if (nFlags & (SvxRulerSupportFlags::PARAGRAPH_MARGINS |SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL))
{
if (bHorz)
pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_PARA_LRSPACE, *this , rBindings));
else
pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_PARA_LRSPACE_VERTICAL, *this , rBindings));
mpIndents.resize(5 + INDENT_GAP);
for (RulerIndent & rIndent : mpIndents)
{
rIndent.nPos = 0 ;
rIndent.nStyle = RulerIndentStyle::Top;
}
mpIndents[0 ].nStyle = RulerIndentStyle::Top;
mpIndents[1 ].nStyle = RulerIndentStyle::Top;
mpIndents[INDENT_FIRST_LINE].nStyle = RulerIndentStyle::Top;
mpIndents[INDENT_LEFT_MARGIN].nStyle = RulerIndentStyle::Bottom;
mpIndents[INDENT_RIGHT_MARGIN].nStyle = RulerIndentStyle::Bottom;
}
if ( (nFlags & SvxRulerSupportFlags::BORDERS) == SvxRulerSupportFlags::BORDERS )
{
pCtrlItems[i++].reset(new SvxRulerItem(bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL, *this , rBindings));
pCtrlItems[i++].reset(new SvxRulerItem(bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL, *this , rBindings));
}
pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_TEXT_RIGHT_TO_LEFT, *this , rBindings));
if ( (nFlags & SvxRulerSupportFlags::OBJECT) == SvxRulerSupportFlags::OBJECT )
{
pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_OBJECT, *this , rBindings));
mpObjectBorders.resize(OBJECT_BORDER_COUNT);
for (sal_uInt16 nBorder = 0 ; nBorder < OBJECT_BORDER_COUNT; ++nBorder)
{
mpObjectBorders[nBorder].nPos = 0 ;
mpObjectBorders[nBorder].nWidth = 0 ;
mpObjectBorders[nBorder].nStyle = RulerBorderStyle::Moveable;
}
}
pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_PROTECT, *this , rBindings));
pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_BORDER_DISTANCE, *this , rBindings));
mxRulerImpl->nControllerItems=i;
if ( (nFlags & SvxRulerSupportFlags::SET_NULLOFFSET) == SvxRulerSupportFlags::SET_NULLOFFSET )
SetExtraType(RulerExtra::NullOffset);
rBindings.LeaveRegistrations();
ruler_tab_svx.DPIScaleFactor = pParent->GetDPIScaleFactor();
ruler_tab_svx.height *= ruler_tab_svx.DPIScaleFactor;
ruler_tab_svx.width *= ruler_tab_svx.DPIScaleFactor;
}
SvxRuler::~SvxRuler()
{
disposeOnce();
}
void SvxRuler::dispose()
{
/* Destructor ruler; release internal buffer */
if (bListening)
EndListening(*pBindings);
pBindings->EnterRegistrations();
pCtrlItems.clear();
pBindings->LeaveRegistrations();
pEditWin.reset();
Ruler::dispose();
}
tools::Long SvxRuler::MakePositionSticky(tools::Long aPosition, tools::Long aPointOfReference, bool aSnapToFrameMargin) const
{
tools::Long aPointOfReferencePixel = ConvertHPosPixel(aPointOfReference);
tools::Long aLeftFramePosition = ConvertHPosPixel(GetLeftFrameMargin());
tools::Long aRightFramePosition = ConvertHPosPixel(GetRightFrameMargin());
double aTick = GetCurrentRulerUnit().nTick1;
if (mbCoarseSnapping)
aTick = GetCurrentRulerUnit().nTick2;
tools::Long aTickPixel = pEditWin->LogicToPixel(Size(aTick, 0 ), GetCurrentMapMode()).Width();
double aHalfTick = aTick / 2 .0 ;
double aHalfTickPixel = aTickPixel / 2 .0 ;
if (aSnapToFrameMargin)
{
if (aPosition > aLeftFramePosition - aHalfTickPixel && aPosition < aLeftFramePosition + aHalfTickPixel)
return aLeftFramePosition;
if (aPosition > aRightFramePosition - aHalfTickPixel && aPosition < aRightFramePosition + aHalfTickPixel)
return aRightFramePosition;
}
if (!mbSnapping)
return aPosition;
// Move "coordinate system" to frame position so ticks are calculated correctly
tools::Long aTranslatedPosition = aPosition - aPointOfReferencePixel;
// Convert position to current selected map mode
tools::Long aPositionLogic = pEditWin->PixelToLogic(Size(aTranslatedPosition, 0 ), GetCurrentMapMode()).Width();
// Normalize -- snap to nearest tick
aPositionLogic = rtl::math::round((aPositionLogic + aHalfTick) / aTick) * aTick;
// Convert back to pixels
aPosition = pEditWin->LogicToPixel(Size(aPositionLogic, 0 ), GetCurrentMapMode()).Width();
// Move "coordinate system" back to original position
return aPosition + aPointOfReferencePixel;
}
tools::Long SvxRuler::ConvertHPosPixel(tools::Long nVal) const
{
return pEditWin->LogicToPixel(Size(nVal, 0 )).Width();
}
tools::Long SvxRuler::ConvertVPosPixel(tools::Long nVal) const
{
return pEditWin->LogicToPixel(Size(0 , nVal)).Height();
}
tools::Long SvxRuler::ConvertHSizePixel(tools::Long nVal) const
{
return pEditWin->LogicToPixel(Size(nVal, 0 )).Width();
}
tools::Long SvxRuler::ConvertVSizePixel(tools::Long nVal) const
{
return pEditWin->LogicToPixel(Size(0 , nVal)).Height();
}
tools::Long SvxRuler::ConvertPosPixel(tools::Long nVal) const
{
return bHorz ? ConvertHPosPixel(nVal): ConvertVPosPixel(nVal);
}
tools::Long SvxRuler::ConvertSizePixel(tools::Long nVal) const
{
return bHorz? ConvertHSizePixel(nVal): ConvertVSizePixel(nVal);
}
inline tools::Long SvxRuler::ConvertHPosLogic(tools::Long nVal) const
{
return pEditWin->PixelToLogic(Size(nVal, 0 )).Width();
}
inline tools::Long SvxRuler::ConvertVPosLogic(tools::Long nVal) const
{
return pEditWin->PixelToLogic(Size(0 , nVal)).Height();
}
inline tools::Long SvxRuler::ConvertHSizeLogic(tools::Long nVal) const
{
return pEditWin->PixelToLogic(Size(nVal, 0 )).Width();
}
inline tools::Long SvxRuler::ConvertVSizeLogic(tools::Long nVal) const
{
return pEditWin->PixelToLogic(Size(0 , nVal)).Height();
}
inline tools::Long SvxRuler::ConvertPosLogic(tools::Long nVal) const
{
return bHorz? ConvertHPosLogic(nVal): ConvertVPosLogic(nVal);
}
inline tools::Long SvxRuler::ConvertSizeLogic(tools::Long nVal) const
{
return bHorz? ConvertHSizeLogic(nVal): ConvertVSizeLogic(nVal);
}
tools::Long SvxRuler::PixelHAdjust(tools::Long nVal, tools::Long nValOld) const
{
if (ConvertHSizePixel(nVal) != ConvertHSizePixel(nValOld))
return nVal;
else
return nValOld;
}
tools::Long SvxRuler::PixelVAdjust(tools::Long nVal, tools::Long nValOld) const
{
if (ConvertVSizePixel(nVal) != ConvertVSizePixel(nValOld))
return nVal;
else
return nValOld;
}
tools::Long SvxRuler::PixelAdjust(tools::Long nVal, tools::Long nValOld) const
{
if (ConvertSizePixel(nVal) != ConvertSizePixel(nValOld))
return nVal;
else
return nValOld;
}
inline sal_uInt16 SvxRuler::GetObjectBordersOff(sal_uInt16 nIdx) const
{
return bHorz ? nIdx : nIdx + 2 ;
}
/*
Update Upper Left edge .
Items are translated into the representation of the ruler .
*/
void SvxRuler::UpdateFrame()
{
const RulerMarginStyle nMarginStyle =
( mxRulerImpl->aProtectItem->IsSizeProtected() ||
mxRulerImpl->aProtectItem->IsPosProtected() ) ?
RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
if (mxLRSpaceItem && mxPagePosItem)
{
// if no initialization by default app behavior
const tools::Long nOld = lLogicNullOffset;
lLogicNullOffset = mxColumnItem ? mxColumnItem->GetLeft() : mxLRSpaceItem->GetLeft();
if (bAppSetNullOffset)
{
lAppNullOffset += lLogicNullOffset - nOld;
}
if (!bAppSetNullOffset || lAppNullOffset == LONG_MAX)
{
Ruler::SetNullOffset(ConvertHPosPixel(lLogicNullOffset));
SetMargin1(0 , nMarginStyle);
lAppNullOffset = 0 ;
}
else
{
SetMargin1(ConvertHPosPixel(lAppNullOffset), nMarginStyle);
}
tools::Long lRight = 0 ;
// evaluate the table right edge of the table
if (mxColumnItem && mxColumnItem->IsTable())
lRight = mxColumnItem->GetRight();
else
lRight = mxLRSpaceItem->GetRight();
tools::Long aWidth = mxPagePosItem->GetWidth() - lRight - lLogicNullOffset + lAppNullOffset;
tools::Long aWidthPixel = ConvertHPosPixel(aWidth);
SetMargin2(aWidthPixel, nMarginStyle);
}
else if (mxULSpaceItem && mxPagePosItem)
{
// relative the upper edge of the surrounding frame
const tools::Long nOld = lLogicNullOffset;
lLogicNullOffset = mxColumnItem ? mxColumnItem->GetLeft() : mxULSpaceItem->GetUpper();
if (bAppSetNullOffset)
{
lAppNullOffset += lLogicNullOffset - nOld;
}
if (!bAppSetNullOffset || lAppNullOffset == LONG_MAX)
{
Ruler::SetNullOffset(ConvertVPosPixel(lLogicNullOffset));
lAppNullOffset = 0 ;
SetMargin1(0 , nMarginStyle);
}
else
{
SetMargin1(ConvertVPosPixel(lAppNullOffset), nMarginStyle);
}
tools::Long lLower = mxColumnItem ? mxColumnItem->GetRight() : mxULSpaceItem->GetLower();
tools::Long nMargin2 = mxPagePosItem->GetHeight() - lLower - lLogicNullOffset + lAppNullOffset;
tools::Long nMargin2Pixel = ConvertVPosPixel(nMargin2);
SetMargin2(nMargin2Pixel, nMarginStyle);
}
else
{
// turns off the view
SetMargin1();
SetMargin2();
}
if (mxColumnItem)
{
mxRulerImpl->nColLeftPix = static_cast <sal_uInt16>(ConvertSizePixel(mxColumnItem->GetLeft()));
mxRulerImpl->nColRightPix = static_cast <sal_uInt16>(ConvertSizePixel(mxColumnItem->GetRight()));
}
}
void SvxRuler::MouseMove( const MouseEvent& rMEvt )
{
if ( bActive )
{
pBindings->Update( SID_RULER_LR_MIN_MAX );
pBindings->Update( SID_ATTR_LONG_ULSPACE );
pBindings->Update( SID_ATTR_LONG_LRSPACE );
pBindings->Update( SID_RULER_PAGE_POS );
pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
pBindings->Update( SID_RULER_OBJECT );
pBindings->Update( SID_RULER_PROTECT );
}
Ruler::MouseMove( rMEvt );
RulerSelection aSelection = GetHoverSelection();
if (aSelection.eType == RulerType::DontKnow)
{
SetQuickHelpText(u"" _ustr);
return ;
}
RulerUnitData aUnitData = GetCurrentRulerUnit();
double aRoundingFactor = aUnitData.nTickUnit / aUnitData.nTick1;
sal_Int32 aNoDecimalPlaces = 1 + std::ceil(std::log10(aRoundingFactor));
OUString sUnit = OUString::createFromAscii(aUnitData.aUnitStr);
switch (aSelection.eType)
{
case RulerType::Indent:
{
if (!mxParaItem)
break ;
tools::Long nIndex = aSelection.nAryPos + INDENT_GAP;
tools::Long nIndentValue = 0 .0 ;
if (nIndex == INDENT_LEFT_MARGIN)
nIndentValue = mxParaItem->ResolveTextLeft({});
else if (nIndex == INDENT_FIRST_LINE)
nIndentValue = mxParaItem->ResolveTextFirstLineOffset({});
else if (nIndex == INDENT_RIGHT_MARGIN)
nIndentValue = mxParaItem->ResolveRight({});
double fValue = OutputDevice::LogicToLogic(Size(nIndentValue, 0 ), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
fValue = rtl::math::round(fValue / aUnitData.nTickUnit, aNoDecimalPlaces);
SetQuickHelpText(OUString::number(fValue) + " " + sUnit);
break ;
}
case RulerType::Border:
{
if (mxColumnItem == nullptr)
break ;
SvxColumnItem& aColumnItem = *mxColumnItem;
if (aSelection.nAryPos + 1 >= aColumnItem.Count())
break ;
double fStart = OutputDevice::LogicToLogic(Size(aColumnItem[aSelection.nAryPos].nEnd, 0 ), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
fStart = rtl::math::round(fStart / aUnitData.nTickUnit, aNoDecimalPlaces);
double fEnd = OutputDevice::LogicToLogic(Size(aColumnItem[aSelection.nAryPos + 1 ].nStart, 0 ), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
fEnd = rtl::math::round(fEnd / aUnitData.nTickUnit, aNoDecimalPlaces);
SetQuickHelpText(
OUString::number(fStart) + " " + sUnit + " - " +
OUString::number(fEnd) + " " + sUnit );
break ;
}
case RulerType::Margin1:
{
tools::Long nLeft = 0 .0 ;
if (mxLRSpaceItem)
nLeft = mxLRSpaceItem->GetLeft();
else if (mxULSpaceItem)
nLeft = mxULSpaceItem->GetUpper();
else
break ;
double fValue = OutputDevice::LogicToLogic(Size(nLeft, 0 ), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
fValue = rtl::math::round(fValue / aUnitData.nTickUnit, aNoDecimalPlaces);
SetQuickHelpText(OUString::number(fValue) + " " + sUnit);
break ;
}
case RulerType::Margin2:
{
tools::Long nRight = 0 .0 ;
if (mxLRSpaceItem)
nRight = mxLRSpaceItem->GetRight();
else if (mxULSpaceItem)
nRight = mxULSpaceItem->GetLower();
else
break ;
double fValue = OutputDevice::LogicToLogic(Size(nRight, 0 ), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
fValue = rtl::math::round(fValue / aUnitData.nTickUnit, aNoDecimalPlaces);
SetQuickHelpText(OUString::number(fValue) + " " + sUnit);
break ;
}
default :
{
SetQuickHelpText(u"" _ustr);
break ;
}
}
}
void SvxRuler::StartListening_Impl()
{
if (!bListening)
{
bValid = false ;
StartListening(*pBindings);
bListening = true ;
}
}
void SvxRuler::UpdateFrame(const SvxLongLRSpaceItem *pItem) // new value LRSpace
{
/* Store new value LRSpace; delete old ones if possible */
if (bActive)
{
if (pItem)
mxLRSpaceItem.reset(new SvxLongLRSpaceItem(*pItem));
else
mxLRSpaceItem.reset();
StartListening_Impl();
}
}
void SvxRuler::UpdateFrameMinMax(const SfxRectangleItem *pItem) // value for MinMax
{
/* Set new value for MinMax; delete old ones if possible */
if (bActive)
{
if (pItem)
mxMinMaxItem.reset(new SfxRectangleItem(*pItem));
else
mxMinMaxItem.reset();
}
}
void SvxRuler::UpdateFrame(const SvxLongULSpaceItem *pItem) // new value
{
/* Update Right/bottom margin */
if (bActive && !bHorz)
{
if (pItem)
mxULSpaceItem.reset(new SvxLongULSpaceItem(*pItem));
else
mxULSpaceItem.reset();
StartListening_Impl();
}
}
void SvxRuler::Update( const SvxProtectItem* pItem )
{
if ( pItem )
mxRulerImpl->aProtectItem.reset(pItem->Clone());
}
void SvxRuler::UpdateTextRTL(const SfxBoolItem* pItem)
{
if (bActive && bHorz)
{
mxRulerImpl->pTextRTLItem.reset();
if (pItem)
mxRulerImpl->pTextRTLItem.reset(new SfxBoolItem(*pItem));
SetTextRTL(mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue());
StartListening_Impl();
}
}
void SvxRuler::Update(
const SvxColumnItem *pItem, // new value
sal_uInt16 nSID) //Slot Id to identify NULL items
{
/* Set new value for column view */
if (!bActive)
return ;
if (pItem)
{
mxColumnItem.reset(new SvxColumnItem(*pItem));
mxRulerImpl->bIsTableRows = (pItem->Which() == SID_RULER_ROWS || pItem->Which() == SID_RULER_ROWS_VERTICAL);
if (!bHorz && !mxRulerImpl->bIsTableRows)
mxColumnItem->SetWhich(SID_RULER_BORDERS_VERTICAL);
}
else if (mxColumnItem && mxColumnItem->Which() == nSID)
//there are two groups of column items table/frame columns and table rows
//both can occur in vertical or horizontal mode
//the horizontal ruler handles the SID_RULER_BORDERS and SID_RULER_ROWS_VERTICAL
//and the vertical handles SID_RULER_BORDERS_VERTICAL and SID_RULER_ROWS
//if mxColumnItem is already set with one of the ids then a NULL pItem argument
//must not delete it
{
mxColumnItem.reset();
mxRulerImpl->bIsTableRows = false ;
}
StartListening_Impl();
}
void SvxRuler::UpdateColumns()
{
/* Update column view */
if (mxColumnItem && mxColumnItem->Count() > 1 )
{
mpBorders.resize(mxColumnItem->Count());
RulerBorderStyle nStyleFlags = RulerBorderStyle::Variable;
bool bProtectColumns =
mxRulerImpl->aProtectItem->IsSizeProtected() ||
mxRulerImpl->aProtectItem->IsPosProtected();
if ( !bProtectColumns )
{
nStyleFlags |= RulerBorderStyle::Moveable;
if ( !mxColumnItem->IsTable() )
nStyleFlags |= RulerBorderStyle::Sizeable;
}
sal_uInt16 nBorders = mxColumnItem->Count();
if (!mxRulerImpl->bIsTableRows)
--nBorders;
for (sal_uInt16 i = 0 ; i < nBorders; ++i)
{
mpBorders[i].nStyle = nStyleFlags;
if (!mxColumnItem->At(i).bVisible)
mpBorders[i].nStyle |= RulerBorderStyle::Invisible;
mpBorders[i].nPos = ConvertPosPixel(mxColumnItem->At(i).nEnd + lAppNullOffset);
if (mxColumnItem->Count() == i + 1 )
{
//with table rows the end of the table is contained in the
//column item but it has no width!
mpBorders[i].nWidth = 0 ;
}
else
{
mpBorders[i].nWidth = ConvertSizePixel(mxColumnItem->At(i + 1 ).nStart - mxColumnItem->At(i).nEnd);
}
mpBorders[i].nMinPos = ConvertPosPixel(mxColumnItem->At(i).nEndMin + lAppNullOffset);
mpBorders[i].nMaxPos = ConvertPosPixel(mxColumnItem->At(i).nEndMax + lAppNullOffset);
}
SetBorders(mxColumnItem->Count() - 1 , mpBorders.data());
}
else
{
SetBorders();
}
}
void SvxRuler::UpdateObject()
{
/* Update view of object representation */
if (mxObjectItem)
{
DBG_ASSERT(!mpObjectBorders.empty(), "no Buffer" );
// !! to the page margin
tools::Long nMargin = mxLRSpaceItem ? mxLRSpaceItem->GetLeft() : 0 ;
mpObjectBorders[0 ].nPos =
ConvertPosPixel(mxObjectItem->GetStartX() -
nMargin + lAppNullOffset);
mpObjectBorders[1 ].nPos =
ConvertPosPixel(mxObjectItem->GetEndX() - nMargin + lAppNullOffset);
nMargin = mxULSpaceItem ? mxULSpaceItem->GetUpper() : 0 ;
mpObjectBorders[2 ].nPos =
ConvertPosPixel(mxObjectItem->GetStartY() -
nMargin + lAppNullOffset);
mpObjectBorders[3 ].nPos =
ConvertPosPixel(mxObjectItem->GetEndY() - nMargin + lAppNullOffset);
const sal_uInt16 nOffset = GetObjectBordersOff(0 );
SetBorders(2 , mpObjectBorders.data() + nOffset);
}
else
{
SetBorders();
}
}
void SvxRuler::UpdatePara()
{
/* Update the view for paragraph indents:
Left margin , first line indent , right margin paragraph update
mpIndents [ 0 ] = Buffer for old intent
mpIndents [ 1 ] = Buffer for old intent
mpIndents [ INDENT_FIRST_LINE ] = first line indent
mpIndents [ INDENT_LEFT_MARGIN ] = left margin
mpIndents [ INDENT_RIGHT_MARGIN ] = right margin
*/
// Dependence on PagePosItem
if (mxParaItem && mxPagePosItem && !mxObjectItem)
{
bool bRTLText = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
// First-line indent is negative to the left paragraph margin
tools::Long nLeftFrameMargin = GetLeftFrameMargin();
tools::Long nRightFrameMargin = GetRightFrameMargin();
SetLeftFrameMargin(ConvertHPosPixel(nLeftFrameMargin));
SetRightFrameMargin(ConvertHPosPixel(nRightFrameMargin));
tools::Long leftMargin;
tools::Long leftFirstLine;
tools::Long rightMargin;
if (bRTLText)
{
leftMargin = nRightFrameMargin - mxParaItem->ResolveTextLeft({}) + lAppNullOffset;
leftFirstLine = leftMargin - mxParaItem->ResolveTextFirstLineOffset({});
rightMargin = nLeftFrameMargin + mxParaItem->ResolveRight({}) + lAppNullOffset;
}
else
{
leftMargin = nLeftFrameMargin + mxParaItem->ResolveTextLeft({}) + lAppNullOffset;
leftFirstLine = leftMargin + mxParaItem->ResolveTextFirstLineOffset({});
rightMargin = nRightFrameMargin - mxParaItem->ResolveRight({}) + lAppNullOffset;
}
mpIndents[INDENT_LEFT_MARGIN].nPos = ConvertHPosPixel(leftMargin);
mpIndents[INDENT_FIRST_LINE].nPos = ConvertHPosPixel(leftFirstLine);
mpIndents[INDENT_RIGHT_MARGIN].nPos = ConvertHPosPixel(rightMargin);
mpIndents[INDENT_FIRST_LINE].bInvisible = mxParaItem->IsAutoFirst();
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
else
{
if (!mpIndents.empty())
{
mpIndents[INDENT_FIRST_LINE].nPos = 0 ;
mpIndents[INDENT_LEFT_MARGIN].nPos = 0 ;
mpIndents[INDENT_RIGHT_MARGIN].nPos = 0 ;
}
SetIndents(); // turn off
}
}
void SvxRuler::UpdatePara(const SvxLRSpaceItem *pItem) // new value of paragraph indents
{
/* Store new value of paragraph indents */
if (bActive)
{
if (pItem)
mxParaItem.reset(new SvxLRSpaceItem(*pItem));
else
mxParaItem.reset();
StartListening_Impl();
}
}
void SvxRuler::UpdateBorder(const SvxLRSpaceItem * pItem)
{
/* Border distance */
if (bActive)
{
if (pItem)
mxBorderItem.reset(new SvxLRSpaceItem(*pItem));
else
mxBorderItem.reset();
StartListening_Impl();
}
}
void SvxRuler::UpdatePage()
{
/* Update view of position and width of page */
if (mxPagePosItem)
{
// all objects are automatically adjusted
if (bHorz)
{
SetPagePos(
pEditWin->LogicToPixel(mxPagePosItem->GetPos()).X(),
pEditWin->LogicToPixel(Size(mxPagePosItem->GetWidth(), 0 )).
Width());
}
else
{
SetPagePos(
pEditWin->LogicToPixel(mxPagePosItem->GetPos()).Y(),
pEditWin->LogicToPixel(Size(0 , mxPagePosItem->GetHeight())).
Height());
}
if (bAppSetNullOffset)
SetNullOffset(ConvertSizePixel(-lAppNullOffset + lLogicNullOffset));
}
else
{
SetPagePos();
}
tools::Long lPos = 0 ;
Point aOwnPos = GetPosPixel();
Point aEdtWinPos = pEditWin->GetPosPixel();
if ( AllSettings::GetLayoutRTL() && bHorz )
{
//#i73321# in RTL the window and the ruler is not mirrored but the
// influence of the vertical ruler is inverted
Size aOwnSize = GetSizePixel();
Size aEdtWinSize = pEditWin->GetSizePixel();
lPos = aOwnSize.Width() - aEdtWinSize.Width();
lPos -= (aEdtWinPos - aOwnPos).X();
}
else
{
Point aPos(aEdtWinPos - aOwnPos);
lPos = bHorz ? aPos.X() : aPos.Y();
}
// Unfortunately, we get the offset of the edit window to the ruler never
// through a status message. So we set it ourselves if necessary.
if (lPos != mxRulerImpl->lOldWinPos)
{
mxRulerImpl->lOldWinPos=lPos;
SetWinPos(lPos);
}
}
void SvxRuler::Update(const SvxPagePosSizeItem *pItem) // new value of page attributes
{
/* Store new value of page attributes */
if (bActive)
{
if (pItem)
mxPagePosItem.reset(new SvxPagePosSizeItem(*pItem));
else
mxPagePosItem.reset();
StartListening_Impl();
}
}
void SvxRuler::SetDefTabDist(tools::Long inDefTabDist) // New distance for DefaultTabs in App-Metrics
{
if (lAppNullOffset == LONG_MAX)
UpdateFrame(); // hack: try to get lAppNullOffset initialized
/* New distance is set for DefaultTabs */
lDefTabDist = inDefTabDist;
if ( !lDefTabDist )
lDefTabDist = 1 ;
UpdateTabs();
}
static sal_uInt16 ToSvTab_Impl(SvxTabAdjust eAdj)
{
/* Internal conversion routine between SV-Tab.-Enum and Svx */
switch (eAdj) {
case SvxTabAdjust::Left: return RULER_TAB_LEFT;
case SvxTabAdjust::Right: return RULER_TAB_RIGHT;
case SvxTabAdjust::Decimal: return RULER_TAB_DECIMAL;
case SvxTabAdjust::Center: return RULER_TAB_CENTER;
case SvxTabAdjust::Default : return RULER_TAB_DEFAULT;
default : ; //prevent warning
}
return 0 ;
}
static SvxTabAdjust ToAttrTab_Impl(sal_uInt16 eAdj)
{
switch (eAdj) {
case RULER_TAB_LEFT: return SvxTabAdjust::Left ;
case RULER_TAB_RIGHT: return SvxTabAdjust::Right ;
case RULER_TAB_DECIMAL: return SvxTabAdjust::Decimal ;
case RULER_TAB_CENTER: return SvxTabAdjust::Center ;
case RULER_TAB_DEFAULT: return SvxTabAdjust::Default ;
}
return SvxTabAdjust::Left;
}
void SvxRuler::UpdateTabs()
{
if (IsDrag())
return ;
if (mxPagePosItem && mxParaItem && mxTabStopItem && !mxObjectItem)
{
// buffer for DefaultTabStop
// Distance last Tab <-> Right paragraph margin / DefaultTabDist
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
const tools::Long nLeftFrameMargin = GetLeftFrameMargin();
const tools::Long nRightFrameMargin = GetRightFrameMargin();
//#i24363# tab stops relative to indent
const tools::Long nParaItemTxtLeft = mxParaItem->ResolveTextLeft({});
const tools::Long lParaIndent = nLeftFrameMargin + nParaItemTxtLeft;
const tools::Long lRightMargin = nRightFrameMargin - nParaItemTxtLeft;
const tools::Long lLastTab = mxTabStopItem->Count()
? ConvertHPosPixel(mxTabStopItem->At(mxTabStopItem->Count() - 1 ).GetTabPos())
: 0 ;
const tools::Long lPosPixel = ConvertHPosPixel(lParaIndent) + lLastTab;
const tools::Long lRightIndent
= ConvertHPosPixel(nRightFrameMargin - mxParaItem->ResolveRight({}));
tools::Long lCurrentDefTabDist = lDefTabDist;
if (mxTabStopItem->GetDefaultDistance())
lCurrentDefTabDist = mxTabStopItem->GetDefaultDistance();
tools::Long nDefTabDist = ConvertHPosPixel(lCurrentDefTabDist);
const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > lRightIndent || nDefTabDist == 0
? 0
: static_cast <sal_uInt16>( (lRightIndent - lPosPixel) / nDefTabDist );
if (mxTabStopItem->Count() + TAB_GAP + nDefTabBuf > nTabBufSize)
{
// 10 (GAP) in stock
nTabBufSize = mxTabStopItem->Count() + TAB_GAP + nDefTabBuf + GAP;
mpTabs.resize(nTabBufSize);
}
nTabCount = 0 ;
sal_uInt16 j;
const tools::Long lParaIndentPix = ConvertSizePixel(lParaIndent);
tools::Long lTabStartLogic = (mxRulerImpl->bIsTabsRelativeToIndent ? lParaIndent : nLeftFrameMargin)
+ lAppNullOffset;
if (bRTL)
{
lTabStartLogic = lParaIndent + lRightMargin - lTabStartLogic;
}
tools::Long lLastTabOffsetLogic = 0 ;
for (j = 0 ; j < mxTabStopItem->Count(); ++j)
{
const SvxTabStop* pTab = &mxTabStopItem->At(j);
lLastTabOffsetLogic = pTab->GetTabPos();
tools::Long lPos = lTabStartLogic + (bRTL ? -lLastTabOffsetLogic : lLastTabOffsetLogic);
mpTabs[nTabCount + TAB_GAP].nPos = ConvertHPosPixel(lPos);
mpTabs[nTabCount + TAB_GAP].nStyle = ToSvTab_Impl(pTab->GetAdjustment());
++nTabCount;
}
// Adjust to previous-to-first default tab stop
lLastTabOffsetLogic -= lLastTabOffsetLogic % lCurrentDefTabDist;
// fill the rest with default Tabs
for (j = 0 ; j < nDefTabBuf; ++j)
{
//simply add the default distance to the last position
lLastTabOffsetLogic += lCurrentDefTabDist;
if (bRTL)
{
mpTabs[nTabCount + TAB_GAP].nPos =
ConvertHPosPixel(lTabStartLogic - lLastTabOffsetLogic);
if (mpTabs[nTabCount + TAB_GAP].nPos <= lParaIndentPix)
break ;
}
else
{
mpTabs[nTabCount + TAB_GAP].nPos =
ConvertHPosPixel(lTabStartLogic + lLastTabOffsetLogic);
if (mpTabs[nTabCount + TAB_GAP].nPos >= lRightIndent)
break ;
}
mpTabs[nTabCount + TAB_GAP].nStyle = RULER_TAB_DEFAULT;
++nTabCount;
}
SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
DBG_ASSERT(nTabCount + TAB_GAP <= nTabBufSize, "BufferSize too small" );
}
else
{
SetTabs();
}
}
void SvxRuler::Update(const SvxTabStopItem *pItem) // new value for tabs
{
/* Store new value for tabs; delete old ones if possible */
if (!bActive)
return ;
if (pItem)
{
mxTabStopItem.reset(new SvxTabStopItem(*pItem));
if (!bHorz)
mxTabStopItem->SetWhich(SID_ATTR_TABSTOP_VERTICAL);
}
else
{
mxTabStopItem.reset();
}
StartListening_Impl();
}
void SvxRuler::Update(const SvxObjectItem *pItem) // new value for objects
{
/* Store new value for objects */
if (bActive)
{
if (pItem)
mxObjectItem.reset(new SvxObjectItem(*pItem));
else
mxObjectItem.reset();
StartListening_Impl();
}
}
void SvxRuler::SetNullOffsetLogic(tools::Long lVal) // Setting of the logic NullOffsets
{
lAppNullOffset = lLogicNullOffset - lVal;
bAppSetNullOffset = true ;
Ruler::SetNullOffset(ConvertSizePixel(lVal));
Update();
}
void SvxRuler::CreateJsonNotification(tools::JsonWriter& rJsonWriter)
{
tools::Long nMargin1 = 0 ;
tools::Long nMargin2 = 0 ;
tools::Long nNullOffset = 0 ;
tools::Long nPageOffset = 0 ;
tools::Long nPageWidthHeight = 0 ;
bool bWriter = false ;
// Determine if we are a Ruler for Writer or not
if (SfxViewFrame* pFrame = SfxViewFrame::Current())
{
uno::Reference<frame::XFrame> xFrame = pFrame->GetFrame().GetFrameInterface();
uno::Reference<frame::XModel> xModel = xFrame->getController()->getModel();
uno::Reference<lang::XServiceInfo> xSI(xModel, uno::UNO_QUERY);
if (xSI.is())
{
bWriter = xSI->supportsService("com.sun.star.text.TextDocument" )
|| xSI->supportsService("com.sun.star.text.WebDocument" )
|| xSI->supportsService("com.sun.star.text.GlobalDocument" );
}
}
if (bWriter)
{
// In Writer the ruler values need to be converted first from pixel to twips (default logical unit) and then to 100thmm
nMargin1 = convertTwipToMm100(ConvertPosLogic(GetMargin1()));
nMargin2 = convertTwipToMm100(ConvertPosLogic(GetMargin2()));
nNullOffset = convertTwipToMm100(ConvertPosLogic(GetNullOffset()));
nPageOffset = convertTwipToMm100(ConvertPosLogic(GetPageOffset()));
nPageWidthHeight = convertTwipToMm100(GetPageWidth());
}
else
{
// Only convert from pixel to default logical unit, which is 100thmm for Impress
nMargin1 = ConvertPosLogic(GetMargin1());
nMargin2 = ConvertPosLogic(GetMargin2());
nPageOffset = ConvertPosLogic(GetPageOffset());
// In LOKit API we expect the ruler 0,0 coordinate is where the document starts.
// In Impress and Draw the ruler 0,0 is where the canvas starts, not where the document starts.
// The margin to the document is 1 document width (on the left and right) and 0.5 document height
// (on the top and bottom).
// So the canvas width = 3 * document width, canvas height = 2 * document height
if (isHorizontal())
{
nPageWidthHeight = GetPageWidth() / 3 ;
nNullOffset = ConvertPosLogic(GetNullOffset()) - nPageWidthHeight;
}
else
{
nPageWidthHeight = GetPageWidth() / 2 ;
nNullOffset = ConvertPosLogic(GetNullOffset()) - (nPageWidthHeight / 2 );
}
}
rJsonWriter.put("margin1" , nMargin1);
rJsonWriter.put("margin2" , nMargin2);
rJsonWriter.put("leftOffset" , nNullOffset);
rJsonWriter.put("pageOffset" , nPageOffset);
rJsonWriter.put("pageWidth" , nPageWidthHeight);
{
auto tabsNode = rJsonWriter.startNode("tabs" );
// The RulerTab array elements that GetTabs() returns have their nPos field in twips. So these
// too are actual mm100.
for (auto const & tab : GetTabs())
{
auto tabNode = rJsonWriter.startNode("" );
rJsonWriter.put("position" , convertTwipToMm100(tab.nPos));
rJsonWriter.put("style" , tab.nStyle);
}
}
RulerUnitData aUnitData = GetCurrentRulerUnit();
rJsonWriter.put("unit" , aUnitData.aUnitStr);
}
void SvxRuler::NotifyKit()
{
if (!comphelper::LibreOfficeKit::isActive())
return ;
SfxViewShell* pViewShell = SfxViewShell::Current();
if (!pViewShell)
return ;
tools::JsonWriter aJsonWriter;
CreateJsonNotification(aJsonWriter);
OString pJsonData = aJsonWriter.finishAndGetAsOString();
LibreOfficeKitCallbackType eType = isHorizontal() ? LOK_CALLBACK_RULER_UPDATE : LOK_CALLBACK_VERTICAL_RULER_UPDATE;
pViewShell->libreOfficeKitViewCallback(eType, pJsonData);
}
void SvxRuler::Update()
{
/* Perform update of view */
if (IsDrag())
return ;
UpdatePage();
UpdateFrame();
if (nFlags & SvxRulerSupportFlags::OBJECT)
UpdateObject();
else
UpdateColumns();
if (nFlags & (SvxRulerSupportFlags::PARAGRAPH_MARGINS | SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL))
UpdatePara();
if (nFlags & SvxRulerSupportFlags::TABS)
UpdateTabs();
NotifyKit();
}
tools::Long SvxRuler::GetPageWidth() const
{
if (!mxPagePosItem)
return 0 ;
return bHorz ? mxPagePosItem->GetWidth() : mxPagePosItem->GetHeight();
}
inline tools::Long SvxRuler::GetFrameLeft() const
{
/* Get Left margin in Pixels */
return bAppSetNullOffset ?
GetMargin1() + ConvertSizePixel(lLogicNullOffset) :
Ruler::GetNullOffset();
}
tools::Long SvxRuler::GetFirstLineIndent() const
{
/* Get First-line indent in pixels */
return mxParaItem ? mpIndents[INDENT_FIRST_LINE].nPos : GetMargin1();
}
tools::Long SvxRuler::GetLeftIndent() const
{
/* Get Left paragraph margin in Pixels */
return mxParaItem ? mpIndents[INDENT_LEFT_MARGIN].nPos : GetMargin1();
}
tools::Long SvxRuler::GetRightIndent() const
{
/* Get Right paragraph margin in Pixels */
return mxParaItem ? mpIndents[INDENT_RIGHT_MARGIN].nPos : GetMargin2();
}
tools::Long SvxRuler::GetLogicRightIndent() const
{
/* Get Right paragraph margin in Logic */
return mxParaItem ? GetRightFrameMargin() - mxParaItem->ResolveRight({})
: GetRightFrameMargin();
}
// Left margin in App values, is either the margin (= 0) or the left edge of
// the column that is set in the column attribute as current column.
tools::Long SvxRuler::GetLeftFrameMargin() const
{
// #126721# for some unknown reason the current column is set to 0xffff
DBG_ASSERT(!mxColumnItem || mxColumnItem->GetActColumn() < mxColumnItem->Count(),
"issue #126721# - invalid current column!" );
tools::Long nLeft = 0 ;
if (mxColumnItem &&
mxColumnItem->Count() &&
mxColumnItem->IsConsistent())
{
nLeft = mxColumnItem->GetActiveColumnDescription().nStart;
}
if (mxBorderItem && (!mxColumnItem || mxColumnItem->IsTable()))
nLeft += mxBorderItem->ResolveLeft({});
return nLeft;
}
inline tools::Long SvxRuler::GetLeftMin() const
{
DBG_ASSERT(mxMinMaxItem, "no MinMax value set" );
if (mxMinMaxItem)
{
if (bHorz)
return mxMinMaxItem->GetValue().Left();
else
return mxMinMaxItem->GetValue().Top();
}
return 0 ;
}
inline tools::Long SvxRuler::GetRightMax() const
{
DBG_ASSERT(mxMinMaxItem, "no MinMax value set" );
if (mxMinMaxItem)
{
if (bHorz)
return mxMinMaxItem->GetValue().Right();
else
return mxMinMaxItem->GetValue().Bottom();
}
return 0 ;
}
tools::Long SvxRuler::GetRightFrameMargin() const
{
/* Get right frame margin (in logical units) */
if (mxColumnItem)
{
if (!IsActLastColumn(true ))
{
return mxColumnItem->At(GetActRightColumn(true )).nEnd;
}
}
tools::Long lResult = lLogicNullOffset;
// If possible deduct right table entry
if (mxColumnItem && mxColumnItem->IsTable())
lResult += mxColumnItem->GetRight();
else if (bHorz && mxLRSpaceItem)
lResult += mxLRSpaceItem->GetRight();
else if (!bHorz && mxULSpaceItem)
lResult += mxULSpaceItem->GetLower();
if (bHorz && mxBorderItem && (!mxColumnItem || mxColumnItem->IsTable()))
lResult += mxBorderItem->ResolveRight({});
if (bHorz)
lResult = mxPagePosItem->GetWidth() - lResult;
else
lResult = mxPagePosItem->GetHeight() - lResult;
return lResult;
}
#define NEG_FLAG ( (nFlags & SvxRulerSupportFlags::NEGATIVE_MARGINS) == \
SvxRulerSupportFlags::NEGATIVE_MARGINS )
#define TAB_FLAG ( mxColumnItem && mxColumnItem->IsTable() )
tools::Long SvxRuler::GetCorrectedDragPos( bool bLeft, bool bRight )
{
/*
Corrects the position within the calculated limits . The limit values are in
pixels relative to the page edge .
*/
const tools::Long lNullPix = Ruler::GetNullOffset();
tools::Long lDragPos = GetDragPos() + lNullPix;
bool bHoriRows = bHorz && mxRulerImpl->bIsTableRows;
if ((bLeft || bHoriRows) && lDragPos < nMaxLeft)
lDragPos = nMaxLeft;
else if ((bRight||bHoriRows) && lDragPos > nMaxRight)
lDragPos = nMaxRight;
return lDragPos - lNullPix;
}
static void ModifyTabs_Impl( sal_uInt16 nCount, // Number of Tabs
RulerTab* pTabs, // Tab buffer
tools::Long lDiff) // difference to be added
{
/* Helper function, move all the tabs by a fixed value */
if ( pTabs )
{
for (sal_uInt16 i = 0 ; i < nCount; ++i)
{
pTabs[i].nPos += lDiff;
}
}
}
void SvxRuler::DragMargin1()
{
/* Dragging the left edge of frame */
tools::Long aDragPosition = GetCorrectedDragPos( !TAB_FLAG || !NEG_FLAG );
aDragPosition = MakePositionSticky(aDragPosition, GetRightFrameMargin(), false );
// Check if position changed
if (aDragPosition == 0 )
return ;
DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 3 : 7 , bHorz);
if (mxColumnItem && (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL))
DragBorders();
AdjustMargin1(aDragPosition);
}
void SvxRuler::AdjustMargin1(tools::Long lInputDiff)
{
const tools::Long nOld = bAppSetNullOffset? GetMargin1(): GetNullOffset();
const tools::Long lDragPos = lInputDiff;
bool bProtectColumns =
mxRulerImpl->aProtectItem->IsSizeProtected() ||
mxRulerImpl->aProtectItem->IsPosProtected();
const RulerMarginStyle nMarginStyle =
bProtectColumns ? RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
if (!bAppSetNullOffset)
{
tools::Long lDiff = lDragPos;
SetNullOffset(nOld + lDiff);
if (!mxColumnItem || !(nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR))
{
SetMargin2( GetMargin2() - lDiff, nMarginStyle );
if (!mxColumnItem && !mxObjectItem && mxParaItem)
{
// Right indent of the old position
mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
if (mxObjectItem)
{
mpObjectBorders[GetObjectBordersOff(0 )].nPos -= lDiff;
mpObjectBorders[GetObjectBordersOff(1 )].nPos -= lDiff;
SetBorders(2 , mpObjectBorders.data() + GetObjectBordersOff(0 ));
}
if (mxColumnItem)
{
for (sal_uInt16 i = 0 ; i < mxColumnItem->Count()-1 ; ++i)
mpBorders[i].nPos -= lDiff;
SetBorders(mxColumnItem->Count()-1 , mpBorders.data());
if (mxColumnItem->IsFirstAct())
{
// Right indent of the old position
if (mxParaItem)
{
mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
}
else
{
if (mxParaItem)
{
mpIndents[INDENT_FIRST_LINE].nPos -= lDiff;
mpIndents[INDENT_LEFT_MARGIN].nPos -= lDiff;
mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
}
if (mxTabStopItem && (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
&&!IsActFirstColumn())
{
ModifyTabs_Impl(nTabCount + TAB_GAP, mpTabs.data(), -lDiff);
SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
}
}
}
}
else
{
tools::Long lDiff = lDragPos - nOld;
SetMargin1(nOld + lDiff, nMarginStyle);
if (!mxColumnItem
|| !(nDragType
& (SvxRulerDragFlags::OBJECT_SIZE_LINEAR
| SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)))
{
if (!mxColumnItem && !mxObjectItem && mxParaItem)
{
// Left indent of the old position
mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
if (mxColumnItem)
{
for (sal_uInt16 i = 0 ; i < mxColumnItem->Count() - 1 ; ++i)
mpBorders[i].nPos += lDiff;
SetBorders(mxColumnItem->Count() - 1 , mpBorders.data());
if (mxColumnItem->IsFirstAct())
{
// Left indent of the old position
if (mxParaItem)
{
mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
}
else
{
if (mxParaItem)
{
mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
mpIndents[INDENT_RIGHT_MARGIN].nPos += lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
}
}
if (mxTabStopItem)
{
ModifyTabs_Impl(nTabCount + TAB_GAP, mpTabs.data(), lDiff);
SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
}
}
}
}
void SvxRuler::DragMargin2()
{
/* Dragging the right edge of frame */
tools::Long aDragPosition = GetCorrectedDragPos( true , !TAB_FLAG || !NEG_FLAG);
aDragPosition = MakePositionSticky(aDragPosition, GetLeftFrameMargin(), false );
tools::Long lDiff = aDragPosition - GetMargin2();
// Check if position changed
if (lDiff == 0 )
return ;
if ( mxRulerImpl->bIsTableRows &&
!bHorz &&
mxColumnItem &&
(nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL))
{
DragBorders();
}
bool bProtectColumns =
mxRulerImpl->aProtectItem->IsSizeProtected() ||
mxRulerImpl->aProtectItem->IsPosProtected();
const RulerMarginStyle nMarginStyle = bProtectColumns ? RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
SetMargin2( aDragPosition, nMarginStyle );
// Right indent of the old position
if ((!mxColumnItem || IsActLastColumn()) && mxParaItem)
{
mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 5 : 7 , bHorz);
}
void SvxRuler::DragIndents()
{
/* Dragging the paragraph indents */
tools::Long aDragPosition = NEG_FLAG ? GetDragPos() : GetCorrectedDragPos();
const sal_uInt16 nIndex = GetDragAryPos() + INDENT_GAP;
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
if (nIndex == INDENT_RIGHT_MARGIN)
aDragPosition = MakePositionSticky(aDragPosition, bRTL ? GetLeftFrameMargin() : GetRightFrameMargin());
else
aDragPosition = MakePositionSticky(aDragPosition, bRTL ? GetRightFrameMargin() : GetLeftFrameMargin());
const tools::Long lDiff = mpIndents[nIndex].nPos - aDragPosition;
// Check if position changed
if (lDiff == 0 )
return ;
if ((nIndex == INDENT_FIRST_LINE || nIndex == INDENT_LEFT_MARGIN ) &&
!(nDragType & SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY))
{
mpIndents[INDENT_FIRST_LINE].nPos -= lDiff;
}
mpIndents[nIndex].nPos = aDragPosition;
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
DrawLine_Impl(lTabPos, 1 , bHorz);
}
void SvxRuler::DrawLine_Impl(tools::Long & lTabPosition, int nNew, bool bHorizontal)
{
/*
Output routine for the ledger line when moving tabs , tables and other
columns
*/
if (bHorizontal)
{
const tools::Long nHeight = pEditWin->GetOutDev()->GetOutputSize().Height();
Point aZero = pEditWin->GetMapMode().GetOrigin();
if (lTabPosition != -1 )
{
pEditWin->InvertTracking(
tools::Rectangle( Point(lTabPosition, -aZero.Y()),
Point(lTabPosition, -aZero.Y() + nHeight)),
ShowTrackFlags::Split | ShowTrackFlags::Clip );
}
if ( nNew & 1 )
{
tools::Long nDrapPosition = GetCorrectedDragPos( ( nNew & 4 ) != 0 , ( nNew & 2 ) != 0 );
nDrapPosition = MakePositionSticky(nDrapPosition, GetLeftFrameMargin());
lTabPosition = ConvertHSizeLogic( nDrapPosition + GetNullOffset() );
if (mxPagePosItem)
lTabPosition += mxPagePosItem->GetPos().X();
pEditWin->InvertTracking(
tools::Rectangle( Point(lTabPosition, -aZero.Y()),
Point(lTabPosition, -aZero.Y() + nHeight) ),
ShowTrackFlags::Clip | ShowTrackFlags::Split );
}
}
else
{
const tools::Long nWidth = pEditWin->GetOutDev()->GetOutputSize().Width();
Point aZero = pEditWin->GetMapMode().GetOrigin();
if (lTabPosition != -1 )
{
pEditWin->InvertTracking(
tools::Rectangle( Point(-aZero.X(), lTabPosition),
Point(-aZero.X() + nWidth, lTabPosition)),
ShowTrackFlags::Split | ShowTrackFlags::Clip );
}
if (nNew & 1 )
{
tools::Long nDrapPosition = GetCorrectedDragPos();
nDrapPosition = MakePositionSticky(nDrapPosition, GetLeftFrameMargin());
lTabPosition = ConvertVSizeLogic(nDrapPosition + GetNullOffset());
if (mxPagePosItem)
lTabPosition += mxPagePosItem->GetPos().Y();
pEditWin->InvertTracking(
tools::Rectangle( Point(-aZero.X(), lTabPosition),
Point(-aZero.X()+nWidth, lTabPosition)),
ShowTrackFlags::Clip | ShowTrackFlags::Split );
}
}
}
void SvxRuler::DragTabs()
{
/* Dragging of Tabs */
tools::Long aDragPosition = GetCorrectedDragPos(true , false );
aDragPosition = MakePositionSticky(aDragPosition, GetLeftFrameMargin());
sal_uInt16 nIdx = GetDragAryPos() + TAB_GAP;
tools::Long nDiff = aDragPosition - mpTabs[nIdx].nPos;
if (nDiff == 0 )
return ;
DrawLine_Impl(lTabPos, 7 , bHorz);
if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR)
{
for (sal_uInt16 i = nIdx; i < nTabCount; ++i)
{
mpTabs[i].nPos += nDiff;
// limit on maximum
if (mpTabs[i].nPos > GetMargin2())
mpTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
else
mpTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
}
}
else if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
{
mxRulerImpl->nTotalDist -= nDiff;
mpTabs[nIdx].nPos = aDragPosition;
for (sal_uInt16 i = nIdx+1 ; i < nTabCount; ++i)
{
if (mpTabs[i].nStyle & RULER_TAB_DEFAULT)
// can be canceled at the DefaultTabs
break ;
tools::Long nDelta = mxRulerImpl->nTotalDist * mxRulerImpl->pPercBuf[i];
nDelta /= 1000 ;
mpTabs[i].nPos = mpTabs[nIdx].nPos + nDelta;
if (mpTabs[i].nPos + GetNullOffset() > nMaxRight)
mpTabs[i].nStyle |= RULER_STYLE_INVISIBLE;
else
mpTabs[i].nStyle &= ~RULER_STYLE_INVISIBLE;
}
}
else
{
mpTabs[nIdx].nPos = aDragPosition;
}
if (IsDragDelete())
mpTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
else
mpTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
}
void SvxRuler::SetActive(bool bOn)
{
if (bOn)
{
Activate();
}
else
Deactivate();
if (bActive!=bOn)
{
pBindings->EnterRegistrations();
if (bOn)
for (sal_uInt16 i=0 ;i<mxRulerImpl->nControllerItems;i++)
pCtrlItems[i]->ReBind();
else
for (sal_uInt16 j=0 ;j<mxRulerImpl->nControllerItems;j++)
pCtrlItems[j]->UnBind();
pBindings->LeaveRegistrations();
}
bActive = bOn;
}
void SvxRuler::UpdateParaContents_Impl(
tools::Long lDifference,
UpdateType eType) // Art (all, left or right)
{
/* Helper function; carry Tabs and Paragraph Margins */
switch (eType)
{
case UpdateType::MoveRight:
mpIndents[INDENT_RIGHT_MARGIN].nPos += lDifference;
break ;
case UpdateType::MoveLeft:
{
mpIndents[INDENT_FIRST_LINE].nPos += lDifference;
mpIndents[INDENT_LEFT_MARGIN].nPos += lDifference;
if (!mpTabs.empty())
{
for (sal_uInt16 i = 0 ; i < nTabCount+TAB_GAP; ++i)
{
mpTabs[i].nPos += lDifference;
}
SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
}
break ;
}
}
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
}
void SvxRuler::DragBorders()
{
/* Dragging of Borders (Tables and other columns) */
bool bLeftIndentsCorrected = false ;
bool bRightIndentsCorrected = false ;
int nIndex;
if (GetDragType() == RulerType::Border)
{
DrawLine_Impl(lTabPos, 7 , bHorz);
nIndex = GetDragAryPos();
}
else
{
nIndex = 0 ;
}
RulerDragSize nDragSize = GetDragSize();
tools::Long lDiff = 0 ;
// the drag position has to be corrected to be able to prevent borders from passing each other
tools::Long lPos = MakePositionSticky(GetCorrectedDragPos(), GetLeftFrameMargin());
switch (nDragSize)
{
case RulerDragSize::Move:
{
if (GetDragType() == RulerType::Border)
lDiff = lPos - nDragOffset - mpBorders[nIndex].nPos;
else
lDiff = GetDragType() == RulerType::Margin1 ? lPos - mxRulerImpl->lLastLMargin : lPos - mxRulerImpl->lLastRMargin;
if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR)
{
tools::Long nRight = GetMargin2() - glMinFrame; // Right limiters
for (int i = mpBorders.size() - 2 ; i >= nIndex; --i)
{
tools::Long l = mpBorders[i].nPos;
mpBorders[i].nPos += lDiff;
mpBorders[i].nPos = std::min(mpBorders[i].nPos, nRight - mpBorders[i].nWidth);
nRight = mpBorders[i].nPos - glMinFrame;
// RR update the column
if (i == GetActRightColumn())
{
UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveRight);
bRightIndentsCorrected = true ;
}
// LAR, EZE update the column
else if (i == GetActLeftColumn())
{
UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveLeft);
bLeftIndentsCorrected = true ;
}
}
}
else if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
{
int nLimit;
tools::Long lLeft;
int nStartLimit = mpBorders.size() - 2 ;
switch (GetDragType())
{
default : ;//prevent warning
OSL_FAIL("svx::SvxRuler::DragBorders(), unknown drag type!" );
[[fallthrough]];
case RulerType::Border:
if (mxRulerImpl->bIsTableRows)
{
mpBorders[nIndex].nPos += lDiff;
if (bHorz)
{
lLeft = mpBorders[nIndex].nPos;
mxRulerImpl->nTotalDist -= lDiff;
nLimit = nIndex + 1 ;
}
else
{
lLeft = 0 ;
nStartLimit = nIndex - 1 ;
mxRulerImpl->nTotalDist += lDiff;
nLimit = 0 ;
}
}
else
{
nLimit = nIndex + 1 ;
mpBorders[nIndex].nPos += lDiff;
lLeft = mpBorders[nIndex].nPos;
mxRulerImpl->nTotalDist -= lDiff;
}
break ;
case RulerType::Margin1:
nLimit = 0 ;
lLeft = mxRulerImpl->lLastLMargin + lDiff;
mxRulerImpl->nTotalDist -= lDiff;
break ;
case RulerType::Margin2:
nLimit = 0 ;
lLeft= 0 ;
nStartLimit = mpBorders.size() - 2 ;
mxRulerImpl->nTotalDist += lDiff;
break ;
}
for (int i = nStartLimit; i >= nLimit; --i)
{
tools::Long l = mpBorders[i].nPos;
mpBorders[i].nPos =
lLeft +
(mxRulerImpl->nTotalDist * mxRulerImpl->pPercBuf[i]) / 1000 +
mxRulerImpl->pBlockBuf[i];
// RR update the column
if (!mxRulerImpl->bIsTableRows)
{
if (i == GetActRightColumn())
{
UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveRight);
bRightIndentsCorrected = true ;
}
// LAR, EZE update the column
else if (i == GetActLeftColumn())
{
UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveLeft);
bLeftIndentsCorrected = true ;
}
}
}
if (mxRulerImpl->bIsTableRows)
{
//in vertical tables the left borders have to be moved
if (bHorz)
{
for (int i = 0 ; i < nIndex; ++i)
mpBorders[i].nPos += lDiff;
AdjustMargin1(lDiff);
}
else
{
//otherwise the right borders are moved
for (int i = mxColumnItem->Count() - 1 ; i > nIndex; --i)
mpBorders[i].nPos += lDiff;
SetMargin2( GetMargin2() + lDiff, RulerMarginStyle::NONE );
}
}
}
else if (mxRulerImpl->bIsTableRows)
{
//moving rows: if a row is resized all following rows
//have to be moved by the same amount.
//This includes the left border when the table is not limited
//to a lower frame border.
int nLimit;
if (GetDragType()==RulerType::Border)
{
nLimit = nIndex + 1 ;
mpBorders[nIndex].nPos += lDiff;
}
else
{
nLimit=0 ;
}
//in vertical tables the left borders have to be moved
if (bHorz)
{
for (int i = 0 ; i < nIndex; ++i)
{
mpBorders[i].nPos += lDiff;
}
AdjustMargin1(lDiff);
}
else
{
//otherwise the right borders are moved
for (int i = mpBorders.size() - 2 ; i >= nLimit; --i)
{
mpBorders[i].nPos += lDiff;
}
SetMargin2( GetMargin2() + lDiff, RulerMarginStyle::NONE );
}
}
else
mpBorders[nIndex].nPos += lDiff;
break ;
}
case RulerDragSize::N1:
{
lDiff = lPos - mpBorders[nIndex].nPos;
mpBorders[nIndex].nWidth += mpBorders[nIndex].nPos - lPos;
mpBorders[nIndex].nPos = lPos;
break ;
}
case RulerDragSize::N2:
{
const tools::Long nOld = mpBorders[nIndex].nWidth;
mpBorders[nIndex].nWidth = lPos - mpBorders[nIndex].nPos;
lDiff = mpBorders[nIndex].nWidth - nOld;
break ;
}
}
if (!bRightIndentsCorrected &&
GetActRightColumn() == nIndex &&
nDragSize != RulerDragSize::N2 &&
!mpIndents.empty() &&
!mxRulerImpl->bIsTableRows)
{
UpdateParaContents_Impl(lDiff, UpdateType::MoveRight);
}
else if (!bLeftIndentsCorrected &&
GetActLeftColumn() == nIndex &&
nDragSize != RulerDragSize::N1 &&
!mpIndents.empty())
{
UpdateParaContents_Impl(lDiff, UpdateType::MoveLeft);
}
SetBorders(mxColumnItem->Count() - 1 , mpBorders.data());
}
void SvxRuler::DragObjectBorder()
{
/* Dragging of object edges */
if (RulerDragSize::Move == GetDragSize())
{
const tools::Long lPosition = MakePositionSticky(GetCorrectedDragPos(), GetLeftFrameMargin());
const sal_uInt16 nIdx = GetDragAryPos();
mpObjectBorders[GetObjectBordersOff(nIdx)].nPos = lPosition;
SetBorders(2 , mpObjectBorders.data() + GetObjectBordersOff(0 ));
DrawLine_Impl(lTabPos, 7 , bHorz);
}
}
void SvxRuler::ApplyMargins()
{
/* Applying margins; changed by dragging. */
const SfxPoolItem* pItem = nullptr;
sal_uInt16 nId = SID_ATTR_LONG_LRSPACE;
if (bHorz)
{
const tools::Long lOldNull = lLogicNullOffset;
if (mxRulerImpl->lMaxLeftLogic != -1 && nMaxLeft == GetMargin1() + Ruler::GetNullOffset())
{
lLogicNullOffset = mxRulerImpl->lMaxLeftLogic;
mxLRSpaceItem->SetLeft(lLogicNullOffset);
}
else
{
lLogicNullOffset = ConvertHPosLogic(GetFrameLeft()) - lAppNullOffset;
mxLRSpaceItem->SetLeft(PixelHAdjust(lLogicNullOffset, mxLRSpaceItem->GetLeft()));
}
if (bAppSetNullOffset)
{
lAppNullOffset += lLogicNullOffset - lOldNull;
}
tools::Long nRight;
if (mxRulerImpl->lMaxRightLogic != -1
&& nMaxRight == GetMargin2() + Ruler::GetNullOffset())
{
nRight = GetPageWidth() - mxRulerImpl->lMaxRightLogic;
}
else
{
nRight = std::max(tools::Long (0 ),
mxPagePosItem->GetWidth() - mxLRSpaceItem->GetLeft() -
(ConvertHPosLogic(GetMargin2()) - lAppNullOffset));
nRight = PixelHAdjust( nRight, mxLRSpaceItem->GetRight());
}
mxLRSpaceItem->SetRight(nRight);
pItem = mxLRSpaceItem.get();
#ifdef DEBUGLIN
Debug_Impl(pEditWin, *mxLRSpaceItem);
#endif // DEBUGLIN
}
else
{
const tools::Long lOldNull = lLogicNullOffset;
lLogicNullOffset =
ConvertVPosLogic(GetFrameLeft()) -
lAppNullOffset;
mxULSpaceItem->SetUpper(
PixelVAdjust(lLogicNullOffset, mxULSpaceItem->GetUpper()));
if (bAppSetNullOffset)
{
lAppNullOffset += lLogicNullOffset - lOldNull;
}
mxULSpaceItem->SetLower(
PixelVAdjust(
std::max(tools::Long (0 ), mxPagePosItem->GetHeight() -
mxULSpaceItem->GetUpper() -
(ConvertVPosLogic(GetMargin2()) -
lAppNullOffset)), mxULSpaceItem->GetLower()));
pItem = mxULSpaceItem.get();
nId = SID_ATTR_LONG_ULSPACE;
#ifdef DEBUGLIN
Debug_Impl(pEditWin,*mxULSpaceItem);
#endif // DEBUGLIN
}
pBindings->GetDispatcher()->ExecuteList(nId, SfxCallMode::RECORD, { pItem });
if (mxTabStopItem)
UpdateTabs();
}
tools::Long SvxRuler::RoundToCurrentMapMode(tools::Long lValue) const
{
RulerUnitData aUnitData = GetCurrentRulerUnit();
double aRoundingFactor = aUnitData.nTickUnit / aUnitData.nTick1;
tools::Long lNewValue = OutputDevice::LogicToLogic(Size(lValue, 0 ), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
lNewValue = (rtl::math::round(lNewValue / static_cast <double >(aUnitData.nTickUnit) * aRoundingFactor) / aRoundingFactor) * aUnitData.nTickUnit;
return OutputDevice::LogicToLogic(Size(lNewValue, 0 ), GetCurrentMapMode(), pEditWin->GetMapMode()).Width();
}
void SvxRuler::ApplyIndents()
{
/* Applying paragraph settings; changed by dragging. */
tools::Long nLeftFrameMargin = GetLeftFrameMargin();
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
tools::Long nNewTxtLeft;
tools::Long nNewFirstLineOffset;
tools::Long nNewRight;
tools::Long nFirstLine = ConvertPosLogic(mpIndents[INDENT_FIRST_LINE].nPos);
tools::Long nLeftMargin = ConvertPosLogic(mpIndents[INDENT_LEFT_MARGIN].nPos);
tools::Long nRightMargin = ConvertPosLogic(mpIndents[INDENT_RIGHT_MARGIN].nPos);
if (mxColumnItem && ((bRTL && !IsActLastColumn(true )) || (!bRTL && !IsActFirstColumn(true ))))
{
if (bRTL)
{
tools::Long nRightColumn = GetActRightColumn(true );
tools::Long nRightBorder = ConvertPosLogic(mpBorders[nRightColumn].nPos);
nNewTxtLeft = nRightBorder - nLeftMargin - lAppNullOffset;
}
else
{
tools::Long nLeftColumn = GetActLeftColumn(true );
tools::Long nLeftBorder = ConvertPosLogic(mpBorders[nLeftColumn].nPos + mpBorders[nLeftColumn].nWidth);
nNewTxtLeft = nLeftMargin - nLeftBorder - lAppNullOffset;
}
}
else
{
if (bRTL)
{
tools::Long nRightBorder = ConvertPosLogic(GetMargin2());
nNewTxtLeft = nRightBorder - nLeftMargin - lAppNullOffset;
}
else
{
tools::Long nLeftBorder = ConvertPosLogic(GetMargin1());
nNewTxtLeft = nLeftBorder + nLeftMargin - nLeftFrameMargin - lAppNullOffset;
}
}
if (bRTL)
nNewFirstLineOffset = nLeftMargin - nFirstLine - lAppNullOffset;
else
nNewFirstLineOffset = nFirstLine - nLeftMargin - lAppNullOffset;
if (mxColumnItem && ((!bRTL && !IsActLastColumn(true )) || (bRTL && !IsActFirstColumn(true ))))
{
if (bRTL)
{
tools::Long nLeftColumn = GetActLeftColumn(true );
tools::Long nLeftBorder = ConvertPosLogic(mpBorders[nLeftColumn].nPos + mpBorders[nLeftColumn].nWidth);
nNewRight = nRightMargin - nLeftBorder - lAppNullOffset;
}
else
{
tools::Long nRightColumn = GetActRightColumn(true );
tools::Long nRightBorder = ConvertPosLogic(mpBorders[nRightColumn].nPos);
nNewRight = nRightBorder - nRightMargin - lAppNullOffset;
}
}
else
{
if (bRTL)
{
tools::Long nLeftBorder = ConvertPosLogic(GetMargin1());
nNewRight = nLeftBorder + nRightMargin - nLeftFrameMargin - lAppNullOffset;
}
else
{
tools::Long nRightBorder = ConvertPosLogic(GetMargin2());
nNewRight = nRightBorder - nRightMargin - lAppNullOffset;
}
}
if (mbSnapping)
{
nNewTxtLeft = RoundToCurrentMapMode(nNewTxtLeft);
nNewFirstLineOffset = RoundToCurrentMapMode(nNewFirstLineOffset);
nNewRight = RoundToCurrentMapMode(nNewRight);
}
mxParaItem->SetTextFirstLineOffset(SvxIndentValue::twips(nNewFirstLineOffset));
mxParaItem->SetTextLeft(SvxIndentValue::twips(nNewTxtLeft));
mxParaItem->SetRight(SvxIndentValue::twips(nNewRight));
sal_uInt16 nParagraphId = bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL;
pBindings->GetDispatcher()->ExecuteList(nParagraphId, SfxCallMode::RECORD,
{ mxParaItem.get() });
UpdateTabs();
}
void SvxRuler::ApplyTabs()
{
/* Apply tab settings, changed by dragging. */
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
const sal_uInt16 nCoreIdx = GetDragAryPos();
if (IsDragDelete())
{
mxTabStopItem->Remove(nCoreIdx);
}
else if (SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType ||
SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType)
{
SvxTabStopItem *pItem = new SvxTabStopItem(mxTabStopItem->Which());
//remove default tab stops
for ( sal_uInt16 i = 0 ; i < pItem->Count(); )
{
if ( SvxTabAdjust::Default == (*pItem)[i].GetAdjustment() )
{
pItem->Remove(i);
continue ;
}
++i;
}
sal_uInt16 j;
for (j = 0 ; j < nCoreIdx; ++j)
{
pItem->Insert(mxTabStopItem->At(j));
}
for (; j < mxTabStopItem->Count(); ++j)
{
SvxTabStop aTabStop = mxTabStopItem->At(j);
aTabStop.GetTabPos() = PixelHAdjust(
ConvertHPosLogic(
mpTabs[j + TAB_GAP].nPos - GetLeftIndent()) - lAppNullOffset,
aTabStop.GetTabPos());
pItem->Insert(aTabStop);
}
mxTabStopItem.reset(pItem);
}
else if ( mxTabStopItem->Count() == 0 )
return ;
else
{
SvxTabStop aTabStop = mxTabStopItem->At(nCoreIdx);
if ( mxRulerImpl->lMaxRightLogic != -1 &&
mpTabs[nCoreIdx + TAB_GAP].nPos + Ruler::GetNullOffset() == nMaxRight )
{
// Set tab pos exactly at the right indent
tools::Long nTmpLeftIndentLogic
= lAppNullOffset + (bRTL ? GetRightFrameMargin() : GetLeftFrameMargin());
if (mxRulerImpl->bIsTabsRelativeToIndent && mxParaItem)
{
nTmpLeftIndentLogic
+= bRTL ? mxParaItem->ResolveRight({}) : mxParaItem->ResolveTextLeft({});
}
aTabStop.GetTabPos()
= mxRulerImpl->lMaxRightLogic - lLogicNullOffset - nTmpLeftIndentLogic;
}
else
{
if (bRTL)
{
//#i24363# tab stops relative to indent
const tools::Long nTmpLeftIndent = mxRulerImpl->bIsTabsRelativeToIndent ?
GetLeftIndent() :
ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset );
tools::Long nNewPosition = ConvertHPosLogic(nTmpLeftIndent - mpTabs[nCoreIdx + TAB_GAP].nPos);
aTabStop.GetTabPos() = PixelHAdjust(nNewPosition - lAppNullOffset, aTabStop.GetTabPos());
}
else
{
//#i24363# tab stops relative to indent
const tools::Long nTmpLeftIndent = mxRulerImpl->bIsTabsRelativeToIndent ?
GetLeftIndent() :
ConvertHPosPixel( GetLeftFrameMargin() + lAppNullOffset );
tools::Long nNewPosition = ConvertHPosLogic(mpTabs[nCoreIdx + TAB_GAP].nPos - nTmpLeftIndent);
aTabStop.GetTabPos() = PixelHAdjust(nNewPosition - lAppNullOffset, aTabStop.GetTabPos());
}
}
mxTabStopItem->Remove(nCoreIdx);
mxTabStopItem->Insert(aTabStop);
}
sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
pBindings->GetDispatcher()->ExecuteList(nTabStopId, SfxCallMode::RECORD,
{ mxTabStopItem.get() });
UpdateTabs();
}
void SvxRuler::ApplyBorders()
{
/* Applying (table) column settings; changed by dragging. */
if (mxColumnItem->IsTable())
{
tools::Long lValue = GetFrameLeft();
if (lValue != mxRulerImpl->nColLeftPix)
{
tools::Long nLeft = PixelHAdjust(
ConvertHPosLogic(lValue) -
lAppNullOffset,
mxColumnItem->GetLeft());
mxColumnItem->SetLeft(nLeft);
}
lValue = GetMargin2();
if (lValue != mxRulerImpl->nColRightPix)
{
tools::Long nWidthOrHeight = bHorz ? mxPagePosItem->GetWidth() : mxPagePosItem->GetHeight();
tools::Long nRight = PixelHAdjust(
nWidthOrHeight -
mxColumnItem->GetLeft() -
ConvertHPosLogic(lValue) -
lAppNullOffset,
mxColumnItem->GetRight() );
mxColumnItem->SetRight(nRight);
}
}
for (sal_uInt16 i = 0 ; i < mxColumnItem->Count() - 1 ; ++i)
{
tools::Long & nEnd = mxColumnItem->At(i).nEnd;
nEnd = PixelHAdjust(
ConvertPosLogic(mpBorders[i].nPos),
mxColumnItem->At(i).nEnd);
tools::Long & nStart = mxColumnItem->At(i + 1 ).nStart;
nStart = PixelHAdjust(
ConvertSizeLogic(mpBorders[i].nPos +
mpBorders[i].nWidth) -
lAppNullOffset,
mxColumnItem->At(i + 1 ).nStart);
// It may be that, due to the PixelHAdjust readjustment to old values,
// the width becomes < 0. This we readjust.
if ( nEnd > nStart )
nStart = nEnd;
}
#ifdef DEBUGLIN
Debug_Impl(pEditWin,*mxColumnItem);
#endif // DEBUGLIN
SfxBoolItem aFlag(SID_RULER_ACT_LINE_ONLY,
bool (nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY));
sal_uInt16 nColId = mxRulerImpl->bIsTableRows ? (bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL) :
(bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
pBindings->GetDispatcher()->ExecuteList(nColId, SfxCallMode::RECORD,
{ mxColumnItem.get(), &aFlag });
}
void SvxRuler::ApplyObject()
{
/* Applying object settings, changed by dragging. */
// to the page margin
tools::Long nMargin = mxLRSpaceItem ? mxLRSpaceItem->GetLeft() : 0 ;
tools::Long nStartX = PixelAdjust(
ConvertPosLogic(mpObjectBorders[0 ].nPos) +
nMargin -
lAppNullOffset,
mxObjectItem->GetStartX());
mxObjectItem->SetStartX(nStartX);
tools::Long nEndX = PixelAdjust(
ConvertPosLogic(mpObjectBorders[1 ].nPos) +
nMargin -
lAppNullOffset,
mxObjectItem->GetEndX());
mxObjectItem->SetEndX(nEndX);
nMargin = mxULSpaceItem ? mxULSpaceItem->GetUpper() : 0 ;
tools::Long nStartY = PixelAdjust(
ConvertPosLogic(mpObjectBorders[2 ].nPos) +
nMargin -
lAppNullOffset,
mxObjectItem->GetStartY());
mxObjectItem->SetStartY(nStartY);
tools::Long nEndY = PixelAdjust(
ConvertPosLogic(mpObjectBorders[3 ].nPos) +
nMargin -
lAppNullOffset,
mxObjectItem->GetEndY());
mxObjectItem->SetEndY(nEndY);
pBindings->GetDispatcher()->ExecuteList(SID_RULER_OBJECT,
SfxCallMode::RECORD, { mxObjectItem.get() });
}
void SvxRuler::PrepareProportional_Impl(RulerType eType)
{
/*
Preparation proportional dragging , and it is calculated based on the
proportional share of the total width in parts per thousand .
*/
mxRulerImpl->nTotalDist = GetMargin2();
switch (eType)
{
case RulerType::Margin2:
case RulerType::Margin1:
case RulerType::Border:
{
DBG_ASSERT(mxColumnItem, "no ColumnItem" );
mxRulerImpl->SetPercSize(mxColumnItem->Count());
tools::Long lPos;
tools::Long lWidth=0 ;
sal_uInt16 nStart;
sal_uInt16 nIdx=GetDragAryPos();
tools::Long lActWidth=0 ;
tools::Long lActBorderSum;
tools::Long lOrigLPos;
if (eType != RulerType::Border)
{
lOrigLPos = GetMargin1();
nStart = 0 ;
lActBorderSum = 0 ;
}
else
{
if (mxRulerImpl->bIsTableRows &&!bHorz)
{
lOrigLPos = GetMargin1();
nStart = 0 ;
}
else
{
lOrigLPos = mpBorders[nIdx].nPos + mpBorders[nIdx].nWidth;
nStart = 1 ;
}
lActBorderSum = mpBorders[nIdx].nWidth;
}
//in horizontal mode the percentage value has to be
//calculated on a "current change" position base
//because the height of the table changes while dragging
if (mxRulerImpl->bIsTableRows && RulerType::Border == eType)
{
sal_uInt16 nStartBorder;
sal_uInt16 nEndBorder;
if (bHorz)
{
nStartBorder = nIdx + 1 ;
nEndBorder = mxColumnItem->Count() - 1 ;
}
else
{
nStartBorder = 0 ;
nEndBorder = nIdx;
}
lWidth = mpBorders[nIdx].nPos;
if (bHorz)
lWidth = GetMargin2() - lWidth;
mxRulerImpl->nTotalDist = lWidth;
lPos = mpBorders[nIdx].nPos;
for (sal_uInt16 i = nStartBorder; i < nEndBorder; ++i)
{
if (bHorz)
{
lActWidth += mpBorders[i].nPos - lPos;
lPos = mpBorders[i].nPos + mpBorders[i].nWidth;
}
else
lActWidth = mpBorders[i].nPos;
mxRulerImpl->pPercBuf[i] = static_cast <sal_uInt16>((lActWidth * 1000 )
/ mxRulerImpl->nTotalDist);
mxRulerImpl->pBlockBuf[i] = static_cast <sal_uInt16>(lActBorderSum);
lActBorderSum += mpBorders[i].nWidth;
}
}
else
{
lPos = lOrigLPos;
for (sal_uInt16 ii = nStart; ii < mxColumnItem->Count() - 1 ; ++ii)
{
lWidth += mpBorders[ii].nPos - lPos;
lPos = mpBorders[ii].nPos + mpBorders[ii].nWidth;
}
lWidth += GetMargin2() - lPos;
mxRulerImpl->nTotalDist = lWidth;
lPos = lOrigLPos;
for (sal_uInt16 i = nStart; i < mxColumnItem->Count() - 1 ; ++i)
{
lActWidth += mpBorders[i].nPos - lPos;
lPos = mpBorders[i].nPos + mpBorders[i].nWidth;
mxRulerImpl->pPercBuf[i] = static_cast <sal_uInt16>((lActWidth * 1000 )
/ mxRulerImpl->nTotalDist);
mxRulerImpl->pBlockBuf[i] = static_cast <sal_uInt16>(lActBorderSum);
lActBorderSum += mpBorders[i].nWidth;
}
}
}
break ;
case RulerType::Tab:
{
const sal_uInt16 nIdx = GetDragAryPos()+TAB_GAP;
mxRulerImpl->nTotalDist -= mpTabs[nIdx].nPos;
mxRulerImpl->SetPercSize(nTabCount);
for (sal_uInt16 n=0 ;n<=nIdx;mxRulerImpl->pPercBuf[n++]=0 ) ;
for (sal_uInt16 i = nIdx+1 ; i < nTabCount; ++i)
{
const tools::Long nDelta = mpTabs[i].nPos - mpTabs[nIdx].nPos;
mxRulerImpl->pPercBuf[i] = static_cast <sal_uInt16>((nDelta * 1000 ) / mxRulerImpl->nTotalDist);
}
break ;
}
default : break ;
}
}
void SvxRuler::EvalModifier()
{
/*
Eval Drag Modifier
Shift : move linear
Control : move proportional
Shift + Control : Table : only current line
Alt : disable snapping
Alt + Shift : coarse snapping
*/
sal_uInt16 nModifier = GetDragModifier();
if (mxRulerImpl->bIsTableRows)
{
//rows can only be moved in one way, additionally current column is possible
if (nModifier == KEY_SHIFT)
nModifier = 0 ;
}
switch (nModifier)
{
case KEY_SHIFT:
nDragType = SvxRulerDragFlags::OBJECT_SIZE_LINEAR;
break ;
case KEY_MOD2 | KEY_SHIFT:
mbCoarseSnapping = true ;
break ;
case KEY_MOD2:
mbSnapping = false ;
break ;
case KEY_MOD1:
{
const RulerType eType = GetDragType();
nDragType = SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL;
if ( RulerType::Tab == eType ||
( ( RulerType::Border == eType ||
RulerType::Margin1 == eType ||
RulerType::Margin2 == eType ) &&
mxColumnItem ) )
{
PrepareProportional_Impl(eType);
}
}
break ;
case KEY_MOD1 | KEY_SHIFT:
if ( GetDragType() != RulerType::Margin1 &&
GetDragType() != RulerType::Margin2 )
{
nDragType = SvxRulerDragFlags::OBJECT_ACTLINE_ONLY;
}
break ;
}
}
void SvxRuler::Click()
{
/* Override handler SV; sets Tab per dispatcher call */
Ruler::Click();
if ( bActive )
{
pBindings->Update( SID_RULER_LR_MIN_MAX );
pBindings->Update( SID_ATTR_LONG_ULSPACE );
pBindings->Update( SID_ATTR_LONG_LRSPACE );
pBindings->Update( SID_RULER_PAGE_POS );
pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
pBindings->Update( SID_RULER_OBJECT );
pBindings->Update( SID_RULER_PROTECT );
pBindings->Update( SID_ATTR_PARA_LRSPACE_VERTICAL );
}
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
if (!(mxTabStopItem &&
(nFlags & SvxRulerSupportFlags::TABS) == SvxRulerSupportFlags::TABS))
return ;
bool bContentProtected = mxRulerImpl->aProtectItem->IsContentProtected();
if ( bContentProtected ) return ;
const tools::Long lPos = GetClickPos();
if (!((bRTL && lPos < std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos > GetRightIndent()) ||
(!bRTL && lPos > std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos < GetRightIndent())))
return ;
//convert position in left-to-right text
tools::Long nTabPos;
//#i24363# tab stops relative to indent
if (bRTL)
nTabPos = ( mxRulerImpl->bIsTabsRelativeToIndent ?
GetLeftIndent() :
ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset ) ) -
lPos;
else
nTabPos = lPos -
( mxRulerImpl->bIsTabsRelativeToIndent ?
GetLeftIndent() :
ConvertHPosPixel( GetLeftFrameMargin() + lAppNullOffset ));
SvxTabStop aTabStop(ConvertHPosLogic(nTabPos),
ToAttrTab_Impl(nDefTabType));
mxTabStopItem->Insert(aTabStop);
UpdateTabs();
}
void SvxRuler::CalcMinMax()
{
/*
Calculates the limits for dragging ; which are in pixels relative to the
page edge
*/
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
const tools::Long lNullPix = ConvertPosPixel(lLogicNullOffset);
mxRulerImpl->lMaxLeftLogic=mxRulerImpl->lMaxRightLogic=-1 ;
switch (GetDragType())
{
case RulerType::Margin1:
{ // left edge of the surrounding Frame
// DragPos - NOf between left - right
mxRulerImpl->lMaxLeftLogic = GetLeftMin();
nMaxLeft=ConvertSizePixel(mxRulerImpl->lMaxLeftLogic);
if (!mxColumnItem || mxColumnItem->Count() == 1 )
{
if (bRTL)
{
nMaxRight = lNullPix - GetRightIndent() +
std::max(GetFirstLineIndent(), GetLeftIndent()) -
glMinFrame;
}
else
{
nMaxRight = lNullPix + GetRightIndent() -
std::max(GetFirstLineIndent(), GetLeftIndent()) -
glMinFrame;
}
}
else if (mxRulerImpl->bIsTableRows)
{
//top border is not moveable when table rows are displayed
// protection of content means the margin is not moveable
if (bHorz && !mxRulerImpl->aProtectItem->IsContentProtected())
{
nMaxLeft = mpBorders[0 ].nMinPos + lNullPix;
if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
nMaxRight = GetRightIndent() + lNullPix -
(mxColumnItem->Count() - 1 ) * glMinFrame;
else
nMaxRight = mpBorders[0 ].nPos - glMinFrame + lNullPix;
}
else
nMaxLeft = nMaxRight = lNullPix;
}
else
{
if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
{
nMaxRight=lNullPix+CalcPropMaxRight();
}
else if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR)
{
nMaxRight = ConvertPosPixel(
GetPageWidth() - (
(mxColumnItem->IsTable() && mxLRSpaceItem)
? mxLRSpaceItem->GetRight() : 0 ))
- GetMargin2() + GetMargin1();
}
else
{
nMaxRight = lNullPix - glMinFrame;
if (mxColumnItem->IsFirstAct())
{
if (bRTL)
{
nMaxRight += std::min(
mpBorders[0 ].nPos,
std::max(GetFirstLineIndent(), GetLeftIndent()) - GetRightIndent());
}
else
{
nMaxRight += std::min(
mpBorders[0 ].nPos, GetRightIndent() -
std::max(GetFirstLineIndent(), GetLeftIndent()));
}
}
else if ( mxColumnItem->Count() > 1 )
{
nMaxRight += mpBorders[0 ].nPos;
}
else
{
nMaxRight += GetRightIndent() - std::max(GetFirstLineIndent(), GetLeftIndent());
}
// Do not drag the left table edge over the edge of the page
if (mxLRSpaceItem && mxColumnItem->IsTable())
{
tools::Long nTmp=ConvertSizePixel(mxLRSpaceItem->GetLeft());
if (nTmp>nMaxLeft)
nMaxLeft=nTmp;
}
}
}
break ;
}
case RulerType::Margin2:
{ // right edge of the surrounding Frame
mxRulerImpl->lMaxRightLogic
= mxMinMaxItem ? GetPageWidth() - GetRightMax() : GetPageWidth();
nMaxRight = ConvertSizePixel(mxRulerImpl->lMaxRightLogic);
if (!mxColumnItem)
{
if (bRTL)
{
nMaxLeft = GetMargin2() + GetRightIndent() -
std::max(GetFirstLineIndent(),GetLeftIndent()) - GetMargin1()+
glMinFrame + lNullPix;
}
else
{
nMaxLeft = GetMargin2() - GetRightIndent() +
std::max(GetFirstLineIndent(),GetLeftIndent()) - GetMargin1()+
glMinFrame + lNullPix;
}
}
else if (mxRulerImpl->bIsTableRows)
{
// get the bottom move range from the last border position - only available for rows!
// protection of content means the margin is not moveable
if (bHorz || mxRulerImpl->aProtectItem->IsContentProtected())
{
nMaxLeft = nMaxRight = mpBorders[mxColumnItem->Count() - 1 ].nMaxPos + lNullPix;
}
else
{
if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
{
nMaxLeft = (mxColumnItem->Count()) * glMinFrame + lNullPix;
}
else
{
if (mxColumnItem->Count() > 1 )
nMaxLeft = mpBorders[mxColumnItem->Count() - 2 ].nPos + glMinFrame + lNullPix;
else
nMaxLeft = glMinFrame + lNullPix;
}
if (mxColumnItem->Count() > 1 )
nMaxRight = mpBorders[mxColumnItem->Count() - 2 ].nMaxPos + lNullPix;
else
nMaxRight -= GetRightIndent() - lNullPix;
}
}
else
{
nMaxLeft = glMinFrame + lNullPix;
if (IsActLastColumn() || mxColumnItem->Count() < 2 ) //If last active column
{
if (bRTL)
{
nMaxLeft = glMinFrame + lNullPix + GetMargin2() +
GetRightIndent() - std::max(GetFirstLineIndent(),
GetLeftIndent());
}
else
{
nMaxLeft = glMinFrame + lNullPix + GetMargin2() -
GetRightIndent() + std::max(GetFirstLineIndent(),
GetLeftIndent());
}
}
if ( mxColumnItem->Count() >= 2 )
{
tools::Long nNewMaxLeft =
glMinFrame + lNullPix +
mpBorders[mxColumnItem->Count() - 2 ].nPos +
mpBorders[mxColumnItem->Count() - 2 ].nWidth;
nMaxLeft = std::max(nMaxLeft, nNewMaxLeft);
}
}
break ;
}
case RulerType::Border:
{ // Table, column (Modifier)
const sal_uInt16 nIdx = GetDragAryPos();
switch (GetDragSize())
{
case RulerDragSize::N1 :
{
nMaxRight = mpBorders[nIdx].nPos +
mpBorders[nIdx].nWidth + lNullPix;
if (0 == nIdx)
nMaxLeft = lNullPix;
else
nMaxLeft = mpBorders[nIdx - 1 ].nPos + mpBorders[nIdx - 1 ].nWidth + lNullPix;
if (mxColumnItem && nIdx == mxColumnItem->GetActColumn())
{
if (bRTL)
{
nMaxLeft += mpBorders[nIdx].nPos +
GetRightIndent() - std::max(GetFirstLineIndent(),
GetLeftIndent());
}
else
{
nMaxLeft += mpBorders[nIdx].nPos -
GetRightIndent() + std::max(GetFirstLineIndent(),
GetLeftIndent());
}
if (0 != nIdx)
nMaxLeft -= mpBorders[nIdx-1 ].nPos +
mpBorders[nIdx-1 ].nWidth;
}
nMaxLeft += glMinFrame;
nMaxLeft += nDragOffset;
break ;
}
case RulerDragSize::Move:
{
if (mxColumnItem)
{
//nIdx contains the position of the currently moved item
//next visible separator on the left
sal_uInt16 nLeftCol=GetActLeftColumn(false , nIdx);
//next visible separator on the right
sal_uInt16 nRightCol=GetActRightColumn(false , nIdx);
//next separator on the left - regardless if visible or not
sal_uInt16 nActLeftCol=GetActLeftColumn();
//next separator on the right - regardless if visible or not
sal_uInt16 nActRightCol=GetActRightColumn();
if (mxColumnItem->IsTable())
{
if (nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY)
{
//the current row/column should be modified only
//then the next/previous visible border position
//marks the min/max positions
nMaxLeft = nLeftCol == USHRT_MAX ?
0 :
mpBorders[nLeftCol].nPos;
//rows can always be increased without a limit
if (mxRulerImpl->bIsTableRows)
nMaxRight = mpBorders[nIdx].nMaxPos;
else
nMaxRight = nRightCol == USHRT_MAX ?
GetMargin2():
mpBorders[nRightCol].nPos;
nMaxLeft += lNullPix;
nMaxRight += lNullPix;
}
else
{
if (SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType && !bHorz && mxRulerImpl->bIsTableRows)
nMaxLeft = (nIdx + 1 ) * glMinFrame + lNullPix;
else
nMaxLeft = mpBorders[nIdx].nMinPos + lNullPix;
if ((SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType) ||
(SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType) )
{
if (mxRulerImpl->bIsTableRows)
{
if (bHorz)
nMaxRight = GetRightIndent() + lNullPix -
(mxColumnItem->Count() - nIdx - 1 ) * glMinFrame;
else
nMaxRight = mpBorders[nIdx].nMaxPos + lNullPix;
}
else
nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
}
else
nMaxRight = mpBorders[nIdx].nMaxPos + lNullPix;
}
nMaxLeft += glMinFrame;
nMaxRight -= glMinFrame;
}
else
{
if (nLeftCol==USHRT_MAX)
nMaxLeft=lNullPix;
else
nMaxLeft = mpBorders[nLeftCol].nPos +
mpBorders[nLeftCol].nWidth + lNullPix;
if (nActRightCol == nIdx)
{
if (bRTL)
{
nMaxLeft += mpBorders[nIdx].nPos +
GetRightIndent() - std::max(GetFirstLineIndent(),
GetLeftIndent());
if (nActLeftCol!=USHRT_MAX)
nMaxLeft -= mpBorders[nActLeftCol].nPos +
mpBorders[nActLeftCol].nWidth;
}
else
{
nMaxLeft += mpBorders[nIdx].nPos -
GetRightIndent() + std::max(GetFirstLineIndent(),
GetLeftIndent());
if (nActLeftCol!=USHRT_MAX)
nMaxLeft -= mpBorders[nActLeftCol].nPos +
mpBorders[nActLeftCol].nWidth;
}
}
nMaxLeft += glMinFrame;
nMaxLeft += nDragOffset;
// nMaxRight
// linear / proportional move
if ((SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType) ||
(SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType) )
{
nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
}
else if (SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType)
{
nMaxRight = lNullPix + GetMargin2() - GetMargin1() +
(mpBorders.size() - nIdx - 1 ) * glMinFrame;
}
else
{
if (nRightCol==USHRT_MAX)
{ // last column
nMaxRight = GetMargin2() + lNullPix;
if (IsActLastColumn())
{
if (bRTL)
{
nMaxRight -=
GetMargin2() + GetRightIndent() -
std::max(GetFirstLineIndent(),
GetLeftIndent());
}
else
{
nMaxRight -=
GetMargin2() - GetRightIndent() +
std::max(GetFirstLineIndent(),
GetLeftIndent());
}
nMaxRight += mpBorders[nIdx].nPos +
mpBorders[nIdx].nWidth;
}
}
else
{
nMaxRight = lNullPix + mpBorders[nRightCol].nPos;
sal_uInt16 nNotHiddenRightCol =
GetActRightColumn(true , nIdx);
if ( nActLeftCol == nIdx )
{
tools::Long nBorder = nNotHiddenRightCol ==
USHRT_MAX ?
GetMargin2() :
mpBorders[nNotHiddenRightCol].nPos;
if (bRTL)
{
nMaxRight -= nBorder + GetRightIndent() -
std::max(GetFirstLineIndent(),
GetLeftIndent());
}
else
{
nMaxRight -= nBorder - GetRightIndent() +
std::max(GetFirstLineIndent(),
GetLeftIndent());
}
nMaxRight += mpBorders[nIdx].nPos +
mpBorders[nIdx].nWidth;
}
}
nMaxRight -= glMinFrame;
nMaxRight -= mpBorders[nIdx].nWidth;
}
}
}
// ObjectItem
else
{
nMaxLeft = LONG_MIN;
nMaxRight = LONG_MAX;
}
break ;
}
case RulerDragSize::N2:
if (mxColumnItem)
{
nMaxLeft = lNullPix + mpBorders[nIdx].nPos;
if (nIdx == mxColumnItem->Count()-2 ) { // last column
nMaxRight = GetMargin2() + lNullPix;
if (mxColumnItem->IsLastAct()) {
nMaxRight -=
GetMargin2() - GetRightIndent() +
std::max(GetFirstLineIndent(),
GetLeftIndent());
nMaxRight += mpBorders[nIdx].nPos +
mpBorders[nIdx].nWidth;
}
}
else {
nMaxRight = lNullPix + mpBorders[nIdx+1 ].nPos;
if (mxColumnItem->GetActColumn()-1 == nIdx) {
nMaxRight -= mpBorders[nIdx+1 ].nPos - GetRightIndent() +
std::max(GetFirstLineIndent(),
GetLeftIndent());
nMaxRight += mpBorders[nIdx].nPos +
mpBorders[nIdx].nWidth;
}
}
nMaxRight -= glMinFrame;
nMaxRight -= mpBorders[nIdx].nWidth;
break ;
}
}
nMaxRight += nDragOffset;
break ;
}
case RulerType::Indent:
{
const sal_uInt16 nIdx = GetDragAryPos();
switch (nIdx) {
case INDENT_FIRST_LINE - INDENT_GAP:
case INDENT_LEFT_MARGIN - INDENT_GAP:
{
if (bRTL)
{
nMaxLeft = lNullPix + GetRightIndent();
if (mxColumnItem && !mxColumnItem->IsFirstAct())
nMaxLeft += mpBorders[mxColumnItem->GetActColumn()-1 ].nPos +
mpBorders[mxColumnItem->GetActColumn()-1 ].nWidth;
nMaxRight = lNullPix + GetMargin2();
// Dragging along
if ((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
!(nDragType & SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY))
{
if (GetLeftIndent() > GetFirstLineIndent())
nMaxLeft += GetLeftIndent() - GetFirstLineIndent();
else
nMaxRight -= GetFirstLineIndent() - GetLeftIndent();
}
}
else
{
nMaxLeft = lNullPix;
if (mxColumnItem && !mxColumnItem->IsFirstAct())
nMaxLeft += mpBorders[mxColumnItem->GetActColumn()-1 ].nPos +
mpBorders[mxColumnItem->GetActColumn()-1 ].nWidth;
nMaxRight = lNullPix + GetRightIndent() - glMinFrame;
// Dragging along
if ((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
!(nDragType & SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY))
{
if (GetLeftIndent() > GetFirstLineIndent())
nMaxLeft += GetLeftIndent() - GetFirstLineIndent();
else
nMaxRight -= GetFirstLineIndent() - GetLeftIndent();
}
}
}
break ;
case INDENT_RIGHT_MARGIN - INDENT_GAP:
{
if (bRTL)
{
nMaxLeft = lNullPix;
nMaxRight = lNullPix + std::min(GetFirstLineIndent(), GetLeftIndent()) - glMinFrame;
if (mxColumnItem)
{
sal_uInt16 nRightCol=GetActRightColumn( true );
if (!IsActLastColumn( true ))
nMaxRight += mpBorders[nRightCol].nPos;
else
nMaxRight += GetMargin2();
}
else
{
nMaxLeft += GetMargin1();
}
nMaxLeft += glMinFrame;
}
else
{
nMaxLeft = lNullPix +
std::max(GetFirstLineIndent(), GetLeftIndent());
nMaxRight = lNullPix;
if (mxColumnItem)
{
sal_uInt16 nRightCol=GetActRightColumn( true );
if (!IsActLastColumn( true ))
nMaxRight += mpBorders[nRightCol].nPos;
else
nMaxRight += GetMargin2();
}
else
nMaxRight += GetMargin2();
nMaxLeft += glMinFrame;
}
}
break ;
}
break ;
}
case RulerType::Tab: // Tabs (Modifier)
/* left = NOf + Max(LAR, EZ)
right = NOf + RAR */
if (bRTL)
nMaxLeft = lNullPix + GetRightIndent();
else
nMaxLeft = lNullPix + std::min(GetFirstLineIndent(), GetLeftIndent());
mxRulerImpl->lMaxRightLogic = GetLogicRightIndent() + lLogicNullOffset;
nMaxRight = ConvertSizePixel(mxRulerImpl->lMaxRightLogic);
break ;
default : ; //prevent warning
}
}
bool SvxRuler::StartDrag()
{
/*
Beginning of a drag operation ( SV - handler ) evaluates modifier and
calculated values
[ Cross - reference ]
< SvxRuler : : EvalModifier ( ) >
< SvxRuler : : CalcMinMax ( ) >
< SvxRuler : : EndDrag ( ) >
*/
bool bContentProtected = mxRulerImpl->aProtectItem->IsContentProtected();
if (!bValid)
return false ;
mxRulerImpl->lLastLMargin = GetMargin1();
mxRulerImpl->lLastRMargin = GetMargin2();
bool bOk = true ;
lInitialDragPos = GetDragPos();
switch (GetDragType())
{
case RulerType::Margin1: // left edge of the surrounding Frame
case RulerType::Margin2: // right edge of the surrounding Frame
if ((bHorz && mxLRSpaceItem) || (!bHorz && mxULSpaceItem))
{
if (!mxColumnItem)
EvalModifier();
else
nDragType = SvxRulerDragFlags::OBJECT;
}
else
{
bOk = false ;
}
break ;
case RulerType::Border: // Table, column (Modifier)
if (mxColumnItem)
{
nDragOffset = 0 ;
if (!mxColumnItem->IsTable())
nDragOffset = GetDragPos() - mpBorders[GetDragAryPos()].nPos;
EvalModifier();
}
else
nDragOffset = 0 ;
break ;
case RulerType::Indent: // Paragraph indents (Modifier)
{
if ( bContentProtected )
return false ;
if (INDENT_LEFT_MARGIN == GetDragAryPos() + INDENT_GAP) { // Left paragraph indent
mpIndents[0 ] = mpIndents[INDENT_FIRST_LINE];
EvalModifier();
}
else
{
nDragType = SvxRulerDragFlags::OBJECT;
}
mpIndents[1 ] = mpIndents[GetDragAryPos() + INDENT_GAP];
break ;
}
case RulerType::Tab: // Tabs (Modifier)
if ( bContentProtected )
return false ;
EvalModifier();
mpTabs[0 ] = mpTabs[GetDragAryPos() + 1 ];
mpTabs[0 ].nStyle |= RULER_STYLE_DONTKNOW;
break ;
default :
nDragType = SvxRulerDragFlags::NONE;
}
if (bOk)
CalcMinMax();
return bOk;
}
void SvxRuler::Drag()
{
/* SV-Draghandler */
if (IsDragCanceled())
{
Ruler::Drag();
return ;
}
switch (GetDragType()) {
case RulerType::Margin1: // left edge of the surrounding Frame
DragMargin1();
mxRulerImpl->lLastLMargin = GetMargin1();
break ;
case RulerType::Margin2: // right edge of the surrounding Frame
DragMargin2();
mxRulerImpl->lLastRMargin = GetMargin2();
break ;
case RulerType::Indent: // Paragraph indents
DragIndents();
break ;
case RulerType::Border: // Table, columns
if (mxColumnItem)
DragBorders();
else if (mxObjectItem)
DragObjectBorder();
break ;
case RulerType::Tab: // Tabs
DragTabs();
break ;
default :
break ; //prevent warning
}
Ruler::Drag();
}
void SvxRuler::EndDrag()
{
/*
SV - handler ; is called when ending the dragging . Triggers the updating of data
on the application , by calling the respective Apply . . . ( ) methods to send the
data to the application .
*/
const bool bUndo = IsDragCanceled();
const tools::Long lPos = GetDragPos();
DrawLine_Impl(lTabPos, 6 , bHorz);
lTabPos = -1 ;
if (!bUndo)
{
switch (GetDragType())
{
case RulerType::Margin1: // upper left edge of the surrounding Frame
case RulerType::Margin2: // lower right edge of the surrounding Frame
{
if (!mxColumnItem || !mxColumnItem->IsTable())
ApplyMargins();
if (mxColumnItem &&
(mxColumnItem->IsTable() ||
(nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)))
ApplyBorders();
}
break ;
case RulerType::Border: // Table, columns
if (lInitialDragPos != lPos ||
(mxRulerImpl->bIsTableRows && bHorz)) //special case - the null offset is changed here
{
if (mxColumnItem)
{
ApplyBorders();
if (bHorz)
UpdateTabs();
}
else if (mxObjectItem)
ApplyObject();
}
break ;
case RulerType::Indent: // Paragraph indents
if (lInitialDragPos != lPos)
ApplyIndents();
SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
break ;
case RulerType::Tab: // Tabs
{
ApplyTabs();
mpTabs[GetDragAryPos()].nStyle &= ~RULER_STYLE_INVISIBLE;
SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
}
break ;
default :
break ; //prevent warning
}
}
nDragType = SvxRulerDragFlags::NONE;
mbCoarseSnapping = false ;
mbSnapping = true ;
Ruler::EndDrag();
if (bUndo)
{
for (sal_uInt16 i = 0 ; i < mxRulerImpl->nControllerItems; i++)
{
pCtrlItems[i]->ClearCache();
pCtrlItems[i]->GetBindings().Invalidate(pCtrlItems[i]->GetId());
}
}
}
void SvxRuler::ExtraDown()
{
/* Override SV method, sets the new type for the Default tab. */
// Switch Tab Type
if (mxTabStopItem &&
(nFlags & SvxRulerSupportFlags::TABS) == SvxRulerSupportFlags::TABS)
{
++nDefTabType;
if (RULER_TAB_DEFAULT == nDefTabType)
nDefTabType = RULER_TAB_LEFT;
SetExtraType(RulerExtra::Tab, nDefTabType);
}
Ruler::ExtraDown();
}
void SvxRuler::Notify(SfxBroadcaster&, const SfxHint& rHint)
{
/*
Report through the bindings that the status update is completed . The ruler
updates its appearance and gets registered again in the bindings .
*/
// start update
if (bActive && rHint.GetId() == SfxHintId::UpdateDone)
{
Update();
EndListening(*pBindings);
bValid = true ;
bListening = false ;
}
}
void SvxRuler::MenuSelect(std::u16string_view ident)
{
if (ident.empty())
return ;
/* Handler of the context menus for switching the unit of measurement */
SetUnit(vcl::EnglishStringToMetric(ident));
}
void SvxRuler::TabMenuSelect(std::u16string_view rIdent)
{
if (rIdent.empty())
return ;
sal_Int32 nId = o3tl::toInt32(rIdent);
/* Handler of the tab menu for setting the type */
if (mxTabStopItem && mxTabStopItem->Count() > mxRulerImpl->nIdx)
{
SvxTabStop aTabStop = mxTabStopItem->At(mxRulerImpl->nIdx);
aTabStop.GetAdjustment() = ToAttrTab_Impl(nId - 1 );
mxTabStopItem->Remove(mxRulerImpl->nIdx);
mxTabStopItem->Insert(aTabStop);
sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
pBindings->GetDispatcher()->ExecuteList(nTabStopId,
SfxCallMode::RECORD, { mxTabStopItem.get() });
UpdateTabs();
mxRulerImpl->nIdx = 0 ;
}
}
const TranslateId RID_SVXSTR_RULER_TAB[] =
{
RID_SVXSTR_RULER_TAB_LEFT,
RID_SVXSTR_RULER_TAB_RIGHT,
RID_SVXSTR_RULER_TAB_CENTER,
RID_SVXSTR_RULER_TAB_DECIMAL
};
void SvxRuler::Command( const CommandEvent& rCommandEvent )
{
/* Mouse context menu for switching the unit of measurement */
if ( CommandEventId::ContextMenu == rCommandEvent.GetCommand() )
{
CancelDrag();
tools::Rectangle aRect(rCommandEvent.GetMousePosPixel(), Size(1 , 1 ));
weld::Window* pPopupParent = weld::GetPopupParent(*this , aRect);
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, u"svx/ui/rulermenu.ui" _ustr));
std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"menu" _ustr));
bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
if ( !mpTabs.empty() &&
RulerType::Tab ==
GetRulerType( rCommandEvent.GetMousePosPixel(), &mxRulerImpl->nIdx ) &&
mpTabs[mxRulerImpl->nIdx + TAB_GAP].nStyle < RULER_TAB_DEFAULT )
{
xMenu->clear();
const Size aSz(ruler_tab_svx.width + 2 , ruler_tab_svx.height + 2 );
const Point aPt(aSz.Width() / 2 , aSz.Height() / 2 );
for ( sal_uInt16 i = RULER_TAB_LEFT; i < RULER_TAB_DEFAULT; ++i )
{
ScopedVclPtr<VirtualDevice> xDev(pPopupParent->create_virtual_device());
xDev->SetOutputSize(aSz);
sal_uInt16 nStyle = bRTL ? i|RULER_TAB_RTL : i;
nStyle |= static_cast <sal_uInt16>(bHorz ? WB_HORZ : WB_VERT);
Color aFillColor(xDev->GetSettings().GetStyleSettings().GetShadowColor());
DrawTab(*xDev, aFillColor, aPt, nStyle);
OUString sId(OUString::number(i + 1 ));
xMenu->insert(-1 , sId, SvxResId(RID_SVXSTR_RULER_TAB[i]),
nullptr, xDev.get(), nullptr, TRISTATE_TRUE);
xMenu->set_active(sId, i == mpTabs[mxRulerImpl->nIdx + TAB_GAP].nStyle);
}
TabMenuSelect(xMenu->popup_at_rect(pPopupParent, aRect));
}
else
{
FieldUnit eUnit = GetUnit();
const int nCount = xMenu->n_children();
bool bReduceMetric = bool (nFlags & SvxRulerSupportFlags::REDUCED_METRIC);
for ( sal_uInt16 i = nCount; i; --i )
{
OUString sIdent = xMenu->get_id(i - 1 );
FieldUnit eMenuUnit = vcl::EnglishStringToMetric(sIdent);
xMenu->set_active(sIdent, eMenuUnit == eUnit);
if ( bReduceMetric )
{
if (eMenuUnit == FieldUnit::M ||
eMenuUnit == FieldUnit::KM ||
eMenuUnit == FieldUnit::FOOT ||
eMenuUnit == FieldUnit::MILE)
{
xMenu->remove(sIdent);
}
else if (( eMenuUnit == FieldUnit::CHAR ) && !bHorz )
{
xMenu->remove(sIdent);
}
else if (( eMenuUnit == FieldUnit::LINE ) && bHorz )
{
xMenu->remove(sIdent);
}
}
}
MenuSelect(xMenu->popup_at_rect(pPopupParent, aRect));
}
}
else
{
Ruler::Command( rCommandEvent );
}
}
sal_uInt16 SvxRuler::GetActRightColumn(
bool bForceDontConsiderHidden,
sal_uInt16 nAct ) const
{
if ( nAct == USHRT_MAX )
nAct = mxColumnItem->GetActColumn();
else
nAct++; //To be able to pass on the ActDrag
bool bConsiderHidden = !bForceDontConsiderHidden &&
!(nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY);
while ( nAct < mxColumnItem->Count() - 1 )
{
if (mxColumnItem->At(nAct).bVisible || bConsiderHidden)
return nAct;
else
nAct++;
}
return USHRT_MAX;
}
sal_uInt16 SvxRuler::GetActLeftColumn(
bool bForceDontConsiderHidden,
sal_uInt16 nAct ) const
{
if (nAct == USHRT_MAX)
nAct = mxColumnItem->GetActColumn();
sal_uInt16 nLeftOffset = 1 ;
bool bConsiderHidden = !bForceDontConsiderHidden &&
!(nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY);
while (nAct >= nLeftOffset)
{
if (mxColumnItem->At(nAct - nLeftOffset).bVisible || bConsiderHidden)
return nAct - nLeftOffset;
else
nLeftOffset++;
}
return USHRT_MAX;
}
bool SvxRuler::IsActLastColumn(
bool bForceDontConsiderHidden,
sal_uInt16 nAct) const
{
return GetActRightColumn(bForceDontConsiderHidden, nAct) == USHRT_MAX;
}
bool SvxRuler::IsActFirstColumn(
bool bForceDontConsiderHidden,
sal_uInt16 nAct) const
{
return GetActLeftColumn(bForceDontConsiderHidden, nAct) == USHRT_MAX;
}
tools::Long SvxRuler::CalcPropMaxRight(sal_uInt16 nCol) const
{
if (!(nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR))
{
// Remove the minimum width for all affected columns
// starting from the right edge
tools::Long _nMaxRight = GetMargin2() - GetMargin1();
tools::Long lFences = 0 ;
tools::Long lMinSpace = USHRT_MAX;
tools::Long lOldPos;
tools::Long lColumns = 0 ;
sal_uInt16 nStart;
if (!mxColumnItem->IsTable())
{
if (nCol == USHRT_MAX)
{
lOldPos = GetMargin1();
nStart = 0 ;
}
else
{
lOldPos = mpBorders[nCol].nPos + mpBorders[nCol].nWidth;
nStart = nCol + 1 ;
lFences = mpBorders[nCol].nWidth;
}
for (size_t i = nStart; i < mpBorders.size() - 1 ; ++i)
{
tools::Long lWidth = mpBorders[i].nPos - lOldPos;
lColumns += lWidth;
if (lWidth < lMinSpace)
lMinSpace = lWidth;
lOldPos = mpBorders[i].nPos + mpBorders[i].nWidth;
lFences += mpBorders[i].nWidth;
}
tools::Long lWidth = GetMargin2() - lOldPos;
lColumns += lWidth;
if (lWidth < lMinSpace)
lMinSpace = lWidth;
}
else
{
sal_uInt16 nActCol;
if (nCol == USHRT_MAX) //CalcMinMax for LeftMargin
{
lOldPos = GetMargin1();
}
else
{
lOldPos = mpBorders[nCol].nPos;
}
lColumns = GetMargin2()-lOldPos;
nActCol = nCol;
lFences = 0 ;
while (nActCol < mpBorders.size() || nActCol == USHRT_MAX)
{
sal_uInt16 nRight;
if (nActCol == USHRT_MAX)
{
nRight = 0 ;
while (!(*mxColumnItem)[nRight].bVisible)
{
nRight++;
}
}
else
{
nRight = GetActRightColumn(false , nActCol);
}
tools::Long lWidth;
if (nRight != USHRT_MAX)
{
lWidth = mpBorders[nRight].nPos - lOldPos;
lOldPos = mpBorders[nRight].nPos;
}
else
{
lWidth=GetMargin2() - lOldPos;
}
nActCol = nRight;
if (lWidth < lMinSpace)
lMinSpace = lWidth;
if (nActCol == USHRT_MAX)
break ;
}
}
_nMaxRight -= static_cast <tools::Long >(lFences + glMinFrame / static_cast <float >(lMinSpace) * lColumns);
return _nMaxRight;
}
else
{
if (mxColumnItem->IsTable())
{
sal_uInt16 nVisCols = 0 ;
for (size_t i = GetActRightColumn(false , nCol); i < mpBorders.size();)
{
if ((*mxColumnItem)[i].bVisible)
nVisCols++;
i = GetActRightColumn(false , i);
}
return GetMargin2() - GetMargin1() - (nVisCols + 1 ) * glMinFrame;
}
else
{
tools::Long lWidth = 0 ;
for (size_t i = nCol; i < mpBorders.size() - 1 ; i++)
{
lWidth += glMinFrame + mpBorders[i].nWidth;
}
return GetMargin2() - GetMargin1() - lWidth;
}
}
}
// Tab stops relative to indent (#i24363#)
void SvxRuler::SetTabsRelativeToIndent( bool bRel )
{
mxRulerImpl->bIsTabsRelativeToIndent = bRel;
}
void SvxRuler::SetValues(RulerChangeType type, tools::Long diffValue)
{
if (diffValue == 0 )
return ;
if (type == RulerChangeType::MARGIN1)
AdjustMargin1(diffValue);
else if (type == RulerChangeType::MARGIN2)
SetMargin2( GetMargin2() - diffValue);
ApplyMargins();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
Messung V0.5 in Prozent C=93 H=94 G=93
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.113Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-27)
¤
*Eine klare Vorstellung vom Zielzustand