1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <cstring>
21 #include <climits>
22
23 #include <vcl/commandevent.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/fieldvalues.hxx>
26 #include <vcl/image.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/virdev.hxx>
30 #include <vcl/weldutils.hxx>
31 #include <svl/eitem.hxx>
32 #include <svl/rectitem.hxx>
33 #include <svl/hint.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <svx/strings.hrc>
36 #include <svx/svxids.hrc>
37 #include <svx/dialmgr.hxx>
38 #include <svx/ruler.hxx>
39 #include <svx/rulritem.hxx>
40 #include <editeng/editids.hrc>
41 #include <editeng/tstpitem.hxx>
42 #include <editeng/lrspitem.hxx>
43 #include <editeng/protitem.hxx>
44 #include <osl/diagnose.h>
45 #include <rtl/math.hxx>
46
47 #include "rlrcitem.hxx"
48 #include <memory>
49
50 #define CTRL_ITEM_COUNT 14
51 #define GAP 10
52 #define OBJECT_BORDER_COUNT 4
53 #define TAB_GAP 1
54 #define INDENT_GAP 2
55 #define INDENT_FIRST_LINE 2
56 #define INDENT_LEFT_MARGIN 3
57 #define INDENT_RIGHT_MARGIN 4
58 #define INDENT_COUNT 3 //without the first two old values
59
60 struct SvxRuler_Impl {
61 std::unique_ptr<sal_uInt16[]> pPercBuf;
62 std::unique_ptr<sal_uInt16[]> pBlockBuf;
63 sal_uInt16 nPercSize;
64 tools::Long nTotalDist;
65 tools::Long lOldWinPos;
66 tools::Long lMaxLeftLogic;
67 tools::Long lMaxRightLogic;
68 tools::Long lLastLMargin;
69 tools::Long lLastRMargin;
70 std::unique_ptr<SvxProtectItem> aProtectItem;
71 std::unique_ptr<SfxBoolItem> pTextRTLItem;
72 sal_uInt16 nControllerItems;
73 sal_uInt16 nIdx;
74 sal_uInt16 nColLeftPix;
75 sal_uInt16 nColRightPix; // Pixel values for left / right edge
76 // For columns; buffered to prevent
77 // recalculation errors
78 // May be has to be widen for future values
79 bool bIsTableRows : 1; // mxColumnItem contains table rows instead of columns
80 //#i24363# tab stops relative to indent
81 bool bIsTabsRelativeToIndent : 1; // Tab stops relative to paragraph indent?
82 // false means relative to SvxRuler::GetLeftFrameMargin()
83
SvxRuler_ImplSvxRuler_Impl84 SvxRuler_Impl() :
85 nPercSize(0), nTotalDist(0),
86 lOldWinPos(0), lMaxLeftLogic(0), lMaxRightLogic(0),
87 lLastLMargin(0), lLastRMargin(0),
88 aProtectItem(std::make_unique<SvxProtectItem>(SID_RULER_PROTECT)),
89 nControllerItems(0), nIdx(0),
90 nColLeftPix(0), nColRightPix(0),
91 bIsTableRows(false),
92 bIsTabsRelativeToIndent(true)
93 {
94 }
95
96 void SetPercSize(sal_uInt16 nSize);
97
98 };
99
100 static RulerTabData ruler_tab_svx =
101 {
102 0, // DPIScaleFactor to be set
103 7, // ruler_tab_width
104 6, // ruler_tab_height
105 0, // ruler_tab_height2
106 0, // ruler_tab_width2
107 0, // ruler_tab_cwidth
108 0, // ruler_tab_cwidth2
109 0, // ruler_tab_cwidth3
110 0, // ruler_tab_cwidth4
111 0, // ruler_tab_dheight
112 0, // ruler_tab_dheight2
113 0, // ruler_tab_dwidth
114 0, // ruler_tab_dwidth2
115 0, // ruler_tab_dwidth3
116 0, // ruler_tab_dwidth4
117 0 // ruler_tab_textoff
118 };
119
SetPercSize(sal_uInt16 nSize)120 void SvxRuler_Impl::SetPercSize(sal_uInt16 nSize)
121 {
122 if(nSize > nPercSize)
123 {
124 nPercSize = nSize;
125 pPercBuf.reset( new sal_uInt16[nPercSize] );
126 pBlockBuf.reset( new sal_uInt16[nPercSize] );
127 }
128 size_t nSize2 = sizeof(sal_uInt16) * nPercSize;
129 memset(pPercBuf.get(), 0, nSize2);
130 memset(pBlockBuf.get(), 0, nSize2);
131 }
132
133 // Constructor of the ruler
134
135 // SID_ATTR_ULSPACE, SID_ATTR_LRSPACE
136 // expects as parameter SvxULSpaceItem for page edge
137 // (either left/right or top/bottom)
138 // Ruler: SetMargin1, SetMargin2
139
140 // SID_RULER_PAGE_POS
141 // expects as parameter the initial value of the page and page width
142 // Ruler: SetPagePos
143
144 // SID_ATTR_TABSTOP
145 // expects: SvxTabStopItem
146 // Ruler: SetTabs
147
148 // SID_ATTR_PARA_LRSPACE
149 // left, right paragraph edge in H-ruler
150 // Ruler: SetIndents
151
152 // SID_RULER_BORDERS
153 // Table borders, columns
154 // expects: something like SwTabCols
155 // Ruler: SetBorders
156
157 constexpr tools::Long glMinFrame = 5; // minimal frame width in pixels
158
SvxRuler(vcl::Window * pParent,vcl::Window * pWin,SvxRulerSupportFlags flags,SfxBindings & rBindings,WinBits nWinStyle)159 SvxRuler::SvxRuler(
160 vcl::Window* pParent, // StarView Parent
161 vcl::Window* pWin, // Output window: is used for conversion
162 // logical units <-> pixels
163 SvxRulerSupportFlags flags, // Display flags, see ruler.hxx
164 SfxBindings &rBindings, // associated Bindings
165 WinBits nWinStyle) : // StarView WinBits
166 Ruler(pParent, nWinStyle),
167 pCtrlItems(CTRL_ITEM_COUNT),
168 pEditWin(pWin),
169 mxRulerImpl(new SvxRuler_Impl),
170 bAppSetNullOffset(false), // Is the 0-offset of the ruler set by the application?
171 lLogicNullOffset(0),
172 lAppNullOffset(LONG_MAX),
173 lInitialDragPos(0),
174 nFlags(flags),
175 nDragType(SvxRulerDragFlags::NONE),
176 nDefTabType(RULER_TAB_LEFT),
177 nTabCount(0),
178 nTabBufSize(0),
179 lDefTabDist(50),
180 lTabPos(-1),
181 mpBorders(1), // due to one column tables
182 pBindings(&rBindings),
183 nDragOffset(0),
184 nMaxLeft(0),
185 nMaxRight(0),
186 bValid(false),
187 bListening(false),
188 bActive(true),
189 mbCoarseSnapping(false),
190 mbSnapping(true)
191
192 {
193 /* Constructor; Initialize data buffer; controller items are created */
194
195 rBindings.EnterRegistrations();
196
197 // Create Supported Items
198 sal_uInt16 i = 0;
199
200 // Page edges
201 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_LR_MIN_MAX, *this, rBindings));
202 if((nWinStyle & WB_VSCROLL) == WB_VSCROLL)
203 {
204 bHorz = false;
205 pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_LONG_ULSPACE, *this, rBindings));
206 }
207 else
208 {
209 bHorz = true;
210 pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_LONG_LRSPACE, *this, rBindings));
211 }
212
213 // Page Position
214 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_PAGE_POS, *this, rBindings));
215
216 if(nFlags & SvxRulerSupportFlags::TABS)
217 {
218 sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
219 pCtrlItems[i++].reset(new SvxRulerItem(nTabStopId, *this, rBindings));
220 SetExtraType(RulerExtra::Tab, nDefTabType);
221 }
222
223 if(nFlags & (SvxRulerSupportFlags::PARAGRAPH_MARGINS |SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL))
224 {
225 if(bHorz)
226 pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_PARA_LRSPACE, *this, rBindings));
227 else
228 pCtrlItems[i++].reset(new SvxRulerItem(SID_ATTR_PARA_LRSPACE_VERTICAL, *this, rBindings));
229
230 mpIndents.resize(5 + INDENT_GAP);
231
232 for(RulerIndent & rIndent : mpIndents)
233 {
234 rIndent.nPos = 0;
235 rIndent.nStyle = RulerIndentStyle::Top;
236 }
237
238 mpIndents[0].nStyle = RulerIndentStyle::Top;
239 mpIndents[1].nStyle = RulerIndentStyle::Top;
240 mpIndents[INDENT_FIRST_LINE].nStyle = RulerIndentStyle::Top;
241 mpIndents[INDENT_LEFT_MARGIN].nStyle = RulerIndentStyle::Bottom;
242 mpIndents[INDENT_RIGHT_MARGIN].nStyle = RulerIndentStyle::Bottom;
243 }
244
245 if( (nFlags & SvxRulerSupportFlags::BORDERS) == SvxRulerSupportFlags::BORDERS )
246 {
247 pCtrlItems[i++].reset(new SvxRulerItem(bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL, *this, rBindings));
248 pCtrlItems[i++].reset(new SvxRulerItem(bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL, *this, rBindings));
249 }
250
251 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_TEXT_RIGHT_TO_LEFT, *this, rBindings));
252
253 if( (nFlags & SvxRulerSupportFlags::OBJECT) == SvxRulerSupportFlags::OBJECT )
254 {
255 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_OBJECT, *this, rBindings));
256 mpObjectBorders.resize(OBJECT_BORDER_COUNT);
257 for(sal_uInt16 nBorder = 0; nBorder < OBJECT_BORDER_COUNT; ++nBorder)
258 {
259 mpObjectBorders[nBorder].nPos = 0;
260 mpObjectBorders[nBorder].nWidth = 0;
261 mpObjectBorders[nBorder].nStyle = RulerBorderStyle::Moveable;
262 }
263 }
264
265 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_PROTECT, *this, rBindings));
266 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_BORDER_DISTANCE, *this, rBindings));
267 mxRulerImpl->nControllerItems=i;
268
269 if( (nFlags & SvxRulerSupportFlags::SET_NULLOFFSET) == SvxRulerSupportFlags::SET_NULLOFFSET )
270 SetExtraType(RulerExtra::NullOffset);
271
272 rBindings.LeaveRegistrations();
273
274 ruler_tab_svx.DPIScaleFactor = pParent->GetDPIScaleFactor();
275 ruler_tab_svx.height *= ruler_tab_svx.DPIScaleFactor;
276 ruler_tab_svx.width *= ruler_tab_svx.DPIScaleFactor;
277
278 }
279
~SvxRuler()280 SvxRuler::~SvxRuler()
281 {
282 disposeOnce();
283 }
284
dispose()285 void SvxRuler::dispose()
286 {
287 /* Destructor ruler; release internal buffer */
288 if(bListening)
289 EndListening(*pBindings);
290
291 pBindings->EnterRegistrations();
292
293 pCtrlItems.clear();
294
295 pBindings->LeaveRegistrations();
296
297 pEditWin.clear();
298 Ruler::dispose();
299 }
300
MakePositionSticky(tools::Long aPosition,tools::Long aPointOfReference,bool aSnapToFrameMargin) const301 tools::Long SvxRuler::MakePositionSticky(tools::Long aPosition, tools::Long aPointOfReference, bool aSnapToFrameMargin) const
302 {
303 tools::Long aPointOfReferencePixel = ConvertHPosPixel(aPointOfReference);
304 tools::Long aLeftFramePosition = ConvertHPosPixel(GetLeftFrameMargin());
305 tools::Long aRightFramePosition = ConvertHPosPixel(GetRightFrameMargin());
306
307 double aTick = GetCurrentRulerUnit().nTick1;
308
309 if (mbCoarseSnapping)
310 aTick = GetCurrentRulerUnit().nTick2;
311
312 tools::Long aTickPixel = pEditWin->LogicToPixel(Size(aTick, 0), GetCurrentMapMode()).Width();
313
314 double aHalfTick = aTick / 2.0;
315 double aHalfTickPixel = aTickPixel / 2.0;
316
317 if (aSnapToFrameMargin)
318 {
319 if (aPosition > aLeftFramePosition - aHalfTickPixel && aPosition < aLeftFramePosition + aHalfTickPixel)
320 return aLeftFramePosition;
321
322 if (aPosition > aRightFramePosition - aHalfTickPixel && aPosition < aRightFramePosition + aHalfTickPixel)
323 return aRightFramePosition;
324 }
325
326 if (!mbSnapping)
327 return aPosition;
328
329 // Move "coordinate system" to frame position so ticks are calculated correctly
330 tools::Long aTranslatedPosition = aPosition - aPointOfReferencePixel;
331 // Convert position to current selected map mode
332 tools::Long aPositionLogic = pEditWin->PixelToLogic(Size(aTranslatedPosition, 0), GetCurrentMapMode()).Width();
333 // Normalize -- snap to nearest tick
334 aPositionLogic = rtl::math::round((aPositionLogic + aHalfTick) / aTick) * aTick;
335 // Convert back to pixels
336 aPosition = pEditWin->LogicToPixel(Size(aPositionLogic, 0), GetCurrentMapMode()).Width();
337 // Move "coordinate system" back to original position
338 return aPosition + aPointOfReferencePixel;
339 }
340
ConvertHPosPixel(tools::Long nVal) const341 tools::Long SvxRuler::ConvertHPosPixel(tools::Long nVal) const
342 {
343 return pEditWin->LogicToPixel(Size(nVal, 0)).Width();
344 }
345
ConvertVPosPixel(tools::Long nVal) const346 tools::Long SvxRuler::ConvertVPosPixel(tools::Long nVal) const
347 {
348 return pEditWin->LogicToPixel(Size(0, nVal)).Height();
349 }
350
ConvertHSizePixel(tools::Long nVal) const351 tools::Long SvxRuler::ConvertHSizePixel(tools::Long nVal) const
352 {
353 return pEditWin->LogicToPixel(Size(nVal, 0)).Width();
354 }
355
ConvertVSizePixel(tools::Long nVal) const356 tools::Long SvxRuler::ConvertVSizePixel(tools::Long nVal) const
357 {
358 return pEditWin->LogicToPixel(Size(0, nVal)).Height();
359 }
360
ConvertPosPixel(tools::Long nVal) const361 tools::Long SvxRuler::ConvertPosPixel(tools::Long nVal) const
362 {
363 return bHorz ? ConvertHPosPixel(nVal): ConvertVPosPixel(nVal);
364 }
365
ConvertSizePixel(tools::Long nVal) const366 tools::Long SvxRuler::ConvertSizePixel(tools::Long nVal) const
367 {
368 return bHorz? ConvertHSizePixel(nVal): ConvertVSizePixel(nVal);
369 }
370
ConvertHPosLogic(tools::Long nVal) const371 inline tools::Long SvxRuler::ConvertHPosLogic(tools::Long nVal) const
372 {
373 return pEditWin->PixelToLogic(Size(nVal, 0)).Width();
374 }
375
ConvertVPosLogic(tools::Long nVal) const376 inline tools::Long SvxRuler::ConvertVPosLogic(tools::Long nVal) const
377 {
378 return pEditWin->PixelToLogic(Size(0, nVal)).Height();
379 }
380
ConvertHSizeLogic(tools::Long nVal) const381 inline tools::Long SvxRuler::ConvertHSizeLogic(tools::Long nVal) const
382 {
383 return pEditWin->PixelToLogic(Size(nVal, 0)).Width();
384 }
385
ConvertVSizeLogic(tools::Long nVal) const386 inline tools::Long SvxRuler::ConvertVSizeLogic(tools::Long nVal) const
387 {
388 return pEditWin->PixelToLogic(Size(0, nVal)).Height();
389 }
390
ConvertPosLogic(tools::Long nVal) const391 inline tools::Long SvxRuler::ConvertPosLogic(tools::Long nVal) const
392 {
393 return bHorz? ConvertHPosLogic(nVal): ConvertVPosLogic(nVal);
394 }
395
ConvertSizeLogic(tools::Long nVal) const396 inline tools::Long SvxRuler::ConvertSizeLogic(tools::Long nVal) const
397 {
398 return bHorz? ConvertHSizeLogic(nVal): ConvertVSizeLogic(nVal);
399 }
400
PixelHAdjust(tools::Long nVal,tools::Long nValOld) const401 tools::Long SvxRuler::PixelHAdjust(tools::Long nVal, tools::Long nValOld) const
402 {
403 if(ConvertHSizePixel(nVal) != ConvertHSizePixel(nValOld))
404 return nVal;
405 else
406 return nValOld;
407 }
408
PixelVAdjust(tools::Long nVal,tools::Long nValOld) const409 tools::Long SvxRuler::PixelVAdjust(tools::Long nVal, tools::Long nValOld) const
410 {
411 if(ConvertVSizePixel(nVal) != ConvertVSizePixel(nValOld))
412 return nVal;
413 else
414 return nValOld;
415 }
416
PixelAdjust(tools::Long nVal,tools::Long nValOld) const417 tools::Long SvxRuler::PixelAdjust(tools::Long nVal, tools::Long nValOld) const
418 {
419 if(ConvertSizePixel(nVal) != ConvertSizePixel(nValOld))
420 return nVal;
421 else
422 return nValOld;
423 }
424
GetObjectBordersOff(sal_uInt16 nIdx) const425 inline sal_uInt16 SvxRuler::GetObjectBordersOff(sal_uInt16 nIdx) const
426 {
427 return bHorz ? nIdx : nIdx + 2;
428 }
429
430 /*
431 Update Upper Left edge.
432 Items are translated into the representation of the ruler.
433 */
UpdateFrame()434 void SvxRuler::UpdateFrame()
435 {
436 const RulerMarginStyle nMarginStyle =
437 ( mxRulerImpl->aProtectItem->IsSizeProtected() ||
438 mxRulerImpl->aProtectItem->IsPosProtected() ) ?
439 RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
440
441 if(mxLRSpaceItem && mxPagePosItem)
442 {
443 // if no initialization by default app behavior
444 const tools::Long nOld = lLogicNullOffset;
445 lLogicNullOffset = mxColumnItem ? mxColumnItem->GetLeft() : mxLRSpaceItem->GetLeft();
446
447 if(bAppSetNullOffset)
448 {
449 lAppNullOffset += lLogicNullOffset - nOld;
450 }
451
452 if(!bAppSetNullOffset || lAppNullOffset == LONG_MAX)
453 {
454 Ruler::SetNullOffset(ConvertHPosPixel(lLogicNullOffset));
455 SetMargin1(0, nMarginStyle);
456 lAppNullOffset = 0;
457 }
458 else
459 {
460 SetMargin1(ConvertHPosPixel(lAppNullOffset), nMarginStyle);
461 }
462
463 tools::Long lRight = 0;
464
465 // evaluate the table right edge of the table
466 if(mxColumnItem && mxColumnItem->IsTable())
467 lRight = mxColumnItem->GetRight();
468 else
469 lRight = mxLRSpaceItem->GetRight();
470
471 tools::Long aWidth = mxPagePosItem->GetWidth() - lRight - lLogicNullOffset + lAppNullOffset;
472 tools::Long aWidthPixel = ConvertHPosPixel(aWidth);
473
474 SetMargin2(aWidthPixel, nMarginStyle);
475 }
476 else if(mxULSpaceItem && mxPagePosItem)
477 {
478 // relative the upper edge of the surrounding frame
479 const tools::Long nOld = lLogicNullOffset;
480 lLogicNullOffset = mxColumnItem ? mxColumnItem->GetLeft() : mxULSpaceItem->GetUpper();
481
482 if(bAppSetNullOffset)
483 {
484 lAppNullOffset += lLogicNullOffset - nOld;
485 }
486
487 if(!bAppSetNullOffset || lAppNullOffset == LONG_MAX)
488 {
489 Ruler::SetNullOffset(ConvertVPosPixel(lLogicNullOffset));
490 lAppNullOffset = 0;
491 SetMargin1(0, nMarginStyle);
492 }
493 else
494 {
495 SetMargin1(ConvertVPosPixel(lAppNullOffset), nMarginStyle);
496 }
497
498 tools::Long lLower = mxColumnItem ? mxColumnItem->GetRight() : mxULSpaceItem->GetLower();
499 tools::Long nMargin2 = mxPagePosItem->GetHeight() - lLower - lLogicNullOffset + lAppNullOffset;
500 tools::Long nMargin2Pixel = ConvertVPosPixel(nMargin2);
501
502 SetMargin2(nMargin2Pixel, nMarginStyle);
503 }
504 else
505 {
506 // turns off the view
507 SetMargin1();
508 SetMargin2();
509 }
510
511 if (mxColumnItem)
512 {
513 mxRulerImpl->nColLeftPix = static_cast<sal_uInt16>(ConvertSizePixel(mxColumnItem->GetLeft()));
514 mxRulerImpl->nColRightPix = static_cast<sal_uInt16>(ConvertSizePixel(mxColumnItem->GetRight()));
515 }
516 }
517
MouseMove(const MouseEvent & rMEvt)518 void SvxRuler::MouseMove( const MouseEvent& rMEvt )
519 {
520 if( bActive )
521 {
522 pBindings->Update( SID_RULER_LR_MIN_MAX );
523 pBindings->Update( SID_ATTR_LONG_ULSPACE );
524 pBindings->Update( SID_ATTR_LONG_LRSPACE );
525 pBindings->Update( SID_RULER_PAGE_POS );
526 pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
527 pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
528 pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
529 pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
530 pBindings->Update( SID_RULER_OBJECT );
531 pBindings->Update( SID_RULER_PROTECT );
532 }
533
534 Ruler::MouseMove( rMEvt );
535
536 RulerSelection aSelection = GetHoverSelection();
537
538 if (aSelection.eType == RulerType::DontKnow)
539 {
540 SetQuickHelpText("");
541 return;
542 }
543
544 RulerUnitData aUnitData = GetCurrentRulerUnit();
545 double aRoundingFactor = aUnitData.nTickUnit / aUnitData.nTick1;
546 sal_Int32 aNoDecimalPlaces = 1 + std::ceil(std::log10(aRoundingFactor));
547 OUString sUnit = OUString::createFromAscii(aUnitData.aUnitStr);
548
549 switch (aSelection.eType)
550 {
551 case RulerType::Indent:
552 {
553 if (!mxParaItem)
554 break;
555
556 tools::Long nIndex = aSelection.nAryPos + INDENT_GAP;
557
558 tools::Long nIndentValue = 0.0;
559 if (nIndex == INDENT_LEFT_MARGIN)
560 nIndentValue = mxParaItem->GetTextLeft();
561 else if (nIndex == INDENT_FIRST_LINE)
562 nIndentValue = mxParaItem->GetTextFirstLineOffset();
563 else if (nIndex == INDENT_RIGHT_MARGIN)
564 nIndentValue = mxParaItem->GetRight();
565
566 double fValue = OutputDevice::LogicToLogic(Size(nIndentValue, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
567 fValue = rtl::math::round(fValue / aUnitData.nTickUnit, aNoDecimalPlaces);
568
569 SetQuickHelpText(OUString::number(fValue) + " " + sUnit);
570 break;
571 }
572 case RulerType::Border:
573 {
574 if (mxColumnItem == nullptr)
575 break;
576
577 SvxColumnItem& aColumnItem = *mxColumnItem;
578
579 if (aSelection.nAryPos + 1 >= aColumnItem.Count())
580 break;
581
582 double fStart = OutputDevice::LogicToLogic(Size(aColumnItem[aSelection.nAryPos].nEnd, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
583 fStart = rtl::math::round(fStart / aUnitData.nTickUnit, aNoDecimalPlaces);
584 double fEnd = OutputDevice::LogicToLogic(Size(aColumnItem[aSelection.nAryPos + 1].nStart, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
585 fEnd = rtl::math::round(fEnd / aUnitData.nTickUnit, aNoDecimalPlaces);
586
587 SetQuickHelpText(
588 OUString::number(fStart) + " " + sUnit + " - " +
589 OUString::number(fEnd) + " " + sUnit );
590 break;
591 }
592 case RulerType::Margin1:
593 {
594 tools::Long nLeft = 0.0;
595 if (mxLRSpaceItem)
596 nLeft = mxLRSpaceItem->GetLeft();
597 else if (mxULSpaceItem)
598 nLeft = mxULSpaceItem->GetUpper();
599 else
600 break;
601
602 double fValue = OutputDevice::LogicToLogic(Size(nLeft, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
603 fValue = rtl::math::round(fValue / aUnitData.nTickUnit, aNoDecimalPlaces);
604 SetQuickHelpText(OUString::number(fValue) + " " + sUnit);
605
606 break;
607 }
608 case RulerType::Margin2:
609 {
610 tools::Long nRight = 0.0;
611 if (mxLRSpaceItem)
612 nRight = mxLRSpaceItem->GetRight();
613 else if (mxULSpaceItem)
614 nRight = mxULSpaceItem->GetLower();
615 else
616 break;
617
618 double fValue = OutputDevice::LogicToLogic(Size(nRight, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
619 fValue = rtl::math::round(fValue / aUnitData.nTickUnit, aNoDecimalPlaces);
620 SetQuickHelpText(OUString::number(fValue) + " " + sUnit);
621
622 break;
623 }
624 default:
625 {
626 SetQuickHelpText("");
627 break;
628 }
629 }
630 }
631
StartListening_Impl()632 void SvxRuler::StartListening_Impl()
633 {
634 if(!bListening)
635 {
636 bValid = false;
637 StartListening(*pBindings);
638 bListening = true;
639 }
640 }
641
UpdateFrame(const SvxLongLRSpaceItem * pItem)642 void SvxRuler::UpdateFrame(const SvxLongLRSpaceItem *pItem) // new value LRSpace
643 {
644 /* Store new value LRSpace; delete old ones if possible */
645 if(bActive)
646 {
647 if(pItem)
648 mxLRSpaceItem.reset(new SvxLongLRSpaceItem(*pItem));
649 else
650 mxLRSpaceItem.reset();
651 StartListening_Impl();
652 }
653 }
654
UpdateFrameMinMax(const SfxRectangleItem * pItem)655 void SvxRuler::UpdateFrameMinMax(const SfxRectangleItem *pItem) // value for MinMax
656 {
657 /* Set new value for MinMax; delete old ones if possible */
658 if(bActive)
659 {
660 if(pItem)
661 mxMinMaxItem.reset(new SfxRectangleItem(*pItem));
662 else
663 mxMinMaxItem.reset();
664 }
665 }
666
667
UpdateFrame(const SvxLongULSpaceItem * pItem)668 void SvxRuler::UpdateFrame(const SvxLongULSpaceItem *pItem) // new value
669 {
670 /* Update Right/bottom margin */
671 if(bActive && !bHorz)
672 {
673 if(pItem)
674 mxULSpaceItem.reset(new SvxLongULSpaceItem(*pItem));
675 else
676 mxULSpaceItem.reset();
677 StartListening_Impl();
678 }
679 }
680
Update(const SvxProtectItem * pItem)681 void SvxRuler::Update( const SvxProtectItem* pItem )
682 {
683 if( pItem )
684 mxRulerImpl->aProtectItem.reset(pItem->Clone());
685 }
686
UpdateTextRTL(const SfxBoolItem * pItem)687 void SvxRuler::UpdateTextRTL(const SfxBoolItem* pItem)
688 {
689 if(bActive && bHorz)
690 {
691 mxRulerImpl->pTextRTLItem.reset();
692 if(pItem)
693 mxRulerImpl->pTextRTLItem.reset(new SfxBoolItem(*pItem));
694 SetTextRTL(mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue());
695 StartListening_Impl();
696 }
697 }
698
Update(const SvxColumnItem * pItem,sal_uInt16 nSID)699 void SvxRuler::Update(
700 const SvxColumnItem *pItem, // new value
701 sal_uInt16 nSID) //Slot Id to identify NULL items
702 {
703 /* Set new value for column view */
704 if(!bActive)
705 return;
706
707 if(pItem)
708 {
709 mxColumnItem.reset(new SvxColumnItem(*pItem));
710 mxRulerImpl->bIsTableRows = (pItem->Which() == SID_RULER_ROWS || pItem->Which() == SID_RULER_ROWS_VERTICAL);
711 if(!bHorz && !mxRulerImpl->bIsTableRows)
712 mxColumnItem->SetWhich(SID_RULER_BORDERS_VERTICAL);
713 }
714 else if(mxColumnItem && mxColumnItem->Which() == nSID)
715 //there are two groups of column items table/frame columns and table rows
716 //both can occur in vertical or horizontal mode
717 //the horizontal ruler handles the SID_RULER_BORDERS and SID_RULER_ROWS_VERTICAL
718 //and the vertical handles SID_RULER_BORDERS_VERTICAL and SID_RULER_ROWS
719 //if mxColumnItem is already set with one of the ids then a NULL pItem argument
720 //must not delete it
721 {
722 mxColumnItem.reset();
723 mxRulerImpl->bIsTableRows = false;
724 }
725 StartListening_Impl();
726 }
727
728
UpdateColumns()729 void SvxRuler::UpdateColumns()
730 {
731 /* Update column view */
732 if(mxColumnItem && mxColumnItem->Count() > 1)
733 {
734 mpBorders.resize(mxColumnItem->Count());
735
736 RulerBorderStyle nStyleFlags = RulerBorderStyle::Variable;
737
738 bool bProtectColumns =
739 mxRulerImpl->aProtectItem->IsSizeProtected() ||
740 mxRulerImpl->aProtectItem->IsPosProtected();
741
742 if( !bProtectColumns )
743 {
744 nStyleFlags |= RulerBorderStyle::Moveable;
745 if( !mxColumnItem->IsTable() )
746 nStyleFlags |= RulerBorderStyle::Sizeable;
747 }
748
749 sal_uInt16 nBorders = mxColumnItem->Count();
750
751 if(!mxRulerImpl->bIsTableRows)
752 --nBorders;
753
754 for(sal_uInt16 i = 0; i < nBorders; ++i)
755 {
756 mpBorders[i].nStyle = nStyleFlags;
757 if(!mxColumnItem->At(i).bVisible)
758 mpBorders[i].nStyle |= RulerBorderStyle::Invisible;
759
760 mpBorders[i].nPos = ConvertPosPixel(mxColumnItem->At(i).nEnd + lAppNullOffset);
761
762 if(mxColumnItem->Count() == i + 1)
763 {
764 //with table rows the end of the table is contained in the
765 //column item but it has no width!
766 mpBorders[i].nWidth = 0;
767 }
768 else
769 {
770 mpBorders[i].nWidth = ConvertSizePixel(mxColumnItem->At(i + 1).nStart - mxColumnItem->At(i).nEnd);
771 }
772 mpBorders[i].nMinPos = ConvertPosPixel(mxColumnItem->At(i).nEndMin + lAppNullOffset);
773 mpBorders[i].nMaxPos = ConvertPosPixel(mxColumnItem->At(i).nEndMax + lAppNullOffset);
774 }
775 SetBorders(mxColumnItem->Count() - 1, mpBorders.data());
776 }
777 else
778 {
779 SetBorders();
780 }
781 }
782
UpdateObject()783 void SvxRuler::UpdateObject()
784 {
785 /* Update view of object representation */
786 if (mxObjectItem)
787 {
788 DBG_ASSERT(!mpObjectBorders.empty(), "no Buffer");
789 // !! to the page margin
790 tools::Long nMargin = mxLRSpaceItem ? mxLRSpaceItem->GetLeft() : 0;
791 mpObjectBorders[0].nPos =
792 ConvertPosPixel(mxObjectItem->GetStartX() -
793 nMargin + lAppNullOffset);
794 mpObjectBorders[1].nPos =
795 ConvertPosPixel(mxObjectItem->GetEndX() - nMargin + lAppNullOffset);
796 nMargin = mxULSpaceItem ? mxULSpaceItem->GetUpper() : 0;
797 mpObjectBorders[2].nPos =
798 ConvertPosPixel(mxObjectItem->GetStartY() -
799 nMargin + lAppNullOffset);
800 mpObjectBorders[3].nPos =
801 ConvertPosPixel(mxObjectItem->GetEndY() - nMargin + lAppNullOffset);
802
803 const sal_uInt16 nOffset = GetObjectBordersOff(0);
804 SetBorders(2, mpObjectBorders.data() + nOffset);
805 }
806 else
807 {
808 SetBorders();
809 }
810 }
811
UpdatePara()812 void SvxRuler::UpdatePara()
813 {
814
815 /* Update the view for paragraph indents:
816 Left margin, first line indent, right margin paragraph update
817 mpIndents[0] = Buffer for old intent
818 mpIndents[1] = Buffer for old intent
819 mpIndents[INDENT_FIRST_LINE] = first line indent
820 mpIndents[INDENT_LEFT_MARGIN] = left margin
821 mpIndents[INDENT_RIGHT_MARGIN] = right margin
822 */
823
824 // Dependence on PagePosItem
825 if (mxParaItem && mxPagePosItem && !mxObjectItem)
826 {
827 bool bRTLText = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
828 // First-line indent is negative to the left paragraph margin
829 tools::Long nLeftFrameMargin = GetLeftFrameMargin();
830 tools::Long nRightFrameMargin = GetRightFrameMargin();
831 SetLeftFrameMargin(ConvertHPosPixel(nLeftFrameMargin));
832 SetRightFrameMargin(ConvertHPosPixel(nRightFrameMargin));
833
834 tools::Long leftMargin;
835 tools::Long leftFirstLine;
836 tools::Long rightMargin;
837
838 if(bRTLText)
839 {
840 leftMargin = nRightFrameMargin - mxParaItem->GetTextLeft() + lAppNullOffset;
841 leftFirstLine = leftMargin - mxParaItem->GetTextFirstLineOffset();
842 rightMargin = nLeftFrameMargin + mxParaItem->GetRight() + lAppNullOffset;
843 }
844 else
845 {
846 leftMargin = nLeftFrameMargin + mxParaItem->GetTextLeft() + lAppNullOffset;
847 leftFirstLine = leftMargin + mxParaItem->GetTextFirstLineOffset();
848 rightMargin = nRightFrameMargin - mxParaItem->GetRight() + lAppNullOffset;
849 }
850
851 mpIndents[INDENT_LEFT_MARGIN].nPos = ConvertHPosPixel(leftMargin);
852 mpIndents[INDENT_FIRST_LINE].nPos = ConvertHPosPixel(leftFirstLine);
853 mpIndents[INDENT_RIGHT_MARGIN].nPos = ConvertHPosPixel(rightMargin);
854
855 mpIndents[INDENT_FIRST_LINE].bInvisible = mxParaItem->IsAutoFirst();
856
857 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
858 }
859 else
860 {
861 if(!mpIndents.empty())
862 {
863 mpIndents[INDENT_FIRST_LINE].nPos = 0;
864 mpIndents[INDENT_LEFT_MARGIN].nPos = 0;
865 mpIndents[INDENT_RIGHT_MARGIN].nPos = 0;
866 }
867 SetIndents(); // turn off
868 }
869 }
870
UpdatePara(const SvxLRSpaceItem * pItem)871 void SvxRuler::UpdatePara(const SvxLRSpaceItem *pItem) // new value of paragraph indents
872 {
873 /* Store new value of paragraph indents */
874 if(bActive)
875 {
876 if(pItem)
877 mxParaItem.reset(new SvxLRSpaceItem(*pItem));
878 else
879 mxParaItem.reset();
880 StartListening_Impl();
881 }
882 }
883
UpdateParaBorder()884 void SvxRuler::UpdateParaBorder()
885 {
886 /* Border distance */
887 if(bActive)
888 {
889 StartListening_Impl();
890 }
891 }
892
UpdatePage()893 void SvxRuler::UpdatePage()
894 {
895 /* Update view of position and width of page */
896 if (mxPagePosItem)
897 {
898 // all objects are automatically adjusted
899 if(bHorz)
900 {
901 SetPagePos(
902 pEditWin->LogicToPixel(mxPagePosItem->GetPos()).X(),
903 pEditWin->LogicToPixel(Size(mxPagePosItem->GetWidth(), 0)).
904 Width());
905 }
906 else
907 {
908 SetPagePos(
909 pEditWin->LogicToPixel(mxPagePosItem->GetPos()).Y(),
910 pEditWin->LogicToPixel(Size(0, mxPagePosItem->GetHeight())).
911 Height());
912 }
913 if(bAppSetNullOffset)
914 SetNullOffset(ConvertSizePixel(-lAppNullOffset + lLogicNullOffset));
915 }
916 else
917 {
918 SetPagePos();
919 }
920
921 tools::Long lPos = 0;
922 Point aOwnPos = GetPosPixel();
923 Point aEdtWinPos = pEditWin->GetPosPixel();
924 if( AllSettings::GetLayoutRTL() && bHorz )
925 {
926 //#i73321# in RTL the window and the ruler is not mirrored but the
927 // influence of the vertical ruler is inverted
928 Size aOwnSize = GetSizePixel();
929 Size aEdtWinSize = pEditWin->GetSizePixel();
930 lPos = aOwnSize.Width() - aEdtWinSize.Width();
931 lPos -= (aEdtWinPos - aOwnPos).X();
932 }
933 else
934 {
935 Point aPos(aEdtWinPos - aOwnPos);
936 lPos = bHorz ? aPos.X() : aPos.Y();
937 }
938
939 // Unfortunately, we get the offset of the edit window to the ruler never
940 // through a status message. So we set it ourselves if necessary.
941 if(lPos != mxRulerImpl->lOldWinPos)
942 {
943 mxRulerImpl->lOldWinPos=lPos;
944 SetWinPos(lPos);
945 }
946 }
947
Update(const SvxPagePosSizeItem * pItem)948 void SvxRuler::Update(const SvxPagePosSizeItem *pItem) // new value of page attributes
949 {
950 /* Store new value of page attributes */
951 if(bActive)
952 {
953 if(pItem)
954 mxPagePosItem.reset(new SvxPagePosSizeItem(*pItem));
955 else
956 mxPagePosItem.reset();
957 StartListening_Impl();
958 }
959 }
960
SetDefTabDist(tools::Long inDefTabDist)961 void SvxRuler::SetDefTabDist(tools::Long inDefTabDist) // New distance for DefaultTabs in App-Metrics
962 {
963 if (lAppNullOffset == LONG_MAX)
964 UpdateFrame(); // hack: try to get lAppNullOffset initialized
965 /* New distance is set for DefaultTabs */
966 lDefTabDist = inDefTabDist;
967 UpdateTabs();
968 }
969
ToSvTab_Impl(SvxTabAdjust eAdj)970 static sal_uInt16 ToSvTab_Impl(SvxTabAdjust eAdj)
971 {
972 /* Internal conversion routine between SV-Tab.-Enum and Svx */
973 switch(eAdj) {
974 case SvxTabAdjust::Left: return RULER_TAB_LEFT;
975 case SvxTabAdjust::Right: return RULER_TAB_RIGHT;
976 case SvxTabAdjust::Decimal: return RULER_TAB_DECIMAL;
977 case SvxTabAdjust::Center: return RULER_TAB_CENTER;
978 case SvxTabAdjust::Default: return RULER_TAB_DEFAULT;
979 default: ; //prevent warning
980 }
981 return 0;
982 }
983
ToAttrTab_Impl(sal_uInt16 eAdj)984 static SvxTabAdjust ToAttrTab_Impl(sal_uInt16 eAdj)
985 {
986 switch(eAdj) {
987 case RULER_TAB_LEFT: return SvxTabAdjust::Left ;
988 case RULER_TAB_RIGHT: return SvxTabAdjust::Right ;
989 case RULER_TAB_DECIMAL: return SvxTabAdjust::Decimal ;
990 case RULER_TAB_CENTER: return SvxTabAdjust::Center ;
991 case RULER_TAB_DEFAULT: return SvxTabAdjust::Default ;
992 }
993 return SvxTabAdjust::Left;
994 }
995
UpdateTabs()996 void SvxRuler::UpdateTabs()
997 {
998 if(IsDrag())
999 return;
1000
1001 if (mxPagePosItem && mxParaItem && mxTabStopItem && !mxObjectItem)
1002 {
1003 // buffer for DefaultTabStop
1004 // Distance last Tab <-> Right paragraph margin / DefaultTabDist
1005 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
1006
1007 const tools::Long nLeftFrameMargin = GetLeftFrameMargin();
1008 const tools::Long nRightFrameMargin = GetRightFrameMargin();
1009
1010 //#i24363# tab stops relative to indent
1011 const tools::Long nParaItemTxtLeft = mxParaItem->GetTextLeft();
1012
1013 const tools::Long lParaIndent = nLeftFrameMargin + nParaItemTxtLeft;
1014 const tools::Long lRightMargin = nRightFrameMargin - nParaItemTxtLeft;
1015
1016 const tools::Long lLastTab = mxTabStopItem->Count()
1017 ? ConvertHPosPixel(mxTabStopItem->At(mxTabStopItem->Count() - 1).GetTabPos())
1018 : 0;
1019 const tools::Long lPosPixel = ConvertHPosPixel(lParaIndent) + lLastTab;
1020 const tools::Long lRightIndent = ConvertHPosPixel(nRightFrameMargin - mxParaItem->GetRight());
1021
1022 tools::Long nDefTabDist = ConvertHPosPixel(lDefTabDist);
1023
1024 if( !nDefTabDist )
1025 nDefTabDist = 1;
1026
1027 const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > lRightIndent
1028 ? 0
1029 : static_cast<sal_uInt16>( (lRightIndent - lPosPixel) / nDefTabDist );
1030
1031 if(mxTabStopItem->Count() + TAB_GAP + nDefTabBuf > nTabBufSize)
1032 {
1033 // 10 (GAP) in stock
1034 nTabBufSize = mxTabStopItem->Count() + TAB_GAP + nDefTabBuf + GAP;
1035 mpTabs.resize(nTabBufSize);
1036 }
1037
1038 nTabCount = 0;
1039 sal_uInt16 j;
1040
1041 const tools::Long lParaIndentPix = ConvertSizePixel(lParaIndent);
1042
1043 tools::Long lTabStartLogic = (mxRulerImpl->bIsTabsRelativeToIndent ? lParaIndent : nLeftFrameMargin)
1044 + lAppNullOffset;
1045 if (bRTL)
1046 {
1047 lTabStartLogic = lParaIndent + lRightMargin - lTabStartLogic;
1048 }
1049 tools::Long lLastTabOffsetLogic = 0;
1050 for(j = 0; j < mxTabStopItem->Count(); ++j)
1051 {
1052 const SvxTabStop* pTab = &mxTabStopItem->At(j);
1053 lLastTabOffsetLogic = pTab->GetTabPos();
1054 tools::Long lPos = lTabStartLogic + (bRTL ? -lLastTabOffsetLogic : lLastTabOffsetLogic);
1055 mpTabs[nTabCount + TAB_GAP].nPos = ConvertHPosPixel(lPos);
1056 mpTabs[nTabCount + TAB_GAP].nStyle = ToSvTab_Impl(pTab->GetAdjustment());
1057 ++nTabCount;
1058 }
1059
1060 // Adjust to previous-to-first default tab stop
1061 lLastTabOffsetLogic -= lLastTabOffsetLogic % lDefTabDist;
1062
1063 // fill the rest with default Tabs
1064 for (j = 0; j < nDefTabBuf; ++j)
1065 {
1066 //simply add the default distance to the last position
1067 lLastTabOffsetLogic += lDefTabDist;
1068 if (bRTL)
1069 {
1070 mpTabs[nTabCount + TAB_GAP].nPos =
1071 ConvertHPosPixel(lTabStartLogic - lLastTabOffsetLogic);
1072 if (mpTabs[nTabCount + TAB_GAP].nPos <= lParaIndentPix)
1073 break;
1074 }
1075 else
1076 {
1077 mpTabs[nTabCount + TAB_GAP].nPos =
1078 ConvertHPosPixel(lTabStartLogic + lLastTabOffsetLogic);
1079 if (mpTabs[nTabCount + TAB_GAP].nPos >= lRightIndent)
1080 break;
1081 }
1082
1083 mpTabs[nTabCount + TAB_GAP].nStyle = RULER_TAB_DEFAULT;
1084 ++nTabCount;
1085 }
1086 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1087 DBG_ASSERT(nTabCount + TAB_GAP <= nTabBufSize, "BufferSize too small");
1088 }
1089 else
1090 {
1091 SetTabs();
1092 }
1093 }
1094
Update(const SvxTabStopItem * pItem)1095 void SvxRuler::Update(const SvxTabStopItem *pItem) // new value for tabs
1096 {
1097 /* Store new value for tabs; delete old ones if possible */
1098 if(!bActive)
1099 return;
1100
1101 if(pItem)
1102 {
1103 mxTabStopItem.reset(new SvxTabStopItem(*pItem));
1104 if(!bHorz)
1105 mxTabStopItem->SetWhich(SID_ATTR_TABSTOP_VERTICAL);
1106 }
1107 else
1108 {
1109 mxTabStopItem.reset();
1110 }
1111 StartListening_Impl();
1112 }
1113
Update(const SvxObjectItem * pItem)1114 void SvxRuler::Update(const SvxObjectItem *pItem) // new value for objects
1115 {
1116 /* Store new value for objects */
1117 if(bActive)
1118 {
1119 if(pItem)
1120 mxObjectItem.reset(new SvxObjectItem(*pItem));
1121 else
1122 mxObjectItem.reset();
1123 StartListening_Impl();
1124 }
1125 }
1126
SetNullOffsetLogic(tools::Long lVal)1127 void SvxRuler::SetNullOffsetLogic(tools::Long lVal) // Setting of the logic NullOffsets
1128 {
1129 lAppNullOffset = lLogicNullOffset - lVal;
1130 bAppSetNullOffset = true;
1131 Ruler::SetNullOffset(ConvertSizePixel(lVal));
1132 Update();
1133 }
1134
Update()1135 void SvxRuler::Update()
1136 {
1137 /* Perform update of view */
1138 if(IsDrag())
1139 return;
1140
1141 UpdatePage();
1142 UpdateFrame();
1143 if(nFlags & SvxRulerSupportFlags::OBJECT)
1144 UpdateObject();
1145 else
1146 UpdateColumns();
1147
1148 if(nFlags & (SvxRulerSupportFlags::PARAGRAPH_MARGINS | SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL))
1149 UpdatePara();
1150
1151 if(nFlags & SvxRulerSupportFlags::TABS)
1152 UpdateTabs();
1153 }
1154
GetPageWidth() const1155 tools::Long SvxRuler::GetPageWidth() const
1156 {
1157 if (!mxPagePosItem)
1158 return 0;
1159 return bHorz ? mxPagePosItem->GetWidth() : mxPagePosItem->GetHeight();
1160 }
1161
GetFrameLeft() const1162 inline tools::Long SvxRuler::GetFrameLeft() const
1163 {
1164 /* Get Left margin in Pixels */
1165 return bAppSetNullOffset ?
1166 GetMargin1() + ConvertSizePixel(lLogicNullOffset) :
1167 Ruler::GetNullOffset();
1168 }
1169
GetFirstLineIndent() const1170 tools::Long SvxRuler::GetFirstLineIndent() const
1171 {
1172 /* Get First-line indent in pixels */
1173 return mxParaItem ? mpIndents[INDENT_FIRST_LINE].nPos : GetMargin1();
1174 }
1175
GetLeftIndent() const1176 tools::Long SvxRuler::GetLeftIndent() const
1177 {
1178 /* Get Left paragraph margin in Pixels */
1179 return mxParaItem ? mpIndents[INDENT_LEFT_MARGIN].nPos : GetMargin1();
1180 }
1181
GetRightIndent() const1182 tools::Long SvxRuler::GetRightIndent() const
1183 {
1184 /* Get Right paragraph margin in Pixels */
1185 return mxParaItem ? mpIndents[INDENT_RIGHT_MARGIN].nPos : GetMargin2();
1186 }
1187
GetLogicRightIndent() const1188 tools::Long SvxRuler::GetLogicRightIndent() const
1189 {
1190 /* Get Right paragraph margin in Logic */
1191 return mxParaItem ? GetRightFrameMargin() - mxParaItem->GetRight() : GetRightFrameMargin();
1192 }
1193
1194 // Left margin in App values, is either the margin (= 0) or the left edge of
1195 // the column that is set in the column attribute as current column.
GetLeftFrameMargin() const1196 tools::Long SvxRuler::GetLeftFrameMargin() const
1197 {
1198 // #126721# for some unknown reason the current column is set to 0xffff
1199 DBG_ASSERT(!mxColumnItem || mxColumnItem->GetActColumn() < mxColumnItem->Count(),
1200 "issue #126721# - invalid current column!");
1201 tools::Long nLeft = 0;
1202 if (mxColumnItem &&
1203 mxColumnItem->Count() &&
1204 mxColumnItem->IsConsistent())
1205 {
1206 nLeft = mxColumnItem->GetActiveColumnDescription().nStart;
1207 }
1208
1209 return nLeft;
1210 }
1211
GetLeftMin() const1212 inline tools::Long SvxRuler::GetLeftMin() const
1213 {
1214 DBG_ASSERT(mxMinMaxItem, "no MinMax value set");
1215 if (mxMinMaxItem)
1216 {
1217 if (bHorz)
1218 return mxMinMaxItem->GetValue().Left();
1219 else
1220 return mxMinMaxItem->GetValue().Top();
1221 }
1222 return 0;
1223 }
1224
GetRightMax() const1225 inline tools::Long SvxRuler::GetRightMax() const
1226 {
1227 DBG_ASSERT(mxMinMaxItem, "no MinMax value set");
1228 if (mxMinMaxItem)
1229 {
1230 if (bHorz)
1231 return mxMinMaxItem->GetValue().Right();
1232 else
1233 return mxMinMaxItem->GetValue().Bottom();
1234 }
1235 return 0;
1236 }
1237
1238
GetRightFrameMargin() const1239 tools::Long SvxRuler::GetRightFrameMargin() const
1240 {
1241 /* Get right frame margin (in logical units) */
1242 if (mxColumnItem)
1243 {
1244 if (!IsActLastColumn(true))
1245 {
1246 return mxColumnItem->At(GetActRightColumn(true)).nEnd;
1247 }
1248 }
1249
1250 tools::Long lResult = lLogicNullOffset;
1251
1252 // If possible deduct right table entry
1253 if(mxColumnItem && mxColumnItem->IsTable())
1254 lResult += mxColumnItem->GetRight();
1255 else if(bHorz && mxLRSpaceItem)
1256 lResult += mxLRSpaceItem->GetRight();
1257 else if(!bHorz && mxULSpaceItem)
1258 lResult += mxULSpaceItem->GetLower();
1259
1260 if(bHorz)
1261 lResult = mxPagePosItem->GetWidth() - lResult;
1262 else
1263 lResult = mxPagePosItem->GetHeight() - lResult;
1264
1265 return lResult;
1266 }
1267
1268 #define NEG_FLAG ( (nFlags & SvxRulerSupportFlags::NEGATIVE_MARGINS) == \
1269 SvxRulerSupportFlags::NEGATIVE_MARGINS )
1270 #define TAB_FLAG ( mxColumnItem && mxColumnItem->IsTable() )
1271
GetCorrectedDragPos(bool bLeft,bool bRight)1272 tools::Long SvxRuler::GetCorrectedDragPos( bool bLeft, bool bRight )
1273 {
1274 /*
1275 Corrects the position within the calculated limits. The limit values are in
1276 pixels relative to the page edge.
1277 */
1278
1279 const tools::Long lNullPix = Ruler::GetNullOffset();
1280 tools::Long lDragPos = GetDragPos() + lNullPix;
1281 bool bHoriRows = bHorz && mxRulerImpl->bIsTableRows;
1282 if((bLeft || bHoriRows) && lDragPos < nMaxLeft)
1283 lDragPos = nMaxLeft;
1284 else if((bRight||bHoriRows) && lDragPos > nMaxRight)
1285 lDragPos = nMaxRight;
1286 return lDragPos - lNullPix;
1287 }
1288
ModifyTabs_Impl(sal_uInt16 nCount,RulerTab * pTabs,tools::Long lDiff)1289 static void ModifyTabs_Impl( sal_uInt16 nCount, // Number of Tabs
1290 RulerTab* pTabs, // Tab buffer
1291 tools::Long lDiff) // difference to be added
1292 {
1293 /* Helper function, move all the tabs by a fixed value */
1294 if( pTabs )
1295 {
1296 for(sal_uInt16 i = 0; i < nCount; ++i)
1297 {
1298 pTabs[i].nPos += lDiff;
1299 }
1300 }
1301 }
1302
DragMargin1()1303 void SvxRuler::DragMargin1()
1304 {
1305 /* Dragging the left edge of frame */
1306 tools::Long aDragPosition = GetCorrectedDragPos( !TAB_FLAG || !NEG_FLAG );
1307
1308 aDragPosition = MakePositionSticky(aDragPosition, GetRightFrameMargin(), false);
1309
1310 // Check if position changed
1311 if (aDragPosition == 0)
1312 return;
1313
1314 DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 3 : 7, bHorz);
1315 if (mxColumnItem && (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL))
1316 DragBorders();
1317 AdjustMargin1(aDragPosition);
1318 }
1319
AdjustMargin1(tools::Long lInputDiff)1320 void SvxRuler::AdjustMargin1(tools::Long lInputDiff)
1321 {
1322 const tools::Long nOld = bAppSetNullOffset? GetMargin1(): GetNullOffset();
1323 const tools::Long lDragPos = lInputDiff;
1324
1325 bool bProtectColumns =
1326 mxRulerImpl->aProtectItem->IsSizeProtected() ||
1327 mxRulerImpl->aProtectItem->IsPosProtected();
1328
1329 const RulerMarginStyle nMarginStyle =
1330 bProtectColumns ? RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
1331
1332 if(!bAppSetNullOffset)
1333 {
1334 tools::Long lDiff = lDragPos;
1335 SetNullOffset(nOld + lDiff);
1336 if (!mxColumnItem || !(nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR))
1337 {
1338 SetMargin2( GetMargin2() - lDiff, nMarginStyle );
1339
1340 if (!mxColumnItem && !mxObjectItem && mxParaItem)
1341 {
1342 // Right indent of the old position
1343 mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
1344 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1345 }
1346 if (mxObjectItem)
1347 {
1348 mpObjectBorders[GetObjectBordersOff(0)].nPos -= lDiff;
1349 mpObjectBorders[GetObjectBordersOff(1)].nPos -= lDiff;
1350 SetBorders(2, mpObjectBorders.data() + GetObjectBordersOff(0));
1351 }
1352 if (mxColumnItem)
1353 {
1354 for(sal_uInt16 i = 0; i < mxColumnItem->Count()-1; ++i)
1355 mpBorders[i].nPos -= lDiff;
1356 SetBorders(mxColumnItem->Count()-1, mpBorders.data());
1357 if(mxColumnItem->IsFirstAct())
1358 {
1359 // Right indent of the old position
1360 if (mxParaItem)
1361 {
1362 mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
1363 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1364 }
1365 }
1366 else
1367 {
1368 if (mxParaItem)
1369 {
1370 mpIndents[INDENT_FIRST_LINE].nPos -= lDiff;
1371 mpIndents[INDENT_LEFT_MARGIN].nPos -= lDiff;
1372 mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
1373 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1374 }
1375 }
1376 if(mxTabStopItem && (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
1377 &&!IsActFirstColumn())
1378 {
1379 ModifyTabs_Impl(nTabCount + TAB_GAP, mpTabs.data(), -lDiff);
1380 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1381 }
1382 }
1383 }
1384 }
1385 else
1386 {
1387 tools::Long lDiff = lDragPos - nOld;
1388 SetMargin1(nOld + lDiff, nMarginStyle);
1389
1390 if (!mxColumnItem
1391 || !(nDragType
1392 & (SvxRulerDragFlags::OBJECT_SIZE_LINEAR
1393 | SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)))
1394 {
1395 if (!mxColumnItem && !mxObjectItem && mxParaItem)
1396 {
1397 // Left indent of the old position
1398 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1399 mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
1400 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1401 }
1402
1403 if (mxColumnItem)
1404 {
1405 for(sal_uInt16 i = 0; i < mxColumnItem->Count() - 1; ++i)
1406 mpBorders[i].nPos += lDiff;
1407 SetBorders(mxColumnItem->Count() - 1, mpBorders.data());
1408 if (mxColumnItem->IsFirstAct())
1409 {
1410 // Left indent of the old position
1411 if (mxParaItem)
1412 {
1413 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1414 mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
1415 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1416 }
1417 }
1418 else
1419 {
1420 if (mxParaItem)
1421 {
1422 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1423 mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
1424 mpIndents[INDENT_RIGHT_MARGIN].nPos += lDiff;
1425 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1426 }
1427 }
1428 }
1429 if (mxTabStopItem)
1430 {
1431 ModifyTabs_Impl(nTabCount + TAB_GAP, mpTabs.data(), lDiff);
1432 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1433 }
1434 }
1435 }
1436 }
1437
DragMargin2()1438 void SvxRuler::DragMargin2()
1439 {
1440 /* Dragging the right edge of frame */
1441 tools::Long aDragPosition = GetCorrectedDragPos( true, !TAB_FLAG || !NEG_FLAG);
1442 aDragPosition = MakePositionSticky(aDragPosition, GetLeftFrameMargin(), false);
1443 tools::Long lDiff = aDragPosition - GetMargin2();
1444
1445 // Check if position changed
1446 if (lDiff == 0)
1447 return;
1448
1449 if( mxRulerImpl->bIsTableRows &&
1450 !bHorz &&
1451 mxColumnItem &&
1452 (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL))
1453 {
1454 DragBorders();
1455 }
1456
1457 bool bProtectColumns =
1458 mxRulerImpl->aProtectItem->IsSizeProtected() ||
1459 mxRulerImpl->aProtectItem->IsPosProtected();
1460
1461 const RulerMarginStyle nMarginStyle = bProtectColumns ? RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
1462
1463 SetMargin2( aDragPosition, nMarginStyle );
1464
1465 // Right indent of the old position
1466 if ((!mxColumnItem || IsActLastColumn()) && mxParaItem)
1467 {
1468 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1469 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1470 }
1471
1472 DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 5 : 7, bHorz);
1473 }
1474
DragIndents()1475 void SvxRuler::DragIndents()
1476 {
1477 /* Dragging the paragraph indents */
1478 tools::Long aDragPosition = NEG_FLAG ? GetDragPos() : GetCorrectedDragPos();
1479 const sal_uInt16 nIndex = GetDragAryPos() + INDENT_GAP;
1480
1481 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
1482
1483 if(nIndex == INDENT_RIGHT_MARGIN)
1484 aDragPosition = MakePositionSticky(aDragPosition, bRTL ? GetLeftFrameMargin() : GetRightFrameMargin());
1485 else
1486 aDragPosition = MakePositionSticky(aDragPosition, bRTL ? GetRightFrameMargin() : GetLeftFrameMargin());
1487
1488 const tools::Long lDiff = mpIndents[nIndex].nPos - aDragPosition;
1489
1490 // Check if position changed
1491 if (lDiff == 0)
1492 return;
1493
1494 if((nIndex == INDENT_FIRST_LINE || nIndex == INDENT_LEFT_MARGIN ) &&
1495 !(nDragType & SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY))
1496 {
1497 mpIndents[INDENT_FIRST_LINE].nPos -= lDiff;
1498 }
1499
1500 mpIndents[nIndex].nPos = aDragPosition;
1501
1502 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1503 DrawLine_Impl(lTabPos, 1, bHorz);
1504 }
1505
DrawLine_Impl(tools::Long & lTabPosition,int nNew,bool bHorizontal)1506 void SvxRuler::DrawLine_Impl(tools::Long& lTabPosition, int nNew, bool bHorizontal)
1507 {
1508 /*
1509 Output routine for the ledger line when moving tabs, tables and other
1510 columns
1511 */
1512 if(bHorizontal)
1513 {
1514 const tools::Long nHeight = pEditWin->GetOutDev()->GetOutputSize().Height();
1515 Point aZero = pEditWin->GetMapMode().GetOrigin();
1516 if(lTabPosition != -1)
1517 {
1518 pEditWin->InvertTracking(
1519 tools::Rectangle( Point(lTabPosition, -aZero.Y()),
1520 Point(lTabPosition, -aZero.Y() + nHeight)),
1521 ShowTrackFlags::Split | ShowTrackFlags::Clip );
1522 }
1523 if( nNew & 1 )
1524 {
1525 tools::Long nDrapPosition = GetCorrectedDragPos( ( nNew & 4 ) != 0, ( nNew & 2 ) != 0 );
1526 nDrapPosition = MakePositionSticky(nDrapPosition, GetLeftFrameMargin());
1527 lTabPosition = ConvertHSizeLogic( nDrapPosition + GetNullOffset() );
1528 if (mxPagePosItem)
1529 lTabPosition += mxPagePosItem->GetPos().X();
1530 pEditWin->InvertTracking(
1531 tools::Rectangle( Point(lTabPosition, -aZero.Y()),
1532 Point(lTabPosition, -aZero.Y() + nHeight) ),
1533 ShowTrackFlags::Clip | ShowTrackFlags::Split );
1534 }
1535 }
1536 else
1537 {
1538 const tools::Long nWidth = pEditWin->GetOutDev()->GetOutputSize().Width();
1539 Point aZero = pEditWin->GetMapMode().GetOrigin();
1540 if(lTabPosition != -1)
1541 {
1542 pEditWin->InvertTracking(
1543 tools::Rectangle( Point(-aZero.X(), lTabPosition),
1544 Point(-aZero.X() + nWidth, lTabPosition)),
1545 ShowTrackFlags::Split | ShowTrackFlags::Clip );
1546 }
1547
1548 if(nNew & 1)
1549 {
1550 tools::Long nDrapPosition = GetCorrectedDragPos();
1551 nDrapPosition = MakePositionSticky(nDrapPosition, GetLeftFrameMargin());
1552 lTabPosition = ConvertVSizeLogic(nDrapPosition + GetNullOffset());
1553 if (mxPagePosItem)
1554 lTabPosition += mxPagePosItem->GetPos().Y();
1555 pEditWin->InvertTracking(
1556 tools::Rectangle( Point(-aZero.X(), lTabPosition),
1557 Point(-aZero.X()+nWidth, lTabPosition)),
1558 ShowTrackFlags::Clip | ShowTrackFlags::Split );
1559 }
1560 }
1561 }
1562
DragTabs()1563 void SvxRuler::DragTabs()
1564 {
1565 /* Dragging of Tabs */
1566 tools::Long aDragPosition = GetCorrectedDragPos(true, false);
1567 aDragPosition = MakePositionSticky(aDragPosition, GetLeftFrameMargin());
1568
1569 sal_uInt16 nIdx = GetDragAryPos() + TAB_GAP;
1570 tools::Long nDiff = aDragPosition - mpTabs[nIdx].nPos;
1571 if (nDiff == 0)
1572 return;
1573
1574 DrawLine_Impl(lTabPos, 7, bHorz);
1575
1576 if(nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR)
1577 {
1578
1579 for(sal_uInt16 i = nIdx; i < nTabCount; ++i)
1580 {
1581 mpTabs[i].nPos += nDiff;
1582 // limit on maximum
1583 if(mpTabs[i].nPos > GetMargin2())
1584 mpTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
1585 else
1586 mpTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
1587 }
1588 }
1589 else if(nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
1590 {
1591 mxRulerImpl->nTotalDist -= nDiff;
1592 mpTabs[nIdx].nPos = aDragPosition;
1593 for(sal_uInt16 i = nIdx+1; i < nTabCount; ++i)
1594 {
1595 if(mpTabs[i].nStyle & RULER_TAB_DEFAULT)
1596 // can be canceled at the DefaultTabs
1597 break;
1598 tools::Long nDelta = mxRulerImpl->nTotalDist * mxRulerImpl->pPercBuf[i];
1599 nDelta /= 1000;
1600 mpTabs[i].nPos = mpTabs[nIdx].nPos + nDelta;
1601 if(mpTabs[i].nPos + GetNullOffset() > nMaxRight)
1602 mpTabs[i].nStyle |= RULER_STYLE_INVISIBLE;
1603 else
1604 mpTabs[i].nStyle &= ~RULER_STYLE_INVISIBLE;
1605 }
1606 }
1607 else
1608 {
1609 mpTabs[nIdx].nPos = aDragPosition;
1610 }
1611
1612 if(IsDragDelete())
1613 mpTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
1614 else
1615 mpTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
1616 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1617 }
1618
SetActive(bool bOn)1619 void SvxRuler::SetActive(bool bOn)
1620 {
1621 if(bOn)
1622 {
1623 Activate();
1624 }
1625 else
1626 Deactivate();
1627 if(bActive!=bOn)
1628 {
1629 pBindings->EnterRegistrations();
1630 if(bOn)
1631 for(sal_uInt16 i=0;i<mxRulerImpl->nControllerItems;i++)
1632 pCtrlItems[i]->ReBind();
1633 else
1634 for(sal_uInt16 j=0;j<mxRulerImpl->nControllerItems;j++)
1635 pCtrlItems[j]->UnBind();
1636 pBindings->LeaveRegistrations();
1637 }
1638 bActive = bOn;
1639 }
1640
UpdateParaContents_Impl(tools::Long lDifference,UpdateType eType)1641 void SvxRuler::UpdateParaContents_Impl(
1642 tools::Long lDifference,
1643 UpdateType eType) // Art (all, left or right)
1644 {
1645 /* Helper function; carry Tabs and Paragraph Margins */
1646 switch(eType)
1647 {
1648 case UpdateType::MoveRight:
1649 mpIndents[INDENT_RIGHT_MARGIN].nPos += lDifference;
1650 break;
1651 case UpdateType::MoveLeft:
1652 {
1653 mpIndents[INDENT_FIRST_LINE].nPos += lDifference;
1654 mpIndents[INDENT_LEFT_MARGIN].nPos += lDifference;
1655 if (!mpTabs.empty())
1656 {
1657 for(sal_uInt16 i = 0; i < nTabCount+TAB_GAP; ++i)
1658 {
1659 mpTabs[i].nPos += lDifference;
1660 }
1661 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1662 }
1663 break;
1664 }
1665 }
1666 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
1667 }
1668
DragBorders()1669 void SvxRuler::DragBorders()
1670 {
1671 /* Dragging of Borders (Tables and other columns) */
1672 bool bLeftIndentsCorrected = false;
1673 bool bRightIndentsCorrected = false;
1674 int nIndex;
1675
1676 if(GetDragType() == RulerType::Border)
1677 {
1678 DrawLine_Impl(lTabPos, 7, bHorz);
1679 nIndex = GetDragAryPos();
1680 }
1681 else
1682 {
1683 nIndex = 0;
1684 }
1685
1686 RulerDragSize nDragSize = GetDragSize();
1687 tools::Long lDiff = 0;
1688
1689 // the drag position has to be corrected to be able to prevent borders from passing each other
1690 tools::Long lPos = MakePositionSticky(GetCorrectedDragPos(), GetLeftFrameMargin());
1691
1692 switch(nDragSize)
1693 {
1694 case RulerDragSize::Move:
1695 {
1696 if(GetDragType() == RulerType::Border)
1697 lDiff = lPos - nDragOffset - mpBorders[nIndex].nPos;
1698 else
1699 lDiff = GetDragType() == RulerType::Margin1 ? lPos - mxRulerImpl->lLastLMargin : lPos - mxRulerImpl->lLastRMargin;
1700
1701 if(nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR)
1702 {
1703 tools::Long nRight = GetMargin2() - glMinFrame; // Right limiters
1704 for(int i = mpBorders.size() - 2; i >= nIndex; --i)
1705 {
1706 tools::Long l = mpBorders[i].nPos;
1707 mpBorders[i].nPos += lDiff;
1708 mpBorders[i].nPos = std::min(mpBorders[i].nPos, nRight - mpBorders[i].nWidth);
1709 nRight = mpBorders[i].nPos - glMinFrame;
1710 // RR update the column
1711 if(i == GetActRightColumn())
1712 {
1713 UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveRight);
1714 bRightIndentsCorrected = true;
1715 }
1716 // LAR, EZE update the column
1717 else if(i == GetActLeftColumn())
1718 {
1719 UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveLeft);
1720 bLeftIndentsCorrected = true;
1721 }
1722 }
1723 }
1724 else if(nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
1725 {
1726 int nLimit;
1727 tools::Long lLeft;
1728 int nStartLimit = mpBorders.size() - 2;
1729 switch(GetDragType())
1730 {
1731 default: ;//prevent warning
1732 OSL_FAIL("svx::SvxRuler::DragBorders(), unknown drag type!" );
1733 [[fallthrough]];
1734 case RulerType::Border:
1735 if(mxRulerImpl->bIsTableRows)
1736 {
1737 mpBorders[nIndex].nPos += lDiff;
1738 if(bHorz)
1739 {
1740 lLeft = mpBorders[nIndex].nPos;
1741 mxRulerImpl->nTotalDist -= lDiff;
1742 nLimit = nIndex + 1;
1743 }
1744 else
1745 {
1746 lLeft = 0;
1747 nStartLimit = nIndex - 1;
1748 mxRulerImpl->nTotalDist += lDiff;
1749 nLimit = 0;
1750 }
1751 }
1752 else
1753 {
1754 nLimit = nIndex + 1;
1755 mpBorders[nIndex].nPos += lDiff;
1756 lLeft = mpBorders[nIndex].nPos;
1757 mxRulerImpl->nTotalDist -= lDiff;
1758 }
1759 break;
1760 case RulerType::Margin1:
1761 nLimit = 0;
1762 lLeft = mxRulerImpl->lLastLMargin + lDiff;
1763 mxRulerImpl->nTotalDist -= lDiff;
1764 break;
1765 case RulerType::Margin2:
1766 nLimit = 0;
1767 lLeft= 0;
1768 nStartLimit = mpBorders.size() - 2;
1769 mxRulerImpl->nTotalDist += lDiff;
1770 break;
1771 }
1772
1773 for(int i = nStartLimit; i >= nLimit; --i)
1774 {
1775
1776 tools::Long l = mpBorders[i].nPos;
1777 mpBorders[i].nPos =
1778 lLeft +
1779 (mxRulerImpl->nTotalDist * mxRulerImpl->pPercBuf[i]) / 1000 +
1780 mxRulerImpl->pBlockBuf[i];
1781
1782 // RR update the column
1783 if(!mxRulerImpl->bIsTableRows)
1784 {
1785 if(i == GetActRightColumn())
1786 {
1787 UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveRight);
1788 bRightIndentsCorrected = true;
1789 }
1790 // LAR, EZE update the column
1791 else if(i == GetActLeftColumn())
1792 {
1793 UpdateParaContents_Impl(mpBorders[i].nPos - l, UpdateType::MoveLeft);
1794 bLeftIndentsCorrected = true;
1795 }
1796 }
1797 }
1798 if(mxRulerImpl->bIsTableRows)
1799 {
1800 //in vertical tables the left borders have to be moved
1801 if(bHorz)
1802 {
1803 for(int i = 0; i < nIndex; ++i)
1804 mpBorders[i].nPos += lDiff;
1805 AdjustMargin1(lDiff);
1806 }
1807 else
1808 {
1809 //otherwise the right borders are moved
1810 for(int i = mxColumnItem->Count() - 1; i > nIndex; --i)
1811 mpBorders[i].nPos += lDiff;
1812 SetMargin2( GetMargin2() + lDiff, RulerMarginStyle::NONE );
1813 }
1814 }
1815 }
1816 else if(mxRulerImpl->bIsTableRows)
1817 {
1818 //moving rows: if a row is resized all following rows
1819 //have to be moved by the same amount.
1820 //This includes the left border when the table is not limited
1821 //to a lower frame border.
1822 int nLimit;
1823 if(GetDragType()==RulerType::Border)
1824 {
1825 nLimit = nIndex + 1;
1826 mpBorders[nIndex].nPos += lDiff;
1827 }
1828 else
1829 {
1830 nLimit=0;
1831 }
1832 //in vertical tables the left borders have to be moved
1833 if(bHorz)
1834 {
1835 for(int i = 0; i < nIndex; ++i)
1836 {
1837 mpBorders[i].nPos += lDiff;
1838 }
1839 AdjustMargin1(lDiff);
1840 }
1841 else
1842 {
1843 //otherwise the right borders are moved
1844 for(int i = mpBorders.size() - 2; i >= nLimit; --i)
1845 {
1846 mpBorders[i].nPos += lDiff;
1847 }
1848 SetMargin2( GetMargin2() + lDiff, RulerMarginStyle::NONE );
1849 }
1850 }
1851 else
1852 mpBorders[nIndex].nPos += lDiff;
1853 break;
1854 }
1855 case RulerDragSize::N1:
1856 {
1857 lDiff = lPos - mpBorders[nIndex].nPos;
1858 mpBorders[nIndex].nWidth += mpBorders[nIndex].nPos - lPos;
1859 mpBorders[nIndex].nPos = lPos;
1860 break;
1861 }
1862 case RulerDragSize::N2:
1863 {
1864 const tools::Long nOld = mpBorders[nIndex].nWidth;
1865 mpBorders[nIndex].nWidth = lPos - mpBorders[nIndex].nPos;
1866 lDiff = mpBorders[nIndex].nWidth - nOld;
1867 break;
1868 }
1869 }
1870 if(!bRightIndentsCorrected &&
1871 GetActRightColumn() == nIndex &&
1872 nDragSize != RulerDragSize::N2 &&
1873 !mpIndents.empty() &&
1874 !mxRulerImpl->bIsTableRows)
1875 {
1876 UpdateParaContents_Impl(lDiff, UpdateType::MoveRight);
1877 }
1878 else if(!bLeftIndentsCorrected &&
1879 GetActLeftColumn() == nIndex &&
1880 nDragSize != RulerDragSize::N1 &&
1881 !mpIndents.empty())
1882 {
1883 UpdateParaContents_Impl(lDiff, UpdateType::MoveLeft);
1884 }
1885 SetBorders(mxColumnItem->Count() - 1, mpBorders.data());
1886 }
1887
DragObjectBorder()1888 void SvxRuler::DragObjectBorder()
1889 {
1890 /* Dragging of object edges */
1891 if(RulerDragSize::Move == GetDragSize())
1892 {
1893 const tools::Long lPosition = MakePositionSticky(GetCorrectedDragPos(), GetLeftFrameMargin());
1894
1895 const sal_uInt16 nIdx = GetDragAryPos();
1896 mpObjectBorders[GetObjectBordersOff(nIdx)].nPos = lPosition;
1897 SetBorders(2, mpObjectBorders.data() + GetObjectBordersOff(0));
1898 DrawLine_Impl(lTabPos, 7, bHorz);
1899
1900 }
1901 }
1902
ApplyMargins()1903 void SvxRuler::ApplyMargins()
1904 {
1905 /* Applying margins; changed by dragging. */
1906 const SfxPoolItem* pItem = nullptr;
1907 sal_uInt16 nId = SID_ATTR_LONG_LRSPACE;
1908
1909 if(bHorz)
1910 {
1911 const tools::Long lOldNull = lLogicNullOffset;
1912 if(mxRulerImpl->lMaxLeftLogic != -1 && nMaxLeft == GetMargin1() + Ruler::GetNullOffset())
1913 {
1914 lLogicNullOffset = mxRulerImpl->lMaxLeftLogic;
1915 mxLRSpaceItem->SetLeft(lLogicNullOffset);
1916 }
1917 else
1918 {
1919 lLogicNullOffset = ConvertHPosLogic(GetFrameLeft()) - lAppNullOffset;
1920 mxLRSpaceItem->SetLeft(PixelHAdjust(lLogicNullOffset, mxLRSpaceItem->GetLeft()));
1921 }
1922
1923 if(bAppSetNullOffset)
1924 {
1925 lAppNullOffset += lLogicNullOffset - lOldNull;
1926 }
1927
1928 tools::Long nRight;
1929 if(mxRulerImpl->lMaxRightLogic != -1
1930 && nMaxRight == GetMargin2() + Ruler::GetNullOffset())
1931 {
1932 nRight = GetPageWidth() - mxRulerImpl->lMaxRightLogic;
1933 }
1934 else
1935 {
1936 nRight = std::max(tools::Long(0),
1937 mxPagePosItem->GetWidth() - mxLRSpaceItem->GetLeft() -
1938 (ConvertHPosLogic(GetMargin2()) - lAppNullOffset));
1939
1940 nRight = PixelHAdjust( nRight, mxLRSpaceItem->GetRight());
1941 }
1942 mxLRSpaceItem->SetRight(nRight);
1943
1944 pItem = mxLRSpaceItem.get();
1945
1946 #ifdef DEBUGLIN
1947 Debug_Impl(pEditWin, *mxLRSpaceItem);
1948 #endif // DEBUGLIN
1949
1950 }
1951 else
1952 {
1953 const tools::Long lOldNull = lLogicNullOffset;
1954 lLogicNullOffset =
1955 ConvertVPosLogic(GetFrameLeft()) -
1956 lAppNullOffset;
1957 mxULSpaceItem->SetUpper(
1958 PixelVAdjust(lLogicNullOffset, mxULSpaceItem->GetUpper()));
1959 if(bAppSetNullOffset)
1960 {
1961 lAppNullOffset += lLogicNullOffset - lOldNull;
1962 }
1963 mxULSpaceItem->SetLower(
1964 PixelVAdjust(
1965 std::max(tools::Long(0), mxPagePosItem->GetHeight() -
1966 mxULSpaceItem->GetUpper() -
1967 (ConvertVPosLogic(GetMargin2()) -
1968 lAppNullOffset)), mxULSpaceItem->GetLower()));
1969 pItem = mxULSpaceItem.get();
1970 nId = SID_ATTR_LONG_ULSPACE;
1971
1972 #ifdef DEBUGLIN
1973 Debug_Impl(pEditWin,*mxULSpaceItem);
1974 #endif // DEBUGLIN
1975
1976 }
1977 pBindings->GetDispatcher()->ExecuteList(nId, SfxCallMode::RECORD, { pItem });
1978 if (mxTabStopItem)
1979 UpdateTabs();
1980 }
1981
RoundToCurrentMapMode(tools::Long lValue) const1982 tools::Long SvxRuler::RoundToCurrentMapMode(tools::Long lValue) const
1983 {
1984 RulerUnitData aUnitData = GetCurrentRulerUnit();
1985 double aRoundingFactor = aUnitData.nTickUnit / aUnitData.nTick1;
1986
1987 tools::Long lNewValue = OutputDevice::LogicToLogic(Size(lValue, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
1988 lNewValue = (rtl::math::round(lNewValue / static_cast<double>(aUnitData.nTickUnit) * aRoundingFactor) / aRoundingFactor) * aUnitData.nTickUnit;
1989 return OutputDevice::LogicToLogic(Size(lNewValue, 0), GetCurrentMapMode(), pEditWin->GetMapMode()).Width();
1990 }
1991
ApplyIndents()1992 void SvxRuler::ApplyIndents()
1993 {
1994 /* Applying paragraph settings; changed by dragging. */
1995
1996 tools::Long nLeftFrameMargin = GetLeftFrameMargin();
1997
1998 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
1999
2000 tools::Long nNewTxtLeft;
2001 tools::Long nNewFirstLineOffset;
2002 tools::Long nNewRight;
2003
2004 tools::Long nFirstLine = ConvertPosLogic(mpIndents[INDENT_FIRST_LINE].nPos);
2005 tools::Long nLeftMargin = ConvertPosLogic(mpIndents[INDENT_LEFT_MARGIN].nPos);
2006 tools::Long nRightMargin = ConvertPosLogic(mpIndents[INDENT_RIGHT_MARGIN].nPos);
2007
2008 if(mxColumnItem && ((bRTL && !IsActLastColumn(true)) || (!bRTL && !IsActFirstColumn(true))))
2009 {
2010 if(bRTL)
2011 {
2012 tools::Long nRightColumn = GetActRightColumn(true);
2013 tools::Long nRightBorder = ConvertPosLogic(mpBorders[nRightColumn].nPos);
2014 nNewTxtLeft = nRightBorder - nLeftMargin - lAppNullOffset;
2015 }
2016 else
2017 {
2018 tools::Long nLeftColumn = GetActLeftColumn(true);
2019 tools::Long nLeftBorder = ConvertPosLogic(mpBorders[nLeftColumn].nPos + mpBorders[nLeftColumn].nWidth);
2020 nNewTxtLeft = nLeftMargin - nLeftBorder - lAppNullOffset;
2021 }
2022 }
2023 else
2024 {
2025 if(bRTL)
2026 {
2027 tools::Long nRightBorder = ConvertPosLogic(GetMargin2());
2028 nNewTxtLeft = nRightBorder - nLeftMargin - lAppNullOffset;
2029 }
2030 else
2031 {
2032 tools::Long nLeftBorder = ConvertPosLogic(GetMargin1());
2033 nNewTxtLeft = nLeftBorder + nLeftMargin - nLeftFrameMargin - lAppNullOffset;
2034 }
2035 }
2036
2037 if(bRTL)
2038 nNewFirstLineOffset = nLeftMargin - nFirstLine - lAppNullOffset;
2039 else
2040 nNewFirstLineOffset = nFirstLine - nLeftMargin - lAppNullOffset;
2041
2042 if(mxColumnItem && ((!bRTL && !IsActLastColumn(true)) || (bRTL && !IsActFirstColumn(true))))
2043 {
2044 if(bRTL)
2045 {
2046 tools::Long nLeftColumn = GetActLeftColumn(true);
2047 tools::Long nLeftBorder = ConvertPosLogic(mpBorders[nLeftColumn].nPos + mpBorders[nLeftColumn].nWidth);
2048 nNewRight = nRightMargin - nLeftBorder - lAppNullOffset;
2049 }
2050 else
2051 {
2052 tools::Long nRightColumn = GetActRightColumn(true);
2053 tools::Long nRightBorder = ConvertPosLogic(mpBorders[nRightColumn].nPos);
2054 nNewRight = nRightBorder - nRightMargin - lAppNullOffset;
2055 }
2056 }
2057 else
2058 {
2059 if(bRTL)
2060 {
2061 tools::Long nLeftBorder = ConvertPosLogic(GetMargin1());
2062 nNewRight = nLeftBorder + nRightMargin - nLeftFrameMargin - lAppNullOffset;
2063 }
2064 else
2065 {
2066 tools::Long nRightBorder = ConvertPosLogic(GetMargin2());
2067 nNewRight = nRightBorder - nRightMargin - lAppNullOffset;
2068 }
2069 }
2070
2071 if (mbSnapping)
2072 {
2073 nNewTxtLeft = RoundToCurrentMapMode(nNewTxtLeft);
2074 nNewFirstLineOffset = RoundToCurrentMapMode(nNewFirstLineOffset);
2075 nNewRight = RoundToCurrentMapMode(nNewRight);
2076 }
2077
2078 mxParaItem->SetTextFirstLineOffset(sal::static_int_cast<short>(nNewFirstLineOffset));
2079 mxParaItem->SetTextLeft(nNewTxtLeft);
2080 mxParaItem->SetRight(nNewRight);
2081
2082 sal_uInt16 nParagraphId = bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL;
2083 pBindings->GetDispatcher()->ExecuteList(nParagraphId, SfxCallMode::RECORD,
2084 { mxParaItem.get() });
2085 UpdateTabs();
2086 }
2087
ApplyTabs()2088 void SvxRuler::ApplyTabs()
2089 {
2090 /* Apply tab settings, changed by dragging. */
2091 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2092 const sal_uInt16 nCoreIdx = GetDragAryPos();
2093 if(IsDragDelete())
2094 {
2095 mxTabStopItem->Remove(nCoreIdx);
2096 }
2097 else if(SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType ||
2098 SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType)
2099 {
2100 SvxTabStopItem *pItem = new SvxTabStopItem(mxTabStopItem->Which());
2101 //remove default tab stops
2102 for ( sal_uInt16 i = 0; i < pItem->Count(); )
2103 {
2104 if ( SvxTabAdjust::Default == (*pItem)[i].GetAdjustment() )
2105 {
2106 pItem->Remove(i);
2107 continue;
2108 }
2109 ++i;
2110 }
2111
2112 sal_uInt16 j;
2113 for(j = 0; j < nCoreIdx; ++j)
2114 {
2115 pItem->Insert(mxTabStopItem->At(j));
2116 }
2117 for(; j < mxTabStopItem->Count(); ++j)
2118 {
2119 SvxTabStop aTabStop = mxTabStopItem->At(j);
2120 aTabStop.GetTabPos() = PixelHAdjust(
2121 ConvertHPosLogic(
2122 mpTabs[j + TAB_GAP].nPos - GetLeftIndent()) - lAppNullOffset,
2123 aTabStop.GetTabPos());
2124 pItem->Insert(aTabStop);
2125 }
2126 mxTabStopItem.reset(pItem);
2127 }
2128 else if( mxTabStopItem->Count() == 0 )
2129 return;
2130 else
2131 {
2132 SvxTabStop aTabStop = mxTabStopItem->At(nCoreIdx);
2133 if( mxRulerImpl->lMaxRightLogic != -1 &&
2134 mpTabs[nCoreIdx + TAB_GAP].nPos + Ruler::GetNullOffset() == nMaxRight )
2135 {
2136 // Set tab pos exactly at the right indent
2137 tools::Long nTmpLeftIndentLogic
2138 = lAppNullOffset + (bRTL ? GetRightFrameMargin() : GetLeftFrameMargin());
2139 if (mxRulerImpl->bIsTabsRelativeToIndent && mxParaItem)
2140 {
2141 nTmpLeftIndentLogic += bRTL ? mxParaItem->GetRight() : mxParaItem->GetLeft();
2142 }
2143 aTabStop.GetTabPos()
2144 = mxRulerImpl->lMaxRightLogic - lLogicNullOffset - nTmpLeftIndentLogic;
2145 }
2146 else
2147 {
2148 if(bRTL)
2149 {
2150 //#i24363# tab stops relative to indent
2151 const tools::Long nTmpLeftIndent = mxRulerImpl->bIsTabsRelativeToIndent ?
2152 GetLeftIndent() :
2153 ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset );
2154
2155 tools::Long nNewPosition = ConvertHPosLogic(nTmpLeftIndent - mpTabs[nCoreIdx + TAB_GAP].nPos);
2156 aTabStop.GetTabPos() = PixelHAdjust(nNewPosition - lAppNullOffset, aTabStop.GetTabPos());
2157 }
2158 else
2159 {
2160 //#i24363# tab stops relative to indent
2161 const tools::Long nTmpLeftIndent = mxRulerImpl->bIsTabsRelativeToIndent ?
2162 GetLeftIndent() :
2163 ConvertHPosPixel( GetLeftFrameMargin() + lAppNullOffset );
2164
2165 tools::Long nNewPosition = ConvertHPosLogic(mpTabs[nCoreIdx + TAB_GAP].nPos - nTmpLeftIndent);
2166 aTabStop.GetTabPos() = PixelHAdjust(nNewPosition - lAppNullOffset, aTabStop.GetTabPos());
2167 }
2168 }
2169 mxTabStopItem->Remove(nCoreIdx);
2170 mxTabStopItem->Insert(aTabStop);
2171 }
2172 sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
2173 pBindings->GetDispatcher()->ExecuteList(nTabStopId, SfxCallMode::RECORD,
2174 { mxTabStopItem.get() });
2175 UpdateTabs();
2176 }
2177
ApplyBorders()2178 void SvxRuler::ApplyBorders()
2179 {
2180 /* Applying (table) column settings; changed by dragging. */
2181 if(mxColumnItem->IsTable())
2182 {
2183 tools::Long lValue = GetFrameLeft();
2184 if(lValue != mxRulerImpl->nColLeftPix)
2185 {
2186 tools::Long nLeft = PixelHAdjust(
2187 ConvertHPosLogic(lValue) -
2188 lAppNullOffset,
2189 mxColumnItem->GetLeft());
2190 mxColumnItem->SetLeft(nLeft);
2191 }
2192
2193 lValue = GetMargin2();
2194
2195 if(lValue != mxRulerImpl->nColRightPix)
2196 {
2197 tools::Long nWidthOrHeight = bHorz ? mxPagePosItem->GetWidth() : mxPagePosItem->GetHeight();
2198 tools::Long nRight = PixelHAdjust(
2199 nWidthOrHeight -
2200 mxColumnItem->GetLeft() -
2201 ConvertHPosLogic(lValue) -
2202 lAppNullOffset,
2203 mxColumnItem->GetRight() );
2204 mxColumnItem->SetRight(nRight);
2205 }
2206 }
2207
2208 for(sal_uInt16 i = 0; i < mxColumnItem->Count() - 1; ++i)
2209 {
2210 tools::Long& nEnd = mxColumnItem->At(i).nEnd;
2211 nEnd = PixelHAdjust(
2212 ConvertPosLogic(mpBorders[i].nPos),
2213 mxColumnItem->At(i).nEnd);
2214 tools::Long& nStart = mxColumnItem->At(i + 1).nStart;
2215 nStart = PixelHAdjust(
2216 ConvertSizeLogic(mpBorders[i].nPos +
2217 mpBorders[i].nWidth) -
2218 lAppNullOffset,
2219 mxColumnItem->At(i + 1).nStart);
2220 // It may be that, due to the PixelHAdjust readjustment to old values,
2221 // the width becomes < 0. This we readjust.
2222 if( nEnd > nStart )
2223 nStart = nEnd;
2224 }
2225
2226 #ifdef DEBUGLIN
2227 Debug_Impl(pEditWin,*mxColumnItem);
2228 #endif // DEBUGLIN
2229
2230 SfxBoolItem aFlag(SID_RULER_ACT_LINE_ONLY,
2231 bool(nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY));
2232
2233 sal_uInt16 nColId = mxRulerImpl->bIsTableRows ? (bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL) :
2234 (bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
2235
2236 pBindings->GetDispatcher()->ExecuteList(nColId, SfxCallMode::RECORD,
2237 { mxColumnItem.get(), &aFlag });
2238 }
2239
ApplyObject()2240 void SvxRuler::ApplyObject()
2241 {
2242 /* Applying object settings, changed by dragging. */
2243
2244 // to the page margin
2245 tools::Long nMargin = mxLRSpaceItem ? mxLRSpaceItem->GetLeft() : 0;
2246 tools::Long nStartX = PixelAdjust(
2247 ConvertPosLogic(mpObjectBorders[0].nPos) +
2248 nMargin -
2249 lAppNullOffset,
2250 mxObjectItem->GetStartX());
2251 mxObjectItem->SetStartX(nStartX);
2252
2253 tools::Long nEndX = PixelAdjust(
2254 ConvertPosLogic(mpObjectBorders[1].nPos) +
2255 nMargin -
2256 lAppNullOffset,
2257 mxObjectItem->GetEndX());
2258 mxObjectItem->SetEndX(nEndX);
2259
2260 nMargin = mxULSpaceItem ? mxULSpaceItem->GetUpper() : 0;
2261 tools::Long nStartY = PixelAdjust(
2262 ConvertPosLogic(mpObjectBorders[2].nPos) +
2263 nMargin -
2264 lAppNullOffset,
2265 mxObjectItem->GetStartY());
2266 mxObjectItem->SetStartY(nStartY);
2267
2268 tools::Long nEndY = PixelAdjust(
2269 ConvertPosLogic(mpObjectBorders[3].nPos) +
2270 nMargin -
2271 lAppNullOffset,
2272 mxObjectItem->GetEndY());
2273 mxObjectItem->SetEndY(nEndY);
2274
2275 pBindings->GetDispatcher()->ExecuteList(SID_RULER_OBJECT,
2276 SfxCallMode::RECORD, { mxObjectItem.get() });
2277 }
2278
PrepareProportional_Impl(RulerType eType)2279 void SvxRuler::PrepareProportional_Impl(RulerType eType)
2280 {
2281 /*
2282 Preparation proportional dragging, and it is calculated based on the
2283 proportional share of the total width in parts per thousand.
2284 */
2285 mxRulerImpl->nTotalDist = GetMargin2();
2286 switch(eType)
2287 {
2288 case RulerType::Margin2:
2289 case RulerType::Margin1:
2290 case RulerType::Border:
2291 {
2292 DBG_ASSERT(mxColumnItem, "no ColumnItem");
2293
2294 mxRulerImpl->SetPercSize(mxColumnItem->Count());
2295
2296 tools::Long lPos;
2297 tools::Long lWidth=0;
2298 sal_uInt16 nStart;
2299 sal_uInt16 nIdx=GetDragAryPos();
2300 tools::Long lActWidth=0;
2301 tools::Long lActBorderSum;
2302 tools::Long lOrigLPos;
2303
2304 if(eType != RulerType::Border)
2305 {
2306 lOrigLPos = GetMargin1();
2307 nStart = 0;
2308 lActBorderSum = 0;
2309 }
2310 else
2311 {
2312 if(mxRulerImpl->bIsTableRows &&!bHorz)
2313 {
2314 lOrigLPos = GetMargin1();
2315 nStart = 0;
2316 }
2317 else
2318 {
2319 lOrigLPos = mpBorders[nIdx].nPos + mpBorders[nIdx].nWidth;
2320 nStart = 1;
2321 }
2322 lActBorderSum = mpBorders[nIdx].nWidth;
2323 }
2324
2325 //in horizontal mode the percentage value has to be
2326 //calculated on a "current change" position base
2327 //because the height of the table changes while dragging
2328 if(mxRulerImpl->bIsTableRows && RulerType::Border == eType)
2329 {
2330 sal_uInt16 nStartBorder;
2331 sal_uInt16 nEndBorder;
2332 if(bHorz)
2333 {
2334 nStartBorder = nIdx + 1;
2335 nEndBorder = mxColumnItem->Count() - 1;
2336 }
2337 else
2338 {
2339 nStartBorder = 0;
2340 nEndBorder = nIdx;
2341 }
2342
2343 lWidth = mpBorders[nIdx].nPos;
2344 if(bHorz)
2345 lWidth = GetMargin2() - lWidth;
2346 mxRulerImpl->nTotalDist = lWidth;
2347 lPos = mpBorders[nIdx].nPos;
2348
2349 for(sal_uInt16 i = nStartBorder; i < nEndBorder; ++i)
2350 {
2351 if(bHorz)
2352 {
2353 lActWidth += mpBorders[i].nPos - lPos;
2354 lPos = mpBorders[i].nPos + mpBorders[i].nWidth;
2355 }
2356 else
2357 lActWidth = mpBorders[i].nPos;
2358 mxRulerImpl->pPercBuf[i] = static_cast<sal_uInt16>((lActWidth * 1000)
2359 / mxRulerImpl->nTotalDist);
2360 mxRulerImpl->pBlockBuf[i] = static_cast<sal_uInt16>(lActBorderSum);
2361 lActBorderSum += mpBorders[i].nWidth;
2362 }
2363 }
2364 else
2365 {
2366 lPos = lOrigLPos;
2367 for(sal_uInt16 ii = nStart; ii < mxColumnItem->Count() - 1; ++ii)
2368 {
2369 lWidth += mpBorders[ii].nPos - lPos;
2370 lPos = mpBorders[ii].nPos + mpBorders[ii].nWidth;
2371 }
2372
2373 lWidth += GetMargin2() - lPos;
2374 mxRulerImpl->nTotalDist = lWidth;
2375 lPos = lOrigLPos;
2376
2377 for(sal_uInt16 i = nStart; i < mxColumnItem->Count() - 1; ++i)
2378 {
2379 lActWidth += mpBorders[i].nPos - lPos;
2380 lPos = mpBorders[i].nPos + mpBorders[i].nWidth;
2381 mxRulerImpl->pPercBuf[i] = static_cast<sal_uInt16>((lActWidth * 1000)
2382 / mxRulerImpl->nTotalDist);
2383 mxRulerImpl->pBlockBuf[i] = static_cast<sal_uInt16>(lActBorderSum);
2384 lActBorderSum += mpBorders[i].nWidth;
2385 }
2386 }
2387 }
2388 break;
2389 case RulerType::Tab:
2390 {
2391 const sal_uInt16 nIdx = GetDragAryPos()+TAB_GAP;
2392 mxRulerImpl->nTotalDist -= mpTabs[nIdx].nPos;
2393 mxRulerImpl->SetPercSize(nTabCount);
2394 for(sal_uInt16 n=0;n<=nIdx;mxRulerImpl->pPercBuf[n++]=0) ;
2395 for(sal_uInt16 i = nIdx+1; i < nTabCount; ++i)
2396 {
2397 const tools::Long nDelta = mpTabs[i].nPos - mpTabs[nIdx].nPos;
2398 mxRulerImpl->pPercBuf[i] = static_cast<sal_uInt16>((nDelta * 1000) / mxRulerImpl->nTotalDist);
2399 }
2400 break;
2401 }
2402 default: break;
2403 }
2404 }
2405
EvalModifier()2406 void SvxRuler::EvalModifier()
2407 {
2408 /*
2409 Eval Drag Modifier
2410 Shift: move linear
2411 Control: move proportional
2412 Shift + Control: Table: only current line
2413 Alt: disable snapping
2414 Alt + Shift: coarse snapping
2415 */
2416
2417 sal_uInt16 nModifier = GetDragModifier();
2418 if(mxRulerImpl->bIsTableRows)
2419 {
2420 //rows can only be moved in one way, additionally current column is possible
2421 if(nModifier == KEY_SHIFT)
2422 nModifier = 0;
2423 }
2424
2425 switch(nModifier)
2426 {
2427 case KEY_SHIFT:
2428 nDragType = SvxRulerDragFlags::OBJECT_SIZE_LINEAR;
2429 break;
2430 case KEY_MOD2 | KEY_SHIFT:
2431 mbCoarseSnapping = true;
2432 break;
2433 case KEY_MOD2:
2434 mbSnapping = false;
2435 break;
2436 case KEY_MOD1:
2437 {
2438 const RulerType eType = GetDragType();
2439 nDragType = SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL;
2440 if( RulerType::Tab == eType ||
2441 ( ( RulerType::Border == eType ||
2442 RulerType::Margin1 == eType ||
2443 RulerType::Margin2 == eType ) &&
2444 mxColumnItem ) )
2445 {
2446 PrepareProportional_Impl(eType);
2447 }
2448 }
2449 break;
2450 case KEY_MOD1 | KEY_SHIFT:
2451 if( GetDragType() != RulerType::Margin1 &&
2452 GetDragType() != RulerType::Margin2 )
2453 {
2454 nDragType = SvxRulerDragFlags::OBJECT_ACTLINE_ONLY;
2455 }
2456 break;
2457 }
2458 }
2459
Click()2460 void SvxRuler::Click()
2461 {
2462 /* Override handler SV; sets Tab per dispatcher call */
2463 Ruler::Click();
2464 if( bActive )
2465 {
2466 pBindings->Update( SID_RULER_LR_MIN_MAX );
2467 pBindings->Update( SID_ATTR_LONG_ULSPACE );
2468 pBindings->Update( SID_ATTR_LONG_LRSPACE );
2469 pBindings->Update( SID_RULER_PAGE_POS );
2470 pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
2471 pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
2472 pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
2473 pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
2474 pBindings->Update( SID_RULER_OBJECT );
2475 pBindings->Update( SID_RULER_PROTECT );
2476 pBindings->Update( SID_ATTR_PARA_LRSPACE_VERTICAL );
2477 }
2478 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2479 if(!(mxTabStopItem &&
2480 (nFlags & SvxRulerSupportFlags::TABS) == SvxRulerSupportFlags::TABS))
2481 return;
2482
2483 bool bContentProtected = mxRulerImpl->aProtectItem->IsContentProtected();
2484 if( bContentProtected ) return;
2485 const tools::Long lPos = GetClickPos();
2486 if(!((bRTL && lPos < std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos > GetRightIndent()) ||
2487 (!bRTL && lPos > std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos < GetRightIndent())))
2488 return;
2489
2490 //convert position in left-to-right text
2491 tools::Long nTabPos;
2492 //#i24363# tab stops relative to indent
2493 if(bRTL)
2494 nTabPos = ( mxRulerImpl->bIsTabsRelativeToIndent ?
2495 GetLeftIndent() :
2496 ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset ) ) -
2497 lPos;
2498 else
2499 nTabPos = lPos -
2500 ( mxRulerImpl->bIsTabsRelativeToIndent ?
2501 GetLeftIndent() :
2502 ConvertHPosPixel( GetLeftFrameMargin() + lAppNullOffset ));
2503
2504 SvxTabStop aTabStop(ConvertHPosLogic(nTabPos),
2505 ToAttrTab_Impl(nDefTabType));
2506 mxTabStopItem->Insert(aTabStop);
2507 UpdateTabs();
2508 }
2509
CalcMinMax()2510 void SvxRuler::CalcMinMax()
2511 {
2512 /*
2513 Calculates the limits for dragging; which are in pixels relative to the
2514 page edge
2515 */
2516 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2517 const tools::Long lNullPix = ConvertPosPixel(lLogicNullOffset);
2518 mxRulerImpl->lMaxLeftLogic=mxRulerImpl->lMaxRightLogic=-1;
2519 switch(GetDragType())
2520 {
2521 case RulerType::Margin1:
2522 { // left edge of the surrounding Frame
2523 // DragPos - NOf between left - right
2524 mxRulerImpl->lMaxLeftLogic = GetLeftMin();
2525 nMaxLeft=ConvertSizePixel(mxRulerImpl->lMaxLeftLogic);
2526
2527 if (!mxColumnItem || mxColumnItem->Count() == 1)
2528 {
2529 if(bRTL)
2530 {
2531 nMaxRight = lNullPix - GetRightIndent() +
2532 std::max(GetFirstLineIndent(), GetLeftIndent()) -
2533 glMinFrame;
2534 }
2535 else
2536 {
2537 nMaxRight = lNullPix + GetRightIndent() -
2538 std::max(GetFirstLineIndent(), GetLeftIndent()) -
2539 glMinFrame;
2540 }
2541 }
2542 else if(mxRulerImpl->bIsTableRows)
2543 {
2544 //top border is not moveable when table rows are displayed
2545 // protection of content means the margin is not moveable
2546 if(bHorz && !mxRulerImpl->aProtectItem->IsContentProtected())
2547 {
2548 nMaxLeft = mpBorders[0].nMinPos + lNullPix;
2549 if(nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
2550 nMaxRight = GetRightIndent() + lNullPix -
2551 (mxColumnItem->Count() - 1 ) * glMinFrame;
2552 else
2553 nMaxRight = mpBorders[0].nPos - glMinFrame + lNullPix;
2554 }
2555 else
2556 nMaxLeft = nMaxRight = lNullPix;
2557 }
2558 else
2559 {
2560 if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
2561 {
2562 nMaxRight=lNullPix+CalcPropMaxRight();
2563 }
2564 else if (nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR)
2565 {
2566 nMaxRight = ConvertPosPixel(
2567 GetPageWidth() - (
2568 (mxColumnItem->IsTable() && mxLRSpaceItem)
2569 ? mxLRSpaceItem->GetRight() : 0))
2570 - GetMargin2() + GetMargin1();
2571 }
2572 else
2573 {
2574 nMaxRight = lNullPix - glMinFrame;
2575 if (mxColumnItem->IsFirstAct())
2576 {
2577 if(bRTL)
2578 {
2579 nMaxRight += std::min(
2580 mpBorders[0].nPos,
2581 std::max(GetFirstLineIndent(), GetLeftIndent()) - GetRightIndent());
2582 }
2583 else
2584 {
2585 nMaxRight += std::min(
2586 mpBorders[0].nPos, GetRightIndent() -
2587 std::max(GetFirstLineIndent(), GetLeftIndent()));
2588 }
2589 }
2590 else if ( mxColumnItem->Count() > 1 )
2591 {
2592 nMaxRight += mpBorders[0].nPos;
2593 }
2594 else
2595 {
2596 nMaxRight += GetRightIndent() - std::max(GetFirstLineIndent(), GetLeftIndent());
2597 }
2598 // Do not drag the left table edge over the edge of the page
2599 if(mxLRSpaceItem && mxColumnItem->IsTable())
2600 {
2601 tools::Long nTmp=ConvertSizePixel(mxLRSpaceItem->GetLeft());
2602 if(nTmp>nMaxLeft)
2603 nMaxLeft=nTmp;
2604 }
2605 }
2606 }
2607 break;
2608 }
2609 case RulerType::Margin2:
2610 { // right edge of the surrounding Frame
2611 mxRulerImpl->lMaxRightLogic
2612 = mxMinMaxItem ? GetPageWidth() - GetRightMax() : GetPageWidth();
2613 nMaxRight = ConvertSizePixel(mxRulerImpl->lMaxRightLogic);
2614
2615 if (!mxColumnItem)
2616 {
2617 if(bRTL)
2618 {
2619 nMaxLeft = GetMargin2() + GetRightIndent() -
2620 std::max(GetFirstLineIndent(),GetLeftIndent()) - GetMargin1()+
2621 glMinFrame + lNullPix;
2622 }
2623 else
2624 {
2625 nMaxLeft = GetMargin2() - GetRightIndent() +
2626 std::max(GetFirstLineIndent(),GetLeftIndent()) - GetMargin1()+
2627 glMinFrame + lNullPix;
2628 }
2629 }
2630 else if(mxRulerImpl->bIsTableRows)
2631 {
2632 // get the bottom move range from the last border position - only available for rows!
2633 // protection of content means the margin is not moveable
2634 if(bHorz || mxRulerImpl->aProtectItem->IsContentProtected())
2635 {
2636 nMaxLeft = nMaxRight = mpBorders[mxColumnItem->Count() - 1].nMaxPos + lNullPix;
2637 }
2638 else
2639 {
2640 if(nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)
2641 {
2642 nMaxLeft = (mxColumnItem->Count()) * glMinFrame + lNullPix;
2643 }
2644 else
2645 {
2646 if(mxColumnItem->Count() > 1)
2647 nMaxLeft = mpBorders[mxColumnItem->Count() - 2].nPos + glMinFrame + lNullPix;
2648 else
2649 nMaxLeft = glMinFrame + lNullPix;
2650 }
2651 if(mxColumnItem->Count() > 1)
2652 nMaxRight = mpBorders[mxColumnItem->Count() - 2].nMaxPos + lNullPix;
2653 else
2654 nMaxRight -= GetRightIndent() - lNullPix;
2655 }
2656 }
2657 else
2658 {
2659 nMaxLeft = glMinFrame + lNullPix;
2660 if(IsActLastColumn() || mxColumnItem->Count() < 2 ) //If last active column
2661 {
2662 if(bRTL)
2663 {
2664 nMaxLeft = glMinFrame + lNullPix + GetMargin2() +
2665 GetRightIndent() - std::max(GetFirstLineIndent(),
2666 GetLeftIndent());
2667 }
2668 else
2669 {
2670 nMaxLeft = glMinFrame + lNullPix + GetMargin2() -
2671 GetRightIndent() + std::max(GetFirstLineIndent(),
2672 GetLeftIndent());
2673 }
2674 }
2675 if( mxColumnItem->Count() >= 2 )
2676 {
2677 tools::Long nNewMaxLeft =
2678 glMinFrame + lNullPix +
2679 mpBorders[mxColumnItem->Count() - 2].nPos +
2680 mpBorders[mxColumnItem->Count() - 2].nWidth;
2681 nMaxLeft = std::max(nMaxLeft, nNewMaxLeft);
2682 }
2683
2684 }
2685 break;
2686 }
2687 case RulerType::Border:
2688 { // Table, column (Modifier)
2689 const sal_uInt16 nIdx = GetDragAryPos();
2690 switch(GetDragSize())
2691 {
2692 case RulerDragSize::N1 :
2693 {
2694 nMaxRight = mpBorders[nIdx].nPos +
2695 mpBorders[nIdx].nWidth + lNullPix;
2696
2697 if(0 == nIdx)
2698 nMaxLeft = lNullPix;
2699 else
2700 nMaxLeft = mpBorders[nIdx - 1].nPos + mpBorders[nIdx - 1].nWidth + lNullPix;
2701 if(nIdx == mxColumnItem->GetActColumn())
2702 {
2703 if(bRTL)
2704 {
2705 nMaxLeft += mpBorders[nIdx].nPos +
2706 GetRightIndent() - std::max(GetFirstLineIndent(),
2707 GetLeftIndent());
2708 }
2709 else
2710 {
2711 nMaxLeft += mpBorders[nIdx].nPos -
2712 GetRightIndent() + std::max(GetFirstLineIndent(),
2713 GetLeftIndent());
2714 }
2715 if(0 != nIdx)
2716 nMaxLeft -= mpBorders[nIdx-1].nPos +
2717 mpBorders[nIdx-1].nWidth;
2718 }
2719 nMaxLeft += glMinFrame;
2720 nMaxLeft += nDragOffset;
2721 break;
2722 }
2723 case RulerDragSize::Move:
2724 {
2725 if (mxColumnItem)
2726 {
2727 //nIdx contains the position of the currently moved item
2728 //next visible separator on the left
2729 sal_uInt16 nLeftCol=GetActLeftColumn(false, nIdx);
2730 //next visible separator on the right
2731 sal_uInt16 nRightCol=GetActRightColumn(false, nIdx);
2732 //next separator on the left - regardless if visible or not
2733 sal_uInt16 nActLeftCol=GetActLeftColumn();
2734 //next separator on the right - regardless if visible or not
2735 sal_uInt16 nActRightCol=GetActRightColumn();
2736 if(mxColumnItem->IsTable())
2737 {
2738 if(nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY)
2739 {
2740 //the current row/column should be modified only
2741 //then the next/previous visible border position
2742 //marks the min/max positions
2743 nMaxLeft = nLeftCol == USHRT_MAX ?
2744 0 :
2745 mpBorders[nLeftCol].nPos;
2746 //rows can always be increased without a limit
2747 if(mxRulerImpl->bIsTableRows)
2748 nMaxRight = mpBorders[nIdx].nMaxPos;
2749 else
2750 nMaxRight = nRightCol == USHRT_MAX ?
2751 GetMargin2():
2752 mpBorders[nRightCol].nPos;
2753 nMaxLeft += lNullPix;
2754 nMaxRight += lNullPix;
2755 }
2756 else
2757 {
2758 if(SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType && !bHorz && mxRulerImpl->bIsTableRows)
2759 nMaxLeft = (nIdx + 1) * glMinFrame + lNullPix;
2760 else
2761 nMaxLeft = mpBorders[nIdx].nMinPos + lNullPix;
2762 if((SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType) ||
2763 (SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType) )
2764 {
2765 if(mxRulerImpl->bIsTableRows)
2766 {
2767 if(bHorz)
2768 nMaxRight = GetRightIndent() + lNullPix -
2769 (mxColumnItem->Count() - nIdx - 1) * glMinFrame;
2770 else
2771 nMaxRight = mpBorders[nIdx].nMaxPos + lNullPix;
2772 }
2773 else
2774 nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
2775 }
2776 else
2777 nMaxRight = mpBorders[nIdx].nMaxPos + lNullPix;
2778 }
2779 nMaxLeft += glMinFrame;
2780 nMaxRight -= glMinFrame;
2781
2782 }
2783 else
2784 {
2785 if(nLeftCol==USHRT_MAX)
2786 nMaxLeft=lNullPix;
2787 else
2788 nMaxLeft = mpBorders[nLeftCol].nPos +
2789 mpBorders[nLeftCol].nWidth + lNullPix;
2790
2791 if(nActRightCol == nIdx)
2792 {
2793 if(bRTL)
2794 {
2795 nMaxLeft += mpBorders[nIdx].nPos +
2796 GetRightIndent() - std::max(GetFirstLineIndent(),
2797 GetLeftIndent());
2798 if(nActLeftCol!=USHRT_MAX)
2799 nMaxLeft -= mpBorders[nActLeftCol].nPos +
2800 mpBorders[nActLeftCol].nWidth;
2801 }
2802 else
2803 {
2804 nMaxLeft += mpBorders[nIdx].nPos -
2805 GetRightIndent() + std::max(GetFirstLineIndent(),
2806 GetLeftIndent());
2807 if(nActLeftCol!=USHRT_MAX)
2808 nMaxLeft -= mpBorders[nActLeftCol].nPos +
2809 mpBorders[nActLeftCol].nWidth;
2810 }
2811 }
2812 nMaxLeft += glMinFrame;
2813 nMaxLeft += nDragOffset;
2814
2815 // nMaxRight
2816 // linear / proportional move
2817 if((SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL & nDragType) ||
2818 (SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType) )
2819 {
2820 nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
2821 }
2822 else if(SvxRulerDragFlags::OBJECT_SIZE_LINEAR & nDragType)
2823 {
2824 nMaxRight = lNullPix + GetMargin2() - GetMargin1() +
2825 (mpBorders.size() - nIdx - 1) * glMinFrame;
2826 }
2827 else
2828 {
2829 if(nRightCol==USHRT_MAX)
2830 { // last column
2831 nMaxRight = GetMargin2() + lNullPix;
2832 if(IsActLastColumn())
2833 {
2834 if(bRTL)
2835 {
2836 nMaxRight -=
2837 GetMargin2() + GetRightIndent() -
2838 std::max(GetFirstLineIndent(),
2839 GetLeftIndent());
2840 }
2841 else
2842 {
2843 nMaxRight -=
2844 GetMargin2() - GetRightIndent() +
2845 std::max(GetFirstLineIndent(),
2846 GetLeftIndent());
2847 }
2848 nMaxRight += mpBorders[nIdx].nPos +
2849 mpBorders[nIdx].nWidth;
2850 }
2851 }
2852 else
2853 {
2854 nMaxRight = lNullPix + mpBorders[nRightCol].nPos;
2855 sal_uInt16 nNotHiddenRightCol =
2856 GetActRightColumn(true, nIdx);
2857
2858 if( nActLeftCol == nIdx )
2859 {
2860 tools::Long nBorder = nNotHiddenRightCol ==
2861 USHRT_MAX ?
2862 GetMargin2() :
2863 mpBorders[nNotHiddenRightCol].nPos;
2864 if(bRTL)
2865 {
2866 nMaxRight -= nBorder + GetRightIndent() -
2867 std::max(GetFirstLineIndent(),
2868 GetLeftIndent());
2869 }
2870 else
2871 {
2872 nMaxRight -= nBorder - GetRightIndent() +
2873 std::max(GetFirstLineIndent(),
2874 GetLeftIndent());
2875 }
2876 nMaxRight += mpBorders[nIdx].nPos +
2877 mpBorders[nIdx].nWidth;
2878 }
2879 }
2880 nMaxRight -= glMinFrame;
2881 nMaxRight -= mpBorders[nIdx].nWidth;
2882 }
2883 }
2884 }
2885 // ObjectItem
2886 else
2887 {
2888 nMaxLeft = LONG_MIN;
2889 nMaxRight = LONG_MAX;
2890 }
2891 break;
2892 }
2893 case RulerDragSize::N2:
2894 {
2895 nMaxLeft = lNullPix + mpBorders[nIdx].nPos;
2896 if(nIdx == mxColumnItem->Count()-2) { // last column
2897 nMaxRight = GetMargin2() + lNullPix;
2898 if(mxColumnItem->IsLastAct()) {
2899 nMaxRight -=
2900 GetMargin2() - GetRightIndent() +
2901 std::max(GetFirstLineIndent(),
2902 GetLeftIndent());
2903 nMaxRight += mpBorders[nIdx].nPos +
2904 mpBorders[nIdx].nWidth;
2905 }
2906 }
2907 else {
2908 nMaxRight = lNullPix + mpBorders[nIdx+1].nPos;
2909 if(mxColumnItem->GetActColumn()-1 == nIdx) {
2910 nMaxRight -= mpBorders[nIdx+1].nPos - GetRightIndent() +
2911 std::max(GetFirstLineIndent(),
2912 GetLeftIndent());
2913 nMaxRight += mpBorders[nIdx].nPos +
2914 mpBorders[nIdx].nWidth;
2915 }
2916 }
2917 nMaxRight -= glMinFrame;
2918 nMaxRight -= mpBorders[nIdx].nWidth;
2919 break;
2920 }
2921 }
2922 nMaxRight += nDragOffset;
2923 break;
2924 }
2925 case RulerType::Indent:
2926 {
2927 const sal_uInt16 nIdx = GetDragAryPos();
2928 switch(nIdx) {
2929 case INDENT_FIRST_LINE - INDENT_GAP:
2930 case INDENT_LEFT_MARGIN - INDENT_GAP:
2931 {
2932 if(bRTL)
2933 {
2934 nMaxLeft = lNullPix + GetRightIndent();
2935
2936 if(mxColumnItem && !mxColumnItem->IsFirstAct())
2937 nMaxLeft += mpBorders[mxColumnItem->GetActColumn()-1].nPos +
2938 mpBorders[mxColumnItem->GetActColumn()-1].nWidth;
2939 nMaxRight = lNullPix + GetMargin2();
2940
2941 // Dragging along
2942 if((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
2943 !(nDragType & SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY))
2944 {
2945 if(GetLeftIndent() > GetFirstLineIndent())
2946 nMaxLeft += GetLeftIndent() - GetFirstLineIndent();
2947 else
2948 nMaxRight -= GetFirstLineIndent() - GetLeftIndent();
2949 }
2950 }
2951 else
2952 {
2953 nMaxLeft = lNullPix;
2954
2955 if(mxColumnItem && !mxColumnItem->IsFirstAct())
2956 nMaxLeft += mpBorders[mxColumnItem->GetActColumn()-1].nPos +
2957 mpBorders[mxColumnItem->GetActColumn()-1].nWidth;
2958 nMaxRight = lNullPix + GetRightIndent() - glMinFrame;
2959
2960 // Dragging along
2961 if((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
2962 !(nDragType & SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY))
2963 {
2964 if(GetLeftIndent() > GetFirstLineIndent())
2965 nMaxLeft += GetLeftIndent() - GetFirstLineIndent();
2966 else
2967 nMaxRight -= GetFirstLineIndent() - GetLeftIndent();
2968 }
2969 }
2970 }
2971 break;
2972 case INDENT_RIGHT_MARGIN - INDENT_GAP:
2973 {
2974 if(bRTL)
2975 {
2976 nMaxLeft = lNullPix;
2977 nMaxRight = lNullPix + std::min(GetFirstLineIndent(), GetLeftIndent()) - glMinFrame;
2978 if (mxColumnItem)
2979 {
2980 sal_uInt16 nRightCol=GetActRightColumn( true );
2981 if(!IsActLastColumn( true ))
2982 nMaxRight += mpBorders[nRightCol].nPos;
2983 else
2984 nMaxRight += GetMargin2();
2985 }
2986 else
2987 {
2988 nMaxLeft += GetMargin1();
2989 }
2990 nMaxLeft += glMinFrame;
2991 }
2992 else
2993 {
2994 nMaxLeft = lNullPix +
2995 std::max(GetFirstLineIndent(), GetLeftIndent());
2996 nMaxRight = lNullPix;
2997 if (mxColumnItem)
2998 {
2999 sal_uInt16 nRightCol=GetActRightColumn( true );
3000 if(!IsActLastColumn( true ))
3001 nMaxRight += mpBorders[nRightCol].nPos;
3002 else
3003 nMaxRight += GetMargin2();
3004 }
3005 else
3006 nMaxRight += GetMargin2();
3007 nMaxLeft += glMinFrame;
3008 }
3009 }
3010 break;
3011 }
3012 break;
3013 }
3014 case RulerType::Tab: // Tabs (Modifier)
3015 /* left = NOf + Max(LAR, EZ)
3016 right = NOf + RAR */
3017
3018 if (bRTL)
3019 nMaxLeft = lNullPix + GetRightIndent();
3020 else
3021 nMaxLeft = lNullPix + std::min(GetFirstLineIndent(), GetLeftIndent());
3022
3023 mxRulerImpl->lMaxRightLogic = GetLogicRightIndent() + lLogicNullOffset;
3024 nMaxRight = ConvertSizePixel(mxRulerImpl->lMaxRightLogic);
3025 break;
3026 default: ; //prevent warning
3027 }
3028 }
3029
StartDrag()3030 bool SvxRuler::StartDrag()
3031 {
3032 /*
3033 Beginning of a drag operation (SV-handler) evaluates modifier and
3034 calculated values
3035
3036 [Cross-reference]
3037
3038 <SvxRuler::EvalModifier()>
3039 <SvxRuler::CalcMinMax()>
3040 <SvxRuler::EndDrag()>
3041 */
3042 bool bContentProtected = mxRulerImpl->aProtectItem->IsContentProtected();
3043
3044 if(!bValid)
3045 return false;
3046
3047 mxRulerImpl->lLastLMargin = GetMargin1();
3048 mxRulerImpl->lLastRMargin = GetMargin2();
3049
3050 bool bOk = true;
3051
3052 lInitialDragPos = GetDragPos();
3053 switch(GetDragType())
3054 {
3055 case RulerType::Margin1: // left edge of the surrounding Frame
3056 case RulerType::Margin2: // right edge of the surrounding Frame
3057 if((bHorz && mxLRSpaceItem) || (!bHorz && mxULSpaceItem))
3058 {
3059 if (!mxColumnItem)
3060 EvalModifier();
3061 else
3062 nDragType = SvxRulerDragFlags::OBJECT;
3063 }
3064 else
3065 {
3066 bOk = false;
3067 }
3068 break;
3069 case RulerType::Border: // Table, column (Modifier)
3070 if (mxColumnItem)
3071 {
3072 nDragOffset = 0;
3073 if (!mxColumnItem->IsTable())
3074 nDragOffset = GetDragPos() - mpBorders[GetDragAryPos()].nPos;
3075 EvalModifier();
3076 }
3077 else
3078 nDragOffset = 0;
3079 break;
3080 case RulerType::Indent: // Paragraph indents (Modifier)
3081 {
3082 if( bContentProtected )
3083 return false;
3084 if(INDENT_LEFT_MARGIN == GetDragAryPos() + INDENT_GAP) { // Left paragraph indent
3085 mpIndents[0] = mpIndents[INDENT_FIRST_LINE];
3086 EvalModifier();
3087 }
3088 else
3089 {
3090 nDragType = SvxRulerDragFlags::OBJECT;
3091 }
3092 mpIndents[1] = mpIndents[GetDragAryPos() + INDENT_GAP];
3093 break;
3094 }
3095 case RulerType::Tab: // Tabs (Modifier)
3096 if( bContentProtected )
3097 return false;
3098 EvalModifier();
3099 mpTabs[0] = mpTabs[GetDragAryPos() + 1];
3100 mpTabs[0].nStyle |= RULER_STYLE_DONTKNOW;
3101 break;
3102 default:
3103 nDragType = SvxRulerDragFlags::NONE;
3104 }
3105
3106 if(bOk)
3107 CalcMinMax();
3108
3109 return bOk;
3110 }
3111
Drag()3112 void SvxRuler::Drag()
3113 {
3114 /* SV-Draghandler */
3115 if(IsDragCanceled())
3116 {
3117 Ruler::Drag();
3118 return;
3119 }
3120 switch(GetDragType()) {
3121 case RulerType::Margin1: // left edge of the surrounding Frame
3122 DragMargin1();
3123 mxRulerImpl->lLastLMargin = GetMargin1();
3124 break;
3125 case RulerType::Margin2: // right edge of the surrounding Frame
3126 DragMargin2();
3127 mxRulerImpl->lLastRMargin = GetMargin2();
3128 break;
3129 case RulerType::Indent: // Paragraph indents
3130 DragIndents();
3131 break;
3132 case RulerType::Border: // Table, columns
3133 if (mxColumnItem)
3134 DragBorders();
3135 else if (mxObjectItem)
3136 DragObjectBorder();
3137 break;
3138 case RulerType::Tab: // Tabs
3139 DragTabs();
3140 break;
3141 default:
3142 break; //prevent warning
3143 }
3144 Ruler::Drag();
3145 }
3146
EndDrag()3147 void SvxRuler::EndDrag()
3148 {
3149 /*
3150 SV-handler; is called when ending the dragging. Triggers the updating of data
3151 on the application, by calling the respective Apply...() methods to send the
3152 data to the application.
3153 */
3154 const bool bUndo = IsDragCanceled();
3155 const tools::Long lPos = GetDragPos();
3156 DrawLine_Impl(lTabPos, 6, bHorz);
3157 lTabPos = -1;
3158
3159 if(!bUndo)
3160 {
3161 switch(GetDragType())
3162 {
3163 case RulerType::Margin1: // upper left edge of the surrounding Frame
3164 case RulerType::Margin2: // lower right edge of the surrounding Frame
3165 {
3166 if (!mxColumnItem || !mxColumnItem->IsTable())
3167 ApplyMargins();
3168
3169 if(mxColumnItem &&
3170 (mxColumnItem->IsTable() ||
3171 (nDragType & SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL)))
3172 ApplyBorders();
3173
3174 }
3175 break;
3176 case RulerType::Border: // Table, columns
3177 if(lInitialDragPos != lPos ||
3178 (mxRulerImpl->bIsTableRows && bHorz)) //special case - the null offset is changed here
3179 {
3180 if (mxColumnItem)
3181 {
3182 ApplyBorders();
3183 if(bHorz)
3184 UpdateTabs();
3185 }
3186 else if (mxObjectItem)
3187 ApplyObject();
3188 }
3189 break;
3190 case RulerType::Indent: // Paragraph indents
3191 if(lInitialDragPos != lPos)
3192 ApplyIndents();
3193 SetIndents(INDENT_COUNT, mpIndents.data() + INDENT_GAP);
3194 break;
3195 case RulerType::Tab: // Tabs
3196 {
3197 ApplyTabs();
3198 mpTabs[GetDragAryPos()].nStyle &= ~RULER_STYLE_INVISIBLE;
3199 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
3200 }
3201 break;
3202 default:
3203 break; //prevent warning
3204 }
3205 }
3206 nDragType = SvxRulerDragFlags::NONE;
3207
3208 mbCoarseSnapping = false;
3209 mbSnapping = true;
3210
3211 Ruler::EndDrag();
3212 if(bUndo)
3213 {
3214 for(sal_uInt16 i = 0; i < mxRulerImpl->nControllerItems; i++)
3215 {
3216 pCtrlItems[i]->ClearCache();
3217 pCtrlItems[i]->GetBindings().Invalidate(pCtrlItems[i]->GetId());
3218 }
3219 }
3220 }
3221
ExtraDown()3222 void SvxRuler::ExtraDown()
3223 {
3224 /* Override SV method, sets the new type for the Default tab. */
3225
3226 // Switch Tab Type
3227 if(mxTabStopItem &&
3228 (nFlags & SvxRulerSupportFlags::TABS) == SvxRulerSupportFlags::TABS)
3229 {
3230 ++nDefTabType;
3231 if(RULER_TAB_DEFAULT == nDefTabType)
3232 nDefTabType = RULER_TAB_LEFT;
3233 SetExtraType(RulerExtra::Tab, nDefTabType);
3234 }
3235 Ruler::ExtraDown();
3236 }
3237
Notify(SfxBroadcaster &,const SfxHint & rHint)3238 void SvxRuler::Notify(SfxBroadcaster&, const SfxHint& rHint)
3239 {
3240 /*
3241 Report through the bindings that the status update is completed. The ruler
3242 updates its appearance and gets registered again in the bindings.
3243 */
3244
3245 // start update
3246 if (bActive && rHint.GetId() == SfxHintId::UpdateDone)
3247 {
3248 Update();
3249 EndListening(*pBindings);
3250 bValid = true;
3251 bListening = false;
3252 }
3253 }
3254
MenuSelect(std::string_view ident)3255 void SvxRuler::MenuSelect(std::string_view ident)
3256 {
3257 if (ident.empty())
3258 return;
3259 /* Handler of the context menus for switching the unit of measurement */
3260 SetUnit(vcl::EnglishStringToMetric(OUString::fromUtf8(ident)));
3261 }
3262
TabMenuSelect(const OString & rIdent)3263 void SvxRuler::TabMenuSelect(const OString& rIdent)
3264 {
3265 if (rIdent.isEmpty())
3266 return;
3267 sal_Int32 nId = rIdent.toInt32();
3268 /* Handler of the tab menu for setting the type */
3269 if (mxTabStopItem && mxTabStopItem->Count() > mxRulerImpl->nIdx)
3270 {
3271 SvxTabStop aTabStop = mxTabStopItem->At(mxRulerImpl->nIdx);
3272 aTabStop.GetAdjustment() = ToAttrTab_Impl(nId - 1);
3273 mxTabStopItem->Remove(mxRulerImpl->nIdx);
3274 mxTabStopItem->Insert(aTabStop);
3275 sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
3276 pBindings->GetDispatcher()->ExecuteList(nTabStopId,
3277 SfxCallMode::RECORD, { mxTabStopItem.get() });
3278 UpdateTabs();
3279 mxRulerImpl->nIdx = 0;
3280 }
3281 }
3282
3283 static const char* RID_SVXSTR_RULER_TAB[] =
3284 {
3285 RID_SVXSTR_RULER_TAB_LEFT,
3286 RID_SVXSTR_RULER_TAB_RIGHT,
3287 RID_SVXSTR_RULER_TAB_CENTER,
3288 RID_SVXSTR_RULER_TAB_DECIMAL
3289 };
3290
Command(const CommandEvent & rCommandEvent)3291 void SvxRuler::Command( const CommandEvent& rCommandEvent )
3292 {
3293 /* Mouse context menu for switching the unit of measurement */
3294 if ( CommandEventId::ContextMenu == rCommandEvent.GetCommand() )
3295 {
3296 CancelDrag();
3297
3298 tools::Rectangle aRect(rCommandEvent.GetMousePosPixel(), Size(1, 1));
3299 weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
3300 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "svx/ui/rulermenu.ui"));
3301 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
3302
3303 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
3304 if ( !mpTabs.empty() &&
3305 RulerType::Tab ==
3306 GetRulerType( rCommandEvent.GetMousePosPixel(), &mxRulerImpl->nIdx ) &&
3307 mpTabs[mxRulerImpl->nIdx + TAB_GAP].nStyle < RULER_TAB_DEFAULT )
3308 {
3309 xMenu->clear();
3310
3311 const Size aSz(ruler_tab_svx.width + 2, ruler_tab_svx.height + 2);
3312 const Point aPt(aSz.Width() / 2, aSz.Height() / 2);
3313
3314 for ( sal_uInt16 i = RULER_TAB_LEFT; i < RULER_TAB_DEFAULT; ++i )
3315 {
3316 ScopedVclPtr<VirtualDevice> xDev(pPopupParent->create_virtual_device());
3317 xDev->SetOutputSize(aSz);
3318
3319 sal_uInt16 nStyle = bRTL ? i|RULER_TAB_RTL : i;
3320 nStyle |= static_cast<sal_uInt16>(bHorz ? WB_HORZ : WB_VERT);
3321
3322 Color aFillColor(xDev->GetSettings().GetStyleSettings().GetShadowColor());
3323 DrawTab(*xDev, aFillColor, aPt, nStyle);
3324
3325 OString sId(OString::number(i + 1));
3326 xMenu->insert(-1, OUString::fromUtf8(sId), SvxResId(RID_SVXSTR_RULER_TAB[i]),
3327 nullptr, xDev.get(), nullptr, TRISTATE_TRUE);
3328 xMenu->set_active(sId, i == mpTabs[mxRulerImpl->nIdx + TAB_GAP].nStyle);
3329 }
3330 TabMenuSelect(xMenu->popup_at_rect(pPopupParent, aRect));
3331 }
3332 else
3333 {
3334 FieldUnit eUnit = GetUnit();
3335 const int nCount = xMenu->n_children();
3336
3337 bool bReduceMetric = bool(nFlags & SvxRulerSupportFlags::REDUCED_METRIC);
3338 for ( sal_uInt16 i = nCount; i; --i )
3339 {
3340 OString sIdent = xMenu->get_id(i - 1);
3341 FieldUnit eMenuUnit = vcl::EnglishStringToMetric(OUString::fromUtf8(sIdent));
3342 xMenu->set_active(sIdent, eMenuUnit == eUnit);
3343 if( bReduceMetric )
3344 {
3345 if (eMenuUnit == FieldUnit::M ||
3346 eMenuUnit == FieldUnit::KM ||
3347 eMenuUnit == FieldUnit::FOOT ||
3348 eMenuUnit == FieldUnit::MILE)
3349 {
3350 xMenu->remove(sIdent);
3351 }
3352 else if (( eMenuUnit == FieldUnit::CHAR ) && !bHorz )
3353 {
3354 xMenu->remove(sIdent);
3355 }
3356 else if (( eMenuUnit == FieldUnit::LINE ) && bHorz )
3357 {
3358 xMenu->remove(sIdent);
3359 }
3360 }
3361 }
3362 MenuSelect(xMenu->popup_at_rect(pPopupParent, aRect));
3363 }
3364 }
3365 else
3366 {
3367 Ruler::Command( rCommandEvent );
3368 }
3369 }
3370
GetActRightColumn(bool bForceDontConsiderHidden,sal_uInt16 nAct) const3371 sal_uInt16 SvxRuler::GetActRightColumn(
3372 bool bForceDontConsiderHidden,
3373 sal_uInt16 nAct ) const
3374 {
3375 if( nAct == USHRT_MAX )
3376 nAct = mxColumnItem->GetActColumn();
3377 else
3378 nAct++; //To be able to pass on the ActDrag
3379
3380 bool bConsiderHidden = !bForceDontConsiderHidden &&
3381 !(nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY);
3382
3383 while( nAct < mxColumnItem->Count() - 1 )
3384 {
3385 if (mxColumnItem->At(nAct).bVisible || bConsiderHidden)
3386 return nAct;
3387 else
3388 nAct++;
3389 }
3390 return USHRT_MAX;
3391 }
3392
GetActLeftColumn(bool bForceDontConsiderHidden,sal_uInt16 nAct) const3393 sal_uInt16 SvxRuler::GetActLeftColumn(
3394 bool bForceDontConsiderHidden,
3395 sal_uInt16 nAct ) const
3396 {
3397 if(nAct == USHRT_MAX)
3398 nAct = mxColumnItem->GetActColumn();
3399
3400 sal_uInt16 nLeftOffset = 1;
3401
3402 bool bConsiderHidden = !bForceDontConsiderHidden &&
3403 !(nDragType & SvxRulerDragFlags::OBJECT_ACTLINE_ONLY);
3404
3405 while(nAct >= nLeftOffset)
3406 {
3407 if (mxColumnItem->At(nAct - nLeftOffset).bVisible || bConsiderHidden)
3408 return nAct - nLeftOffset;
3409 else
3410 nLeftOffset++;
3411 }
3412 return USHRT_MAX;
3413 }
3414
IsActLastColumn(bool bForceDontConsiderHidden,sal_uInt16 nAct) const3415 bool SvxRuler::IsActLastColumn(
3416 bool bForceDontConsiderHidden,
3417 sal_uInt16 nAct) const
3418 {
3419 return GetActRightColumn(bForceDontConsiderHidden, nAct) == USHRT_MAX;
3420 }
3421
IsActFirstColumn(bool bForceDontConsiderHidden,sal_uInt16 nAct) const3422 bool SvxRuler::IsActFirstColumn(
3423 bool bForceDontConsiderHidden,
3424 sal_uInt16 nAct) const
3425 {
3426 return GetActLeftColumn(bForceDontConsiderHidden, nAct) == USHRT_MAX;
3427 }
3428
CalcPropMaxRight(sal_uInt16 nCol) const3429 tools::Long SvxRuler::CalcPropMaxRight(sal_uInt16 nCol) const
3430 {
3431
3432 if(!(nDragType & SvxRulerDragFlags::OBJECT_SIZE_LINEAR))
3433 {
3434 // Remove the minimum width for all affected columns
3435 // starting from the right edge
3436 tools::Long _nMaxRight = GetMargin2() - GetMargin1();
3437
3438 tools::Long lFences = 0;
3439 tools::Long lMinSpace = USHRT_MAX;
3440 tools::Long lOldPos;
3441 tools::Long lColumns = 0;
3442
3443 sal_uInt16 nStart;
3444 if(!mxColumnItem->IsTable())
3445 {
3446 if(nCol == USHRT_MAX)
3447 {
3448 lOldPos = GetMargin1();
3449 nStart = 0;
3450 }
3451 else
3452 {
3453 lOldPos = mpBorders[nCol].nPos + mpBorders[nCol].nWidth;
3454 nStart = nCol + 1;
3455 lFences = mpBorders[nCol].nWidth;
3456 }
3457
3458 for(size_t i = nStart; i < mpBorders.size() - 1; ++i)
3459 {
3460 tools::Long lWidth = mpBorders[i].nPos - lOldPos;
3461 lColumns += lWidth;
3462 if(lWidth < lMinSpace)
3463 lMinSpace = lWidth;
3464 lOldPos = mpBorders[i].nPos + mpBorders[i].nWidth;
3465 lFences += mpBorders[i].nWidth;
3466 }
3467 tools::Long lWidth = GetMargin2() - lOldPos;
3468 lColumns += lWidth;
3469 if(lWidth < lMinSpace)
3470 lMinSpace = lWidth;
3471 }
3472 else
3473 {
3474 sal_uInt16 nActCol;
3475 if(nCol == USHRT_MAX) //CalcMinMax for LeftMargin
3476 {
3477 lOldPos = GetMargin1();
3478 }
3479 else
3480 {
3481 lOldPos = mpBorders[nCol].nPos;
3482 }
3483 lColumns = GetMargin2()-lOldPos;
3484 nActCol = nCol;
3485 lFences = 0;
3486 while(nActCol < mpBorders.size() || nActCol == USHRT_MAX)
3487 {
3488 sal_uInt16 nRight;
3489 if(nActCol == USHRT_MAX)
3490 {
3491 nRight = 0;
3492 while (!(*mxColumnItem)[nRight].bVisible)
3493 {
3494 nRight++;
3495 }
3496 }
3497 else
3498 {
3499 nRight = GetActRightColumn(false, nActCol);
3500 }
3501
3502 tools::Long lWidth;
3503 if(nRight != USHRT_MAX)
3504 {
3505 lWidth = mpBorders[nRight].nPos - lOldPos;
3506 lOldPos = mpBorders[nRight].nPos;
3507 }
3508 else
3509 {
3510 lWidth=GetMargin2() - lOldPos;
3511 }
3512 nActCol = nRight;
3513 if(lWidth < lMinSpace)
3514 lMinSpace = lWidth;
3515 if(nActCol == USHRT_MAX)
3516 break;
3517 }
3518 }
3519
3520 _nMaxRight -= static_cast<tools::Long>(lFences + glMinFrame / static_cast<float>(lMinSpace) * lColumns);
3521 return _nMaxRight;
3522 }
3523 else
3524 {
3525 if(mxColumnItem->IsTable())
3526 {
3527 sal_uInt16 nVisCols = 0;
3528 for(size_t i = GetActRightColumn(false, nCol); i < mpBorders.size();)
3529 {
3530 if ((*mxColumnItem)[i].bVisible)
3531 nVisCols++;
3532 i = GetActRightColumn(false, i);
3533 }
3534 return GetMargin2() - GetMargin1() - (nVisCols + 1) * glMinFrame;
3535 }
3536 else
3537 {
3538 tools::Long lWidth = 0;
3539 for(size_t i = nCol; i < mpBorders.size() - 1; i++)
3540 {
3541 lWidth += glMinFrame + mpBorders[i].nWidth;
3542 }
3543 return GetMargin2() - GetMargin1() - lWidth;
3544 }
3545 }
3546 }
3547
3548 // Tab stops relative to indent (#i24363#)
SetTabsRelativeToIndent(bool bRel)3549 void SvxRuler::SetTabsRelativeToIndent( bool bRel )
3550 {
3551 mxRulerImpl->bIsTabsRelativeToIndent = bRel;
3552 }
3553
SetValues(RulerChangeType type,tools::Long diffValue)3554 void SvxRuler::SetValues(RulerChangeType type, tools::Long diffValue)
3555 {
3556 if (diffValue == 0)
3557 return;
3558
3559 if (type == RulerChangeType::MARGIN1)
3560 AdjustMargin1(diffValue);
3561 else if (type == RulerChangeType::MARGIN2)
3562 SetMargin2( GetMargin2() - diffValue);
3563 ApplyMargins();
3564 }
3565
3566 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
3567