summaryrefslogtreecommitdiffstats
path: root/svtools/source/control/ruler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/control/ruler.cxx')
-rw-r--r--svtools/source/control/ruler.cxx2778
1 files changed, 2778 insertions, 0 deletions
diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx
new file mode 100644
index 0000000000..6ddac0ccd7
--- /dev/null
+++ b/svtools/source/control/ruler.cxx
@@ -0,0 +1,2778 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tools/debug.hxx>
+#include <tools/poly.hxx>
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/vcllayout.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <sal/log.hxx>
+
+#include <svtools/ruler.hxx>
+#include <svtools/svtresid.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/colorcfg.hxx>
+#include "accessibleruler.hxx"
+
+#include <memory>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+#define RULER_OFF 3
+#define RULER_RESIZE_OFF 4
+#define RULER_MIN_SIZE 3
+
+#define RULER_VAR_SIZE 8
+
+#define RULER_UPDATE_LINES 0x01
+
+#define RULER_CLIP 150
+
+#define RULER_UNIT_MM 0
+#define RULER_UNIT_CM 1
+#define RULER_UNIT_M 2
+#define RULER_UNIT_KM 3
+#define RULER_UNIT_INCH 4
+#define RULER_UNIT_FOOT 5
+#define RULER_UNIT_MILE 6
+#define RULER_UNIT_POINT 7
+#define RULER_UNIT_PICA 8
+#define RULER_UNIT_CHAR 9
+#define RULER_UNIT_LINE 10
+#define RULER_UNIT_COUNT 11
+
+namespace
+{
+/**
+ * Pre-calculates glyph items for rText on rRenderContext. Subsequent calls
+ * avoid the calculation and just return a pointer to rTextGlyphs.
+ */
+SalLayoutGlyphs* lcl_GetRulerTextGlyphs(const vcl::RenderContext& rRenderContext, const OUString& rText,
+ SalLayoutGlyphs& rTextGlyphs)
+{
+ if (rTextGlyphs.IsValid())
+ // Use pre-calculated result.
+ return &rTextGlyphs;
+
+ // Calculate glyph items.
+
+ std::unique_ptr<SalLayout> pLayout = rRenderContext.ImplLayout(
+ rText, 0, rText.getLength(), Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly);
+ if (!pLayout)
+ return nullptr;
+
+ // Remember the calculation result.
+ rTextGlyphs = pLayout->GetGlyphs();
+
+ return &rTextGlyphs;
+}
+}
+
+class ImplRulerData
+{
+ friend class Ruler;
+
+private:
+ std::vector<RulerLine> pLines;
+ std::vector<RulerBorder> pBorders;
+ std::vector<RulerIndent> pIndents;
+ std::vector<RulerTab> pTabs;
+
+ tools::Long nNullVirOff;
+ tools::Long nRulVirOff;
+ tools::Long nRulWidth;
+ tools::Long nPageOff;
+ tools::Long nPageWidth;
+ tools::Long nNullOff;
+ tools::Long nMargin1;
+ tools::Long nMargin2;
+ // In this context, "frame margin" means paragraph margins (indents)
+ tools::Long nLeftFrameMargin;
+ tools::Long nRightFrameMargin;
+ RulerMarginStyle nMargin1Style;
+ RulerMarginStyle nMargin2Style;
+ bool bAutoPageWidth;
+ bool bTextRTL;
+
+public:
+ ImplRulerData();
+};
+
+ImplRulerData::ImplRulerData() :
+ nNullVirOff (0),
+ nRulVirOff (0),
+ nRulWidth (0),
+ nPageOff (0),
+ nPageWidth (0),
+ nNullOff (0),
+ nMargin1 (0),
+ nMargin2 (0),
+ nLeftFrameMargin (0),
+ nRightFrameMargin (0),
+ nMargin1Style (RulerMarginStyle::NONE),
+ nMargin2Style (RulerMarginStyle::NONE),
+ bAutoPageWidth (true), // Page width == EditWin width
+ bTextRTL (false)
+{
+}
+
+const RulerUnitData aImplRulerUnitTab[RULER_UNIT_COUNT] =
+{
+{ MapUnit::Map100thMM, 100, 25.0, 25.0, 50.0, 100.0, " mm" }, // MM
+{ MapUnit::Map100thMM, 1000, 100.0, 500.0, 1000.0, 1000.0, " cm" }, // CM
+{ MapUnit::MapMM, 1000, 10.0, 250.0, 500.0, 1000.0, " m" }, // M
+{ MapUnit::MapCM, 100000, 12500.0, 25000.0, 50000.0, 100000.0, " km" }, // KM
+{ MapUnit::Map1000thInch, 1000, 62.5, 125.0, 500.0, 1000.0, "\"" }, // INCH
+{ MapUnit::Map100thInch, 1200, 120.0, 120.0, 600.0, 1200.0, "'" }, // FOOT
+{ MapUnit::Map10thInch, 633600, 63360.0, 63360.0, 316800.0, 633600.0, " miles" }, // MILE
+{ MapUnit::MapPoint, 1, 12.0, 12.0, 12.0, 36.0, " pt" }, // POINT
+{ MapUnit::Map100thMM, 423, 423.0, 423.0, 423.0, 846.0, " pc" }, // PICA
+{ MapUnit::Map100thMM, 371, 371.0, 371.0, 371.0, 743.0, " ch" }, // CHAR
+{ MapUnit::Map100thMM, 551, 551.0, 551.0, 551.0, 1102.0, " li" } // LINE
+};
+
+static RulerTabData ruler_tab =
+{
+ 0, // DPIScaleFactor to be set
+ 7, // ruler_tab_width
+ 6, // ruler_tab_height
+ 2, // ruler_tab_height2
+ 2, // ruler_tab_width2
+ 8, // ruler_tab_cwidth
+ 4, // ruler_tab_cwidth2
+ 4, // ruler_tab_cwidth3
+ 2, // ruler_tab_cwidth4
+ 4, // ruler_tab_dheight
+ 1, // ruler_tab_dheight2
+ 5, // ruler_tab_dwidth
+ 3, // ruler_tab_dwidth2
+ 3, // ruler_tab_dwidth3
+ 1, // ruler_tab_dwidth4
+ 5 // ruler_tab_textoff
+};
+
+void Ruler::ImplInit( WinBits nWinBits )
+{
+ // Set default WinBits
+ if ( !(nWinBits & WB_VERT) )
+ {
+ nWinBits |= WB_HORZ;
+
+ // RTL: no UI mirroring for horizontal rulers, because
+ // the document is also not mirrored
+ EnableRTL( false );
+ }
+
+ // Initialize variables
+ mnWinStyle = nWinBits; // Window-Style
+ mnBorderOff = 0; // Border-Offset
+ mnWinOff = 0; // EditWinOffset
+ mnWinWidth = 0; // EditWinWidth
+ mnWidth = 0; // Window width
+ mnHeight = 0; // Window height
+ mnVirOff = 0; // Offset of VirtualDevice from top-left corner
+ mnVirWidth = 0; // width or height from VirtualDevice
+ mnVirHeight = 0; // height of width from VirtualDevice
+ mnDragPos = 0; // Drag-Position (Null point)
+ mnDragAryPos = 0; // Drag-Array-Index
+ mnDragSize = RulerDragSize::Move; // Did size change at dragging
+ mnDragModifier = 0; // Modifier key at dragging
+ mnExtraStyle = 0; // Style of Extra field
+ mnCharWidth = 371;
+ mnLineHeight = 551;
+ mbCalc = true; // Should recalculate page width
+ mbFormat = true; // Should redraw
+ mbDrag = false; // Currently at dragging
+ mbDragDelete = false; // Has mouse left the dragging area
+ mbDragCanceled = false; // Dragging cancelled?
+ mbAutoWinWidth = true; // EditWinWidth == RulerWidth
+ mbActive = true; // Is ruler active
+ mnUpdateFlags = 0; // What needs to be updated
+ mpData = mpSaveData.get(); // Pointer to normal data
+ meExtraType = RulerExtra::DontKnow; // What is in extra field
+ meDragType = RulerType::DontKnow; // Which element is dragged
+
+ // Initialize Units
+ mnUnitIndex = RULER_UNIT_CM;
+ meUnit = FieldUnit::CM;
+ maZoom = Fraction( 1, 1 );
+
+ // Recalculate border widths
+ if ( nWinBits & WB_BORDER )
+ mnBorderWidth = 1;
+ else
+ mnBorderWidth = 0;
+
+ // Settings
+ ImplInitSettings( true, true, true );
+
+ // Setup the default size
+ tools::Rectangle aRect;
+ GetOutDev()->GetTextBoundRect( aRect, "0123456789" );
+ tools::Long nDefHeight = aRect.GetHeight() + RULER_OFF * 2 + ruler_tab.textoff * 2 + mnBorderWidth;
+
+ Size aDefSize;
+ if ( nWinBits & WB_HORZ )
+ aDefSize.setHeight( nDefHeight );
+ else
+ aDefSize.setWidth( nDefHeight );
+ SetOutputSizePixel( aDefSize );
+ SetType(WindowType::RULER);
+}
+
+Ruler::Ruler( vcl::Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, nWinStyle & WB_3DLOOK ),
+ maVirDev( VclPtr<VirtualDevice>::Create(*GetOutDev()) ),
+ maMapMode( MapUnit::Map100thMM ),
+ mpSaveData(new ImplRulerData),
+ mpData(nullptr),
+ mpDragData(new ImplRulerData)
+{
+ // Check to see if the ruler constructor has
+ // already been called before otherwise
+ // we end up with over-scaled elements
+ if (ruler_tab.DPIScaleFactor == 0)
+ {
+ ruler_tab.DPIScaleFactor = GetDPIScaleFactor();
+ ruler_tab.width *= ruler_tab.DPIScaleFactor;
+ ruler_tab.height *= ruler_tab.DPIScaleFactor;
+ ruler_tab.height2 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.width2 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.cwidth *= ruler_tab.DPIScaleFactor;
+ ruler_tab.cwidth2 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.cwidth3 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.cwidth4 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.dheight *= ruler_tab.DPIScaleFactor;
+ ruler_tab.dheight2 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.dwidth *= ruler_tab.DPIScaleFactor;
+ ruler_tab.dwidth2 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.dwidth3 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.dwidth4 *= ruler_tab.DPIScaleFactor;
+ ruler_tab.textoff *= ruler_tab.DPIScaleFactor;
+ }
+
+
+ ImplInit( nWinStyle );
+}
+
+Ruler::~Ruler()
+{
+ disposeOnce();
+}
+
+void Ruler::dispose()
+{
+ mpSaveData.reset();
+ mpDragData.reset();
+ mxAccContext.clear();
+ Window::dispose();
+}
+
+void Ruler::ImplVDrawLine(vcl::RenderContext& rRenderContext, tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2)
+{
+ if ( nX1 < -RULER_CLIP )
+ {
+ nX1 = -RULER_CLIP;
+ if ( nX2 < -RULER_CLIP )
+ return;
+ }
+ tools::Long nClip = mnVirWidth + RULER_CLIP;
+ if ( nX2 > nClip )
+ {
+ nX2 = nClip;
+ if ( nX1 > nClip )
+ return;
+ }
+
+ if ( mnWinStyle & WB_HORZ )
+ rRenderContext.DrawLine( Point( nX1, nY1 ), Point( nX2, nY2 ) );
+ else
+ rRenderContext.DrawLine( Point( nY1, nX1 ), Point( nY2, nX2 ) );
+}
+
+void Ruler::ImplVDrawRect(vcl::RenderContext& rRenderContext, tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2)
+{
+ if ( nX1 < -RULER_CLIP )
+ {
+ nX1 = -RULER_CLIP;
+ if ( nX2 < -RULER_CLIP )
+ return;
+ }
+ tools::Long nClip = mnVirWidth + RULER_CLIP;
+ if ( nX2 > nClip )
+ {
+ nX2 = nClip;
+ if ( nX1 > nClip )
+ return;
+ }
+
+ if ( mnWinStyle & WB_HORZ )
+ rRenderContext.DrawRect(tools::Rectangle(nX1, nY1, nX2, nY2));
+ else
+ rRenderContext.DrawRect(tools::Rectangle(nY1, nX1, nY2, nX2));
+}
+
+void Ruler::ImplVDrawText(vcl::RenderContext& rRenderContext, tools::Long nX, tools::Long nY, const OUString& rText, tools::Long nMin, tools::Long nMax)
+{
+ tools::Rectangle aRect;
+ SalLayoutGlyphs* pTextLayout
+ = lcl_GetRulerTextGlyphs(rRenderContext, rText, maTextGlyphs[rText]);
+ rRenderContext.GetTextBoundRect(aRect, rText, 0, 0, -1, 0, {}, {}, pTextLayout);
+
+ tools::Long nShiftX = ( aRect.GetWidth() / 2 ) + aRect.Left();
+ tools::Long nShiftY = ( aRect.GetHeight() / 2 ) + aRect.Top();
+
+ if ( (nX > -RULER_CLIP) && (nX < mnVirWidth + RULER_CLIP) && ( nX < nMax - nShiftX ) && ( nX > nMin + nShiftX ) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ rRenderContext.DrawText(Point(nX - nShiftX, nY - nShiftY), rText, 0, -1, nullptr,
+ nullptr, pTextLayout);
+ else
+ rRenderContext.DrawText(Point(nY - nShiftX, nX - nShiftY), rText, 0, -1, nullptr,
+ nullptr, pTextLayout);
+ }
+}
+
+void Ruler::ImplInvertLines(vcl::RenderContext& rRenderContext)
+{
+ // Position lines
+ if (mpData->pLines.empty() || !mbActive || mbDrag || mbFormat || (mnUpdateFlags & RULER_UPDATE_LINES) )
+ return;
+
+ tools::Long nNullWinOff = mpData->nNullVirOff + mnVirOff;
+ tools::Long nRulX1 = mpData->nRulVirOff + mnVirOff;
+ tools::Long nRulX2 = nRulX1 + mpData->nRulWidth;
+ tools::Long nY = (RULER_OFF * 2) + mnVirHeight - 1;
+
+ // Calculate rectangle
+ tools::Rectangle aRect;
+ if (mnWinStyle & WB_HORZ)
+ aRect.SetBottom( nY );
+ else
+ aRect.SetRight( nY );
+
+ // Draw lines
+ for (const RulerLine & rLine : mpData->pLines)
+ {
+ const tools::Long n = rLine.nPos + nNullWinOff;
+ if ((n >= nRulX1) && (n < nRulX2))
+ {
+ if (mnWinStyle & WB_HORZ )
+ {
+ aRect.SetLeft( n );
+ aRect.SetRight( n );
+ }
+ else
+ {
+ aRect.SetTop( n );
+ aRect.SetBottom( n );
+ }
+ tools::Rectangle aTempRect = aRect;
+
+ if (mnWinStyle & WB_HORZ)
+ aTempRect.SetBottom( RULER_OFF - 1 );
+ else
+ aTempRect.SetRight( RULER_OFF - 1 );
+
+ rRenderContext.Erase(aTempRect);
+
+ if (mnWinStyle & WB_HORZ)
+ {
+ aTempRect.SetBottom( aRect.Bottom() );
+ aTempRect.SetTop( aTempRect.Bottom() - RULER_OFF + 1 );
+ }
+ else
+ {
+ aTempRect.SetRight( aRect.Right() );
+ aTempRect.SetLeft( aTempRect.Right() - RULER_OFF + 1 );
+ }
+ rRenderContext.Erase(aTempRect);
+ GetOutDev()->Invert(aRect);
+ }
+ }
+ mnUpdateFlags = 0;
+}
+
+void Ruler::ImplDrawTicks(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nStart, tools::Long nTop, tools::Long nBottom)
+{
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ double nCenter = nTop + ((nBottom - nTop) / 2);
+
+ tools::Long nTickLength3 = (nBottom - nTop) * 0.5;
+ tools::Long nTickLength2 = nTickLength3 * 0.66;
+ tools::Long nTickLength1 = nTickLength2 * 0.66;
+
+ tools::Long nScale = ruler_tab.DPIScaleFactor;
+ tools::Long DPIOffset = nScale - 1;
+
+ double nTick4 = aImplRulerUnitTab[mnUnitIndex].nTick4;
+ double nTick2 = 0;
+ double nTickCount = aImplRulerUnitTab[mnUnitIndex].nTick1 / nScale;
+ double nTickUnit = 0;
+ tools::Long nTickWidth;
+ bool bNoTicks = false;
+
+ Size aPixSize = rRenderContext.LogicToPixel(Size(nTick4, nTick4), maMapMode);
+
+ if (mnUnitIndex == RULER_UNIT_CHAR)
+ {
+ if (mnCharWidth == 0)
+ mnCharWidth = 371;
+ nTick4 = mnCharWidth * 2;
+ nTick2 = mnCharWidth;
+ nTickCount = mnCharWidth;
+ nTickUnit = mnCharWidth;
+ }
+ else if (mnUnitIndex == RULER_UNIT_LINE)
+ {
+ if (mnLineHeight == 0)
+ mnLineHeight = 551;
+ nTick4 = mnLineHeight * 2;
+ nTick2 = mnLineHeight;
+ nTickUnit = mnLineHeight;
+ nTickCount = mnLineHeight;
+ }
+
+ if (mnWinStyle & WB_HORZ)
+ {
+ nTickWidth = aPixSize.Width();
+ }
+ else
+ {
+ vcl::Font aFont = rRenderContext.GetFont();
+ if (mnWinStyle & WB_RIGHT_ALIGNED)
+ aFont.SetOrientation(2700_deg10);
+ else
+ aFont.SetOrientation(900_deg10);
+ rRenderContext.SetFont(aFont);
+ nTickWidth = aPixSize.Height();
+ }
+
+ tools::Long nMaxWidth = rRenderContext.PixelToLogic(Size(mpData->nPageWidth, 0), maMapMode).Width();
+ if (nMaxWidth < 0)
+ nMaxWidth = -nMaxWidth;
+
+ if ((mnUnitIndex == RULER_UNIT_CHAR) || (mnUnitIndex == RULER_UNIT_LINE))
+ nMaxWidth /= nTickUnit;
+ else
+ nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
+
+ OUString aNumString = OUString::number(nMaxWidth);
+ tools::Long nTxtWidth = rRenderContext.GetTextWidth( aNumString );
+ const tools::Long nTextOff = 4;
+
+ // Determine the number divider for ruler drawn numbers - means which numbers
+ // should be shown on the ruler and which should be skipped because the ruler
+ // is not big enough to draw them
+ if (nTickWidth < nTxtWidth + nTextOff)
+ {
+ // Calculate the scale of the ruler
+ tools::Long nMulti = 1;
+ tools::Long nOrgTick4 = nTick4;
+
+ while (nTickWidth < nTxtWidth + nTextOff)
+ {
+ tools::Long nOldMulti = nMulti;
+ if (nTickWidth == 0)
+ nMulti *= 10;
+ else if (nMulti < 10)
+ nMulti++;
+ else if (nMulti < 100)
+ nMulti += 10;
+ else if (nMulti < 1000)
+ nMulti += 100;
+ else
+ nMulti += 1000;
+
+ // Overflow - in this case don't draw ticks and exit
+ if (nMulti < nOldMulti)
+ {
+ bNoTicks = true;
+ break;
+ }
+
+ nTick4 = nOrgTick4 * nMulti;
+ aPixSize = rRenderContext.LogicToPixel(Size(nTick4, nTick4), maMapMode);
+ if (mnWinStyle & WB_HORZ)
+ nTickWidth = aPixSize.Width();
+ else
+ nTickWidth = aPixSize.Height();
+ }
+ nTickCount = nTick4;
+ }
+ else
+ {
+ rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
+ }
+
+ if (bNoTicks)
+ return;
+
+ tools::Long n = 0;
+ double nTick = 0.0;
+ double nTick3 = 0;
+
+ if ((mnUnitIndex != RULER_UNIT_CHAR) && (mnUnitIndex != RULER_UNIT_LINE))
+ {
+ nTick2 = aImplRulerUnitTab[mnUnitIndex].nTick2;
+ nTick3 = aImplRulerUnitTab[mnUnitIndex].nTick3;
+ }
+
+ Size nTickGapSize;
+
+ nTickGapSize = rRenderContext.LogicToPixel(Size(nTickCount, nTickCount), maMapMode);
+ tools::Long nTickGap1 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
+ nTickGapSize = rRenderContext.LogicToPixel(Size(nTick2, nTick2), maMapMode);
+ tools::Long nTickGap2 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
+ nTickGapSize = rRenderContext.LogicToPixel(Size(nTick3, nTick3), maMapMode);
+ tools::Long nTickGap3 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
+
+ while (((nStart - n) >= nMin) || ((nStart + n) <= nMax))
+ {
+ // Null point
+ if (nTick == 0.0)
+ {
+ if (nStart > nMin)
+ {
+ // 0 is only painted when Margin1 is not equal to zero
+ if ((mpData->nMargin1Style & RulerMarginStyle::Invisible) || (mpData->nMargin1 != 0))
+ {
+ aNumString = "0";
+ ImplVDrawText(rRenderContext, nStart, nCenter, aNumString);
+ }
+ }
+ }
+ else
+ {
+ aPixSize = rRenderContext.LogicToPixel(Size(nTick, nTick), maMapMode);
+
+ if (mnWinStyle & WB_HORZ)
+ n = aPixSize.Width();
+ else
+ n = aPixSize.Height();
+
+ // Tick4 - Output (Text)
+ double aStep = nTick / nTick4;
+ double aRest = std::abs(aStep - std::floor(aStep));
+ double nAcceptanceDelta = 0.0001;
+ rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
+
+ if (aRest < nAcceptanceDelta)
+ {
+ if ((mnUnitIndex == RULER_UNIT_CHAR) || (mnUnitIndex == RULER_UNIT_LINE))
+ aNumString = OUString::number(nTick / nTickUnit);
+ else
+ aNumString = OUString::number(nTick / aImplRulerUnitTab[mnUnitIndex].nTickUnit);
+
+ tools::Long nHorizontalLocation = nStart + n;
+ ImplVDrawText(rRenderContext, nHorizontalLocation, nCenter, aNumString, nMin, nMax);
+
+ if (nMin < nHorizontalLocation && nHorizontalLocation < nMax)
+ {
+ ImplVDrawRect(rRenderContext, nHorizontalLocation, nBottom - 1 * nScale, nHorizontalLocation + DPIOffset, nBottom);
+ ImplVDrawRect(rRenderContext, nHorizontalLocation, nTop, nHorizontalLocation + DPIOffset, nTop + 1 * nScale);
+ }
+
+ nHorizontalLocation = nStart - n;
+ ImplVDrawText(rRenderContext, nHorizontalLocation, nCenter, aNumString, nMin, nMax);
+
+ if (nMin < nHorizontalLocation && nHorizontalLocation < nMax)
+ {
+ ImplVDrawRect(rRenderContext, nHorizontalLocation, nBottom,
+ nHorizontalLocation + DPIOffset, nBottom - 1 * nScale);
+ ImplVDrawRect(rRenderContext, nHorizontalLocation, nTop,
+ nHorizontalLocation + DPIOffset, nTop + 1 * nScale);
+ }
+ }
+ // Tick/Tick2 - Output (Strokes)
+ else
+ {
+ tools::Long nTickLength = nTickLength1;
+
+ aStep = (nTick / nTick2);
+ aRest = std::abs(aStep - std::floor(aStep));
+ if (aRest < nAcceptanceDelta)
+ nTickLength = nTickLength2;
+
+ aStep = (nTick / nTick3);
+ aRest = std::abs(aStep - std::floor(aStep));
+ if (aRest < nAcceptanceDelta )
+ nTickLength = nTickLength3;
+
+ if ((nTickLength == nTickLength1 && nTickGap1 > 6) ||
+ (nTickLength == nTickLength2 && nTickGap2 > 6) ||
+ (nTickLength == nTickLength3 && nTickGap3 > 6))
+ {
+ tools::Long nT1 = nCenter - (nTickLength / 2.0);
+ tools::Long nT2 = nT1 + nTickLength - 1;
+ tools::Long nT;
+
+ nT = nStart + n;
+
+ if (nT < nMax)
+ ImplVDrawRect(rRenderContext, nT, nT1, nT + DPIOffset, nT2);
+ nT = nStart - n;
+ if (nT > nMin)
+ ImplVDrawRect(rRenderContext, nT, nT1, nT + DPIOffset, nT2);
+ }
+ }
+ }
+ nTick += nTickCount;
+ }
+}
+
+void Ruler::ImplDrawBorders(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom)
+{
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ tools::Long n;
+ tools::Long n1;
+ tools::Long n2;
+ tools::Long nTemp1;
+ tools::Long nTemp2;
+
+ for (std::vector<RulerBorder>::size_type i = 0; i < mpData->pBorders.size(); i++)
+ {
+ if (mpData->pBorders[i].nStyle & RulerBorderStyle::Invisible)
+ continue;
+
+ n1 = mpData->pBorders[i].nPos + mpData->nNullVirOff;
+ n2 = n1 + mpData->pBorders[i].nWidth;
+
+ if (((n1 >= nMin) && (n1 <= nMax)) || ((n2 >= nMin) && (n2 <= nMax)))
+ {
+ if ((n2 - n1) > 3)
+ {
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
+ ImplVDrawRect(rRenderContext, n1, nVirTop, n2, nVirBottom);
+
+ rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
+ ImplVDrawLine(rRenderContext, n1 + 1, nVirTop, n1 + 1, nVirBottom);
+ ImplVDrawLine(rRenderContext, n1, nVirTop, n2, nVirTop);
+
+ rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
+ ImplVDrawLine(rRenderContext, n1, nVirTop, n1, nVirBottom);
+ ImplVDrawLine(rRenderContext, n1, nVirBottom, n2, nVirBottom);
+ ImplVDrawLine(rRenderContext, n2 - 1, nVirTop, n2 - 1, nVirBottom);
+
+ rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
+ ImplVDrawLine(rRenderContext, n2, nVirTop, n2, nVirBottom);
+
+ if (mpData->pBorders[i].nStyle & RulerBorderStyle::Variable)
+ {
+ if (n2 - n1 > RULER_VAR_SIZE + 4)
+ {
+ nTemp1 = n1 + (((n2 - n1 + 1) - RULER_VAR_SIZE) / 2);
+ nTemp2 = nVirTop + (((nVirBottom - nVirTop + 1) - RULER_VAR_SIZE) / 2);
+ tools::Long nTemp3 = nTemp1 + RULER_VAR_SIZE - 1;
+ tools::Long nTemp4 = nTemp2 + RULER_VAR_SIZE - 1;
+ tools::Long nTempY = nTemp2;
+
+ rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
+ while (nTempY <= nTemp4)
+ {
+ ImplVDrawLine(rRenderContext, nTemp1, nTempY, nTemp3, nTempY);
+ nTempY += 2;
+ }
+
+ nTempY = nTemp2 + 1;
+ rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
+ while (nTempY <= nTemp4)
+ {
+ ImplVDrawLine(rRenderContext, nTemp1, nTempY, nTemp3, nTempY);
+ nTempY += 2;
+ }
+ }
+ }
+
+ if (mpData->pBorders[i].nStyle & RulerBorderStyle::Sizeable)
+ {
+ if (n2 - n1 > RULER_VAR_SIZE + 10)
+ {
+ rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
+ ImplVDrawLine(rRenderContext, n1 + 4, nVirTop + 3, n1 + 4, nVirBottom - 3);
+ ImplVDrawLine(rRenderContext, n2 - 5, nVirTop + 3, n2 - 5, nVirBottom - 3);
+ rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
+ ImplVDrawLine(rRenderContext, n1 + 5, nVirTop + 3, n1 + 5, nVirBottom - 3);
+ ImplVDrawLine(rRenderContext, n2 - 4, nVirTop + 3, n2 - 4, nVirBottom - 3);
+ }
+ }
+ }
+ else
+ {
+ n = n1 + ((n2 - n1) / 2);
+ rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
+
+ ImplVDrawLine(rRenderContext, n - 1, nVirTop, n - 1, nVirBottom);
+ ImplVDrawLine(rRenderContext, n + 1, nVirTop, n + 1, nVirBottom);
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rStyleSettings.GetWindowColor());
+ ImplVDrawRect(rRenderContext, n, nVirTop, n, nVirBottom);
+ }
+ }
+ }
+}
+
+void Ruler::ImplDrawIndent(vcl::RenderContext& rRenderContext, const tools::Polygon& rPoly, bool bIsHit)
+{
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+
+ rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
+ rRenderContext.SetFillColor(bIsHit ? rStyleSettings.GetDarkShadowColor() : rStyleSettings.GetWorkspaceColor());
+ tools::Polygon aPolygon(rPoly);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+ rRenderContext.DrawPolygon(aPolygon);
+}
+
+void Ruler::ImplDrawIndents(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom)
+{
+ tools::Long n;
+ tools::Long nIndentHeight = (mnVirHeight / 2) - 1;
+ tools::Long nIndentWidth2 = nIndentHeight-3;
+
+ tools::Polygon aPoly(5);
+
+ for (std::vector<RulerIndent>::size_type j = 0; j < mpData->pIndents.size(); j++)
+ {
+ if (mpData->pIndents[j].bInvisible)
+ continue;
+
+ RulerIndentStyle nIndentStyle = mpData->pIndents[j].nStyle;
+
+ n = mpData->pIndents[j].nPos+mpData->nNullVirOff;
+
+ if ((n >= nMin) && (n <= nMax))
+ {
+ if (nIndentStyle == RulerIndentStyle::Bottom)
+ {
+ aPoly.SetPoint(Point(n + 0, nVirBottom - nIndentHeight), 0);
+ aPoly.SetPoint(Point(n - nIndentWidth2, nVirBottom - 3), 1);
+ aPoly.SetPoint(Point(n - nIndentWidth2, nVirBottom), 2);
+ aPoly.SetPoint(Point(n + nIndentWidth2, nVirBottom), 3);
+ aPoly.SetPoint(Point(n + nIndentWidth2, nVirBottom - 3), 4);
+ }
+ else
+ {
+ aPoly.SetPoint(Point(n + 0, nVirTop + nIndentHeight), 0);
+ aPoly.SetPoint(Point(n - nIndentWidth2, nVirTop + 3), 1);
+ aPoly.SetPoint(Point(n - nIndentWidth2, nVirTop), 2);
+ aPoly.SetPoint(Point(n + nIndentWidth2, nVirTop), 3);
+ aPoly.SetPoint(Point(n + nIndentWidth2, nVirTop + 3), 4);
+ }
+
+ if (0 == (mnWinStyle & WB_HORZ))
+ {
+ Point aTmp;
+ for (sal_uInt16 i = 0; i < 5; i++)
+ {
+ aTmp = aPoly[i];
+ Point aSet(nVirBottom - aTmp.Y(), aTmp.X());
+ aPoly[i] = aSet;
+ }
+ }
+ bool bIsHit = false;
+ if (mxCurrentHitTest != nullptr && mxCurrentHitTest->eType == RulerType::Indent)
+ {
+ bIsHit = mxCurrentHitTest->nAryPos == j;
+ }
+ else if(mbDrag && meDragType == RulerType::Indent)
+ {
+ bIsHit = mnDragAryPos == j;
+ }
+ ImplDrawIndent(rRenderContext, aPoly, bIsHit);
+ }
+ }
+}
+
+static void ImplCenterTabPos(Point& rPos, sal_uInt16 nTabStyle)
+{
+ bool bRTL = 0 != (nTabStyle & RULER_TAB_RTL);
+ nTabStyle &= RULER_TAB_STYLE;
+ rPos.AdjustY(ruler_tab.height/2 );
+
+ if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||
+ ( bRTL && nTabStyle == RULER_TAB_RIGHT) )
+ {
+ rPos.AdjustX( -(ruler_tab.width / 2) );
+ }
+ else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||
+ ( bRTL && nTabStyle == RULER_TAB_LEFT) )
+ {
+ rPos.AdjustX(ruler_tab.width / 2 );
+ }
+}
+
+static void lcl_RotateRect_Impl(tools::Rectangle& rRect, const tools::Long nReference, bool bRightAligned)
+{
+ if (rRect.IsEmpty())
+ return;
+
+ tools::Rectangle aTmp(rRect);
+ rRect.SetTop( aTmp.Left() );
+ rRect.SetBottom( aTmp.Right() );
+ rRect.SetLeft( aTmp.Top() );
+ rRect.SetRight( aTmp.Bottom() );
+
+ if (bRightAligned)
+ {
+ tools::Long nRef = 2 * nReference;
+ rRect.SetLeft( nRef - rRect.Left() );
+ rRect.SetRight( nRef - rRect.Right() );
+ }
+}
+
+static void ImplDrawRulerTab(vcl::RenderContext& rRenderContext, const Point& rPos,
+ sal_uInt16 nStyle, WinBits nWinBits)
+{
+ if (nStyle & RULER_STYLE_INVISIBLE)
+ return;
+
+ sal_uInt16 nTabStyle = nStyle & RULER_TAB_STYLE;
+ bool bRTL = 0 != (nStyle & RULER_TAB_RTL);
+
+ // Scale by the screen DPI scaling factor
+ // However when doing this some of the rectangles
+ // drawn become asymmetric due to the +1 offsets
+ sal_uInt16 DPIOffset = rRenderContext.GetDPIScaleFactor() - 1;
+
+ // A tabstop is drawn using three rectangles
+ tools::Rectangle aRect1; // A horizontal short line
+ tools::Rectangle aRect2; // A vertical short line
+ tools::Rectangle aRect3; // A small square
+
+ aRect3.SetEmpty();
+
+ if (nTabStyle == RULER_TAB_DEFAULT)
+ {
+ aRect1.SetLeft( rPos.X() - ruler_tab.dwidth2 + 1 );
+ aRect1.SetTop( rPos.Y() - ruler_tab.dheight2 + 1 );
+ aRect1.SetRight( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth + DPIOffset );
+ aRect1.SetBottom( rPos.Y() );
+
+ aRect2.SetLeft( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth3 );
+ aRect2.SetTop( rPos.Y() - ruler_tab.dheight + 1 );
+ aRect2.SetRight( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth3 + ruler_tab.dwidth4 - 1 );
+ aRect2.SetBottom( rPos.Y() );
+
+ }
+ else if ((!bRTL && nTabStyle == RULER_TAB_LEFT) || (bRTL && nTabStyle == RULER_TAB_RIGHT))
+ {
+ aRect1.SetLeft( rPos.X() );
+ aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
+ aRect1.SetRight( rPos.X() + ruler_tab.width - 1 );
+ aRect1.SetBottom( rPos.Y() );
+
+ aRect2.SetLeft( rPos.X() );
+ aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
+ aRect2.SetRight( rPos.X() + ruler_tab.width2 - 1 );
+ aRect2.SetBottom( rPos.Y() );
+ }
+ else if ((!bRTL && nTabStyle == RULER_TAB_RIGHT) || (bRTL && nTabStyle == RULER_TAB_LEFT))
+ {
+ aRect1.SetLeft( rPos.X() - ruler_tab.width + 1 );
+ aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
+ aRect1.SetRight( rPos.X() );
+ aRect1.SetBottom( rPos.Y() );
+
+ aRect2.SetLeft( rPos.X() - ruler_tab.width2 + 1 );
+ aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
+ aRect2.SetRight( rPos.X() );
+ aRect2.SetBottom( rPos.Y() );
+ }
+ else
+ {
+ aRect1.SetLeft( rPos.X() - ruler_tab.cwidth2 + 1 );
+ aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
+ aRect1.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth + DPIOffset );
+ aRect1.SetBottom( rPos.Y() );
+
+ aRect2.SetLeft( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth3 );
+ aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
+ aRect2.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth3 + ruler_tab.cwidth4 - 1 );
+ aRect2.SetBottom( rPos.Y() );
+
+ if (nTabStyle == RULER_TAB_DECIMAL)
+ {
+ aRect3.SetLeft( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth - 1 );
+ aRect3.SetTop( rPos.Y() - ruler_tab.height + 1 + 1 - DPIOffset );
+ aRect3.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth + DPIOffset );
+ aRect3.SetBottom( rPos.Y() - ruler_tab.height + 1 + 2 );
+ }
+ }
+ if (0 == (nWinBits & WB_HORZ))
+ {
+ bool bRightAligned = 0 != (nWinBits & WB_RIGHT_ALIGNED);
+ lcl_RotateRect_Impl(aRect1, rPos.Y(), bRightAligned);
+ lcl_RotateRect_Impl(aRect2, rPos.Y(), bRightAligned);
+ lcl_RotateRect_Impl(aRect3, rPos.Y(), bRightAligned);
+ }
+ rRenderContext.DrawRect(aRect1);
+ rRenderContext.DrawRect(aRect2);
+
+ if (!aRect3.IsEmpty())
+ rRenderContext.DrawRect(aRect3);
+}
+
+void Ruler::ImplDrawTab(vcl::RenderContext& rRenderContext, const Point& rPos, sal_uInt16 nStyle)
+{
+ if (nStyle & RULER_STYLE_INVISIBLE)
+ return;
+
+ rRenderContext.SetLineColor();
+
+ if (nStyle & RULER_STYLE_DONTKNOW)
+ rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetFaceColor());
+ else
+ rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetDarkShadowColor());
+
+ if (mpData->bTextRTL)
+ nStyle |= RULER_TAB_RTL;
+
+ ImplDrawRulerTab(rRenderContext, rPos, nStyle, GetStyle());
+}
+
+void Ruler::ImplDrawTabs(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom)
+{
+ for (const RulerTab & rTab : mpData->pTabs)
+ {
+ if (rTab.nStyle & RULER_STYLE_INVISIBLE)
+ continue;
+
+ tools::Long aPosition;
+ aPosition = rTab.nPos;
+ aPosition += +mpData->nNullVirOff;
+ tools::Long nTopBottom = (GetStyle() & WB_RIGHT_ALIGNED) ? nVirTop : nVirBottom;
+ if (nMin <= aPosition && aPosition <= nMax)
+ ImplDrawTab(rRenderContext, Point( aPosition, nTopBottom ), rTab.nStyle);
+ }
+}
+
+static int adjustSize(int nOrig)
+{
+ if (nOrig <= 0)
+ return 0;
+
+ // make sure we return an odd number, that looks better in the ruler
+ return ( (3*nOrig) / 8) * 2 + 1;
+}
+
+void Ruler::ApplySettings(vcl::RenderContext& rRenderContext)
+{
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+
+ vcl::Font aFont = rStyleSettings.GetToolFont();
+ // make the font a bit smaller than default
+ Size aSize(adjustSize(aFont.GetFontSize().Width()), adjustSize(aFont.GetFontSize().Height()));
+ aFont.SetFontSize(aSize);
+
+ ApplyControlFont(rRenderContext, aFont);
+
+ ApplyControlForeground(*GetOutDev(), rStyleSettings.GetDarkShadowColor());
+ SetTextFillColor();
+
+ Color aColor;
+ svtools::ColorConfig aColorConfig;
+ aColor = aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
+ ApplyControlBackground(rRenderContext, aColor);
+ // A hack to get it to change the non-ruler application background to change immediately
+ if (aColor != maVirDev->GetBackground().GetColor())
+ {
+ maVirDev->SetBackground(aColor);
+ Resize();
+ }
+}
+
+void Ruler::ImplInitSettings(bool bFont, bool bForeground, bool bBackground)
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if (bFont)
+ {
+ vcl::Font aFont = rStyleSettings.GetToolFont();
+ // make the font a bit smaller than default
+ Size aSize(adjustSize(aFont.GetFontSize().Width()), adjustSize(aFont.GetFontSize().Height()));
+ aFont.SetFontSize(aSize);
+
+ ApplyControlFont(*GetOutDev(), aFont);
+ }
+
+ if (bForeground || bFont)
+ {
+ ApplyControlForeground(*GetOutDev(), rStyleSettings.GetDarkShadowColor());
+ SetTextFillColor();
+ }
+
+ if (bBackground)
+ {
+ Color aColor;
+ svtools::ColorConfig aColorConfig;
+ aColor = aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
+ ApplyControlBackground(*GetOutDev(), aColor);
+ }
+
+ maVirDev->SetSettings( GetSettings() );
+ maVirDev->SetBackground( GetBackground() );
+ vcl::Font aFont = GetFont();
+
+ if (mnWinStyle & WB_VERT)
+ aFont.SetOrientation(900_deg10);
+
+ maVirDev->SetFont(aFont);
+ maVirDev->SetTextColor(GetTextColor());
+ maVirDev->SetTextFillColor(GetTextFillColor());
+}
+
+void Ruler::ImplCalc()
+{
+ // calculate offset
+ mpData->nRulVirOff = mnWinOff + mpData->nPageOff;
+ if ( mpData->nRulVirOff > mnVirOff )
+ mpData->nRulVirOff -= mnVirOff;
+ else
+ mpData->nRulVirOff = 0;
+ tools::Long nRulWinOff = mpData->nRulVirOff+mnVirOff;
+
+ // calculate non-visual part of the page
+ tools::Long nNotVisPageWidth;
+ if ( mpData->nPageOff < 0 )
+ {
+ nNotVisPageWidth = -(mpData->nPageOff);
+ if ( nRulWinOff < mnWinOff )
+ nNotVisPageWidth -= mnWinOff-nRulWinOff;
+ }
+ else
+ nNotVisPageWidth = 0;
+
+ // calculate width
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( mbAutoWinWidth )
+ mnWinWidth = mnWidth - mnVirOff;
+ if ( mpData->bAutoPageWidth )
+ mpData->nPageWidth = mnWinWidth;
+ mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
+ if ( nRulWinOff+mpData->nRulWidth > mnWidth )
+ mpData->nRulWidth = mnWidth-nRulWinOff;
+ }
+ else
+ {
+ if ( mbAutoWinWidth )
+ mnWinWidth = mnHeight - mnVirOff;
+ if ( mpData->bAutoPageWidth )
+ mpData->nPageWidth = mnWinWidth;
+ mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
+ if ( nRulWinOff+mpData->nRulWidth > mnHeight )
+ mpData->nRulWidth = mnHeight-nRulWinOff;
+ }
+
+ mbCalc = false;
+}
+
+void Ruler::ImplFormat(vcl::RenderContext const & rRenderContext)
+{
+ // if already formatted, don't do it again
+ if (!mbFormat)
+ return;
+
+ // don't do anything if the window still has no size
+ if (!mnVirWidth)
+ return;
+
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ tools::Long nP1; // pixel position of Page1
+ tools::Long nP2; // pixel position of Page2
+ tools::Long nM1; // pixel position of Margin1
+ tools::Long nM2; // pixel position of Margin2
+ tools::Long nVirTop; // top/left corner
+ tools::Long nVirBottom; // bottom/right corner
+ tools::Long nVirLeft; // left/top corner
+ tools::Long nVirRight; // right/bottom corner
+ tools::Long nNullVirOff; // for faster calculation
+
+ // calculate values
+ if (mbCalc)
+ ImplCalc();
+
+ mpData->nNullVirOff = mnWinOff + mpData->nPageOff + mpData->nNullOff - mnVirOff;
+
+ nNullVirOff = mpData->nNullVirOff;
+ nVirLeft = mpData->nRulVirOff;
+ nVirRight = nVirLeft + mpData->nRulWidth - 1;
+ nVirTop = 0;
+ nVirBottom = mnVirHeight - 1;
+
+ if (!IsReallyVisible())
+ return;
+
+ Size aVirDevSize;
+
+ // initialize VirtualDevice
+ if (mnWinStyle & WB_HORZ)
+ {
+ aVirDevSize.setWidth( mnVirWidth );
+ aVirDevSize.setHeight( mnVirHeight );
+ }
+ else
+ {
+ aVirDevSize.setHeight( mnVirWidth );
+ aVirDevSize.setWidth( mnVirHeight );
+ }
+ if (aVirDevSize != maVirDev->GetOutputSizePixel())
+ maVirDev->SetOutputSizePixel(aVirDevSize);
+ else
+ maVirDev->Erase();
+
+ // calculate margins
+ if (!(mpData->nMargin1Style & RulerMarginStyle::Invisible))
+ {
+ nM1 = mpData->nMargin1 + nNullVirOff;
+ if (mpData->bAutoPageWidth)
+ {
+ nP1 = nVirLeft;
+ if (nM1 < nVirLeft)
+ nP1--;
+ }
+ else
+ nP1 = nNullVirOff - mpData->nNullOff;
+ }
+ else
+ {
+ nM1 = nVirLeft-1;
+ nP1 = nM1;
+ }
+ if (!(mpData->nMargin2Style & RulerMarginStyle::Invisible))
+ {
+ nM2 = mpData->nMargin2 + nNullVirOff;
+ if (mpData->bAutoPageWidth)
+ {
+ nP2 = nVirRight;
+ if (nM2 > nVirRight)
+ nP2++;
+ }
+ else
+ nP2 = nNullVirOff - mpData->nNullOff + mpData->nPageWidth;
+ if (nM2 > nP2)
+ nM2 = nP2;
+ }
+ else
+ {
+ nM2 = nVirRight+1;
+ nP2 = nM2;
+ }
+
+ // top/bottom border
+ maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
+ ImplVDrawLine(*maVirDev, nVirLeft, nVirTop + 1, nM1, nVirTop + 1); //top left line
+ ImplVDrawLine(*maVirDev, nM2, nVirTop + 1, nP2 - 1, nVirTop + 1); //top right line
+
+ nVirTop++;
+ nVirBottom--;
+
+ // draw margin1, margin2 and in-between
+ maVirDev->SetLineColor();
+ maVirDev->SetFillColor(rStyleSettings.GetDialogColor());
+ if (nM1 > nVirLeft)
+ ImplVDrawRect(*maVirDev, nP1, nVirTop + 1, nM1, nVirBottom); //left gray rectangle
+ if (nM2 < nP2)
+ ImplVDrawRect(*maVirDev, nM2, nVirTop + 1, nP2, nVirBottom); //right gray rectangle
+ if (nM2 - nM1 > 0)
+ {
+ maVirDev->SetFillColor(rStyleSettings.GetWindowColor());
+ ImplVDrawRect(*maVirDev, nM1 + 1, nVirTop, nM2 - 1, nVirBottom); //center rectangle
+ }
+ maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
+ if (nM1 > nVirLeft)
+ {
+ ImplVDrawLine(*maVirDev, nM1, nVirTop + 1, nM1, nVirBottom); //right line of the left rectangle
+ ImplVDrawLine(*maVirDev, nP1, nVirBottom, nM1, nVirBottom); //bottom line of the left rectangle
+ if (nP1 >= nVirLeft)
+ {
+ ImplVDrawLine(*maVirDev, nP1, nVirTop + 1, nP1, nVirBottom); //left line of the left rectangle
+ ImplVDrawLine(*maVirDev, nP1, nVirBottom, nP1 + 1, nVirBottom); //?
+ }
+ }
+ if (nM2 < nP2)
+ {
+ ImplVDrawLine(*maVirDev, nM2, nVirBottom, nP2 - 1, nVirBottom); //bottom line of the right rectangle
+ ImplVDrawLine(*maVirDev, nM2, nVirTop + 1, nM2, nVirBottom); //left line of the right rectangle
+ if (nP2 <= nVirRight + 1)
+ ImplVDrawLine(*maVirDev, nP2 - 1, nVirTop + 1, nP2 - 1, nVirBottom); //right line of the right rectangle
+ }
+
+ tools::Long nMin = nVirLeft;
+ tools::Long nMax = nP2;
+ tools::Long nStart = 0;
+
+ if (mpData->bTextRTL)
+ nStart = mpData->nRightFrameMargin + nNullVirOff;
+ else
+ nStart = mpData->nLeftFrameMargin + nNullVirOff;
+
+ if (nP1 > nVirLeft)
+ nMin++;
+
+ if (nP2 < nVirRight)
+ nMax--;
+
+ // Draw captions
+ ImplDrawTicks(*maVirDev, nMin, nMax, nStart, nVirTop, nVirBottom);
+
+ // Draw borders
+ if (!mpData->pBorders.empty())
+ ImplDrawBorders(*maVirDev, nVirLeft, nP2, nVirTop, nVirBottom);
+
+ // Draw indents
+ if (!mpData->pIndents.empty())
+ ImplDrawIndents(*maVirDev, nVirLeft, nP2, nVirTop - 1, nVirBottom + 1);
+
+ // Tabs
+ if (!mpData->pTabs.empty())
+ ImplDrawTabs(*maVirDev, nVirLeft, nP2, nVirTop-1, nVirBottom + 1);
+
+ mbFormat = false;
+}
+
+void Ruler::ImplInitExtraField( bool bUpdate )
+{
+ Size aWinSize = GetOutputSizePixel();
+
+ // extra field evaluate
+ if ( mnWinStyle & WB_EXTRAFIELD )
+ {
+ maExtraRect.SetLeft( RULER_OFF );
+ maExtraRect.SetTop( RULER_OFF );
+ maExtraRect.SetRight( RULER_OFF + mnVirHeight - 1 );
+ maExtraRect.SetBottom( RULER_OFF + mnVirHeight - 1 );
+ if(mpData->bTextRTL)
+ {
+ if(mnWinStyle & WB_HORZ)
+ maExtraRect.Move(aWinSize.Width() - maExtraRect.GetWidth() - maExtraRect.Left(), 0);
+ else
+ maExtraRect.Move(0, aWinSize.Height() - maExtraRect.GetHeight() - maExtraRect.Top());
+ mnVirOff = 0;
+ }
+ else
+ mnVirOff = maExtraRect.Right()+1;
+
+ }
+ else
+ {
+ maExtraRect.SetEmpty();
+ mnVirOff = 0;
+ }
+
+ // mnVirWidth depends on mnVirOff
+ if ( (mnVirWidth > RULER_MIN_SIZE) ||
+ ((aWinSize.Width() > RULER_MIN_SIZE) && (aWinSize.Height() > RULER_MIN_SIZE)) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ mnVirWidth = aWinSize.Width()-mnVirOff;
+ else
+ mnVirWidth = aWinSize.Height()-mnVirOff;
+
+ if ( mnVirWidth < RULER_MIN_SIZE )
+ mnVirWidth = 0;
+ }
+
+ if ( bUpdate )
+ {
+ mbCalc = true;
+ mbFormat = true;
+ Invalidate();
+ }
+}
+
+void Ruler::ImplDraw(vcl::RenderContext& rRenderContext)
+{
+ if (mbFormat)
+ {
+ ImplFormat(rRenderContext);
+ }
+
+ if (!IsReallyVisible())
+ return;
+
+ // output the ruler to the virtual device
+ Point aOffPos;
+ Size aVirDevSize = maVirDev->GetOutputSizePixel();
+
+ if (mnWinStyle & WB_HORZ)
+ {
+ aOffPos.setX( mnVirOff );
+ if (mpData->bTextRTL)
+ aVirDevSize.AdjustWidth( -(maExtraRect.GetWidth()) );
+
+ aOffPos.setY( RULER_OFF );
+ }
+ else
+ {
+ aOffPos.setX( RULER_OFF );
+ aOffPos.setY( mnVirOff );
+ }
+ rRenderContext.DrawOutDev(aOffPos, aVirDevSize, Point(), aVirDevSize, *maVirDev);
+
+ // redraw positionlines
+ ImplInvertLines(rRenderContext);
+}
+
+void Ruler::ImplDrawExtra(vcl::RenderContext& rRenderContext)
+{
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ tools::Rectangle aRect = maExtraRect;
+ bool bEraseRect = false;
+
+ aRect.AdjustLeft(2 );
+ aRect.AdjustTop(2 );
+ aRect.AdjustRight( -2 );
+ aRect.AdjustBottom( -2 );
+
+ if (mnExtraStyle & RULER_STYLE_HIGHLIGHT)
+ {
+ rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
+ bEraseRect = true;
+ }
+
+ if (bEraseRect)
+ {
+ rRenderContext.SetLineColor();
+ rRenderContext.DrawRect(aRect);
+ }
+
+ // output content
+ if (meExtraType == RulerExtra::NullOffset)
+ {
+ rRenderContext.SetLineColor(rStyleSettings.GetButtonTextColor());
+ rRenderContext.DrawLine(Point(aRect.Left() + 1, aRect.Top() + 4),
+ Point(aRect.Right() - 1, aRect.Top() + 4));
+ rRenderContext.DrawLine(Point(aRect.Left() + 4, aRect.Top() + 1),
+ Point(aRect.Left() + 4, aRect.Bottom() - 1));
+ }
+ else if (meExtraType == RulerExtra::Tab)
+ {
+ sal_uInt16 nTabStyle = mnExtraStyle & RULER_TAB_STYLE;
+ if (mpData->bTextRTL)
+ nTabStyle |= RULER_TAB_RTL;
+ Point aCenter = aRect.Center();
+ Point aDraw(aCenter);
+ ImplCenterTabPos(aDraw, nTabStyle);
+ WinBits nWinBits = GetStyle();
+ if (0 == (nWinBits & WB_HORZ))
+ {
+ if ((nWinBits & WB_RIGHT_ALIGNED) != 0)
+ aDraw.setY( 2 * aCenter.Y() - aDraw.Y() );
+
+ if (mpData->bTextRTL)
+ {
+ tools::Long nTemp = aDraw.X();
+ aDraw.setX( aDraw.Y() );
+ aDraw.setY( nTemp );
+ }
+ }
+ ImplDrawTab(rRenderContext, aDraw, nTabStyle);
+ }
+}
+
+void Ruler::ImplUpdate( bool bMustCalc )
+{
+ // clear lines in this place so they aren't considered at recalculation
+ if (!mbFormat)
+ Invalidate(InvalidateFlags::NoErase);
+
+ // set flags
+ if (bMustCalc)
+ mbCalc = true;
+ mbFormat = true;
+
+ // abort if we are dragging as drag-handler will update the ruler after drag is finished
+ if (mbDrag)
+ return;
+
+ // otherwise trigger update
+ if (IsReallyVisible() && IsUpdateMode())
+ {
+ Invalidate(InvalidateFlags::NoErase);
+ }
+}
+
+bool Ruler::ImplDoHitTest( const Point& rPos, RulerSelection* pHitTest,
+ bool bRequireStyle, RulerIndentStyle nRequiredStyle ) const
+{
+ sal_Int32 i;
+ sal_uInt16 nStyle;
+ tools::Long nHitBottom;
+ tools::Long nX;
+ tools::Long nY;
+ tools::Long n1;
+
+ if ( !mbActive )
+ return false;
+
+ // determine positions
+ bool bIsHori = 0 != (mnWinStyle & WB_HORZ);
+ if ( bIsHori )
+ {
+ nX = rPos.X();
+ nY = rPos.Y();
+ }
+ else
+ {
+ nX = rPos.Y();
+ nY = rPos.X();
+ }
+ nHitBottom = mnVirHeight + (RULER_OFF * 2);
+
+ // #i32608#
+ pHitTest->nAryPos = 0;
+ pHitTest->mnDragSize = RulerDragSize::Move;
+ pHitTest->bSize = false;
+ pHitTest->bSizeBar = false;
+
+ // so that leftover tabs and indents are taken into account
+ tools::Long nXExtraOff;
+ if ( !mpData->pTabs.empty() || !mpData->pIndents.empty() )
+ nXExtraOff = (mnVirHeight / 2) - 4;
+ else
+ nXExtraOff = 0;
+
+ // test if outside
+ nX -= mnVirOff;
+ if ( (nX < mpData->nRulVirOff - nXExtraOff) ||
+ (nX > mpData->nRulVirOff + mpData->nRulWidth + nXExtraOff) ||
+ (nY < 0) ||
+ (nY > nHitBottom) )
+ {
+ pHitTest->nPos = 0;
+ pHitTest->eType = RulerType::Outside;
+ return false;
+ }
+
+ nX -= mpData->nNullVirOff;
+ pHitTest->nPos = nX;
+ pHitTest->eType = RulerType::DontKnow;
+
+ // first test the tabs
+ tools::Rectangle aRect;
+ if ( !mpData->pTabs.empty() )
+ {
+ aRect.SetBottom( nHitBottom );
+ aRect.SetTop( aRect.Bottom() - ruler_tab.height - RULER_OFF );
+
+ for ( i = mpData->pTabs.size() - 1; i >= 0; i-- )
+ {
+ nStyle = mpData->pTabs[i].nStyle;
+ if ( !(nStyle & RULER_STYLE_INVISIBLE) )
+ {
+ nStyle &= RULER_TAB_STYLE;
+
+ // default tabs are only shown (no action)
+ if ( nStyle != RULER_TAB_DEFAULT )
+ {
+ n1 = mpData->pTabs[i].nPos;
+
+ if ( nStyle == RULER_TAB_LEFT )
+ {
+ aRect.SetLeft( n1 );
+ aRect.SetRight( n1 + ruler_tab.width - 1 );
+ }
+ else if ( nStyle == RULER_TAB_RIGHT )
+ {
+ aRect.SetRight( n1 );
+ aRect.SetLeft( n1 - ruler_tab.width - 1 );
+ }
+ else
+ {
+ aRect.SetLeft( n1 - ruler_tab.cwidth2 + 1 );
+ aRect.SetRight( n1 - ruler_tab.cwidth2 + ruler_tab.cwidth );
+ }
+
+ if ( aRect.Contains( Point( nX, nY ) ) )
+ {
+ pHitTest->eType = RulerType::Tab;
+ pHitTest->nAryPos = i;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ // Indents
+ if ( !mpData->pIndents.empty() )
+ {
+ tools::Long nIndentHeight = (mnVirHeight / 2) - 1;
+ tools::Long nIndentWidth2 = nIndentHeight - 3;
+
+ for ( i = mpData->pIndents.size(); i; i-- )
+ {
+ RulerIndentStyle nIndentStyle = mpData->pIndents[i-1].nStyle;
+ if ( (! bRequireStyle || nIndentStyle == nRequiredStyle) &&
+ !mpData->pIndents[i-1].bInvisible )
+ {
+ n1 = mpData->pIndents[i-1].nPos;
+
+ if ( (nIndentStyle == RulerIndentStyle::Bottom) != !bIsHori )
+ {
+ aRect.SetLeft( n1-nIndentWidth2 );
+ aRect.SetRight( n1+nIndentWidth2 );
+ aRect.SetTop( nHitBottom-nIndentHeight-RULER_OFF+1 );
+ aRect.SetBottom( nHitBottom );
+ }
+ else
+ {
+ aRect.SetLeft( n1-nIndentWidth2 );
+ aRect.SetRight( n1+nIndentWidth2 );
+ aRect.SetTop( 0 );
+ aRect.SetBottom( nIndentHeight+RULER_OFF-1 );
+ }
+
+ if ( aRect.Contains( Point( nX, nY ) ) )
+ {
+ pHitTest->eType = RulerType::Indent;
+ pHitTest->nAryPos = i-1;
+ return true;
+ }
+ }
+ }
+ }
+
+ // test the borders
+ int nBorderTolerance = 1;
+ if(pHitTest->bExpandTest)
+ {
+ nBorderTolerance++;
+ }
+
+ for ( i = mpData->pBorders.size(); i; i-- )
+ {
+ n1 = mpData->pBorders[i-1].nPos;
+ tools::Long n2 = n1 + mpData->pBorders[i-1].nWidth;
+
+ // borders have at least 3 pixel padding
+ if ( !mpData->pBorders[i-1].nWidth )
+ {
+ n1 -= nBorderTolerance;
+ n2 += nBorderTolerance;
+
+ }
+
+ if ( (nX >= n1) && (nX <= n2) )
+ {
+ RulerBorderStyle nBorderStyle = mpData->pBorders[i-1].nStyle;
+ if ( !(nBorderStyle & RulerBorderStyle::Invisible) )
+ {
+ pHitTest->eType = RulerType::Border;
+ pHitTest->nAryPos = i-1;
+
+ if ( !(nBorderStyle & RulerBorderStyle::Sizeable) )
+ {
+ if ( nBorderStyle & RulerBorderStyle::Moveable )
+ {
+ pHitTest->bSizeBar = true;
+ pHitTest->mnDragSize = RulerDragSize::Move;
+ }
+ }
+ else
+ {
+ tools::Long nMOff = RULER_MOUSE_BORDERWIDTH;
+ while ( nMOff*2 >= (n2-n1-RULER_MOUSE_BORDERMOVE) )
+ {
+ if ( nMOff < 2 )
+ {
+ nMOff = 0;
+ break;
+ }
+ else
+ nMOff--;
+ }
+
+ if ( nX <= n1+nMOff )
+ {
+ pHitTest->bSize = true;
+ pHitTest->mnDragSize = RulerDragSize::N1;
+ }
+ else if ( nX >= n2-nMOff )
+ {
+ pHitTest->bSize = true;
+ pHitTest->mnDragSize = RulerDragSize::N2;
+ }
+ else
+ {
+ if ( nBorderStyle & RulerBorderStyle::Moveable )
+ {
+ pHitTest->bSizeBar = true;
+ pHitTest->mnDragSize = RulerDragSize::Move;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+
+ // Margins
+ int nMarginTolerance = pHitTest->bExpandTest ? nBorderTolerance : RULER_MOUSE_MARGINWIDTH;
+
+ if ( (mpData->nMargin1Style & (RulerMarginStyle::Sizeable | RulerMarginStyle::Invisible)) == RulerMarginStyle::Sizeable )
+ {
+ n1 = mpData->nMargin1;
+ if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
+ {
+ pHitTest->eType = RulerType::Margin1;
+ pHitTest->bSize = true;
+ return true;
+ }
+ }
+ if ( (mpData->nMargin2Style & (RulerMarginStyle::Sizeable | RulerMarginStyle::Invisible)) == RulerMarginStyle::Sizeable )
+ {
+ n1 = mpData->nMargin2;
+ if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
+ {
+ pHitTest->eType = RulerType::Margin2;
+ pHitTest->bSize = true;
+ return true;
+ }
+ }
+
+ // test tabs again
+ if ( !mpData->pTabs.empty() )
+ {
+ aRect.SetTop( RULER_OFF );
+ aRect.SetBottom( nHitBottom );
+
+ for ( i = mpData->pTabs.size() - 1; i >= 0; i-- )
+ {
+ nStyle = mpData->pTabs[i].nStyle;
+ if ( !(nStyle & RULER_STYLE_INVISIBLE) )
+ {
+ nStyle &= RULER_TAB_STYLE;
+
+ // default tabs are only shown (no action)
+ if ( nStyle != RULER_TAB_DEFAULT )
+ {
+ n1 = mpData->pTabs[i].nPos;
+
+ if ( nStyle == RULER_TAB_LEFT )
+ {
+ aRect.SetLeft( n1 );
+ aRect.SetRight( n1 + ruler_tab.width - 1 );
+ }
+ else if ( nStyle == RULER_TAB_RIGHT )
+ {
+ aRect.SetRight( n1 );
+ aRect.SetLeft( n1 - ruler_tab.width - 1 );
+ }
+ else
+ {
+ aRect.SetLeft( n1 - ruler_tab.cwidth2 + 1 );
+ aRect.SetRight( n1 - ruler_tab.cwidth2 + ruler_tab.cwidth );
+ }
+
+ aRect.AdjustLeft( -1 );
+ aRect.AdjustRight( 1 );
+
+ if ( aRect.Contains( Point( nX, nY ) ) )
+ {
+ pHitTest->eType = RulerType::Tab;
+ pHitTest->nAryPos = i;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
+ RulerSelection* pHitTest ) const
+{
+ Point aPos = rPos;
+ bool bRequiredStyle = false;
+ RulerIndentStyle nRequiredStyle = RulerIndentStyle::Top;
+
+ if (eDragType == RulerType::Indent)
+ {
+ bRequiredStyle = true;
+ nRequiredStyle = RulerIndentStyle::Bottom;
+ }
+
+ if ( mnWinStyle & WB_HORZ )
+ aPos.AdjustX(mnWinOff );
+ else
+ aPos.AdjustY(mnWinOff );
+
+ if ( (eDragType == RulerType::Indent) || (eDragType == RulerType::DontKnow) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPos.setY( RULER_OFF + 1 );
+ else
+ aPos.setX( RULER_OFF + 1 );
+
+ if ( ImplDoHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
+ {
+ if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
+ return true;
+ }
+ }
+
+ if ( (eDragType == RulerType::Indent) ||
+ (eDragType == RulerType::Tab) ||
+ (eDragType == RulerType::DontKnow) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPos.setY( mnHeight - RULER_OFF - 1 );
+ else
+ aPos.setX( mnWidth - RULER_OFF - 1 );
+
+ if ( ImplDoHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
+ {
+ if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
+ return true;
+ }
+ }
+
+ if ( (eDragType == RulerType::Margin1) || (eDragType == RulerType::Margin2) ||
+ (eDragType == RulerType::Border) || (eDragType == RulerType::DontKnow) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPos.setY( RULER_OFF + (mnVirHeight / 2) );
+ else
+ aPos.setX( RULER_OFF + (mnVirHeight / 2) );
+
+ if ( ImplDoHitTest( aPos, pHitTest ) )
+ {
+ if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
+ return true;
+ }
+ }
+
+ pHitTest->eType = RulerType::DontKnow;
+
+ return false;
+}
+
+bool Ruler::ImplStartDrag( RulerSelection const * pHitTest, sal_uInt16 nModifier )
+{
+ // don't trigger drag if a border that was clicked can not be changed
+ if ( (pHitTest->eType == RulerType::Border) &&
+ !pHitTest->bSize && !pHitTest->bSizeBar )
+ return false;
+
+ // Set drag data
+ meDragType = pHitTest->eType;
+ mnDragPos = pHitTest->nPos;
+ mnDragAryPos = pHitTest->nAryPos;
+ mnDragSize = pHitTest->mnDragSize;
+ mnDragModifier = nModifier;
+ *mpDragData = *mpSaveData;
+ mpData = mpDragData.get();
+
+ // call handler
+ if (StartDrag())
+ {
+ // if the handler allows dragging, initialize dragging
+ mbDrag = true;
+ mnStartDragPos = mnDragPos;
+ StartTracking();
+ Invalidate(InvalidateFlags::NoErase);
+ return true;
+ }
+ else
+ {
+ // otherwise reset the data
+ meDragType = RulerType::DontKnow;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ mnDragSize = RulerDragSize::Move;
+ mnDragModifier = 0;
+ mpData = mpSaveData.get();
+ }
+
+ return false;
+}
+
+void Ruler::ImplDrag( const Point& rPos )
+{
+ tools::Long nX;
+ tools::Long nY;
+ tools::Long nOutHeight;
+
+ if ( mnWinStyle & WB_HORZ )
+ {
+ nX = rPos.X();
+ nY = rPos.Y();
+ nOutHeight = mnHeight;
+ }
+ else
+ {
+ nX = rPos.Y();
+ nY = rPos.X();
+ nOutHeight = mnWidth;
+ }
+
+ // calculate and fit X
+ nX -= mnVirOff;
+ if ( nX < mpData->nRulVirOff )
+ {
+ nX = mpData->nRulVirOff;
+ }
+ else if ( nX > mpData->nRulVirOff+mpData->nRulWidth )
+ {
+ nX = mpData->nRulVirOff+mpData->nRulWidth;
+ }
+ nX -= mpData->nNullVirOff;
+
+ // if upper or left from ruler, then consider old values
+ mbDragDelete = false;
+ if ( nY < 0 )
+ {
+ if ( !mbDragCanceled )
+ {
+ // reset the data
+ mbDragCanceled = true;
+ ImplRulerData aTempData = *mpDragData;
+ *mpDragData = *mpSaveData;
+ mbCalc = true;
+ mbFormat = true;
+
+ // call handler
+ mnDragPos = mnStartDragPos;
+ Drag();
+
+ // and redraw
+ Invalidate(InvalidateFlags::NoErase);
+
+ // reset the data as before cancel
+ *mpDragData = aTempData;
+ }
+ }
+ else
+ {
+ mbDragCanceled = false;
+
+ // +2, so the tabs are not cleared too quickly
+ if ( nY > nOutHeight + 2 )
+ mbDragDelete = true;
+
+ mnDragPos = nX;
+
+ // call handler
+ Drag();
+
+ // redraw
+ if (mbFormat)
+ Invalidate(InvalidateFlags::NoErase);
+ }
+}
+
+void Ruler::ImplEndDrag()
+{
+ // get values
+ if ( mbDragCanceled )
+ *mpDragData = *mpSaveData;
+ else
+ *mpSaveData = *mpDragData;
+
+ mpData = mpSaveData.get();
+ mbDrag = false;
+
+ // call handler
+ EndDrag();
+
+ // reset drag values
+ meDragType = RulerType::DontKnow;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ mnDragSize = RulerDragSize::Move;
+ mbDragCanceled = false;
+ mbDragDelete = false;
+ mnDragModifier = 0;
+ mnStartDragPos = 0;
+
+ // redraw
+ Invalidate(InvalidateFlags::NoErase);
+}
+
+void Ruler::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( !rMEvt.IsLeft() || IsTracking() )
+ return;
+
+ Point aMousePos = rMEvt.GetPosPixel();
+ sal_uInt16 nMouseClicks = rMEvt.GetClicks();
+ sal_uInt16 nMouseModifier = rMEvt.GetModifier();
+
+ // update ruler
+ if ( mbFormat )
+ {
+ Invalidate(InvalidateFlags::NoErase);
+ }
+
+ if ( maExtraRect.Contains( aMousePos ) )
+ {
+ ExtraDown();
+ }
+ else
+ {
+ RulerSelection aHitTest;
+ bool bHitTestResult = ImplDoHitTest(aMousePos, &aHitTest);
+
+ if ( nMouseClicks == 1 )
+ {
+ if ( bHitTestResult )
+ {
+ ImplStartDrag( &aHitTest, nMouseModifier );
+ }
+ else
+ {
+ // calculate position inside of ruler area
+ if ( aHitTest.eType == RulerType::DontKnow )
+ {
+ mnDragPos = aHitTest.nPos;
+ Click();
+ mnDragPos = 0;
+
+ // call HitTest again as a click, for example, could set a new tab
+ if ( ImplDoHitTest(aMousePos, &aHitTest) )
+ ImplStartDrag(&aHitTest, nMouseModifier);
+ }
+ }
+ }
+ else
+ {
+ if (bHitTestResult)
+ {
+ mnDragPos = aHitTest.nPos;
+ mnDragAryPos = aHitTest.nAryPos;
+ }
+ meDragType = aHitTest.eType;
+
+ DoubleClick();
+
+ meDragType = RulerType::DontKnow;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ }
+ }
+}
+
+void Ruler::MouseMove( const MouseEvent& rMEvt )
+{
+ PointerStyle ePtrStyle = PointerStyle::Arrow;
+
+ mxPreviousHitTest.swap(mxCurrentHitTest);
+
+ mxCurrentHitTest.reset(new RulerSelection);
+
+ maHoverSelection.eType = RulerType::DontKnow;
+
+ if (ImplDoHitTest( rMEvt.GetPosPixel(), mxCurrentHitTest.get() ))
+ {
+ maHoverSelection = *mxCurrentHitTest;
+
+ if (mxCurrentHitTest->bSize)
+ {
+ if (mnWinStyle & WB_HORZ)
+ {
+ if (mxCurrentHitTest->mnDragSize == RulerDragSize::N1)
+ ePtrStyle = PointerStyle::TabSelectW;
+ else if (mxCurrentHitTest->mnDragSize == RulerDragSize::N2)
+ ePtrStyle = PointerStyle::TabSelectE;
+ else
+ ePtrStyle = PointerStyle::ESize;
+ }
+ else
+ {
+ if (mxCurrentHitTest->mnDragSize == RulerDragSize::N1)
+ ePtrStyle = PointerStyle::WindowNSize;
+ else if (mxCurrentHitTest->mnDragSize == RulerDragSize::N2)
+ ePtrStyle = PointerStyle::WindowSSize;
+ else
+ ePtrStyle = PointerStyle::SSize;
+ }
+ }
+ else if (mxCurrentHitTest->bSizeBar)
+ {
+ if (mnWinStyle & WB_HORZ)
+ ePtrStyle = PointerStyle::HSizeBar;
+ else
+ ePtrStyle = PointerStyle::VSizeBar;
+ }
+ }
+
+ if (mxPreviousHitTest != nullptr && mxPreviousHitTest->eType != mxCurrentHitTest->eType)
+ {
+ mbFormat = true;
+ }
+
+ SetPointer( ePtrStyle );
+
+ if (mbFormat)
+ {
+ Invalidate(InvalidateFlags::NoErase);
+ }
+}
+
+void Ruler::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ // reset the old state at cancel
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ mbDragCanceled = true;
+ mbFormat = true;
+ }
+
+ ImplEndDrag();
+ }
+ else
+ ImplDrag( rTEvt.GetMouseEvent().GetPosPixel() );
+}
+
+void Ruler::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ ImplDraw(rRenderContext);
+
+ // consider extra field
+ if (mnWinStyle & WB_EXTRAFIELD)
+ ImplDrawExtra(rRenderContext);
+}
+
+void Ruler::Resize()
+{
+ Size aWinSize = GetOutputSizePixel();
+
+ tools::Long nNewHeight;
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( aWinSize.Height() != mnHeight )
+ nNewHeight = aWinSize.Height();
+ else
+ nNewHeight = 0;
+ }
+ else
+ {
+ if ( aWinSize.Width() != mnWidth )
+ nNewHeight = aWinSize.Width();
+ else
+ nNewHeight = 0;
+ }
+
+ mbFormat = true;
+
+ // clear lines
+ bool bVisible = IsReallyVisible();
+ if ( bVisible && !mpData->pLines.empty() )
+ {
+ mnUpdateFlags |= RULER_UPDATE_LINES;
+ Invalidate(InvalidateFlags::NoErase);
+ }
+
+ // recalculate some values if the height/width changes
+ // extra field should always be updated
+ ImplInitExtraField( mpData->bTextRTL );
+ if ( nNewHeight )
+ {
+ mbCalc = true;
+ mnVirHeight = nNewHeight - mnBorderWidth - ( RULER_OFF * 2 );
+ }
+ else
+ {
+ if ( mpData->bAutoPageWidth )
+ ImplUpdate( true );
+ else if ( mbAutoWinWidth )
+ mbCalc = true;
+ }
+
+ // clear part of the border
+ if ( bVisible )
+ {
+ if ( nNewHeight )
+ Invalidate(InvalidateFlags::NoErase);
+ else if ( mpData->bAutoPageWidth )
+ {
+ // only at AutoPageWidth do we need to redraw
+ tools::Rectangle aRect;
+
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( mnWidth < aWinSize.Width() )
+ aRect.SetLeft( mnWidth - RULER_RESIZE_OFF );
+ else
+ aRect.SetLeft( aWinSize.Width() - RULER_RESIZE_OFF );
+ aRect.SetRight( aRect.Left() + RULER_RESIZE_OFF );
+ aRect.SetTop( RULER_OFF );
+ aRect.SetBottom( RULER_OFF + mnVirHeight );
+ }
+ else
+ {
+ if ( mnHeight < aWinSize.Height() )
+ aRect.SetTop( mnHeight-RULER_RESIZE_OFF );
+ else
+ aRect.SetTop( aWinSize.Height()-RULER_RESIZE_OFF );
+ aRect.SetBottom( aRect.Top() + RULER_RESIZE_OFF );
+ aRect.SetLeft( RULER_OFF );
+ aRect.SetRight( RULER_OFF + mnVirHeight );
+ }
+
+ Invalidate(aRect, InvalidateFlags::NoErase);
+ }
+ }
+
+ mnWidth = aWinSize.Width();
+ mnHeight = aWinSize.Height();
+}
+
+void Ruler::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == StateChangedType::InitShow )
+ Invalidate();
+ else if ( nType == StateChangedType::UpdateMode )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( (nType == StateChangedType::Zoom) ||
+ (nType == StateChangedType::ControlFont) )
+ {
+ ImplInitSettings( true, false, false );
+ Invalidate();
+ }
+ else if ( nType == StateChangedType::ControlForeground )
+ {
+ ImplInitSettings( false, true, false );
+ Invalidate();
+ }
+ else if ( nType == StateChangedType::ControlBackground )
+ {
+ ImplInitSettings( false, false, true );
+ Invalidate();
+ }
+}
+
+void Ruler::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
+ (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
+ (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
+ (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
+ {
+ mbFormat = true;
+ ImplInitSettings( true, true, true );
+ Invalidate();
+ }
+}
+
+bool Ruler::StartDrag()
+{
+ return false;
+}
+
+void Ruler::Drag()
+{
+}
+
+void Ruler::EndDrag()
+{
+}
+
+void Ruler::Click()
+{
+}
+
+void Ruler::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+void Ruler::ExtraDown()
+{
+}
+
+void Ruler::Activate()
+{
+ mbActive = true;
+
+ // update positionlines - draw is delayed
+ mnUpdateFlags |= RULER_UPDATE_LINES;
+ Invalidate(InvalidateFlags::NoErase);
+}
+
+void Ruler::Deactivate()
+{
+ // clear positionlines
+ Invalidate(InvalidateFlags::NoErase);
+
+ mbActive = false;
+}
+
+bool Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
+{
+ if ( !mbDrag )
+ {
+ Point aMousePos = rMEvt.GetPosPixel();
+ sal_uInt16 nMouseClicks = rMEvt.GetClicks();
+ sal_uInt16 nMouseModifier = rMEvt.GetModifier();
+ RulerSelection aHitTest;
+
+ if(eDragType != RulerType::DontKnow)
+ aHitTest.bExpandTest = true;
+
+ // update ruler
+ if ( mbFormat )
+ {
+ if (!IsReallyVisible())
+ {
+ // set mpData for ImplDocHitTest()
+ ImplFormat(*GetOutDev());
+ }
+
+ Invalidate(InvalidateFlags::NoErase);
+ }
+
+ if ( nMouseClicks == 1 )
+ {
+ if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
+ {
+ PointerStyle aPtr = PointerStyle::Arrow;
+
+ if ( aHitTest.bSize )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPtr = PointerStyle::ESize;
+ else
+ aPtr = PointerStyle::SSize;
+ }
+ else if ( aHitTest.bSizeBar )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPtr = PointerStyle::HSizeBar;
+ else
+ aPtr = PointerStyle::VSizeBar;
+ }
+ SetPointer( aPtr );
+ return ImplStartDrag( &aHitTest, nMouseModifier );
+ }
+ }
+ else if ( nMouseClicks == 2 )
+ {
+ if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
+ {
+ mnDragPos = aHitTest.nPos;
+ mnDragAryPos = aHitTest.nAryPos;
+ }
+
+ DoubleClick();
+
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Ruler::CancelDrag()
+{
+ if ( mbDrag )
+ {
+ ImplDrag( Point( -1, -1 ) );
+ ImplEndDrag();
+ }
+}
+
+RulerType Ruler::GetRulerType( const Point& rPos, sal_uInt16* pAryPos )
+{
+ RulerSelection aHitTest;
+
+ // update ruler
+ if ( IsReallyVisible() && mbFormat )
+ {
+ Invalidate(InvalidateFlags::NoErase);
+ }
+
+ (void)ImplDoHitTest(rPos, &aHitTest);
+
+ // return values
+ if ( pAryPos )
+ *pAryPos = aHitTest.nAryPos;
+ return aHitTest.eType;
+}
+
+void Ruler::SetWinPos( tools::Long nNewOff, tools::Long nNewWidth )
+{
+ // should widths be automatically calculated
+ if ( !nNewWidth )
+ mbAutoWinWidth = true;
+ else
+ mbAutoWinWidth = false;
+
+ mnWinOff = nNewOff;
+ mnWinWidth = nNewWidth;
+ ImplUpdate( true );
+}
+
+void Ruler::SetPagePos( tools::Long nNewOff, tools::Long nNewWidth )
+{
+ // should we do anything?
+ if ( (mpData->nPageOff == nNewOff) && (mpData->nPageWidth == nNewWidth) )
+ return;
+
+ // should widths be automatically calculated
+ if ( !nNewWidth )
+ mpData->bAutoPageWidth = true;
+ else
+ mpData->bAutoPageWidth = false;
+
+ mpData->nPageOff = nNewOff;
+ mpData->nPageWidth = nNewWidth;
+ ImplUpdate( true );
+}
+
+void Ruler::SetBorderPos( tools::Long nOff )
+{
+ if ( mnWinStyle & WB_BORDER )
+ {
+ if ( mnBorderOff != nOff )
+ {
+ mnBorderOff = nOff;
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate(InvalidateFlags::NoErase);
+ }
+ }
+}
+
+void Ruler::SetUnit( FieldUnit eNewUnit )
+{
+ if ( meUnit == eNewUnit )
+ return;
+
+ meUnit = eNewUnit;
+ switch ( meUnit )
+ {
+ case FieldUnit::MM:
+ mnUnitIndex = RULER_UNIT_MM;
+ break;
+ case FieldUnit::CM:
+ mnUnitIndex = RULER_UNIT_CM;
+ break;
+ case FieldUnit::M:
+ mnUnitIndex = RULER_UNIT_M;
+ break;
+ case FieldUnit::KM:
+ mnUnitIndex = RULER_UNIT_KM;
+ break;
+ case FieldUnit::INCH:
+ mnUnitIndex = RULER_UNIT_INCH;
+ break;
+ case FieldUnit::FOOT:
+ mnUnitIndex = RULER_UNIT_FOOT;
+ break;
+ case FieldUnit::MILE:
+ mnUnitIndex = RULER_UNIT_MILE;
+ break;
+ case FieldUnit::POINT:
+ mnUnitIndex = RULER_UNIT_POINT;
+ break;
+ case FieldUnit::PICA:
+ mnUnitIndex = RULER_UNIT_PICA;
+ break;
+ case FieldUnit::CHAR:
+ mnUnitIndex = RULER_UNIT_CHAR;
+ break;
+ case FieldUnit::LINE:
+ mnUnitIndex = RULER_UNIT_LINE;
+ break;
+ default:
+ SAL_WARN( "svtools.control", "Ruler::SetUnit() - Wrong Unit" );
+ break;
+ }
+
+ maMapMode.SetMapUnit( aImplRulerUnitTab[mnUnitIndex].eMapUnit );
+ ImplUpdate();
+}
+
+void Ruler::SetZoom( const Fraction& rNewZoom )
+{
+ DBG_ASSERT( rNewZoom.GetNumerator(), "Ruler::SetZoom() with scale 0 is not allowed" );
+
+ if ( maZoom != rNewZoom )
+ {
+ maZoom = rNewZoom;
+ maMapMode.SetScaleX( maZoom );
+ maMapMode.SetScaleY( maZoom );
+ ImplUpdate();
+ }
+}
+
+void Ruler::SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle )
+{
+ if ( mnWinStyle & WB_EXTRAFIELD )
+ {
+ meExtraType = eNewExtraType;
+ mnExtraStyle = nStyle;
+ if (IsReallyVisible() && IsUpdateMode())
+ Invalidate();
+ }
+}
+
+void Ruler::SetNullOffset( tools::Long nPos )
+{
+ if ( mpData->nNullOff != nPos )
+ {
+ mpData->nNullVirOff += nPos - mpData->nNullOff;
+ mpData->nNullOff = nPos;
+ ImplUpdate();
+ }
+}
+
+void Ruler::SetLeftFrameMargin( tools::Long nPos )
+{
+ if ( mpData->nLeftFrameMargin != nPos )
+ {
+ mpData->nLeftFrameMargin = nPos;
+ ImplUpdate();
+ }
+}
+
+void Ruler::SetRightFrameMargin( tools::Long nPos )
+{
+ if ( mpData->nRightFrameMargin != nPos )
+ {
+ mpData->nRightFrameMargin = nPos;
+ ImplUpdate();
+ }
+}
+
+void Ruler::SetMargin1( tools::Long nPos, RulerMarginStyle nMarginStyle )
+{
+ if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
+ {
+ mpData->nMargin1 = nPos;
+ mpData->nMargin1Style = nMarginStyle;
+ ImplUpdate();
+ }
+}
+
+void Ruler::SetMargin2( tools::Long nPos, RulerMarginStyle nMarginStyle )
+{
+ DBG_ASSERT( (nPos >= mpData->nMargin1) ||
+ (mpData->nMargin1Style & RulerMarginStyle::Invisible) ||
+ (mpData->nMargin2Style & RulerMarginStyle::Invisible),
+ "Ruler::SetMargin2() - Margin2 < Margin1" );
+
+ if ( (mpData->nMargin2 != nPos) || (mpData->nMargin2Style != nMarginStyle) )
+ {
+ mpData->nMargin2 = nPos;
+ mpData->nMargin2Style = nMarginStyle;
+ ImplUpdate();
+ }
+}
+
+void Ruler::SetLines( sal_uInt32 aLineArraySize, const RulerLine* pLineArray )
+{
+ // To determine if what has changed
+ if ( mpData->pLines.size() == aLineArraySize )
+ {
+ sal_uInt32 i = aLineArraySize;
+ std::vector<RulerLine>::const_iterator aItr1 = mpData->pLines.begin();
+ const RulerLine* pAry2 = pLineArray;
+ while ( i )
+ {
+ if ( aItr1->nPos != pAry2->nPos )
+ break;
+ ++aItr1;
+ ++pAry2;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ // New values and new share issue
+ bool bMustUpdate;
+ bMustUpdate = IsReallyVisible() && IsUpdateMode();
+
+ // Delete old lines
+ if ( bMustUpdate )
+ Invalidate(InvalidateFlags::NoErase);
+
+ // New data set
+ if ( !aLineArraySize || !pLineArray )
+ {
+ if ( mpData->pLines.empty() )
+ return;
+ mpData->pLines.clear();
+ }
+ else
+ {
+ if ( mpData->pLines.size() != aLineArraySize )
+ {
+ mpData->pLines.resize(aLineArraySize);
+ }
+
+ std::copy( pLineArray,
+ pLineArray + aLineArraySize,
+ mpData->pLines.begin() );
+
+ if ( bMustUpdate )
+ Invalidate(InvalidateFlags::NoErase);
+ }
+}
+
+void Ruler::SetBorders( sal_uInt32 aBorderArraySize, const RulerBorder* pBorderArray )
+{
+ if ( !aBorderArraySize || !pBorderArray )
+ {
+ if ( mpData->pBorders.empty() )
+ return;
+ mpData->pBorders.clear();
+ }
+ else
+ {
+ if ( mpData->pBorders.size() != aBorderArraySize )
+ {
+ mpData->pBorders.resize(aBorderArraySize);
+ }
+ else
+ {
+ sal_uInt32 i = aBorderArraySize;
+ const RulerBorder* pAry1 = mpData->pBorders.data();
+ const RulerBorder* pAry2 = pBorderArray;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nWidth != pAry2->nWidth) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+ std::copy( pBorderArray,
+ pBorderArray + aBorderArraySize,
+ mpData->pBorders.begin() );
+ }
+
+ ImplUpdate();
+}
+
+void Ruler::SetIndents( sal_uInt32 aIndentArraySize, const RulerIndent* pIndentArray )
+{
+
+ if ( !aIndentArraySize || !pIndentArray )
+ {
+ if ( mpData->pIndents.empty() )
+ return;
+ mpData->pIndents.clear();
+ }
+ else
+ {
+ if ( mpData->pIndents.size() != aIndentArraySize )
+ {
+ mpData->pIndents.resize(aIndentArraySize);
+ }
+ else
+ {
+ sal_uInt32 i = aIndentArraySize;
+ const RulerIndent* pAry1 = mpData->pIndents.data();
+ const RulerIndent* pAry2 = pIndentArray;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ std::copy( pIndentArray,
+ pIndentArray + aIndentArraySize,
+ mpData->pIndents.begin() );
+ }
+
+ ImplUpdate();
+}
+
+void Ruler::SetTabs( sal_uInt32 aTabArraySize, const RulerTab* pTabArray )
+{
+ if ( aTabArraySize == 0 || pTabArray == nullptr )
+ {
+ if ( mpData->pTabs.empty() )
+ return;
+ mpData->pTabs.clear();
+ }
+ else
+ {
+ if ( mpData->pTabs.size() != aTabArraySize )
+ {
+ mpData->pTabs.resize(aTabArraySize);
+ }
+ else
+ {
+ sal_uInt32 i = aTabArraySize;
+ std::vector<RulerTab>::iterator aTabIterator = mpData->pTabs.begin();
+ const RulerTab* pInputArray = pTabArray;
+ while ( i )
+ {
+ RulerTab& aCurrent = *aTabIterator;
+ if ( aCurrent.nPos != pInputArray->nPos ||
+ aCurrent.nStyle != pInputArray->nStyle )
+ {
+ break;
+ }
+ ++aTabIterator;
+ pInputArray++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+ std::copy(pTabArray, pTabArray + aTabArraySize, mpData->pTabs.begin());
+ }
+
+ ImplUpdate();
+}
+
+const std::vector<RulerTab>& Ruler::GetTabs() const
+{
+ return mpData->pTabs;
+}
+
+void Ruler::SetStyle( WinBits nStyle )
+{
+ if ( mnWinStyle != nStyle )
+ {
+ mnWinStyle = nStyle;
+ ImplInitExtraField( true );
+ }
+}
+
+void Ruler::DrawTab(vcl::RenderContext& rRenderContext, const Color &rFillColor, const Point& rPos, sal_uInt16 nStyle)
+{
+ Point aPos(rPos);
+ sal_uInt16 nTabStyle = nStyle & (RULER_TAB_STYLE | RULER_TAB_RTL);
+
+ rRenderContext.Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rFillColor);
+ ImplCenterTabPos(aPos, nTabStyle);
+ ImplDrawRulerTab(rRenderContext, aPos, nTabStyle, nStyle);
+ rRenderContext.Pop();
+}
+
+void Ruler::SetTextRTL(bool bRTL)
+{
+ if(mpData->bTextRTL != bRTL)
+ {
+ mpData->bTextRTL = bRTL;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplInitExtraField( true );
+ }
+
+}
+
+tools::Long Ruler::GetPageOffset() const
+{
+ return mpData->nPageOff;
+}
+
+tools::Long Ruler::GetNullOffset() const
+{
+ return mpData->nNullOff;
+}
+
+tools::Long Ruler::GetMargin1() const
+{
+ return mpData->nMargin1;
+}
+
+tools::Long Ruler::GetMargin2() const
+{
+ return mpData->nMargin2;
+}
+
+
+bool Ruler::GetTextRTL() const
+{
+ return mpData->bTextRTL;
+}
+
+const RulerUnitData& Ruler::GetCurrentRulerUnit() const
+{
+ return aImplRulerUnitTab[mnUnitIndex];
+}
+
+void Ruler::DrawTicks()
+{
+ mbFormat = true;
+ Invalidate(InvalidateFlags::NoErase);
+}
+
+uno::Reference< XAccessible > Ruler::CreateAccessible()
+{
+ vcl::Window* pParent = GetAccessibleParentWindow();
+ OSL_ENSURE( pParent, "-SvxRuler::CreateAccessible(): No Parent!" );
+ uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
+ if( xAccParent.is() )
+ {
+ // MT: Fixed compiler issue because the address from a temporary object was used.
+ // BUT: Should it really be a Pointer, instead of const&???
+ OUString aStr;
+ if ( mnWinStyle & WB_HORZ )
+ {
+ aStr = SvtResId(STR_SVT_ACC_RULER_HORZ_NAME);
+ }
+ else
+ {
+ aStr = SvtResId(STR_SVT_ACC_RULER_VERT_NAME);
+ }
+ mxAccContext = new SvtRulerAccessible( xAccParent, *this, aStr );
+ SetAccessible(mxAccContext);
+ return mxAccContext;
+ }
+ else
+ return uno::Reference< XAccessible >();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */