1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <tools/debug.hxx>
21 #include <tools/poly.hxx>
22 #include <vcl/event.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/vcllayout.hxx>
25 #include <vcl/virdev.hxx>
26 #include <vcl/ptrstyle.hxx>
27 #include <sal/log.hxx>
28
29 #include <svtools/ruler.hxx>
30 #include <svtools/svtresid.hxx>
31 #include <svtools/strings.hrc>
32 #include <svtools/colorcfg.hxx>
33 #include "accessibleruler.hxx"
34
35 #include <memory>
36 #include <vector>
37
38 using namespace std;
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::accessibility;
43
44 #define RULER_OFF 3
45 #define RULER_RESIZE_OFF 4
46 #define RULER_MIN_SIZE 3
47
48 #define RULER_VAR_SIZE 8
49
50 #define RULER_UPDATE_LINES 0x01
51
52 #define RULER_CLIP 150
53
54 #define RULER_UNIT_MM 0
55 #define RULER_UNIT_CM 1
56 #define RULER_UNIT_M 2
57 #define RULER_UNIT_KM 3
58 #define RULER_UNIT_INCH 4
59 #define RULER_UNIT_FOOT 5
60 #define RULER_UNIT_MILE 6
61 #define RULER_UNIT_POINT 7
62 #define RULER_UNIT_PICA 8
63 #define RULER_UNIT_CHAR 9
64 #define RULER_UNIT_LINE 10
65 #define RULER_UNIT_COUNT 11
66
67 namespace
68 {
69 /**
70 * Pre-calculates glyph items for rText on rRenderContext. Subsequent calls
71 * avoid the calculation and just return a pointer to rTextGlyphs.
72 */
lcl_GetRulerTextGlyphs(const vcl::RenderContext & rRenderContext,const OUString & rText,SalLayoutGlyphs & rTextGlyphs)73 SalLayoutGlyphs* lcl_GetRulerTextGlyphs(const vcl::RenderContext& rRenderContext, const OUString& rText,
74 SalLayoutGlyphs& rTextGlyphs)
75 {
76 if (rTextGlyphs.IsValid())
77 // Use pre-calculated result.
78 return &rTextGlyphs;
79
80 // Calculate glyph items.
81
82 std::unique_ptr<SalLayout> pLayout = rRenderContext.ImplLayout(
83 rText, 0, rText.getLength(), Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly);
84 if (!pLayout)
85 return nullptr;
86
87 // Remember the calculation result.
88 rTextGlyphs = pLayout->GetGlyphs();
89
90 return &rTextGlyphs;
91 }
92 }
93
94 class ImplRulerData
95 {
96 friend class Ruler;
97
98 private:
99 vector<RulerLine> pLines;
100 vector<RulerBorder> pBorders;
101 vector<RulerIndent> pIndents;
102 vector<RulerTab> pTabs;
103
104 tools::Long nNullVirOff;
105 tools::Long nRulVirOff;
106 tools::Long nRulWidth;
107 tools::Long nPageOff;
108 tools::Long nPageWidth;
109 tools::Long nNullOff;
110 tools::Long nMargin1;
111 tools::Long nMargin2;
112 // In this context, "frame margin" means paragraph margins (indents)
113 tools::Long nLeftFrameMargin;
114 tools::Long nRightFrameMargin;
115 RulerMarginStyle nMargin1Style;
116 RulerMarginStyle nMargin2Style;
117 bool bAutoPageWidth;
118 bool bTextRTL;
119
120 public:
121 ImplRulerData();
122 };
123
ImplRulerData()124 ImplRulerData::ImplRulerData() :
125 nNullVirOff (0),
126 nRulVirOff (0),
127 nRulWidth (0),
128 nPageOff (0),
129 nPageWidth (0),
130 nNullOff (0),
131 nMargin1 (0),
132 nMargin2 (0),
133 nLeftFrameMargin (0),
134 nRightFrameMargin (0),
135 nMargin1Style (RulerMarginStyle::NONE),
136 nMargin2Style (RulerMarginStyle::NONE),
137 bAutoPageWidth (true), // Page width == EditWin width
138 bTextRTL (false)
139 {
140 }
141
142 const RulerUnitData aImplRulerUnitTab[RULER_UNIT_COUNT] =
143 {
144 { MapUnit::Map100thMM, 100, 25.0, 25.0, 50.0, 100.0, " mm" }, // MM
145 { MapUnit::Map100thMM, 1000, 100.0, 500.0, 1000.0, 1000.0, " cm" }, // CM
146 { MapUnit::MapMM, 1000, 10.0, 250.0, 500.0, 1000.0, " m" }, // M
147 { MapUnit::MapCM, 100000, 12500.0, 25000.0, 50000.0, 100000.0, " km" }, // KM
148 { MapUnit::Map1000thInch, 1000, 62.5, 125.0, 500.0, 1000.0, "\"" }, // INCH
149 { MapUnit::Map100thInch, 1200, 120.0, 120.0, 600.0, 1200.0, "'" }, // FOOT
150 { MapUnit::Map10thInch, 633600, 63360.0, 63360.0, 316800.0, 633600.0, " miles" }, // MILE
151 { MapUnit::MapPoint, 1, 12.0, 12.0, 12.0, 36.0, " pt" }, // POINT
152 { MapUnit::Map100thMM, 423, 423.0, 423.0, 423.0, 846.0, " pc" }, // PICA
153 { MapUnit::Map100thMM, 371, 371.0, 371.0, 371.0, 743.0, " ch" }, // CHAR
154 { MapUnit::Map100thMM, 551, 551.0, 551.0, 551.0, 1102.0, " li" } // LINE
155 };
156
157 static RulerTabData ruler_tab =
158 {
159 0, // DPIScaleFactor to be set
160 7, // ruler_tab_width
161 6, // ruler_tab_height
162 2, // ruler_tab_height2
163 2, // ruler_tab_width2
164 8, // ruler_tab_cwidth
165 4, // ruler_tab_cwidth2
166 4, // ruler_tab_cwidth3
167 2, // ruler_tab_cwidth4
168 4, // ruler_tab_dheight
169 1, // ruler_tab_dheight2
170 5, // ruler_tab_dwidth
171 3, // ruler_tab_dwidth2
172 3, // ruler_tab_dwidth3
173 1, // ruler_tab_dwidth4
174 5 // ruler_tab_textoff
175 };
176
ImplInit(WinBits nWinBits)177 void Ruler::ImplInit( WinBits nWinBits )
178 {
179 // Set default WinBits
180 if ( !(nWinBits & WB_VERT) )
181 {
182 nWinBits |= WB_HORZ;
183
184 // RTL: no UI mirroring for horizontal rulers, because
185 // the document is also not mirrored
186 EnableRTL( false );
187 }
188
189 // Initialize variables
190 mnWinStyle = nWinBits; // Window-Style
191 mnBorderOff = 0; // Border-Offset
192 mnWinOff = 0; // EditWinOffset
193 mnWinWidth = 0; // EditWinWidth
194 mnWidth = 0; // Window width
195 mnHeight = 0; // Window height
196 mnVirOff = 0; // Offset of VirtualDevice from top-left corner
197 mnVirWidth = 0; // width or height from VirtualDevice
198 mnVirHeight = 0; // height of width from VirtualDevice
199 mnDragPos = 0; // Drag-Position (Null point)
200 mnDragAryPos = 0; // Drag-Array-Index
201 mnDragSize = RulerDragSize::Move; // Did size change at dragging
202 mnDragModifier = 0; // Modifier key at dragging
203 mnExtraStyle = 0; // Style of Extra field
204 mnCharWidth = 371;
205 mnLineHeight = 551;
206 mbCalc = true; // Should recalculate page width
207 mbFormat = true; // Should redraw
208 mbDrag = false; // Currently at dragging
209 mbDragDelete = false; // Has mouse left the dragging area
210 mbDragCanceled = false; // Dragging cancelled?
211 mbAutoWinWidth = true; // EditWinWidth == RulerWidth
212 mbActive = true; // Is ruler active
213 mnUpdateFlags = 0; // What needs to be updated
214 mpData = mpSaveData.get(); // Pointer to normal data
215 meExtraType = RulerExtra::DontKnow; // What is in extra field
216 meDragType = RulerType::DontKnow; // Which element is dragged
217
218 // Initialize Units
219 mnUnitIndex = RULER_UNIT_CM;
220 meUnit = FieldUnit::CM;
221 maZoom = Fraction( 1, 1 );
222
223 // Recalculate border widths
224 if ( nWinBits & WB_BORDER )
225 mnBorderWidth = 1;
226 else
227 mnBorderWidth = 0;
228
229 // Settings
230 ImplInitSettings( true, true, true );
231
232 // Setup the default size
233 tools::Rectangle aRect;
234 GetOutDev()->GetTextBoundRect( aRect, "0123456789" );
235 tools::Long nDefHeight = aRect.GetHeight() + RULER_OFF * 2 + ruler_tab.textoff * 2 + mnBorderWidth;
236
237 Size aDefSize;
238 if ( nWinBits & WB_HORZ )
239 aDefSize.setHeight( nDefHeight );
240 else
241 aDefSize.setWidth( nDefHeight );
242 SetOutputSizePixel( aDefSize );
243 SetType(WindowType::RULER);
244 }
245
Ruler(vcl::Window * pParent,WinBits nWinStyle)246 Ruler::Ruler( vcl::Window* pParent, WinBits nWinStyle ) :
247 Window( pParent, nWinStyle & WB_3DLOOK ),
248 maVirDev( VclPtr<VirtualDevice>::Create(*GetOutDev()) ),
249 maMapMode( MapUnit::Map100thMM ),
250 mpSaveData(new ImplRulerData),
251 mpData(nullptr),
252 mpDragData(new ImplRulerData)
253 {
254 // Check to see if the ruler constructor has
255 // already been called before otherwise
256 // we end up with over-scaled elements
257 if (ruler_tab.DPIScaleFactor == 0)
258 {
259 ruler_tab.DPIScaleFactor = GetDPIScaleFactor();
260 ruler_tab.width *= ruler_tab.DPIScaleFactor;
261 ruler_tab.height *= ruler_tab.DPIScaleFactor;
262 ruler_tab.height2 *= ruler_tab.DPIScaleFactor;
263 ruler_tab.width2 *= ruler_tab.DPIScaleFactor;
264 ruler_tab.cwidth *= ruler_tab.DPIScaleFactor;
265 ruler_tab.cwidth2 *= ruler_tab.DPIScaleFactor;
266 ruler_tab.cwidth3 *= ruler_tab.DPIScaleFactor;
267 ruler_tab.cwidth4 *= ruler_tab.DPIScaleFactor;
268 ruler_tab.dheight *= ruler_tab.DPIScaleFactor;
269 ruler_tab.dheight2 *= ruler_tab.DPIScaleFactor;
270 ruler_tab.dwidth *= ruler_tab.DPIScaleFactor;
271 ruler_tab.dwidth2 *= ruler_tab.DPIScaleFactor;
272 ruler_tab.dwidth3 *= ruler_tab.DPIScaleFactor;
273 ruler_tab.dwidth4 *= ruler_tab.DPIScaleFactor;
274 ruler_tab.textoff *= ruler_tab.DPIScaleFactor;
275 }
276
277
278 ImplInit( nWinStyle );
279 }
280
~Ruler()281 Ruler::~Ruler()
282 {
283 disposeOnce();
284 }
285
dispose()286 void Ruler::dispose()
287 {
288 mpSaveData.reset();
289 mpDragData.reset();
290 mxAccContext.clear();
291 Window::dispose();
292 }
293
ImplVDrawLine(vcl::RenderContext & rRenderContext,tools::Long nX1,tools::Long nY1,tools::Long nX2,tools::Long nY2)294 void Ruler::ImplVDrawLine(vcl::RenderContext& rRenderContext, tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2)
295 {
296 if ( nX1 < -RULER_CLIP )
297 {
298 nX1 = -RULER_CLIP;
299 if ( nX2 < -RULER_CLIP )
300 return;
301 }
302 tools::Long nClip = mnVirWidth + RULER_CLIP;
303 if ( nX2 > nClip )
304 {
305 nX2 = nClip;
306 if ( nX1 > nClip )
307 return;
308 }
309
310 if ( mnWinStyle & WB_HORZ )
311 rRenderContext.DrawLine( Point( nX1, nY1 ), Point( nX2, nY2 ) );
312 else
313 rRenderContext.DrawLine( Point( nY1, nX1 ), Point( nY2, nX2 ) );
314 }
315
ImplVDrawRect(vcl::RenderContext & rRenderContext,tools::Long nX1,tools::Long nY1,tools::Long nX2,tools::Long nY2)316 void Ruler::ImplVDrawRect(vcl::RenderContext& rRenderContext, tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2)
317 {
318 if ( nX1 < -RULER_CLIP )
319 {
320 nX1 = -RULER_CLIP;
321 if ( nX2 < -RULER_CLIP )
322 return;
323 }
324 tools::Long nClip = mnVirWidth + RULER_CLIP;
325 if ( nX2 > nClip )
326 {
327 nX2 = nClip;
328 if ( nX1 > nClip )
329 return;
330 }
331
332 if ( mnWinStyle & WB_HORZ )
333 rRenderContext.DrawRect(tools::Rectangle(nX1, nY1, nX2, nY2));
334 else
335 rRenderContext.DrawRect(tools::Rectangle(nY1, nX1, nY2, nX2));
336 }
337
ImplVDrawText(vcl::RenderContext & rRenderContext,tools::Long nX,tools::Long nY,const OUString & rText,tools::Long nMin,tools::Long nMax)338 void Ruler::ImplVDrawText(vcl::RenderContext& rRenderContext, tools::Long nX, tools::Long nY, const OUString& rText, tools::Long nMin, tools::Long nMax)
339 {
340 tools::Rectangle aRect;
341 SalLayoutGlyphs* pTextLayout
342 = lcl_GetRulerTextGlyphs(rRenderContext, rText, maTextGlyphs[rText]);
343 rRenderContext.GetTextBoundRect(aRect, rText, 0, 0, -1, 0, nullptr, pTextLayout);
344
345 tools::Long nShiftX = ( aRect.GetWidth() / 2 ) + aRect.Left();
346 tools::Long nShiftY = ( aRect.GetHeight() / 2 ) + aRect.Top();
347
348 if ( (nX > -RULER_CLIP) && (nX < mnVirWidth + RULER_CLIP) && ( nX < nMax - nShiftX ) && ( nX > nMin + nShiftX ) )
349 {
350 if ( mnWinStyle & WB_HORZ )
351 rRenderContext.DrawText(Point(nX - nShiftX, nY - nShiftY), rText, 0, -1, nullptr,
352 nullptr, pTextLayout);
353 else
354 rRenderContext.DrawText(Point(nY - nShiftX, nX - nShiftY), rText, 0, -1, nullptr,
355 nullptr, pTextLayout);
356 }
357 }
358
ImplInvertLines(vcl::RenderContext & rRenderContext)359 void Ruler::ImplInvertLines(vcl::RenderContext& rRenderContext)
360 {
361 // Position lines
362 if (mpData->pLines.empty() || !mbActive || mbDrag || mbFormat || (mnUpdateFlags & RULER_UPDATE_LINES) )
363 return;
364
365 tools::Long nNullWinOff = mpData->nNullVirOff + mnVirOff;
366 tools::Long nRulX1 = mpData->nRulVirOff + mnVirOff;
367 tools::Long nRulX2 = nRulX1 + mpData->nRulWidth;
368 tools::Long nY = (RULER_OFF * 2) + mnVirHeight - 1;
369
370 // Calculate rectangle
371 tools::Rectangle aRect;
372 if (mnWinStyle & WB_HORZ)
373 aRect.SetBottom( nY );
374 else
375 aRect.SetRight( nY );
376
377 // Draw lines
378 for (const RulerLine & rLine : mpData->pLines)
379 {
380 const tools::Long n = rLine.nPos + nNullWinOff;
381 if ((n >= nRulX1) && (n < nRulX2))
382 {
383 if (mnWinStyle & WB_HORZ )
384 {
385 aRect.SetLeft( n );
386 aRect.SetRight( n );
387 }
388 else
389 {
390 aRect.SetTop( n );
391 aRect.SetBottom( n );
392 }
393 tools::Rectangle aTempRect = aRect;
394
395 if (mnWinStyle & WB_HORZ)
396 aTempRect.SetBottom( RULER_OFF - 1 );
397 else
398 aTempRect.SetRight( RULER_OFF - 1 );
399
400 rRenderContext.Erase(aTempRect);
401
402 if (mnWinStyle & WB_HORZ)
403 {
404 aTempRect.SetBottom( aRect.Bottom() );
405 aTempRect.SetTop( aTempRect.Bottom() - RULER_OFF + 1 );
406 }
407 else
408 {
409 aTempRect.SetRight( aRect.Right() );
410 aTempRect.SetLeft( aTempRect.Right() - RULER_OFF + 1 );
411 }
412 rRenderContext.Erase(aTempRect);
413 GetOutDev()->Invert(aRect);
414 }
415 }
416 mnUpdateFlags = 0;
417 }
418
ImplDrawTicks(vcl::RenderContext & rRenderContext,tools::Long nMin,tools::Long nMax,tools::Long nStart,tools::Long nTop,tools::Long nBottom)419 void Ruler::ImplDrawTicks(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nStart, tools::Long nTop, tools::Long nBottom)
420 {
421 double nCenter = nTop + ((nBottom - nTop) / 2);
422
423 tools::Long nTickLength3 = (nBottom - nTop) * 0.5;
424 tools::Long nTickLength2 = nTickLength3 * 0.66;
425 tools::Long nTickLength1 = nTickLength2 * 0.66;
426
427 tools::Long nScale = ruler_tab.DPIScaleFactor;
428 tools::Long DPIOffset = nScale - 1;
429
430 double nTick4 = aImplRulerUnitTab[mnUnitIndex].nTick4;
431 double nTick2 = 0;
432 double nTickCount = aImplRulerUnitTab[mnUnitIndex].nTick1 / nScale;
433 double nTickUnit = 0;
434 tools::Long nTickWidth;
435 bool bNoTicks = false;
436
437 Size aPixSize = rRenderContext.LogicToPixel(Size(nTick4, nTick4), maMapMode);
438
439 if (mnUnitIndex == RULER_UNIT_CHAR)
440 {
441 if (mnCharWidth == 0)
442 mnCharWidth = 371;
443 nTick4 = mnCharWidth * 2;
444 nTick2 = mnCharWidth;
445 nTickCount = mnCharWidth;
446 nTickUnit = mnCharWidth;
447 }
448 else if (mnUnitIndex == RULER_UNIT_LINE)
449 {
450 if (mnLineHeight == 0)
451 mnLineHeight = 551;
452 nTick4 = mnLineHeight * 2;
453 nTick2 = mnLineHeight;
454 nTickUnit = mnLineHeight;
455 nTickCount = mnLineHeight;
456 }
457
458 if (mnWinStyle & WB_HORZ)
459 {
460 nTickWidth = aPixSize.Width();
461 }
462 else
463 {
464 vcl::Font aFont = rRenderContext.GetFont();
465 if (mnWinStyle & WB_RIGHT_ALIGNED)
466 aFont.SetOrientation(2700_deg10);
467 else
468 aFont.SetOrientation(900_deg10);
469 rRenderContext.SetFont(aFont);
470 nTickWidth = aPixSize.Height();
471 }
472
473 tools::Long nMaxWidth = rRenderContext.PixelToLogic(Size(mpData->nPageWidth, 0), maMapMode).Width();
474 if (nMaxWidth < 0)
475 nMaxWidth = -nMaxWidth;
476
477 if ((mnUnitIndex == RULER_UNIT_CHAR) || (mnUnitIndex == RULER_UNIT_LINE))
478 nMaxWidth /= nTickUnit;
479 else
480 nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
481
482 OUString aNumString = OUString::number(nMaxWidth);
483 tools::Long nTxtWidth = rRenderContext.GetTextWidth( aNumString );
484 const tools::Long nTextOff = 4;
485
486 // Determine the number divider for ruler drawn numbers - means which numbers
487 // should be shown on the ruler and which should be skipped because the ruler
488 // is not big enough to draw them
489 if (nTickWidth < nTxtWidth + nTextOff)
490 {
491 // Calculate the scale of the ruler
492 tools::Long nMulti = 1;
493 tools::Long nOrgTick4 = nTick4;
494
495 while (nTickWidth < nTxtWidth + nTextOff)
496 {
497 tools::Long nOldMulti = nMulti;
498 if (nTickWidth == 0)
499 nMulti *= 10;
500 else if (nMulti < 10)
501 nMulti++;
502 else if (nMulti < 100)
503 nMulti += 10;
504 else if (nMulti < 1000)
505 nMulti += 100;
506 else
507 nMulti += 1000;
508
509 // Overflow - in this case don't draw ticks and exit
510 if (nMulti < nOldMulti)
511 {
512 bNoTicks = true;
513 break;
514 }
515
516 nTick4 = nOrgTick4 * nMulti;
517 aPixSize = rRenderContext.LogicToPixel(Size(nTick4, nTick4), maMapMode);
518 if (mnWinStyle & WB_HORZ)
519 nTickWidth = aPixSize.Width();
520 else
521 nTickWidth = aPixSize.Height();
522 }
523 nTickCount = nTick4;
524 }
525 else
526 {
527 rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetShadowColor());
528 }
529
530 if (bNoTicks)
531 return;
532
533 tools::Long n = 0;
534 double nTick = 0.0;
535 double nTick3 = 0;
536
537 if ((mnUnitIndex != RULER_UNIT_CHAR) && (mnUnitIndex != RULER_UNIT_LINE))
538 {
539 nTick2 = aImplRulerUnitTab[mnUnitIndex].nTick2;
540 nTick3 = aImplRulerUnitTab[mnUnitIndex].nTick3;
541 }
542
543 Size nTickGapSize;
544
545 nTickGapSize = rRenderContext.LogicToPixel(Size(nTickCount, nTickCount), maMapMode);
546 tools::Long nTickGap1 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
547 nTickGapSize = rRenderContext.LogicToPixel(Size(nTick2, nTick2), maMapMode);
548 tools::Long nTickGap2 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
549 nTickGapSize = rRenderContext.LogicToPixel(Size(nTick3, nTick3), maMapMode);
550 tools::Long nTickGap3 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
551
552 while (((nStart - n) >= nMin) || ((nStart + n) <= nMax))
553 {
554 // Null point
555 if (nTick == 0.0)
556 {
557 if (nStart > nMin)
558 {
559 // 0 is only painted when Margin1 is not equal to zero
560 if ((mpData->nMargin1Style & RulerMarginStyle::Invisible) || (mpData->nMargin1 != 0))
561 {
562 aNumString = "0";
563 ImplVDrawText(rRenderContext, nStart, nCenter, aNumString);
564 }
565 }
566 }
567 else
568 {
569 aPixSize = rRenderContext.LogicToPixel(Size(nTick, nTick), maMapMode);
570
571 if (mnWinStyle & WB_HORZ)
572 n = aPixSize.Width();
573 else
574 n = aPixSize.Height();
575
576 // Tick4 - Output (Text)
577 double aStep = nTick / nTick4;
578 double aRest = std::abs(aStep - std::floor(aStep));
579 double nAcceptanceDelta = 0.0001;
580
581 if (aRest < nAcceptanceDelta)
582 {
583 if ((mnUnitIndex == RULER_UNIT_CHAR) || (mnUnitIndex == RULER_UNIT_LINE))
584 aNumString = OUString::number(nTick / nTickUnit);
585 else
586 aNumString = OUString::number(nTick / aImplRulerUnitTab[mnUnitIndex].nTickUnit);
587
588 tools::Long nHorizontalLocation = nStart + n;
589 ImplVDrawText(rRenderContext, nHorizontalLocation, nCenter, aNumString, nMin, nMax);
590
591 if (nMin < nHorizontalLocation && nHorizontalLocation < nMax)
592 {
593 ImplVDrawRect(rRenderContext, nHorizontalLocation, nBottom - 1 * nScale, nHorizontalLocation + DPIOffset, nBottom);
594 ImplVDrawRect(rRenderContext, nHorizontalLocation, nTop, nHorizontalLocation + DPIOffset, nTop + 1 * nScale);
595 }
596
597 nHorizontalLocation = nStart - n;
598 ImplVDrawText(rRenderContext, nHorizontalLocation, nCenter, aNumString, nMin, nMax);
599
600 if (nMin < nHorizontalLocation && nHorizontalLocation < nMax)
601 {
602 ImplVDrawRect(rRenderContext, nHorizontalLocation, nBottom,
603 nHorizontalLocation + DPIOffset, nBottom - 1 * nScale);
604 ImplVDrawRect(rRenderContext, nHorizontalLocation, nTop,
605 nHorizontalLocation + DPIOffset, nTop + 1 * nScale);
606 }
607 }
608 // Tick/Tick2 - Output (Strokes)
609 else
610 {
611 tools::Long nTickLength = nTickLength1;
612
613 aStep = (nTick / nTick2);
614 aRest = std::abs(aStep - std::floor(aStep));
615 if (aRest < nAcceptanceDelta)
616 nTickLength = nTickLength2;
617
618 aStep = (nTick / nTick3);
619 aRest = std::abs(aStep - std::floor(aStep));
620 if (aRest < nAcceptanceDelta )
621 nTickLength = nTickLength3;
622
623 if ((nTickLength == nTickLength1 && nTickGap1 > 6) ||
624 (nTickLength == nTickLength2 && nTickGap2 > 6) ||
625 (nTickLength == nTickLength3 && nTickGap3 > 6))
626 {
627 tools::Long nT1 = nCenter - (nTickLength / 2.0);
628 tools::Long nT2 = nT1 + nTickLength - 1;
629 tools::Long nT;
630
631 nT = nStart + n;
632
633 if (nT < nMax)
634 ImplVDrawRect(rRenderContext, nT, nT1, nT + DPIOffset, nT2);
635 nT = nStart - n;
636 if (nT > nMin)
637 ImplVDrawRect(rRenderContext, nT, nT1, nT + DPIOffset, nT2);
638 }
639 }
640 }
641 nTick += nTickCount;
642 }
643 }
644
ImplDrawBorders(vcl::RenderContext & rRenderContext,tools::Long nMin,tools::Long nMax,tools::Long nVirTop,tools::Long nVirBottom)645 void Ruler::ImplDrawBorders(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom)
646 {
647 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
648 tools::Long n;
649 tools::Long n1;
650 tools::Long n2;
651 tools::Long nTemp1;
652 tools::Long nTemp2;
653
654 for (std::vector<RulerBorder>::size_type i = 0; i < mpData->pBorders.size(); i++)
655 {
656 if (mpData->pBorders[i].nStyle & RulerBorderStyle::Invisible)
657 continue;
658
659 n1 = mpData->pBorders[i].nPos + mpData->nNullVirOff;
660 n2 = n1 + mpData->pBorders[i].nWidth;
661
662 if (((n1 >= nMin) && (n1 <= nMax)) || ((n2 >= nMin) && (n2 <= nMax)))
663 {
664 if ((n2 - n1) > 3)
665 {
666 rRenderContext.SetLineColor();
667 rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
668 ImplVDrawRect(rRenderContext, n1, nVirTop, n2, nVirBottom);
669
670 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
671 ImplVDrawLine(rRenderContext, n1 + 1, nVirTop, n1 + 1, nVirBottom);
672 ImplVDrawLine(rRenderContext, n1, nVirTop, n2, nVirTop);
673
674 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
675 ImplVDrawLine(rRenderContext, n1, nVirTop, n1, nVirBottom);
676 ImplVDrawLine(rRenderContext, n1, nVirBottom, n2, nVirBottom);
677 ImplVDrawLine(rRenderContext, n2 - 1, nVirTop, n2 - 1, nVirBottom);
678
679 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
680 ImplVDrawLine(rRenderContext, n2, nVirTop, n2, nVirBottom);
681
682 if (mpData->pBorders[i].nStyle & RulerBorderStyle::Variable)
683 {
684 if (n2 - n1 > RULER_VAR_SIZE + 4)
685 {
686 nTemp1 = n1 + (((n2 - n1 + 1) - RULER_VAR_SIZE) / 2);
687 nTemp2 = nVirTop + (((nVirBottom - nVirTop + 1) - RULER_VAR_SIZE) / 2);
688 tools::Long nTemp3 = nTemp1 + RULER_VAR_SIZE - 1;
689 tools::Long nTemp4 = nTemp2 + RULER_VAR_SIZE - 1;
690 tools::Long nTempY = nTemp2;
691
692 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
693 while (nTempY <= nTemp4)
694 {
695 ImplVDrawLine(rRenderContext, nTemp1, nTempY, nTemp3, nTempY);
696 nTempY += 2;
697 }
698
699 nTempY = nTemp2 + 1;
700 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
701 while (nTempY <= nTemp4)
702 {
703 ImplVDrawLine(rRenderContext, nTemp1, nTempY, nTemp3, nTempY);
704 nTempY += 2;
705 }
706 }
707 }
708
709 if (mpData->pBorders[i].nStyle & RulerBorderStyle::Sizeable)
710 {
711 if (n2 - n1 > RULER_VAR_SIZE + 10)
712 {
713 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
714 ImplVDrawLine(rRenderContext, n1 + 4, nVirTop + 3, n1 + 4, nVirBottom - 3);
715 ImplVDrawLine(rRenderContext, n2 - 5, nVirTop + 3, n2 - 5, nVirBottom - 3);
716 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
717 ImplVDrawLine(rRenderContext, n1 + 5, nVirTop + 3, n1 + 5, nVirBottom - 3);
718 ImplVDrawLine(rRenderContext, n2 - 4, nVirTop + 3, n2 - 4, nVirBottom - 3);
719 }
720 }
721 }
722 else
723 {
724 n = n1 + ((n2 - n1) / 2);
725 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
726
727 ImplVDrawLine(rRenderContext, n - 1, nVirTop, n - 1, nVirBottom);
728 ImplVDrawLine(rRenderContext, n + 1, nVirTop, n + 1, nVirBottom);
729 rRenderContext.SetLineColor();
730 rRenderContext.SetFillColor(rStyleSettings.GetWindowColor());
731 ImplVDrawRect(rRenderContext, n, nVirTop, n, nVirBottom);
732 }
733 }
734 }
735 }
736
ImplDrawIndent(vcl::RenderContext & rRenderContext,const tools::Polygon & rPoly,bool bIsHit)737 void Ruler::ImplDrawIndent(vcl::RenderContext& rRenderContext, const tools::Polygon& rPoly, bool bIsHit)
738 {
739 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
740
741 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
742 rRenderContext.SetFillColor(bIsHit ? rStyleSettings.GetDarkShadowColor() : rStyleSettings.GetWorkspaceColor());
743 tools::Polygon aPolygon(rPoly);
744 aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
745 rRenderContext.DrawPolygon(aPolygon);
746 }
747
ImplDrawIndents(vcl::RenderContext & rRenderContext,tools::Long nMin,tools::Long nMax,tools::Long nVirTop,tools::Long nVirBottom)748 void Ruler::ImplDrawIndents(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom)
749 {
750 tools::Long n;
751 tools::Long nIndentHeight = (mnVirHeight / 2) - 1;
752 tools::Long nIndentWidth2 = nIndentHeight-3;
753
754 tools::Polygon aPoly(5);
755
756 for (std::vector<RulerIndent>::size_type j = 0; j < mpData->pIndents.size(); j++)
757 {
758 if (mpData->pIndents[j].bInvisible)
759 continue;
760
761 RulerIndentStyle nIndentStyle = mpData->pIndents[j].nStyle;
762
763 n = mpData->pIndents[j].nPos+mpData->nNullVirOff;
764
765 if ((n >= nMin) && (n <= nMax))
766 {
767 if (nIndentStyle == RulerIndentStyle::Bottom)
768 {
769 aPoly.SetPoint(Point(n + 0, nVirBottom - nIndentHeight), 0);
770 aPoly.SetPoint(Point(n - nIndentWidth2, nVirBottom - 3), 1);
771 aPoly.SetPoint(Point(n - nIndentWidth2, nVirBottom), 2);
772 aPoly.SetPoint(Point(n + nIndentWidth2, nVirBottom), 3);
773 aPoly.SetPoint(Point(n + nIndentWidth2, nVirBottom - 3), 4);
774 }
775 else
776 {
777 aPoly.SetPoint(Point(n + 0, nVirTop + nIndentHeight), 0);
778 aPoly.SetPoint(Point(n - nIndentWidth2, nVirTop + 3), 1);
779 aPoly.SetPoint(Point(n - nIndentWidth2, nVirTop), 2);
780 aPoly.SetPoint(Point(n + nIndentWidth2, nVirTop), 3);
781 aPoly.SetPoint(Point(n + nIndentWidth2, nVirTop + 3), 4);
782 }
783
784 if (0 == (mnWinStyle & WB_HORZ))
785 {
786 Point aTmp;
787 for (sal_uInt16 i = 0; i < 5; i++)
788 {
789 aTmp = aPoly[i];
790 Point aSet(nVirBottom - aTmp.Y(), aTmp.X());
791 aPoly[i] = aSet;
792 }
793 }
794 bool bIsHit = false;
795 if (mxCurrentHitTest != nullptr && mxCurrentHitTest->eType == RulerType::Indent)
796 {
797 bIsHit = mxCurrentHitTest->nAryPos == j;
798 }
799 else if(mbDrag && meDragType == RulerType::Indent)
800 {
801 bIsHit = mnDragAryPos == j;
802 }
803 ImplDrawIndent(rRenderContext, aPoly, bIsHit);
804 }
805 }
806 }
807
ImplCenterTabPos(Point & rPos,sal_uInt16 nTabStyle)808 static void ImplCenterTabPos(Point& rPos, sal_uInt16 nTabStyle)
809 {
810 bool bRTL = 0 != (nTabStyle & RULER_TAB_RTL);
811 nTabStyle &= RULER_TAB_STYLE;
812 rPos.AdjustY(ruler_tab.height/2 );
813
814 if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||
815 ( bRTL && nTabStyle == RULER_TAB_RIGHT) )
816 {
817 rPos.AdjustX( -(ruler_tab.width / 2) );
818 }
819 else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||
820 ( bRTL && nTabStyle == RULER_TAB_LEFT) )
821 {
822 rPos.AdjustX(ruler_tab.width / 2 );
823 }
824 }
825
lcl_RotateRect_Impl(tools::Rectangle & rRect,const tools::Long nReference,bool bRightAligned)826 static void lcl_RotateRect_Impl(tools::Rectangle& rRect, const tools::Long nReference, bool bRightAligned)
827 {
828 if (rRect.IsEmpty())
829 return;
830
831 tools::Rectangle aTmp(rRect);
832 rRect.SetTop( aTmp.Left() );
833 rRect.SetBottom( aTmp.Right() );
834 rRect.SetLeft( aTmp.Top() );
835 rRect.SetRight( aTmp.Bottom() );
836
837 if (bRightAligned)
838 {
839 tools::Long nRef = 2 * nReference;
840 rRect.SetLeft( nRef - rRect.Left() );
841 rRect.SetRight( nRef - rRect.Right() );
842 }
843 }
844
ImplDrawRulerTab(vcl::RenderContext & rRenderContext,const Point & rPos,sal_uInt16 nStyle,WinBits nWinBits)845 static void ImplDrawRulerTab(vcl::RenderContext& rRenderContext, const Point& rPos,
846 sal_uInt16 nStyle, WinBits nWinBits)
847 {
848 if (nStyle & RULER_STYLE_INVISIBLE)
849 return;
850
851 sal_uInt16 nTabStyle = nStyle & RULER_TAB_STYLE;
852 bool bRTL = 0 != (nStyle & RULER_TAB_RTL);
853
854 // Scale by the screen DPI scaling factor
855 // However when doing this some of the rectangles
856 // drawn become asymmetric due to the +1 offsets
857 sal_uInt16 DPIOffset = rRenderContext.GetDPIScaleFactor() - 1;
858
859 // A tabstop is drawn using three rectangles
860 tools::Rectangle aRect1; // A horizontal short line
861 tools::Rectangle aRect2; // A vertical short line
862 tools::Rectangle aRect3; // A small square
863
864 aRect3.SetEmpty();
865
866 if (nTabStyle == RULER_TAB_DEFAULT)
867 {
868 aRect1.SetLeft( rPos.X() - ruler_tab.dwidth2 + 1 );
869 aRect1.SetTop( rPos.Y() - ruler_tab.dheight2 + 1 );
870 aRect1.SetRight( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth + DPIOffset );
871 aRect1.SetBottom( rPos.Y() );
872
873 aRect2.SetLeft( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth3 );
874 aRect2.SetTop( rPos.Y() - ruler_tab.dheight + 1 );
875 aRect2.SetRight( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth3 + ruler_tab.dwidth4 - 1 );
876 aRect2.SetBottom( rPos.Y() );
877
878 }
879 else if ((!bRTL && nTabStyle == RULER_TAB_LEFT) || (bRTL && nTabStyle == RULER_TAB_RIGHT))
880 {
881 aRect1.SetLeft( rPos.X() );
882 aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
883 aRect1.SetRight( rPos.X() + ruler_tab.width - 1 );
884 aRect1.SetBottom( rPos.Y() );
885
886 aRect2.SetLeft( rPos.X() );
887 aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
888 aRect2.SetRight( rPos.X() + ruler_tab.width2 - 1 );
889 aRect2.SetBottom( rPos.Y() );
890 }
891 else if ((!bRTL && nTabStyle == RULER_TAB_RIGHT) || (bRTL && nTabStyle == RULER_TAB_LEFT))
892 {
893 aRect1.SetLeft( rPos.X() - ruler_tab.width + 1 );
894 aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
895 aRect1.SetRight( rPos.X() );
896 aRect1.SetBottom( rPos.Y() );
897
898 aRect2.SetLeft( rPos.X() - ruler_tab.width2 + 1 );
899 aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
900 aRect2.SetRight( rPos.X() );
901 aRect2.SetBottom( rPos.Y() );
902 }
903 else
904 {
905 aRect1.SetLeft( rPos.X() - ruler_tab.cwidth2 + 1 );
906 aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
907 aRect1.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth + DPIOffset );
908 aRect1.SetBottom( rPos.Y() );
909
910 aRect2.SetLeft( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth3 );
911 aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
912 aRect2.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth3 + ruler_tab.cwidth4 - 1 );
913 aRect2.SetBottom( rPos.Y() );
914
915 if (nTabStyle == RULER_TAB_DECIMAL)
916 {
917 aRect3.SetLeft( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth - 1 );
918 aRect3.SetTop( rPos.Y() - ruler_tab.height + 1 + 1 - DPIOffset );
919 aRect3.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth + DPIOffset );
920 aRect3.SetBottom( rPos.Y() - ruler_tab.height + 1 + 2 );
921 }
922 }
923 if (0 == (nWinBits & WB_HORZ))
924 {
925 bool bRightAligned = 0 != (nWinBits & WB_RIGHT_ALIGNED);
926 lcl_RotateRect_Impl(aRect1, rPos.Y(), bRightAligned);
927 lcl_RotateRect_Impl(aRect2, rPos.Y(), bRightAligned);
928 lcl_RotateRect_Impl(aRect3, rPos.Y(), bRightAligned);
929 }
930 rRenderContext.DrawRect(aRect1);
931 rRenderContext.DrawRect(aRect2);
932
933 if (!aRect3.IsEmpty())
934 rRenderContext.DrawRect(aRect3);
935 }
936
ImplDrawTab(vcl::RenderContext & rRenderContext,const Point & rPos,sal_uInt16 nStyle)937 void Ruler::ImplDrawTab(vcl::RenderContext& rRenderContext, const Point& rPos, sal_uInt16 nStyle)
938 {
939 if (nStyle & RULER_STYLE_INVISIBLE)
940 return;
941
942 rRenderContext.SetLineColor();
943
944 if (nStyle & RULER_STYLE_DONTKNOW)
945 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetFaceColor());
946 else
947 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetDarkShadowColor());
948
949 if (mpData->bTextRTL)
950 nStyle |= RULER_TAB_RTL;
951
952 ImplDrawRulerTab(rRenderContext, rPos, nStyle, GetStyle());
953 }
954
ImplDrawTabs(vcl::RenderContext & rRenderContext,tools::Long nMin,tools::Long nMax,tools::Long nVirTop,tools::Long nVirBottom)955 void Ruler::ImplDrawTabs(vcl::RenderContext& rRenderContext, tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom)
956 {
957 for (const RulerTab & rTab : mpData->pTabs)
958 {
959 if (rTab.nStyle & RULER_STYLE_INVISIBLE)
960 continue;
961
962 tools::Long aPosition;
963 aPosition = rTab.nPos;
964 aPosition += +mpData->nNullVirOff;
965 tools::Long nTopBottom = (GetStyle() & WB_RIGHT_ALIGNED) ? nVirTop : nVirBottom;
966 if (nMin <= aPosition && aPosition <= nMax)
967 ImplDrawTab(rRenderContext, Point( aPosition, nTopBottom ), rTab.nStyle);
968 }
969 }
970
adjustSize(int nOrig)971 static int adjustSize(int nOrig)
972 {
973 if (nOrig <= 0)
974 return 0;
975
976 // make sure we return an odd number, that looks better in the ruler
977 return ( (3*nOrig) / 8) * 2 + 1;
978 }
979
ApplySettings(vcl::RenderContext & rRenderContext)980 void Ruler::ApplySettings(vcl::RenderContext& rRenderContext)
981 {
982 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
983
984 vcl::Font aFont = rStyleSettings.GetToolFont();
985 // make the font a bit smaller than default
986 Size aSize(adjustSize(aFont.GetFontSize().Width()), adjustSize(aFont.GetFontSize().Height()));
987 aFont.SetFontSize(aSize);
988
989 ApplyControlFont(rRenderContext, aFont);
990
991 ApplyControlForeground(*GetOutDev(), rStyleSettings.GetDarkShadowColor());
992 SetTextFillColor();
993
994 Color aColor;
995 svtools::ColorConfig aColorConfig;
996 aColor = aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
997 ApplyControlBackground(rRenderContext, aColor);
998 }
999
ImplInitSettings(bool bFont,bool bForeground,bool bBackground)1000 void Ruler::ImplInitSettings(bool bFont, bool bForeground, bool bBackground)
1001 {
1002 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1003
1004 if (bFont)
1005 {
1006 vcl::Font aFont = rStyleSettings.GetToolFont();
1007 // make the font a bit smaller than default
1008 Size aSize(adjustSize(aFont.GetFontSize().Width()), adjustSize(aFont.GetFontSize().Height()));
1009 aFont.SetFontSize(aSize);
1010
1011 ApplyControlFont(*GetOutDev(), aFont);
1012 }
1013
1014 if (bForeground || bFont)
1015 {
1016 ApplyControlForeground(*GetOutDev(), rStyleSettings.GetDarkShadowColor());
1017 SetTextFillColor();
1018 }
1019
1020 if (bBackground)
1021 {
1022 Color aColor;
1023 svtools::ColorConfig aColorConfig;
1024 aColor = aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
1025 ApplyControlBackground(*GetOutDev(), aColor);
1026 }
1027
1028 maVirDev->SetSettings( GetSettings() );
1029 maVirDev->SetBackground( GetBackground() );
1030 vcl::Font aFont = GetFont();
1031
1032 if (mnWinStyle & WB_VERT)
1033 aFont.SetOrientation(900_deg10);
1034
1035 maVirDev->SetFont(aFont);
1036 maVirDev->SetTextColor(GetTextColor());
1037 maVirDev->SetTextFillColor(GetTextFillColor());
1038 }
1039
ImplCalc()1040 void Ruler::ImplCalc()
1041 {
1042 // calculate offset
1043 mpData->nRulVirOff = mnWinOff + mpData->nPageOff;
1044 if ( mpData->nRulVirOff > mnVirOff )
1045 mpData->nRulVirOff -= mnVirOff;
1046 else
1047 mpData->nRulVirOff = 0;
1048 tools::Long nRulWinOff = mpData->nRulVirOff+mnVirOff;
1049
1050 // calculate non-visual part of the page
1051 tools::Long nNotVisPageWidth;
1052 if ( mpData->nPageOff < 0 )
1053 {
1054 nNotVisPageWidth = -(mpData->nPageOff);
1055 if ( nRulWinOff < mnWinOff )
1056 nNotVisPageWidth -= mnWinOff-nRulWinOff;
1057 }
1058 else
1059 nNotVisPageWidth = 0;
1060
1061 // calculate width
1062 if ( mnWinStyle & WB_HORZ )
1063 {
1064 if ( mbAutoWinWidth )
1065 mnWinWidth = mnWidth - mnVirOff;
1066 if ( mpData->bAutoPageWidth )
1067 mpData->nPageWidth = mnWinWidth;
1068 mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1069 if ( nRulWinOff+mpData->nRulWidth > mnWidth )
1070 mpData->nRulWidth = mnWidth-nRulWinOff;
1071 }
1072 else
1073 {
1074 if ( mbAutoWinWidth )
1075 mnWinWidth = mnHeight - mnVirOff;
1076 if ( mpData->bAutoPageWidth )
1077 mpData->nPageWidth = mnWinWidth;
1078 mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1079 if ( nRulWinOff+mpData->nRulWidth > mnHeight )
1080 mpData->nRulWidth = mnHeight-nRulWinOff;
1081 }
1082
1083 mbCalc = false;
1084 }
1085
ImplFormat(vcl::RenderContext const & rRenderContext)1086 void Ruler::ImplFormat(vcl::RenderContext const & rRenderContext)
1087 {
1088 // if already formatted, don't do it again
1089 if (!mbFormat)
1090 return;
1091
1092 // don't do anything if the window still has no size
1093 if (!mnVirWidth)
1094 return;
1095
1096 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1097 tools::Long nP1; // pixel position of Page1
1098 tools::Long nP2; // pixel position of Page2
1099 tools::Long nM1; // pixel position of Margin1
1100 tools::Long nM2; // pixel position of Margin2
1101 tools::Long nVirTop; // top/left corner
1102 tools::Long nVirBottom; // bottom/right corner
1103 tools::Long nVirLeft; // left/top corner
1104 tools::Long nVirRight; // right/bottom corner
1105 tools::Long nNullVirOff; // for faster calculation
1106
1107 // calculate values
1108 if (mbCalc)
1109 ImplCalc();
1110
1111 mpData->nNullVirOff = mnWinOff + mpData->nPageOff + mpData->nNullOff - mnVirOff;
1112
1113 nNullVirOff = mpData->nNullVirOff;
1114 nVirLeft = mpData->nRulVirOff;
1115 nVirRight = nVirLeft + mpData->nRulWidth - 1;
1116 nVirTop = 0;
1117 nVirBottom = mnVirHeight - 1;
1118
1119 if (!IsReallyVisible())
1120 return;
1121
1122 Size aVirDevSize;
1123
1124 // initialize VirtualDevice
1125 if (mnWinStyle & WB_HORZ)
1126 {
1127 aVirDevSize.setWidth( mnVirWidth );
1128 aVirDevSize.setHeight( mnVirHeight );
1129 }
1130 else
1131 {
1132 aVirDevSize.setHeight( mnVirWidth );
1133 aVirDevSize.setWidth( mnVirHeight );
1134 }
1135 if (aVirDevSize != maVirDev->GetOutputSizePixel())
1136 maVirDev->SetOutputSizePixel(aVirDevSize);
1137 else
1138 maVirDev->Erase();
1139
1140 // calculate margins
1141 if (!(mpData->nMargin1Style & RulerMarginStyle::Invisible))
1142 {
1143 nM1 = mpData->nMargin1 + nNullVirOff;
1144 if (mpData->bAutoPageWidth)
1145 {
1146 nP1 = nVirLeft;
1147 if (nM1 < nVirLeft)
1148 nP1--;
1149 }
1150 else
1151 nP1 = nNullVirOff - mpData->nNullOff;
1152 }
1153 else
1154 {
1155 nM1 = nVirLeft-1;
1156 nP1 = nM1;
1157 }
1158 if (!(mpData->nMargin2Style & RulerMarginStyle::Invisible))
1159 {
1160 nM2 = mpData->nMargin2 + nNullVirOff;
1161 if (mpData->bAutoPageWidth)
1162 {
1163 nP2 = nVirRight;
1164 if (nM2 > nVirRight)
1165 nP2++;
1166 }
1167 else
1168 nP2 = nNullVirOff - mpData->nNullOff + mpData->nPageWidth;
1169 if (nM2 > nP2)
1170 nM2 = nP2;
1171 }
1172 else
1173 {
1174 nM2 = nVirRight+1;
1175 nP2 = nM2;
1176 }
1177
1178 // top/bottom border
1179 maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
1180 ImplVDrawLine(*maVirDev, nVirLeft, nVirTop + 1, nM1, nVirTop + 1); //top left line
1181 ImplVDrawLine(*maVirDev, nM2, nVirTop + 1, nP2 - 1, nVirTop + 1); //top right line
1182
1183 nVirTop++;
1184 nVirBottom--;
1185
1186 // draw margin1, margin2 and in-between
1187 maVirDev->SetLineColor();
1188 maVirDev->SetFillColor(rStyleSettings.GetDialogColor());
1189 if (nM1 > nVirLeft)
1190 ImplVDrawRect(*maVirDev, nP1, nVirTop + 1, nM1, nVirBottom); //left gray rectangle
1191 if (nM2 < nP2)
1192 ImplVDrawRect(*maVirDev, nM2, nVirTop + 1, nP2, nVirBottom); //right gray rectangle
1193 if (nM2 - nM1 > 0)
1194 {
1195 maVirDev->SetFillColor(rStyleSettings.GetWindowColor());
1196 ImplVDrawRect(*maVirDev, nM1 + 1, nVirTop, nM2 - 1, nVirBottom); //center rectangle
1197 }
1198 maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
1199 if (nM1 > nVirLeft)
1200 {
1201 ImplVDrawLine(*maVirDev, nM1, nVirTop + 1, nM1, nVirBottom); //right line of the left rectangle
1202 ImplVDrawLine(*maVirDev, nP1, nVirBottom, nM1, nVirBottom); //bottom line of the left rectangle
1203 if (nP1 >= nVirLeft)
1204 {
1205 ImplVDrawLine(*maVirDev, nP1, nVirTop + 1, nP1, nVirBottom); //left line of the left rectangle
1206 ImplVDrawLine(*maVirDev, nP1, nVirBottom, nP1 + 1, nVirBottom); //?
1207 }
1208 }
1209 if (nM2 < nP2)
1210 {
1211 ImplVDrawLine(*maVirDev, nM2, nVirBottom, nP2 - 1, nVirBottom); //bottom line of the right rectangle
1212 ImplVDrawLine(*maVirDev, nM2, nVirTop + 1, nM2, nVirBottom); //left line of the right rectangle
1213 if (nP2 <= nVirRight + 1)
1214 ImplVDrawLine(*maVirDev, nP2 - 1, nVirTop + 1, nP2 - 1, nVirBottom); //right line of the right rectangle
1215 }
1216
1217 tools::Long nMin = nVirLeft;
1218 tools::Long nMax = nP2;
1219 tools::Long nStart = 0;
1220
1221 if (mpData->bTextRTL)
1222 nStart = mpData->nRightFrameMargin + nNullVirOff;
1223 else
1224 nStart = mpData->nLeftFrameMargin + nNullVirOff;
1225
1226 if (nP1 > nVirLeft)
1227 nMin++;
1228
1229 if (nP2 < nVirRight)
1230 nMax--;
1231
1232 // Draw captions
1233 ImplDrawTicks(*maVirDev, nMin, nMax, nStart, nVirTop, nVirBottom);
1234
1235 // Draw borders
1236 if (!mpData->pBorders.empty())
1237 ImplDrawBorders(*maVirDev, nVirLeft, nP2, nVirTop, nVirBottom);
1238
1239 // Draw indents
1240 if (!mpData->pIndents.empty())
1241 ImplDrawIndents(*maVirDev, nVirLeft, nP2, nVirTop - 1, nVirBottom + 1);
1242
1243 // Tabs
1244 if (!mpData->pTabs.empty())
1245 ImplDrawTabs(*maVirDev, nVirLeft, nP2, nVirTop-1, nVirBottom + 1);
1246
1247 mbFormat = false;
1248 }
1249
ImplInitExtraField(bool bUpdate)1250 void Ruler::ImplInitExtraField( bool bUpdate )
1251 {
1252 Size aWinSize = GetOutputSizePixel();
1253
1254 // extra field evaluate
1255 if ( mnWinStyle & WB_EXTRAFIELD )
1256 {
1257 maExtraRect.SetLeft( RULER_OFF );
1258 maExtraRect.SetTop( RULER_OFF );
1259 maExtraRect.SetRight( RULER_OFF + mnVirHeight - 1 );
1260 maExtraRect.SetBottom( RULER_OFF + mnVirHeight - 1 );
1261 if(mpData->bTextRTL)
1262 {
1263 if(mnWinStyle & WB_HORZ)
1264 maExtraRect.Move(aWinSize.Width() - maExtraRect.GetWidth() - maExtraRect.Left(), 0);
1265 else
1266 maExtraRect.Move(0, aWinSize.Height() - maExtraRect.GetHeight() - maExtraRect.Top());
1267 mnVirOff = 0;
1268 }
1269 else
1270 mnVirOff = maExtraRect.Right()+1;
1271
1272 }
1273 else
1274 {
1275 maExtraRect.SetEmpty();
1276 mnVirOff = 0;
1277 }
1278
1279 // mnVirWidth depends on mnVirOff
1280 if ( (mnVirWidth > RULER_MIN_SIZE) ||
1281 ((aWinSize.Width() > RULER_MIN_SIZE) && (aWinSize.Height() > RULER_MIN_SIZE)) )
1282 {
1283 if ( mnWinStyle & WB_HORZ )
1284 mnVirWidth = aWinSize.Width()-mnVirOff;
1285 else
1286 mnVirWidth = aWinSize.Height()-mnVirOff;
1287
1288 if ( mnVirWidth < RULER_MIN_SIZE )
1289 mnVirWidth = 0;
1290 }
1291
1292 if ( bUpdate )
1293 {
1294 mbCalc = true;
1295 mbFormat = true;
1296 Invalidate();
1297 }
1298 }
1299
ImplDraw(vcl::RenderContext & rRenderContext)1300 void Ruler::ImplDraw(vcl::RenderContext& rRenderContext)
1301 {
1302 if (mbFormat)
1303 {
1304 ImplFormat(rRenderContext);
1305 }
1306
1307 if (!IsReallyVisible())
1308 return;
1309
1310 // output the ruler to the virtual device
1311 Point aOffPos;
1312 Size aVirDevSize = maVirDev->GetOutputSizePixel();
1313
1314 if (mnWinStyle & WB_HORZ)
1315 {
1316 aOffPos.setX( mnVirOff );
1317 if (mpData->bTextRTL)
1318 aVirDevSize.AdjustWidth( -(maExtraRect.GetWidth()) );
1319
1320 aOffPos.setY( RULER_OFF );
1321 }
1322 else
1323 {
1324 aOffPos.setX( RULER_OFF );
1325 aOffPos.setY( mnVirOff );
1326 }
1327 rRenderContext.DrawOutDev(aOffPos, aVirDevSize, Point(), aVirDevSize, *maVirDev);
1328
1329 // redraw positionlines
1330 ImplInvertLines(rRenderContext);
1331 }
1332
ImplDrawExtra(vcl::RenderContext & rRenderContext)1333 void Ruler::ImplDrawExtra(vcl::RenderContext& rRenderContext)
1334 {
1335 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1336 tools::Rectangle aRect = maExtraRect;
1337 bool bEraseRect = false;
1338
1339 aRect.AdjustLeft(2 );
1340 aRect.AdjustTop(2 );
1341 aRect.AdjustRight( -2 );
1342 aRect.AdjustBottom( -2 );
1343
1344 if (mnExtraStyle & RULER_STYLE_HIGHLIGHT)
1345 {
1346 rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
1347 bEraseRect = true;
1348 }
1349
1350 if (bEraseRect)
1351 {
1352 rRenderContext.SetLineColor();
1353 rRenderContext.DrawRect(aRect);
1354 }
1355
1356 // output content
1357 if (meExtraType == RulerExtra::NullOffset)
1358 {
1359 rRenderContext.SetLineColor(rStyleSettings.GetButtonTextColor());
1360 rRenderContext.DrawLine(Point(aRect.Left() + 1, aRect.Top() + 4),
1361 Point(aRect.Right() - 1, aRect.Top() + 4));
1362 rRenderContext.DrawLine(Point(aRect.Left() + 4, aRect.Top() + 1),
1363 Point(aRect.Left() + 4, aRect.Bottom() - 1));
1364 }
1365 else if (meExtraType == RulerExtra::Tab)
1366 {
1367 sal_uInt16 nTabStyle = mnExtraStyle & RULER_TAB_STYLE;
1368 if (mpData->bTextRTL)
1369 nTabStyle |= RULER_TAB_RTL;
1370 Point aCenter = aRect.Center();
1371 Point aDraw(aCenter);
1372 ImplCenterTabPos(aDraw, nTabStyle);
1373 WinBits nWinBits = GetStyle();
1374 if (0 == (nWinBits & WB_HORZ))
1375 {
1376 if ((nWinBits & WB_RIGHT_ALIGNED) != 0)
1377 aDraw.setY( 2 * aCenter.Y() - aDraw.Y() );
1378
1379 if (mpData->bTextRTL)
1380 {
1381 tools::Long nTemp = aDraw.X();
1382 aDraw.setX( aDraw.Y() );
1383 aDraw.setY( nTemp );
1384 }
1385 }
1386 ImplDrawTab(rRenderContext, aDraw, nTabStyle);
1387 }
1388 }
1389
ImplUpdate(bool bMustCalc)1390 void Ruler::ImplUpdate( bool bMustCalc )
1391 {
1392 // clear lines in this place so they aren't considered at recalculation
1393 if (!mbFormat)
1394 Invalidate(InvalidateFlags::NoErase);
1395
1396 // set flags
1397 if (bMustCalc)
1398 mbCalc = true;
1399 mbFormat = true;
1400
1401 // abort if we are dragging as drag-handler will update the ruler after drag is finished
1402 if (mbDrag)
1403 return;
1404
1405 // otherwise trigger update
1406 if (IsReallyVisible() && IsUpdateMode())
1407 {
1408 Invalidate(InvalidateFlags::NoErase);
1409 }
1410 }
1411
ImplDoHitTest(const Point & rPos,RulerSelection * pHitTest,bool bRequireStyle,RulerIndentStyle nRequiredStyle) const1412 bool Ruler::ImplDoHitTest( const Point& rPos, RulerSelection* pHitTest,
1413 bool bRequireStyle, RulerIndentStyle nRequiredStyle ) const
1414 {
1415 sal_Int32 i;
1416 sal_uInt16 nStyle;
1417 tools::Long nHitBottom;
1418 tools::Long nX;
1419 tools::Long nY;
1420 tools::Long n1;
1421
1422 if ( !mbActive )
1423 return false;
1424
1425 // determine positions
1426 bool bIsHori = 0 != (mnWinStyle & WB_HORZ);
1427 if ( bIsHori )
1428 {
1429 nX = rPos.X();
1430 nY = rPos.Y();
1431 }
1432 else
1433 {
1434 nX = rPos.Y();
1435 nY = rPos.X();
1436 }
1437 nHitBottom = mnVirHeight + (RULER_OFF * 2);
1438
1439 // #i32608#
1440 pHitTest->nAryPos = 0;
1441 pHitTest->mnDragSize = RulerDragSize::Move;
1442 pHitTest->bSize = false;
1443 pHitTest->bSizeBar = false;
1444
1445 // so that leftover tabs and indents are taken into account
1446 tools::Long nXExtraOff;
1447 if ( !mpData->pTabs.empty() || !mpData->pIndents.empty() )
1448 nXExtraOff = (mnVirHeight / 2) - 4;
1449 else
1450 nXExtraOff = 0;
1451
1452 // test if outside
1453 nX -= mnVirOff;
1454 if ( (nX < mpData->nRulVirOff - nXExtraOff) ||
1455 (nX > mpData->nRulVirOff + mpData->nRulWidth + nXExtraOff) ||
1456 (nY < 0) ||
1457 (nY > nHitBottom) )
1458 {
1459 pHitTest->nPos = 0;
1460 pHitTest->eType = RulerType::Outside;
1461 return false;
1462 }
1463
1464 nX -= mpData->nNullVirOff;
1465 pHitTest->nPos = nX;
1466 pHitTest->eType = RulerType::DontKnow;
1467
1468 // first test the tabs
1469 tools::Rectangle aRect;
1470 if ( !mpData->pTabs.empty() )
1471 {
1472 aRect.SetBottom( nHitBottom );
1473 aRect.SetTop( aRect.Bottom() - ruler_tab.height - RULER_OFF );
1474
1475 for ( i = mpData->pTabs.size() - 1; i >= 0; i-- )
1476 {
1477 nStyle = mpData->pTabs[i].nStyle;
1478 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1479 {
1480 nStyle &= RULER_TAB_STYLE;
1481
1482 // default tabs are only shown (no action)
1483 if ( nStyle != RULER_TAB_DEFAULT )
1484 {
1485 n1 = mpData->pTabs[i].nPos;
1486
1487 if ( nStyle == RULER_TAB_LEFT )
1488 {
1489 aRect.SetLeft( n1 );
1490 aRect.SetRight( n1 + ruler_tab.width - 1 );
1491 }
1492 else if ( nStyle == RULER_TAB_RIGHT )
1493 {
1494 aRect.SetRight( n1 );
1495 aRect.SetLeft( n1 - ruler_tab.width - 1 );
1496 }
1497 else
1498 {
1499 aRect.SetLeft( n1 - ruler_tab.cwidth2 + 1 );
1500 aRect.SetRight( n1 - ruler_tab.cwidth2 + ruler_tab.cwidth );
1501 }
1502
1503 if ( aRect.IsInside( Point( nX, nY ) ) )
1504 {
1505 pHitTest->eType = RulerType::Tab;
1506 pHitTest->nAryPos = i;
1507 return true;
1508 }
1509 }
1510 }
1511 }
1512 }
1513
1514 // Indents
1515 if ( !mpData->pIndents.empty() )
1516 {
1517 tools::Long nIndentHeight = (mnVirHeight / 2) - 1;
1518 tools::Long nIndentWidth2 = nIndentHeight - 3;
1519
1520 for ( i = mpData->pIndents.size(); i; i-- )
1521 {
1522 RulerIndentStyle nIndentStyle = mpData->pIndents[i-1].nStyle;
1523 if ( (! bRequireStyle || nIndentStyle == nRequiredStyle) &&
1524 !mpData->pIndents[i-1].bInvisible )
1525 {
1526 n1 = mpData->pIndents[i-1].nPos;
1527
1528 if ( (nIndentStyle == RulerIndentStyle::Bottom) != !bIsHori )
1529 {
1530 aRect.SetLeft( n1-nIndentWidth2 );
1531 aRect.SetRight( n1+nIndentWidth2 );
1532 aRect.SetTop( nHitBottom-nIndentHeight-RULER_OFF+1 );
1533 aRect.SetBottom( nHitBottom );
1534 }
1535 else
1536 {
1537 aRect.SetLeft( n1-nIndentWidth2 );
1538 aRect.SetRight( n1+nIndentWidth2 );
1539 aRect.SetTop( 0 );
1540 aRect.SetBottom( nIndentHeight+RULER_OFF-1 );
1541 }
1542
1543 if ( aRect.IsInside( Point( nX, nY ) ) )
1544 {
1545 pHitTest->eType = RulerType::Indent;
1546 pHitTest->nAryPos = i-1;
1547 return true;
1548 }
1549 }
1550 }
1551 }
1552
1553 // test the borders
1554 int nBorderTolerance = 1;
1555 if(pHitTest->bExpandTest)
1556 {
1557 nBorderTolerance++;
1558 }
1559
1560 for ( i = mpData->pBorders.size(); i; i-- )
1561 {
1562 n1 = mpData->pBorders[i-1].nPos;
1563 tools::Long n2 = n1 + mpData->pBorders[i-1].nWidth;
1564
1565 // borders have at least 3 pixel padding
1566 if ( !mpData->pBorders[i-1].nWidth )
1567 {
1568 n1 -= nBorderTolerance;
1569 n2 += nBorderTolerance;
1570
1571 }
1572
1573 if ( (nX >= n1) && (nX <= n2) )
1574 {
1575 RulerBorderStyle nBorderStyle = mpData->pBorders[i-1].nStyle;
1576 if ( !(nBorderStyle & RulerBorderStyle::Invisible) )
1577 {
1578 pHitTest->eType = RulerType::Border;
1579 pHitTest->nAryPos = i-1;
1580
1581 if ( !(nBorderStyle & RulerBorderStyle::Sizeable) )
1582 {
1583 if ( nBorderStyle & RulerBorderStyle::Moveable )
1584 {
1585 pHitTest->bSizeBar = true;
1586 pHitTest->mnDragSize = RulerDragSize::Move;
1587 }
1588 }
1589 else
1590 {
1591 tools::Long nMOff = RULER_MOUSE_BORDERWIDTH;
1592 while ( nMOff*2 >= (n2-n1-RULER_MOUSE_BORDERMOVE) )
1593 {
1594 if ( nMOff < 2 )
1595 {
1596 nMOff = 0;
1597 break;
1598 }
1599 else
1600 nMOff--;
1601 }
1602
1603 if ( nX <= n1+nMOff )
1604 {
1605 pHitTest->bSize = true;
1606 pHitTest->mnDragSize = RulerDragSize::N1;
1607 }
1608 else if ( nX >= n2-nMOff )
1609 {
1610 pHitTest->bSize = true;
1611 pHitTest->mnDragSize = RulerDragSize::N2;
1612 }
1613 else
1614 {
1615 if ( nBorderStyle & RulerBorderStyle::Moveable )
1616 {
1617 pHitTest->bSizeBar = true;
1618 pHitTest->mnDragSize = RulerDragSize::Move;
1619 }
1620 }
1621 }
1622
1623 return true;
1624 }
1625 }
1626 }
1627
1628 // Margins
1629 int nMarginTolerance = pHitTest->bExpandTest ? nBorderTolerance : RULER_MOUSE_MARGINWIDTH;
1630
1631 if ( (mpData->nMargin1Style & (RulerMarginStyle::Sizeable | RulerMarginStyle::Invisible)) == RulerMarginStyle::Sizeable )
1632 {
1633 n1 = mpData->nMargin1;
1634 if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1635 {
1636 pHitTest->eType = RulerType::Margin1;
1637 pHitTest->bSize = true;
1638 return true;
1639 }
1640 }
1641 if ( (mpData->nMargin2Style & (RulerMarginStyle::Sizeable | RulerMarginStyle::Invisible)) == RulerMarginStyle::Sizeable )
1642 {
1643 n1 = mpData->nMargin2;
1644 if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1645 {
1646 pHitTest->eType = RulerType::Margin2;
1647 pHitTest->bSize = true;
1648 return true;
1649 }
1650 }
1651
1652 // test tabs again
1653 if ( !mpData->pTabs.empty() )
1654 {
1655 aRect.SetTop( RULER_OFF );
1656 aRect.SetBottom( nHitBottom );
1657
1658 for ( i = mpData->pTabs.size() - 1; i >= 0; i-- )
1659 {
1660 nStyle = mpData->pTabs[i].nStyle;
1661 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1662 {
1663 nStyle &= RULER_TAB_STYLE;
1664
1665 // default tabs are only shown (no action)
1666 if ( nStyle != RULER_TAB_DEFAULT )
1667 {
1668 n1 = mpData->pTabs[i].nPos;
1669
1670 if ( nStyle == RULER_TAB_LEFT )
1671 {
1672 aRect.SetLeft( n1 );
1673 aRect.SetRight( n1 + ruler_tab.width - 1 );
1674 }
1675 else if ( nStyle == RULER_TAB_RIGHT )
1676 {
1677 aRect.SetRight( n1 );
1678 aRect.SetLeft( n1 - ruler_tab.width - 1 );
1679 }
1680 else
1681 {
1682 aRect.SetLeft( n1 - ruler_tab.cwidth2 + 1 );
1683 aRect.SetRight( n1 - ruler_tab.cwidth2 + ruler_tab.cwidth );
1684 }
1685
1686 aRect.AdjustLeft( -1 );
1687 aRect.AdjustRight( 1 );
1688
1689 if ( aRect.IsInside( Point( nX, nY ) ) )
1690 {
1691 pHitTest->eType = RulerType::Tab;
1692 pHitTest->nAryPos = i;
1693 return true;
1694 }
1695 }
1696 }
1697 }
1698 }
1699
1700 return false;
1701 }
1702
ImplDocHitTest(const Point & rPos,RulerType eDragType,RulerSelection * pHitTest) const1703 bool Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
1704 RulerSelection* pHitTest ) const
1705 {
1706 Point aPos = rPos;
1707 bool bRequiredStyle = false;
1708 RulerIndentStyle nRequiredStyle = RulerIndentStyle::Top;
1709
1710 if (eDragType == RulerType::Indent)
1711 {
1712 bRequiredStyle = true;
1713 nRequiredStyle = RulerIndentStyle::Bottom;
1714 }
1715
1716 if ( mnWinStyle & WB_HORZ )
1717 aPos.AdjustX(mnWinOff );
1718 else
1719 aPos.AdjustY(mnWinOff );
1720
1721 if ( (eDragType == RulerType::Indent) || (eDragType == RulerType::DontKnow) )
1722 {
1723 if ( mnWinStyle & WB_HORZ )
1724 aPos.setY( RULER_OFF + 1 );
1725 else
1726 aPos.setX( RULER_OFF + 1 );
1727
1728 if ( ImplDoHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1729 {
1730 if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
1731 return true;
1732 }
1733 }
1734
1735 if ( (eDragType == RulerType::Indent) ||
1736 (eDragType == RulerType::Tab) ||
1737 (eDragType == RulerType::DontKnow) )
1738 {
1739 if ( mnWinStyle & WB_HORZ )
1740 aPos.setY( mnHeight - RULER_OFF - 1 );
1741 else
1742 aPos.setX( mnWidth - RULER_OFF - 1 );
1743
1744 if ( ImplDoHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1745 {
1746 if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
1747 return true;
1748 }
1749 }
1750
1751 if ( (eDragType == RulerType::Margin1) || (eDragType == RulerType::Margin2) ||
1752 (eDragType == RulerType::Border) || (eDragType == RulerType::DontKnow) )
1753 {
1754 if ( mnWinStyle & WB_HORZ )
1755 aPos.setY( RULER_OFF + (mnVirHeight / 2) );
1756 else
1757 aPos.setX( RULER_OFF + (mnVirHeight / 2) );
1758
1759 if ( ImplDoHitTest( aPos, pHitTest ) )
1760 {
1761 if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
1762 return true;
1763 }
1764 }
1765
1766 pHitTest->eType = RulerType::DontKnow;
1767
1768 return false;
1769 }
1770
ImplStartDrag(RulerSelection const * pHitTest,sal_uInt16 nModifier)1771 bool Ruler::ImplStartDrag( RulerSelection const * pHitTest, sal_uInt16 nModifier )
1772 {
1773 // don't trigger drag if a border that was clicked can not be changed
1774 if ( (pHitTest->eType == RulerType::Border) &&
1775 !pHitTest->bSize && !pHitTest->bSizeBar )
1776 return false;
1777
1778 // Set drag data
1779 meDragType = pHitTest->eType;
1780 mnDragPos = pHitTest->nPos;
1781 mnDragAryPos = pHitTest->nAryPos;
1782 mnDragSize = pHitTest->mnDragSize;
1783 mnDragModifier = nModifier;
1784 *mpDragData = *mpSaveData;
1785 mpData = mpDragData.get();
1786
1787 // call handler
1788 if (StartDrag())
1789 {
1790 // if the handler allows dragging, initialize dragging
1791 mbDrag = true;
1792 mnStartDragPos = mnDragPos;
1793 StartTracking();
1794 Invalidate(InvalidateFlags::NoErase);
1795 return true;
1796 }
1797 else
1798 {
1799 // otherwise reset the data
1800 meDragType = RulerType::DontKnow;
1801 mnDragPos = 0;
1802 mnDragAryPos = 0;
1803 mnDragSize = RulerDragSize::Move;
1804 mnDragModifier = 0;
1805 mpData = mpSaveData.get();
1806 }
1807
1808 return false;
1809 }
1810
ImplDrag(const Point & rPos)1811 void Ruler::ImplDrag( const Point& rPos )
1812 {
1813 tools::Long nX;
1814 tools::Long nY;
1815 tools::Long nOutHeight;
1816
1817 if ( mnWinStyle & WB_HORZ )
1818 {
1819 nX = rPos.X();
1820 nY = rPos.Y();
1821 nOutHeight = mnHeight;
1822 }
1823 else
1824 {
1825 nX = rPos.Y();
1826 nY = rPos.X();
1827 nOutHeight = mnWidth;
1828 }
1829
1830 // calculate and fit X
1831 nX -= mnVirOff;
1832 if ( nX < mpData->nRulVirOff )
1833 {
1834 nX = mpData->nRulVirOff;
1835 }
1836 else if ( nX > mpData->nRulVirOff+mpData->nRulWidth )
1837 {
1838 nX = mpData->nRulVirOff+mpData->nRulWidth;
1839 }
1840 nX -= mpData->nNullVirOff;
1841
1842 // if upper or left from ruler, then consider old values
1843 mbDragDelete = false;
1844 if ( nY < 0 )
1845 {
1846 if ( !mbDragCanceled )
1847 {
1848 // reset the data
1849 mbDragCanceled = true;
1850 ImplRulerData aTempData = *mpDragData;
1851 *mpDragData = *mpSaveData;
1852 mbCalc = true;
1853 mbFormat = true;
1854
1855 // call handler
1856 mnDragPos = mnStartDragPos;
1857 Drag();
1858
1859 // and redraw
1860 Invalidate(InvalidateFlags::NoErase);
1861
1862 // reset the data as before cancel
1863 *mpDragData = aTempData;
1864 }
1865 }
1866 else
1867 {
1868 mbDragCanceled = false;
1869
1870 // +2, so the tabs are not cleared too quickly
1871 if ( nY > nOutHeight + 2 )
1872 mbDragDelete = true;
1873
1874 mnDragPos = nX;
1875
1876 // call handler
1877 Drag();
1878
1879 // redraw
1880 if (mbFormat)
1881 Invalidate(InvalidateFlags::NoErase);
1882 }
1883 }
1884
ImplEndDrag()1885 void Ruler::ImplEndDrag()
1886 {
1887 // get values
1888 if ( mbDragCanceled )
1889 *mpDragData = *mpSaveData;
1890 else
1891 *mpSaveData = *mpDragData;
1892
1893 mpData = mpSaveData.get();
1894 mbDrag = false;
1895
1896 // call handler
1897 EndDrag();
1898
1899 // reset drag values
1900 meDragType = RulerType::DontKnow;
1901 mnDragPos = 0;
1902 mnDragAryPos = 0;
1903 mnDragSize = RulerDragSize::Move;
1904 mbDragCanceled = false;
1905 mbDragDelete = false;
1906 mnDragModifier = 0;
1907 mnStartDragPos = 0;
1908
1909 // redraw
1910 Invalidate(InvalidateFlags::NoErase);
1911 }
1912
MouseButtonDown(const MouseEvent & rMEvt)1913 void Ruler::MouseButtonDown( const MouseEvent& rMEvt )
1914 {
1915 if ( !rMEvt.IsLeft() || IsTracking() )
1916 return;
1917
1918 Point aMousePos = rMEvt.GetPosPixel();
1919 sal_uInt16 nMouseClicks = rMEvt.GetClicks();
1920 sal_uInt16 nMouseModifier = rMEvt.GetModifier();
1921
1922 // update ruler
1923 if ( mbFormat )
1924 {
1925 Invalidate(InvalidateFlags::NoErase);
1926 }
1927
1928 if ( maExtraRect.IsInside( aMousePos ) )
1929 {
1930 ExtraDown();
1931 }
1932 else
1933 {
1934 RulerSelection aHitTest;
1935 bool bHitTestResult = ImplDoHitTest(aMousePos, &aHitTest);
1936
1937 if ( nMouseClicks == 1 )
1938 {
1939 if ( bHitTestResult )
1940 {
1941 ImplStartDrag( &aHitTest, nMouseModifier );
1942 }
1943 else
1944 {
1945 // calculate position inside of ruler area
1946 if ( aHitTest.eType == RulerType::DontKnow )
1947 {
1948 mnDragPos = aHitTest.nPos;
1949 Click();
1950 mnDragPos = 0;
1951
1952 // call HitTest again as a click, for example, could set a new tab
1953 if ( ImplDoHitTest(aMousePos, &aHitTest) )
1954 ImplStartDrag(&aHitTest, nMouseModifier);
1955 }
1956 }
1957 }
1958 else
1959 {
1960 if (bHitTestResult)
1961 {
1962 mnDragPos = aHitTest.nPos;
1963 mnDragAryPos = aHitTest.nAryPos;
1964 }
1965 meDragType = aHitTest.eType;
1966
1967 DoubleClick();
1968
1969 meDragType = RulerType::DontKnow;
1970 mnDragPos = 0;
1971 mnDragAryPos = 0;
1972 }
1973 }
1974 }
1975
MouseMove(const MouseEvent & rMEvt)1976 void Ruler::MouseMove( const MouseEvent& rMEvt )
1977 {
1978 PointerStyle ePtrStyle = PointerStyle::Arrow;
1979
1980 mxPreviousHitTest.swap(mxCurrentHitTest);
1981
1982 mxCurrentHitTest.reset(new RulerSelection);
1983
1984 maHoverSelection.eType = RulerType::DontKnow;
1985
1986 if (ImplDoHitTest( rMEvt.GetPosPixel(), mxCurrentHitTest.get() ))
1987 {
1988 maHoverSelection = *mxCurrentHitTest;
1989
1990 if (mxCurrentHitTest->bSize)
1991 {
1992 if (mnWinStyle & WB_HORZ)
1993 {
1994 if (mxCurrentHitTest->mnDragSize == RulerDragSize::N1)
1995 ePtrStyle = PointerStyle::TabSelectW;
1996 else if (mxCurrentHitTest->mnDragSize == RulerDragSize::N2)
1997 ePtrStyle = PointerStyle::TabSelectE;
1998 else
1999 ePtrStyle = PointerStyle::ESize;
2000 }
2001 else
2002 {
2003 if (mxCurrentHitTest->mnDragSize == RulerDragSize::N1)
2004 ePtrStyle = PointerStyle::WindowNSize;
2005 else if (mxCurrentHitTest->mnDragSize == RulerDragSize::N2)
2006 ePtrStyle = PointerStyle::WindowSSize;
2007 else
2008 ePtrStyle = PointerStyle::SSize;
2009 }
2010 }
2011 else if (mxCurrentHitTest->bSizeBar)
2012 {
2013 if (mnWinStyle & WB_HORZ)
2014 ePtrStyle = PointerStyle::HSizeBar;
2015 else
2016 ePtrStyle = PointerStyle::VSizeBar;
2017 }
2018 }
2019
2020 if (mxPreviousHitTest != nullptr && mxPreviousHitTest->eType != mxCurrentHitTest->eType)
2021 {
2022 mbFormat = true;
2023 }
2024
2025 SetPointer( ePtrStyle );
2026
2027 if (mbFormat)
2028 {
2029 Invalidate(InvalidateFlags::NoErase);
2030 }
2031 }
2032
Tracking(const TrackingEvent & rTEvt)2033 void Ruler::Tracking( const TrackingEvent& rTEvt )
2034 {
2035 if ( rTEvt.IsTrackingEnded() )
2036 {
2037 // reset the old state at cancel
2038 if ( rTEvt.IsTrackingCanceled() )
2039 {
2040 mbDragCanceled = true;
2041 mbFormat = true;
2042 }
2043
2044 ImplEndDrag();
2045 }
2046 else
2047 ImplDrag( rTEvt.GetMouseEvent().GetPosPixel() );
2048 }
2049
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)2050 void Ruler::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
2051 {
2052 ImplDraw(rRenderContext);
2053
2054 // consider extra field
2055 if (mnWinStyle & WB_EXTRAFIELD)
2056 ImplDrawExtra(rRenderContext);
2057 }
2058
Resize()2059 void Ruler::Resize()
2060 {
2061 Size aWinSize = GetOutputSizePixel();
2062
2063 tools::Long nNewHeight;
2064 if ( mnWinStyle & WB_HORZ )
2065 {
2066 if ( aWinSize.Height() != mnHeight )
2067 nNewHeight = aWinSize.Height();
2068 else
2069 nNewHeight = 0;
2070 }
2071 else
2072 {
2073 if ( aWinSize.Width() != mnWidth )
2074 nNewHeight = aWinSize.Width();
2075 else
2076 nNewHeight = 0;
2077 }
2078
2079 mbFormat = true;
2080
2081 // clear lines
2082 bool bVisible = IsReallyVisible();
2083 if ( bVisible && !mpData->pLines.empty() )
2084 {
2085 mnUpdateFlags |= RULER_UPDATE_LINES;
2086 Invalidate(InvalidateFlags::NoErase);
2087 }
2088
2089 // recalculate some values if the height/width changes
2090 // extra field should always be updated
2091 ImplInitExtraField( mpData->bTextRTL );
2092 if ( nNewHeight )
2093 {
2094 mbCalc = true;
2095 mnVirHeight = nNewHeight - mnBorderWidth - ( RULER_OFF * 2 );
2096 }
2097 else
2098 {
2099 if ( mpData->bAutoPageWidth )
2100 ImplUpdate( true );
2101 else if ( mbAutoWinWidth )
2102 mbCalc = true;
2103 }
2104
2105 // clear part of the border
2106 if ( bVisible )
2107 {
2108 if ( nNewHeight )
2109 Invalidate(InvalidateFlags::NoErase);
2110 else if ( mpData->bAutoPageWidth )
2111 {
2112 // only at AutoPageWidth do we need to redraw
2113 tools::Rectangle aRect;
2114
2115 if ( mnWinStyle & WB_HORZ )
2116 {
2117 if ( mnWidth < aWinSize.Width() )
2118 aRect.SetLeft( mnWidth - RULER_RESIZE_OFF );
2119 else
2120 aRect.SetLeft( aWinSize.Width() - RULER_RESIZE_OFF );
2121 aRect.SetRight( aRect.Left() + RULER_RESIZE_OFF );
2122 aRect.SetTop( RULER_OFF );
2123 aRect.SetBottom( RULER_OFF + mnVirHeight );
2124 }
2125 else
2126 {
2127 if ( mnHeight < aWinSize.Height() )
2128 aRect.SetTop( mnHeight-RULER_RESIZE_OFF );
2129 else
2130 aRect.SetTop( aWinSize.Height()-RULER_RESIZE_OFF );
2131 aRect.SetBottom( aRect.Top() + RULER_RESIZE_OFF );
2132 aRect.SetLeft( RULER_OFF );
2133 aRect.SetRight( RULER_OFF + mnVirHeight );
2134 }
2135
2136 Invalidate(aRect, InvalidateFlags::NoErase);
2137 }
2138 }
2139
2140 mnWidth = aWinSize.Width();
2141 mnHeight = aWinSize.Height();
2142 }
2143
StateChanged(StateChangedType nType)2144 void Ruler::StateChanged( StateChangedType nType )
2145 {
2146 Window::StateChanged( nType );
2147
2148 if ( nType == StateChangedType::InitShow )
2149 Invalidate();
2150 else if ( nType == StateChangedType::UpdateMode )
2151 {
2152 if ( IsReallyVisible() && IsUpdateMode() )
2153 Invalidate();
2154 }
2155 else if ( (nType == StateChangedType::Zoom) ||
2156 (nType == StateChangedType::ControlFont) )
2157 {
2158 ImplInitSettings( true, false, false );
2159 Invalidate();
2160 }
2161 else if ( nType == StateChangedType::ControlForeground )
2162 {
2163 ImplInitSettings( false, true, false );
2164 Invalidate();
2165 }
2166 else if ( nType == StateChangedType::ControlBackground )
2167 {
2168 ImplInitSettings( false, false, true );
2169 Invalidate();
2170 }
2171 }
2172
DataChanged(const DataChangedEvent & rDCEvt)2173 void Ruler::DataChanged( const DataChangedEvent& rDCEvt )
2174 {
2175 Window::DataChanged( rDCEvt );
2176
2177 if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
2178 (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
2179 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
2180 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2181 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
2182 {
2183 mbFormat = true;
2184 ImplInitSettings( true, true, true );
2185 Invalidate();
2186 }
2187 }
2188
StartDrag()2189 bool Ruler::StartDrag()
2190 {
2191 return false;
2192 }
2193
Drag()2194 void Ruler::Drag()
2195 {
2196 }
2197
EndDrag()2198 void Ruler::EndDrag()
2199 {
2200 }
2201
Click()2202 void Ruler::Click()
2203 {
2204 }
2205
DoubleClick()2206 void Ruler::DoubleClick()
2207 {
2208 maDoubleClickHdl.Call( this );
2209 }
2210
ExtraDown()2211 void Ruler::ExtraDown()
2212 {
2213 }
2214
Activate()2215 void Ruler::Activate()
2216 {
2217 mbActive = true;
2218
2219 // update positionlines - draw is delayed
2220 mnUpdateFlags |= RULER_UPDATE_LINES;
2221 Invalidate(InvalidateFlags::NoErase);
2222 }
2223
Deactivate()2224 void Ruler::Deactivate()
2225 {
2226 // clear positionlines
2227 Invalidate(InvalidateFlags::NoErase);
2228
2229 mbActive = false;
2230 }
2231
StartDocDrag(const MouseEvent & rMEvt,RulerType eDragType)2232 bool Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
2233 {
2234 if ( !mbDrag )
2235 {
2236 Point aMousePos = rMEvt.GetPosPixel();
2237 sal_uInt16 nMouseClicks = rMEvt.GetClicks();
2238 sal_uInt16 nMouseModifier = rMEvt.GetModifier();
2239 RulerSelection aHitTest;
2240
2241 if(eDragType != RulerType::DontKnow)
2242 aHitTest.bExpandTest = true;
2243
2244 // update ruler
2245 if ( mbFormat )
2246 {
2247 if (!IsReallyVisible())
2248 {
2249 // set mpData for ImplDocHitTest()
2250 ImplFormat(*GetOutDev());
2251 }
2252
2253 Invalidate(InvalidateFlags::NoErase);
2254 }
2255
2256 if ( nMouseClicks == 1 )
2257 {
2258 if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2259 {
2260 PointerStyle aPtr = PointerStyle::Arrow;
2261
2262 if ( aHitTest.bSize )
2263 {
2264 if ( mnWinStyle & WB_HORZ )
2265 aPtr = PointerStyle::ESize;
2266 else
2267 aPtr = PointerStyle::SSize;
2268 }
2269 else if ( aHitTest.bSizeBar )
2270 {
2271 if ( mnWinStyle & WB_HORZ )
2272 aPtr = PointerStyle::HSizeBar;
2273 else
2274 aPtr = PointerStyle::VSizeBar;
2275 }
2276 SetPointer( aPtr );
2277 return ImplStartDrag( &aHitTest, nMouseModifier );
2278 }
2279 }
2280 else if ( nMouseClicks == 2 )
2281 {
2282 if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2283 {
2284 mnDragPos = aHitTest.nPos;
2285 mnDragAryPos = aHitTest.nAryPos;
2286 }
2287
2288 DoubleClick();
2289
2290 mnDragPos = 0;
2291 mnDragAryPos = 0;
2292
2293 return true;
2294 }
2295 }
2296
2297 return false;
2298 }
2299
CancelDrag()2300 void Ruler::CancelDrag()
2301 {
2302 if ( mbDrag )
2303 {
2304 ImplDrag( Point( -1, -1 ) );
2305 ImplEndDrag();
2306 }
2307 }
2308
GetRulerType(const Point & rPos,sal_uInt16 * pAryPos)2309 RulerType Ruler::GetRulerType( const Point& rPos, sal_uInt16* pAryPos )
2310 {
2311 RulerSelection aHitTest;
2312
2313 // update ruler
2314 if ( IsReallyVisible() && mbFormat )
2315 {
2316 Invalidate(InvalidateFlags::NoErase);
2317 }
2318
2319 (void)ImplDoHitTest(rPos, &aHitTest);
2320
2321 // return values
2322 if ( pAryPos )
2323 *pAryPos = aHitTest.nAryPos;
2324 return aHitTest.eType;
2325 }
2326
SetWinPos(tools::Long nNewOff,tools::Long nNewWidth)2327 void Ruler::SetWinPos( tools::Long nNewOff, tools::Long nNewWidth )
2328 {
2329 // should widths be automatically calculated
2330 if ( !nNewWidth )
2331 mbAutoWinWidth = true;
2332 else
2333 mbAutoWinWidth = false;
2334
2335 mnWinOff = nNewOff;
2336 mnWinWidth = nNewWidth;
2337 ImplUpdate( true );
2338 }
2339
SetPagePos(tools::Long nNewOff,tools::Long nNewWidth)2340 void Ruler::SetPagePos( tools::Long nNewOff, tools::Long nNewWidth )
2341 {
2342 // should we do anything?
2343 if ( (mpData->nPageOff == nNewOff) && (mpData->nPageWidth == nNewWidth) )
2344 return;
2345
2346 // should widths be automatically calculated
2347 if ( !nNewWidth )
2348 mpData->bAutoPageWidth = true;
2349 else
2350 mpData->bAutoPageWidth = false;
2351
2352 mpData->nPageOff = nNewOff;
2353 mpData->nPageWidth = nNewWidth;
2354 ImplUpdate( true );
2355 }
2356
SetBorderPos(tools::Long nOff)2357 void Ruler::SetBorderPos( tools::Long nOff )
2358 {
2359 if ( mnWinStyle & WB_BORDER )
2360 {
2361 if ( mnBorderOff != nOff )
2362 {
2363 mnBorderOff = nOff;
2364
2365 if ( IsReallyVisible() && IsUpdateMode() )
2366 Invalidate(InvalidateFlags::NoErase);
2367 }
2368 }
2369 }
2370
SetUnit(FieldUnit eNewUnit)2371 void Ruler::SetUnit( FieldUnit eNewUnit )
2372 {
2373 if ( meUnit == eNewUnit )
2374 return;
2375
2376 meUnit = eNewUnit;
2377 switch ( meUnit )
2378 {
2379 case FieldUnit::MM:
2380 mnUnitIndex = RULER_UNIT_MM;
2381 break;
2382 case FieldUnit::CM:
2383 mnUnitIndex = RULER_UNIT_CM;
2384 break;
2385 case FieldUnit::M:
2386 mnUnitIndex = RULER_UNIT_M;
2387 break;
2388 case FieldUnit::KM:
2389 mnUnitIndex = RULER_UNIT_KM;
2390 break;
2391 case FieldUnit::INCH:
2392 mnUnitIndex = RULER_UNIT_INCH;
2393 break;
2394 case FieldUnit::FOOT:
2395 mnUnitIndex = RULER_UNIT_FOOT;
2396 break;
2397 case FieldUnit::MILE:
2398 mnUnitIndex = RULER_UNIT_MILE;
2399 break;
2400 case FieldUnit::POINT:
2401 mnUnitIndex = RULER_UNIT_POINT;
2402 break;
2403 case FieldUnit::PICA:
2404 mnUnitIndex = RULER_UNIT_PICA;
2405 break;
2406 case FieldUnit::CHAR:
2407 mnUnitIndex = RULER_UNIT_CHAR;
2408 break;
2409 case FieldUnit::LINE:
2410 mnUnitIndex = RULER_UNIT_LINE;
2411 break;
2412 default:
2413 SAL_WARN( "svtools.control", "Ruler::SetUnit() - Wrong Unit" );
2414 break;
2415 }
2416
2417 maMapMode.SetMapUnit( aImplRulerUnitTab[mnUnitIndex].eMapUnit );
2418 ImplUpdate();
2419 }
2420
SetZoom(const Fraction & rNewZoom)2421 void Ruler::SetZoom( const Fraction& rNewZoom )
2422 {
2423 DBG_ASSERT( rNewZoom.GetNumerator(), "Ruler::SetZoom() with scale 0 is not allowed" );
2424
2425 if ( maZoom != rNewZoom )
2426 {
2427 maZoom = rNewZoom;
2428 maMapMode.SetScaleX( maZoom );
2429 maMapMode.SetScaleY( maZoom );
2430 ImplUpdate();
2431 }
2432 }
2433
SetExtraType(RulerExtra eNewExtraType,sal_uInt16 nStyle)2434 void Ruler::SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle )
2435 {
2436 if ( mnWinStyle & WB_EXTRAFIELD )
2437 {
2438 meExtraType = eNewExtraType;
2439 mnExtraStyle = nStyle;
2440 if (IsReallyVisible() && IsUpdateMode())
2441 Invalidate();
2442 }
2443 }
2444
SetNullOffset(tools::Long nPos)2445 void Ruler::SetNullOffset( tools::Long nPos )
2446 {
2447 if ( mpData->nNullOff != nPos )
2448 {
2449 mpData->nNullVirOff += nPos - mpData->nNullOff;
2450 mpData->nNullOff = nPos;
2451 ImplUpdate();
2452 }
2453 }
2454
SetLeftFrameMargin(tools::Long nPos)2455 void Ruler::SetLeftFrameMargin( tools::Long nPos )
2456 {
2457 if ( mpData->nLeftFrameMargin != nPos )
2458 {
2459 mpData->nLeftFrameMargin = nPos;
2460 ImplUpdate();
2461 }
2462 }
2463
SetRightFrameMargin(tools::Long nPos)2464 void Ruler::SetRightFrameMargin( tools::Long nPos )
2465 {
2466 if ( mpData->nRightFrameMargin != nPos )
2467 {
2468 mpData->nRightFrameMargin = nPos;
2469 ImplUpdate();
2470 }
2471 }
2472
SetMargin1(tools::Long nPos,RulerMarginStyle nMarginStyle)2473 void Ruler::SetMargin1( tools::Long nPos, RulerMarginStyle nMarginStyle )
2474 {
2475 if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
2476 {
2477 mpData->nMargin1 = nPos;
2478 mpData->nMargin1Style = nMarginStyle;
2479 ImplUpdate();
2480 }
2481 }
2482
SetMargin2(tools::Long nPos,RulerMarginStyle nMarginStyle)2483 void Ruler::SetMargin2( tools::Long nPos, RulerMarginStyle nMarginStyle )
2484 {
2485 DBG_ASSERT( (nPos >= mpData->nMargin1) ||
2486 (mpData->nMargin1Style & RulerMarginStyle::Invisible) ||
2487 (mpData->nMargin2Style & RulerMarginStyle::Invisible),
2488 "Ruler::SetMargin2() - Margin2 < Margin1" );
2489
2490 if ( (mpData->nMargin2 != nPos) || (mpData->nMargin2Style != nMarginStyle) )
2491 {
2492 mpData->nMargin2 = nPos;
2493 mpData->nMargin2Style = nMarginStyle;
2494 ImplUpdate();
2495 }
2496 }
2497
SetLines(sal_uInt32 aLineArraySize,const RulerLine * pLineArray)2498 void Ruler::SetLines( sal_uInt32 aLineArraySize, const RulerLine* pLineArray )
2499 {
2500 // To determine if what has changed
2501 if ( mpData->pLines.size() == aLineArraySize )
2502 {
2503 sal_uInt32 i = aLineArraySize;
2504 vector<RulerLine>::const_iterator aItr1 = mpData->pLines.begin();
2505 const RulerLine* pAry2 = pLineArray;
2506 while ( i )
2507 {
2508 if ( aItr1->nPos != pAry2->nPos )
2509 break;
2510 ++aItr1;
2511 ++pAry2;
2512 i--;
2513 }
2514 if ( !i )
2515 return;
2516 }
2517
2518 // New values and new share issue
2519 bool bMustUpdate;
2520 bMustUpdate = IsReallyVisible() && IsUpdateMode();
2521
2522 // Delete old lines
2523 if ( bMustUpdate )
2524 Invalidate(InvalidateFlags::NoErase);
2525
2526 // New data set
2527 if ( !aLineArraySize || !pLineArray )
2528 {
2529 if ( mpData->pLines.empty() )
2530 return;
2531 mpData->pLines.clear();
2532 }
2533 else
2534 {
2535 if ( mpData->pLines.size() != aLineArraySize )
2536 {
2537 mpData->pLines.resize(aLineArraySize);
2538 }
2539
2540 std::copy( pLineArray,
2541 pLineArray + aLineArraySize,
2542 mpData->pLines.begin() );
2543
2544 if ( bMustUpdate )
2545 Invalidate(InvalidateFlags::NoErase);
2546 }
2547 }
2548
SetBorders(sal_uInt32 aBorderArraySize,const RulerBorder * pBorderArray)2549 void Ruler::SetBorders( sal_uInt32 aBorderArraySize, const RulerBorder* pBorderArray )
2550 {
2551 if ( !aBorderArraySize || !pBorderArray )
2552 {
2553 if ( mpData->pBorders.empty() )
2554 return;
2555 mpData->pBorders.clear();
2556 }
2557 else
2558 {
2559 if ( mpData->pBorders.size() != aBorderArraySize )
2560 {
2561 mpData->pBorders.resize(aBorderArraySize);
2562 }
2563 else
2564 {
2565 sal_uInt32 i = aBorderArraySize;
2566 const RulerBorder* pAry1 = mpData->pBorders.data();
2567 const RulerBorder* pAry2 = pBorderArray;
2568 while ( i )
2569 {
2570 if ( (pAry1->nPos != pAry2->nPos) ||
2571 (pAry1->nWidth != pAry2->nWidth) ||
2572 (pAry1->nStyle != pAry2->nStyle) )
2573 break;
2574 pAry1++;
2575 pAry2++;
2576 i--;
2577 }
2578 if ( !i )
2579 return;
2580 }
2581 std::copy( pBorderArray,
2582 pBorderArray + aBorderArraySize,
2583 mpData->pBorders.begin() );
2584 }
2585
2586 ImplUpdate();
2587 }
2588
SetIndents(sal_uInt32 aIndentArraySize,const RulerIndent * pIndentArray)2589 void Ruler::SetIndents( sal_uInt32 aIndentArraySize, const RulerIndent* pIndentArray )
2590 {
2591
2592 if ( !aIndentArraySize || !pIndentArray )
2593 {
2594 if ( mpData->pIndents.empty() )
2595 return;
2596 mpData->pIndents.clear();
2597 }
2598 else
2599 {
2600 if ( mpData->pIndents.size() != aIndentArraySize )
2601 {
2602 mpData->pIndents.resize(aIndentArraySize);
2603 }
2604 else
2605 {
2606 sal_uInt32 i = aIndentArraySize;
2607 const RulerIndent* pAry1 = mpData->pIndents.data();
2608 const RulerIndent* pAry2 = pIndentArray;
2609 while ( i )
2610 {
2611 if ( (pAry1->nPos != pAry2->nPos) ||
2612 (pAry1->nStyle != pAry2->nStyle) )
2613 break;
2614 pAry1++;
2615 pAry2++;
2616 i--;
2617 }
2618 if ( !i )
2619 return;
2620 }
2621
2622 std::copy( pIndentArray,
2623 pIndentArray + aIndentArraySize,
2624 mpData->pIndents.begin() );
2625 }
2626
2627 ImplUpdate();
2628 }
2629
SetTabs(sal_uInt32 aTabArraySize,const RulerTab * pTabArray)2630 void Ruler::SetTabs( sal_uInt32 aTabArraySize, const RulerTab* pTabArray )
2631 {
2632 if ( aTabArraySize == 0 || pTabArray == nullptr )
2633 {
2634 if ( mpData->pTabs.empty() )
2635 return;
2636 mpData->pTabs.clear();
2637 }
2638 else
2639 {
2640 if ( mpData->pTabs.size() != aTabArraySize )
2641 {
2642 mpData->pTabs.resize(aTabArraySize);
2643 }
2644 else
2645 {
2646 sal_uInt32 i = aTabArraySize;
2647 vector<RulerTab>::iterator aTabIterator = mpData->pTabs.begin();
2648 const RulerTab* pInputArray = pTabArray;
2649 while ( i )
2650 {
2651 RulerTab& aCurrent = *aTabIterator;
2652 if ( aCurrent.nPos != pInputArray->nPos ||
2653 aCurrent.nStyle != pInputArray->nStyle )
2654 {
2655 break;
2656 }
2657 ++aTabIterator;
2658 pInputArray++;
2659 i--;
2660 }
2661 if ( !i )
2662 return;
2663 }
2664 std::copy(pTabArray, pTabArray + aTabArraySize, mpData->pTabs.begin());
2665 }
2666
2667 ImplUpdate();
2668 }
2669
GetTabs() const2670 const std::vector<RulerTab>& Ruler::GetTabs() const
2671 {
2672 return mpData->pTabs;
2673 }
2674
SetStyle(WinBits nStyle)2675 void Ruler::SetStyle( WinBits nStyle )
2676 {
2677 if ( mnWinStyle != nStyle )
2678 {
2679 mnWinStyle = nStyle;
2680 ImplInitExtraField( true );
2681 }
2682 }
2683
DrawTab(vcl::RenderContext & rRenderContext,const Color & rFillColor,const Point & rPos,sal_uInt16 nStyle)2684 void Ruler::DrawTab(vcl::RenderContext& rRenderContext, const Color &rFillColor, const Point& rPos, sal_uInt16 nStyle)
2685 {
2686 Point aPos(rPos);
2687 sal_uInt16 nTabStyle = nStyle & (RULER_TAB_STYLE | RULER_TAB_RTL);
2688
2689 rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
2690 rRenderContext.SetLineColor();
2691 rRenderContext.SetFillColor(rFillColor);
2692 ImplCenterTabPos(aPos, nTabStyle);
2693 ImplDrawRulerTab(rRenderContext, aPos, nTabStyle, nStyle);
2694 rRenderContext.Pop();
2695 }
2696
SetTextRTL(bool bRTL)2697 void Ruler::SetTextRTL(bool bRTL)
2698 {
2699 if(mpData->bTextRTL != bRTL)
2700 {
2701 mpData->bTextRTL = bRTL;
2702 if ( IsReallyVisible() && IsUpdateMode() )
2703 ImplInitExtraField( true );
2704 }
2705
2706 }
2707
GetPageOffset() const2708 tools::Long Ruler::GetPageOffset() const
2709 {
2710 return mpData->nPageOff;
2711 }
2712
GetNullOffset() const2713 tools::Long Ruler::GetNullOffset() const
2714 {
2715 return mpData->nNullOff;
2716 }
2717
GetMargin1() const2718 tools::Long Ruler::GetMargin1() const
2719 {
2720 return mpData->nMargin1;
2721 }
2722
GetMargin2() const2723 tools::Long Ruler::GetMargin2() const
2724 {
2725 return mpData->nMargin2;
2726 }
2727
2728
GetTextRTL() const2729 bool Ruler::GetTextRTL() const
2730 {
2731 return mpData->bTextRTL;
2732 }
2733
GetCurrentRulerUnit() const2734 const RulerUnitData& Ruler::GetCurrentRulerUnit() const
2735 {
2736 return aImplRulerUnitTab[mnUnitIndex];
2737 }
2738
DrawTicks()2739 void Ruler::DrawTicks()
2740 {
2741 mbFormat = true;
2742 Invalidate(InvalidateFlags::NoErase);
2743 }
2744
CreateAccessible()2745 uno::Reference< XAccessible > Ruler::CreateAccessible()
2746 {
2747 vcl::Window* pParent = GetAccessibleParentWindow();
2748 OSL_ENSURE( pParent, "-SvxRuler::CreateAccessible(): No Parent!" );
2749 uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
2750 if( xAccParent.is() )
2751 {
2752 // MT: Fixed compiler issue because the address from a temporary object was used.
2753 // BUT: Should it really be a Pointer, instead of const&???
2754 OUString aStr;
2755 if ( mnWinStyle & WB_HORZ )
2756 {
2757 aStr = SvtResId(STR_SVT_ACC_RULER_HORZ_NAME);
2758 }
2759 else
2760 {
2761 aStr = SvtResId(STR_SVT_ACC_RULER_VERT_NAME);
2762 }
2763 mxAccContext = new SvtRulerAccessible( xAccParent, *this, aStr );
2764 SetAccessible(mxAccContext);
2765 return mxAccContext;
2766 }
2767 else
2768 return uno::Reference< XAccessible >();
2769 }
2770
2771 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2772