LibreOffice Module svx (master) 1
svxruler.cxx
Go to the documentation of this file.
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/settings.hxx>
27#include <vcl/svapp.hxx>
28#include <vcl/virdev.hxx>
29#include <vcl/weldutils.hxx>
30#include <svl/eitem.hxx>
31#include <svl/rectitem.hxx>
32#include <svl/hint.hxx>
33#include <sfx2/dispatch.hxx>
34#include <svx/strings.hrc>
35#include <svx/svxids.hrc>
36#include <svx/dialmgr.hxx>
37#include <svx/ruler.hxx>
38#include <svx/rulritem.hxx>
39#include <editeng/editids.hrc>
40#include <editeng/tstpitem.hxx>
41#include <editeng/lrspitem.hxx>
42#include <editeng/protitem.hxx>
43#include <osl/diagnose.h>
44#include <rtl/math.hxx>
45#include <o3tl/string_view.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
61 std::unique_ptr<sal_uInt16[]> pPercBuf;
62 std::unique_ptr<sal_uInt16[]> pBlockBuf;
63 sal_uInt16 nPercSize;
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
85 nPercSize(0), nTotalDist(0),
88 aProtectItem(std::make_unique<SvxProtectItem>(SID_RULER_PROTECT)),
91 bIsTableRows(false),
93 {
94 }
95
96 void SetPercSize(sal_uInt16 nSize);
97
98};
99
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
120void 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
157constexpr tools::Long glMinFrame = 5; // minimal frame width in pixels
158
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
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
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
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
254 {
255 pCtrlItems[i++].reset(new SvxRulerItem(SID_RULER_OBJECT, *this, rBindings));
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
270 SetExtraType(RulerExtra::NullOffset);
271
272 rBindings.LeaveRegistrations();
273
277
278}
279
281{
282 disposeOnce();
283}
284
286{
287 /* Destructor ruler; release internal buffer */
288 if(bListening)
290
292
293 pCtrlItems.clear();
294
296
297 pEditWin.clear();
299}
300
301tools::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
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
342{
343 return pEditWin->LogicToPixel(Size(nVal, 0)).Width();
344}
345
347{
348 return pEditWin->LogicToPixel(Size(0, nVal)).Height();
349}
350
352{
353 return pEditWin->LogicToPixel(Size(nVal, 0)).Width();
354}
355
357{
358 return pEditWin->LogicToPixel(Size(0, nVal)).Height();
359}
360
362{
363 return bHorz ? ConvertHPosPixel(nVal): ConvertVPosPixel(nVal);
364}
365
367{
368 return bHorz? ConvertHSizePixel(nVal): ConvertVSizePixel(nVal);
369}
370
372{
373 return pEditWin->PixelToLogic(Size(nVal, 0)).Width();
374}
375
377{
378 return pEditWin->PixelToLogic(Size(0, nVal)).Height();
379}
380
382{
383 return pEditWin->PixelToLogic(Size(nVal, 0)).Width();
384}
385
387{
388 return pEditWin->PixelToLogic(Size(0, nVal)).Height();
389}
390
392{
393 return bHorz? ConvertHPosLogic(nVal): ConvertVPosLogic(nVal);
394}
395
397{
398 return bHorz? ConvertHSizeLogic(nVal): ConvertVSizeLogic(nVal);
399}
400
402{
403 if(ConvertHSizePixel(nVal) != ConvertHSizePixel(nValOld))
404 return nVal;
405 else
406 return nValOld;
407}
408
410{
411 if(ConvertVSizePixel(nVal) != ConvertVSizePixel(nValOld))
412 return nVal;
413 else
414 return nValOld;
415}
416
418{
419 if(ConvertSizePixel(nVal) != ConvertSizePixel(nValOld))
420 return nVal;
421 else
422 return nValOld;
423}
424
425inline 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*/
435{
436 const RulerMarginStyle nMarginStyle =
437 ( mxRulerImpl->aProtectItem->IsSizeProtected() ||
438 mxRulerImpl->aProtectItem->IsPosProtected() ) ?
439 RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
440
442 {
443 // if no initialization by default app behavior
444 const tools::Long nOld = lLogicNullOffset;
445 lLogicNullOffset = mxColumnItem ? mxColumnItem->GetLeft() : mxLRSpaceItem->GetLeft();
446
448 {
450 }
451
453 {
455 SetMargin1(0, nMarginStyle);
456 lAppNullOffset = 0;
457 }
458 else
459 {
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
483 {
485 }
486
488 {
490 lAppNullOffset = 0;
491 SetMargin1(0, nMarginStyle);
492 }
493 else
494 {
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
518void 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
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;
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
633{
634 if(!bListening)
635 {
636 bValid = false;
638 bListening = true;
639 }
640}
641
642void 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();
652 }
653}
654
655void 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
668void 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();
678 }
679}
680
682{
683 if( pItem )
684 mxRulerImpl->aProtectItem.reset(pItem->Clone());
685}
686
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());
696 }
697}
698
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 }
726}
727
728
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
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
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
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
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
852 mpIndents[INDENT_FIRST_LINE].nPos = ConvertHPosPixel(leftFirstLine);
854
855 mpIndents[INDENT_FIRST_LINE].bInvisible = mxParaItem->IsAutoFirst();
856
858 }
859 else
860 {
861 if(!mpIndents.empty())
862 {
866 }
867 SetIndents(); // turn off
868 }
869}
870
871void 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();
881 }
882}
883
885{
886 /* Border distance */
887 if(bActive)
888 {
889 if (pItem)
890 mxBorderItem.reset(new SvxLRSpaceItem(*pItem));
891 else
892 mxBorderItem.reset();
893
895 }
896}
897
899{
900 /* Update view of position and width of page */
901 if (mxPagePosItem)
902 {
903 // all objects are automatically adjusted
904 if(bHorz)
905 {
907 pEditWin->LogicToPixel(mxPagePosItem->GetPos()).X(),
908 pEditWin->LogicToPixel(Size(mxPagePosItem->GetWidth(), 0)).
909 Width());
910 }
911 else
912 {
914 pEditWin->LogicToPixel(mxPagePosItem->GetPos()).Y(),
915 pEditWin->LogicToPixel(Size(0, mxPagePosItem->GetHeight())).
916 Height());
917 }
920 }
921 else
922 {
923 SetPagePos();
924 }
925
926 tools::Long lPos = 0;
927 Point aOwnPos = GetPosPixel();
928 Point aEdtWinPos = pEditWin->GetPosPixel();
930 {
931 //#i73321# in RTL the window and the ruler is not mirrored but the
932 // influence of the vertical ruler is inverted
933 Size aOwnSize = GetSizePixel();
934 Size aEdtWinSize = pEditWin->GetSizePixel();
935 lPos = aOwnSize.Width() - aEdtWinSize.Width();
936 lPos -= (aEdtWinPos - aOwnPos).X();
937 }
938 else
939 {
940 Point aPos(aEdtWinPos - aOwnPos);
941 lPos = bHorz ? aPos.X() : aPos.Y();
942 }
943
944 // Unfortunately, we get the offset of the edit window to the ruler never
945 // through a status message. So we set it ourselves if necessary.
946 if(lPos != mxRulerImpl->lOldWinPos)
947 {
948 mxRulerImpl->lOldWinPos=lPos;
949 SetWinPos(lPos);
950 }
951}
952
953void SvxRuler::Update(const SvxPagePosSizeItem *pItem) // new value of page attributes
954{
955 /* Store new value of page attributes */
956 if(bActive)
957 {
958 if(pItem)
959 mxPagePosItem.reset(new SvxPagePosSizeItem(*pItem));
960 else
961 mxPagePosItem.reset();
963 }
964}
965
966void SvxRuler::SetDefTabDist(tools::Long inDefTabDist) // New distance for DefaultTabs in App-Metrics
967{
969 UpdateFrame(); // hack: try to get lAppNullOffset initialized
970 /* New distance is set for DefaultTabs */
971 lDefTabDist = inDefTabDist;
972 UpdateTabs();
973}
974
975static sal_uInt16 ToSvTab_Impl(SvxTabAdjust eAdj)
976{
977 /* Internal conversion routine between SV-Tab.-Enum and Svx */
978 switch(eAdj) {
979 case SvxTabAdjust::Left: return RULER_TAB_LEFT;
980 case SvxTabAdjust::Right: return RULER_TAB_RIGHT;
981 case SvxTabAdjust::Decimal: return RULER_TAB_DECIMAL;
982 case SvxTabAdjust::Center: return RULER_TAB_CENTER;
983 case SvxTabAdjust::Default: return RULER_TAB_DEFAULT;
984 default: ; //prevent warning
985 }
986 return 0;
987}
988
989static SvxTabAdjust ToAttrTab_Impl(sal_uInt16 eAdj)
990{
991 switch(eAdj) {
992 case RULER_TAB_LEFT: return SvxTabAdjust::Left ;
993 case RULER_TAB_RIGHT: return SvxTabAdjust::Right ;
994 case RULER_TAB_DECIMAL: return SvxTabAdjust::Decimal ;
995 case RULER_TAB_CENTER: return SvxTabAdjust::Center ;
996 case RULER_TAB_DEFAULT: return SvxTabAdjust::Default ;
997 }
998 return SvxTabAdjust::Left;
999}
1000
1002{
1003 if(IsDrag())
1004 return;
1005
1007 {
1008 // buffer for DefaultTabStop
1009 // Distance last Tab <-> Right paragraph margin / DefaultTabDist
1010 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
1011
1012 const tools::Long nLeftFrameMargin = GetLeftFrameMargin();
1013 const tools::Long nRightFrameMargin = GetRightFrameMargin();
1014
1015 //#i24363# tab stops relative to indent
1016 const tools::Long nParaItemTxtLeft = mxParaItem->GetTextLeft();
1017
1018 const tools::Long lParaIndent = nLeftFrameMargin + nParaItemTxtLeft;
1019 const tools::Long lRightMargin = nRightFrameMargin - nParaItemTxtLeft;
1020
1021 const tools::Long lLastTab = mxTabStopItem->Count()
1022 ? ConvertHPosPixel(mxTabStopItem->At(mxTabStopItem->Count() - 1).GetTabPos())
1023 : 0;
1024 const tools::Long lPosPixel = ConvertHPosPixel(lParaIndent) + lLastTab;
1025 const tools::Long lRightIndent = ConvertHPosPixel(nRightFrameMargin - mxParaItem->GetRight());
1026
1028
1029 if( !nDefTabDist )
1030 nDefTabDist = 1;
1031
1032 const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > lRightIndent
1033 ? 0
1034 : static_cast<sal_uInt16>( (lRightIndent - lPosPixel) / nDefTabDist );
1035
1036 if(mxTabStopItem->Count() + TAB_GAP + nDefTabBuf > nTabBufSize)
1037 {
1038 // 10 (GAP) in stock
1039 nTabBufSize = mxTabStopItem->Count() + TAB_GAP + nDefTabBuf + GAP;
1040 mpTabs.resize(nTabBufSize);
1041 }
1042
1043 nTabCount = 0;
1044 sal_uInt16 j;
1045
1046 const tools::Long lParaIndentPix = ConvertSizePixel(lParaIndent);
1047
1048 tools::Long lTabStartLogic = (mxRulerImpl->bIsTabsRelativeToIndent ? lParaIndent : nLeftFrameMargin)
1050 if (bRTL)
1051 {
1052 lTabStartLogic = lParaIndent + lRightMargin - lTabStartLogic;
1053 }
1054 tools::Long lLastTabOffsetLogic = 0;
1055 for(j = 0; j < mxTabStopItem->Count(); ++j)
1056 {
1057 const SvxTabStop* pTab = &mxTabStopItem->At(j);
1058 lLastTabOffsetLogic = pTab->GetTabPos();
1059 tools::Long lPos = lTabStartLogic + (bRTL ? -lLastTabOffsetLogic : lLastTabOffsetLogic);
1060 mpTabs[nTabCount + TAB_GAP].nPos = ConvertHPosPixel(lPos);
1061 mpTabs[nTabCount + TAB_GAP].nStyle = ToSvTab_Impl(pTab->GetAdjustment());
1062 ++nTabCount;
1063 }
1064
1065 // Adjust to previous-to-first default tab stop
1066 lLastTabOffsetLogic -= lLastTabOffsetLogic % lDefTabDist;
1067
1068 // fill the rest with default Tabs
1069 for (j = 0; j < nDefTabBuf; ++j)
1070 {
1071 //simply add the default distance to the last position
1072 lLastTabOffsetLogic += lDefTabDist;
1073 if (bRTL)
1074 {
1075 mpTabs[nTabCount + TAB_GAP].nPos =
1076 ConvertHPosPixel(lTabStartLogic - lLastTabOffsetLogic);
1077 if (mpTabs[nTabCount + TAB_GAP].nPos <= lParaIndentPix)
1078 break;
1079 }
1080 else
1081 {
1082 mpTabs[nTabCount + TAB_GAP].nPos =
1083 ConvertHPosPixel(lTabStartLogic + lLastTabOffsetLogic);
1084 if (mpTabs[nTabCount + TAB_GAP].nPos >= lRightIndent)
1085 break;
1086 }
1087
1089 ++nTabCount;
1090 }
1091 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1092 DBG_ASSERT(nTabCount + TAB_GAP <= nTabBufSize, "BufferSize too small");
1093 }
1094 else
1095 {
1096 SetTabs();
1097 }
1098}
1099
1100void SvxRuler::Update(const SvxTabStopItem *pItem) // new value for tabs
1101{
1102 /* Store new value for tabs; delete old ones if possible */
1103 if(!bActive)
1104 return;
1105
1106 if(pItem)
1107 {
1108 mxTabStopItem.reset(new SvxTabStopItem(*pItem));
1109 if(!bHorz)
1110 mxTabStopItem->SetWhich(SID_ATTR_TABSTOP_VERTICAL);
1111 }
1112 else
1113 {
1114 mxTabStopItem.reset();
1115 }
1117}
1118
1119void SvxRuler::Update(const SvxObjectItem *pItem) // new value for objects
1120{
1121 /* Store new value for objects */
1122 if(bActive)
1123 {
1124 if(pItem)
1125 mxObjectItem.reset(new SvxObjectItem(*pItem));
1126 else
1127 mxObjectItem.reset();
1129 }
1130}
1131
1132void SvxRuler::SetNullOffsetLogic(tools::Long lVal) // Setting of the logic NullOffsets
1133{
1135 bAppSetNullOffset = true;
1137 Update();
1138}
1139
1141{
1142 /* Perform update of view */
1143 if(IsDrag())
1144 return;
1145
1146 UpdatePage();
1147 UpdateFrame();
1149 UpdateObject();
1150 else
1151 UpdateColumns();
1152
1154 UpdatePara();
1155
1157 UpdateTabs();
1158}
1159
1161{
1162 if (!mxPagePosItem)
1163 return 0;
1164 return bHorz ? mxPagePosItem->GetWidth() : mxPagePosItem->GetHeight();
1165}
1166
1168{
1169 /* Get Left margin in Pixels */
1170 return bAppSetNullOffset ?
1173}
1174
1176{
1177 /* Get First-line indent in pixels */
1179}
1180
1182{
1183 /* Get Left paragraph margin in Pixels */
1185}
1186
1188{
1189 /* Get Right paragraph margin in Pixels */
1191}
1192
1194{
1195 /* Get Right paragraph margin in Logic */
1196 return mxParaItem ? GetRightFrameMargin() - mxParaItem->GetRight() : GetRightFrameMargin();
1197}
1198
1199// Left margin in App values, is either the margin (= 0) or the left edge of
1200// the column that is set in the column attribute as current column.
1202{
1203 // #126721# for some unknown reason the current column is set to 0xffff
1204 DBG_ASSERT(!mxColumnItem || mxColumnItem->GetActColumn() < mxColumnItem->Count(),
1205 "issue #126721# - invalid current column!");
1206 tools::Long nLeft = 0;
1207 if (mxColumnItem &&
1208 mxColumnItem->Count() &&
1209 mxColumnItem->IsConsistent())
1210 {
1211 nLeft = mxColumnItem->GetActiveColumnDescription().nStart;
1212 }
1213
1214 if (mxBorderItem && (!mxColumnItem || mxColumnItem->IsTable()))
1215 nLeft += mxBorderItem->GetLeft();
1216
1217 return nLeft;
1218}
1219
1221{
1222 DBG_ASSERT(mxMinMaxItem, "no MinMax value set");
1223 if (mxMinMaxItem)
1224 {
1225 if (bHorz)
1226 return mxMinMaxItem->GetValue().Left();
1227 else
1228 return mxMinMaxItem->GetValue().Top();
1229 }
1230 return 0;
1231}
1232
1234{
1235 DBG_ASSERT(mxMinMaxItem, "no MinMax value set");
1236 if (mxMinMaxItem)
1237 {
1238 if (bHorz)
1239 return mxMinMaxItem->GetValue().Right();
1240 else
1241 return mxMinMaxItem->GetValue().Bottom();
1242 }
1243 return 0;
1244}
1245
1246
1248{
1249 /* Get right frame margin (in logical units) */
1250 if (mxColumnItem)
1251 {
1252 if (!IsActLastColumn(true))
1253 {
1254 return mxColumnItem->At(GetActRightColumn(true)).nEnd;
1255 }
1256 }
1257
1258 tools::Long lResult = lLogicNullOffset;
1259
1260 // If possible deduct right table entry
1261 if(mxColumnItem && mxColumnItem->IsTable())
1262 lResult += mxColumnItem->GetRight();
1263 else if(bHorz && mxLRSpaceItem)
1264 lResult += mxLRSpaceItem->GetRight();
1265 else if(!bHorz && mxULSpaceItem)
1266 lResult += mxULSpaceItem->GetLower();
1267
1268 if (bHorz && mxBorderItem && (!mxColumnItem || mxColumnItem->IsTable()))
1269 lResult += mxBorderItem->GetRight();
1270
1271 if(bHorz)
1272 lResult = mxPagePosItem->GetWidth() - lResult;
1273 else
1274 lResult = mxPagePosItem->GetHeight() - lResult;
1275
1276 return lResult;
1277}
1278
1279#define NEG_FLAG ( (nFlags & SvxRulerSupportFlags::NEGATIVE_MARGINS) == \
1280 SvxRulerSupportFlags::NEGATIVE_MARGINS )
1281#define TAB_FLAG ( mxColumnItem && mxColumnItem->IsTable() )
1282
1284{
1285 /*
1286 Corrects the position within the calculated limits. The limit values are in
1287 pixels relative to the page edge.
1288 */
1289
1290 const tools::Long lNullPix = Ruler::GetNullOffset();
1291 tools::Long lDragPos = GetDragPos() + lNullPix;
1292 bool bHoriRows = bHorz && mxRulerImpl->bIsTableRows;
1293 if((bLeft || bHoriRows) && lDragPos < nMaxLeft)
1294 lDragPos = nMaxLeft;
1295 else if((bRight||bHoriRows) && lDragPos > nMaxRight)
1296 lDragPos = nMaxRight;
1297 return lDragPos - lNullPix;
1298}
1299
1300static void ModifyTabs_Impl( sal_uInt16 nCount, // Number of Tabs
1301 RulerTab* pTabs, // Tab buffer
1302 tools::Long lDiff) // difference to be added
1303{
1304 /* Helper function, move all the tabs by a fixed value */
1305 if( pTabs )
1306 {
1307 for(sal_uInt16 i = 0; i < nCount; ++i)
1308 {
1309 pTabs[i].nPos += lDiff;
1310 }
1311 }
1312}
1313
1315{
1316 /* Dragging the left edge of frame */
1317 tools::Long aDragPosition = GetCorrectedDragPos( !TAB_FLAG || !NEG_FLAG );
1318
1319 aDragPosition = MakePositionSticky(aDragPosition, GetRightFrameMargin(), false);
1320
1321 // Check if position changed
1322 if (aDragPosition == 0)
1323 return;
1324
1325 DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 3 : 7, bHorz);
1327 DragBorders();
1328 AdjustMargin1(aDragPosition);
1329}
1330
1332{
1334 const tools::Long lDragPos = lInputDiff;
1335
1336 bool bProtectColumns =
1337 mxRulerImpl->aProtectItem->IsSizeProtected() ||
1338 mxRulerImpl->aProtectItem->IsPosProtected();
1339
1340 const RulerMarginStyle nMarginStyle =
1341 bProtectColumns ? RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
1342
1344 {
1345 tools::Long lDiff = lDragPos;
1346 SetNullOffset(nOld + lDiff);
1348 {
1349 SetMargin2( GetMargin2() - lDiff, nMarginStyle );
1350
1352 {
1353 // Right indent of the old position
1354 mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
1356 }
1357 if (mxObjectItem)
1358 {
1359 mpObjectBorders[GetObjectBordersOff(0)].nPos -= lDiff;
1360 mpObjectBorders[GetObjectBordersOff(1)].nPos -= lDiff;
1362 }
1363 if (mxColumnItem)
1364 {
1365 for(sal_uInt16 i = 0; i < mxColumnItem->Count()-1; ++i)
1366 mpBorders[i].nPos -= lDiff;
1367 SetBorders(mxColumnItem->Count()-1, mpBorders.data());
1368 if(mxColumnItem->IsFirstAct())
1369 {
1370 // Right indent of the old position
1371 if (mxParaItem)
1372 {
1373 mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
1375 }
1376 }
1377 else
1378 {
1379 if (mxParaItem)
1380 {
1381 mpIndents[INDENT_FIRST_LINE].nPos -= lDiff;
1382 mpIndents[INDENT_LEFT_MARGIN].nPos -= lDiff;
1383 mpIndents[INDENT_RIGHT_MARGIN].nPos -= lDiff;
1385 }
1386 }
1388 &&!IsActFirstColumn())
1389 {
1390 ModifyTabs_Impl(nTabCount + TAB_GAP, mpTabs.data(), -lDiff);
1391 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1392 }
1393 }
1394 }
1395 }
1396 else
1397 {
1398 tools::Long lDiff = lDragPos - nOld;
1399 SetMargin1(nOld + lDiff, nMarginStyle);
1400
1401 if (!mxColumnItem
1402 || !(nDragType
1405 {
1407 {
1408 // Left indent of the old position
1409 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1410 mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
1412 }
1413
1414 if (mxColumnItem)
1415 {
1416 for(sal_uInt16 i = 0; i < mxColumnItem->Count() - 1; ++i)
1417 mpBorders[i].nPos += lDiff;
1418 SetBorders(mxColumnItem->Count() - 1, mpBorders.data());
1419 if (mxColumnItem->IsFirstAct())
1420 {
1421 // Left indent of the old position
1422 if (mxParaItem)
1423 {
1424 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1425 mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
1427 }
1428 }
1429 else
1430 {
1431 if (mxParaItem)
1432 {
1433 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1434 mpIndents[INDENT_LEFT_MARGIN].nPos += lDiff;
1435 mpIndents[INDENT_RIGHT_MARGIN].nPos += lDiff;
1437 }
1438 }
1439 }
1440 if (mxTabStopItem)
1441 {
1442 ModifyTabs_Impl(nTabCount + TAB_GAP, mpTabs.data(), lDiff);
1443 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1444 }
1445 }
1446 }
1447}
1448
1450{
1451 /* Dragging the right edge of frame */
1452 tools::Long aDragPosition = GetCorrectedDragPos( true, !TAB_FLAG || !NEG_FLAG);
1453 aDragPosition = MakePositionSticky(aDragPosition, GetLeftFrameMargin(), false);
1454 tools::Long lDiff = aDragPosition - GetMargin2();
1455
1456 // Check if position changed
1457 if (lDiff == 0)
1458 return;
1459
1460 if( mxRulerImpl->bIsTableRows &&
1461 !bHorz &&
1462 mxColumnItem &&
1464 {
1465 DragBorders();
1466 }
1467
1468 bool bProtectColumns =
1469 mxRulerImpl->aProtectItem->IsSizeProtected() ||
1470 mxRulerImpl->aProtectItem->IsPosProtected();
1471
1472 const RulerMarginStyle nMarginStyle = bProtectColumns ? RulerMarginStyle::NONE : RulerMarginStyle::Sizeable;
1473
1474 SetMargin2( aDragPosition, nMarginStyle );
1475
1476 // Right indent of the old position
1478 {
1479 mpIndents[INDENT_FIRST_LINE].nPos += lDiff;
1481 }
1482
1483 DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 5 : 7, bHorz);
1484}
1485
1487{
1488 /* Dragging the paragraph indents */
1489 tools::Long aDragPosition = NEG_FLAG ? GetDragPos() : GetCorrectedDragPos();
1490 const sal_uInt16 nIndex = GetDragAryPos() + INDENT_GAP;
1491
1492 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
1493
1495 aDragPosition = MakePositionSticky(aDragPosition, bRTL ? GetLeftFrameMargin() : GetRightFrameMargin());
1496 else
1497 aDragPosition = MakePositionSticky(aDragPosition, bRTL ? GetRightFrameMargin() : GetLeftFrameMargin());
1498
1499 const tools::Long lDiff = mpIndents[nIndex].nPos - aDragPosition;
1500
1501 // Check if position changed
1502 if (lDiff == 0)
1503 return;
1504
1507 {
1508 mpIndents[INDENT_FIRST_LINE].nPos -= lDiff;
1509 }
1510
1511 mpIndents[nIndex].nPos = aDragPosition;
1512
1515}
1516
1517void SvxRuler::DrawLine_Impl(tools::Long& lTabPosition, int nNew, bool bHorizontal)
1518{
1519 /*
1520 Output routine for the ledger line when moving tabs, tables and other
1521 columns
1522 */
1523 if(bHorizontal)
1524 {
1525 const tools::Long nHeight = pEditWin->GetOutDev()->GetOutputSize().Height();
1526 Point aZero = pEditWin->GetMapMode().GetOrigin();
1527 if(lTabPosition != -1)
1528 {
1529 pEditWin->InvertTracking(
1530 tools::Rectangle( Point(lTabPosition, -aZero.Y()),
1531 Point(lTabPosition, -aZero.Y() + nHeight)),
1532 ShowTrackFlags::Split | ShowTrackFlags::Clip );
1533 }
1534 if( nNew & 1 )
1535 {
1536 tools::Long nDrapPosition = GetCorrectedDragPos( ( nNew & 4 ) != 0, ( nNew & 2 ) != 0 );
1537 nDrapPosition = MakePositionSticky(nDrapPosition, GetLeftFrameMargin());
1538 lTabPosition = ConvertHSizeLogic( nDrapPosition + GetNullOffset() );
1539 if (mxPagePosItem)
1540 lTabPosition += mxPagePosItem->GetPos().X();
1541 pEditWin->InvertTracking(
1542 tools::Rectangle( Point(lTabPosition, -aZero.Y()),
1543 Point(lTabPosition, -aZero.Y() + nHeight) ),
1544 ShowTrackFlags::Clip | ShowTrackFlags::Split );
1545 }
1546 }
1547 else
1548 {
1549 const tools::Long nWidth = pEditWin->GetOutDev()->GetOutputSize().Width();
1550 Point aZero = pEditWin->GetMapMode().GetOrigin();
1551 if(lTabPosition != -1)
1552 {
1553 pEditWin->InvertTracking(
1554 tools::Rectangle( Point(-aZero.X(), lTabPosition),
1555 Point(-aZero.X() + nWidth, lTabPosition)),
1556 ShowTrackFlags::Split | ShowTrackFlags::Clip );
1557 }
1558
1559 if(nNew & 1)
1560 {
1561 tools::Long nDrapPosition = GetCorrectedDragPos();
1562 nDrapPosition = MakePositionSticky(nDrapPosition, GetLeftFrameMargin());
1563 lTabPosition = ConvertVSizeLogic(nDrapPosition + GetNullOffset());
1564 if (mxPagePosItem)
1565 lTabPosition += mxPagePosItem->GetPos().Y();
1566 pEditWin->InvertTracking(
1567 tools::Rectangle( Point(-aZero.X(), lTabPosition),
1568 Point(-aZero.X()+nWidth, lTabPosition)),
1569 ShowTrackFlags::Clip | ShowTrackFlags::Split );
1570 }
1571 }
1572}
1573
1575{
1576 /* Dragging of Tabs */
1577 tools::Long aDragPosition = GetCorrectedDragPos(true, false);
1578 aDragPosition = MakePositionSticky(aDragPosition, GetLeftFrameMargin());
1579
1580 sal_uInt16 nIdx = GetDragAryPos() + TAB_GAP;
1581 tools::Long nDiff = aDragPosition - mpTabs[nIdx].nPos;
1582 if (nDiff == 0)
1583 return;
1584
1586
1588 {
1589
1590 for(sal_uInt16 i = nIdx; i < nTabCount; ++i)
1591 {
1592 mpTabs[i].nPos += nDiff;
1593 // limit on maximum
1594 if(mpTabs[i].nPos > GetMargin2())
1595 mpTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
1596 else
1597 mpTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
1598 }
1599 }
1601 {
1602 mxRulerImpl->nTotalDist -= nDiff;
1603 mpTabs[nIdx].nPos = aDragPosition;
1604 for(sal_uInt16 i = nIdx+1; i < nTabCount; ++i)
1605 {
1606 if(mpTabs[i].nStyle & RULER_TAB_DEFAULT)
1607 // can be canceled at the DefaultTabs
1608 break;
1609 tools::Long nDelta = mxRulerImpl->nTotalDist * mxRulerImpl->pPercBuf[i];
1610 nDelta /= 1000;
1611 mpTabs[i].nPos = mpTabs[nIdx].nPos + nDelta;
1613 mpTabs[i].nStyle |= RULER_STYLE_INVISIBLE;
1614 else
1615 mpTabs[i].nStyle &= ~RULER_STYLE_INVISIBLE;
1616 }
1617 }
1618 else
1619 {
1620 mpTabs[nIdx].nPos = aDragPosition;
1621 }
1622
1623 if(IsDragDelete())
1624 mpTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
1625 else
1626 mpTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
1627 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1628}
1629
1631{
1632 if(bOn)
1633 {
1634 Activate();
1635 }
1636 else
1637 Deactivate();
1638 if(bActive!=bOn)
1639 {
1641 if(bOn)
1642 for(sal_uInt16 i=0;i<mxRulerImpl->nControllerItems;i++)
1643 pCtrlItems[i]->ReBind();
1644 else
1645 for(sal_uInt16 j=0;j<mxRulerImpl->nControllerItems;j++)
1646 pCtrlItems[j]->UnBind();
1648 }
1649 bActive = bOn;
1650}
1651
1653 tools::Long lDifference,
1654 UpdateType eType) // Art (all, left or right)
1655{
1656 /* Helper function; carry Tabs and Paragraph Margins */
1657 switch(eType)
1658 {
1660 mpIndents[INDENT_RIGHT_MARGIN].nPos += lDifference;
1661 break;
1663 {
1664 mpIndents[INDENT_FIRST_LINE].nPos += lDifference;
1665 mpIndents[INDENT_LEFT_MARGIN].nPos += lDifference;
1666 if (!mpTabs.empty())
1667 {
1668 for(sal_uInt16 i = 0; i < nTabCount+TAB_GAP; ++i)
1669 {
1670 mpTabs[i].nPos += lDifference;
1671 }
1672 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
1673 }
1674 break;
1675 }
1676 }
1678}
1679
1681{
1682 /* Dragging of Borders (Tables and other columns) */
1683 bool bLeftIndentsCorrected = false;
1684 bool bRightIndentsCorrected = false;
1685 int nIndex;
1686
1687 if(GetDragType() == RulerType::Border)
1688 {
1691 }
1692 else
1693 {
1694 nIndex = 0;
1695 }
1696
1697 RulerDragSize nDragSize = GetDragSize();
1698 tools::Long lDiff = 0;
1699
1700 // the drag position has to be corrected to be able to prevent borders from passing each other
1702
1703 switch(nDragSize)
1704 {
1705 case RulerDragSize::Move:
1706 {
1707 if(GetDragType() == RulerType::Border)
1708 lDiff = lPos - nDragOffset - mpBorders[nIndex].nPos;
1709 else
1710 lDiff = GetDragType() == RulerType::Margin1 ? lPos - mxRulerImpl->lLastLMargin : lPos - mxRulerImpl->lLastRMargin;
1711
1713 {
1714 tools::Long nRight = GetMargin2() - glMinFrame; // Right limiters
1715 for(int i = mpBorders.size() - 2; i >= nIndex; --i)
1716 {
1717 tools::Long l = mpBorders[i].nPos;
1718 mpBorders[i].nPos += lDiff;
1719 mpBorders[i].nPos = std::min(mpBorders[i].nPos, nRight - mpBorders[i].nWidth);
1720 nRight = mpBorders[i].nPos - glMinFrame;
1721 // RR update the column
1722 if(i == GetActRightColumn())
1723 {
1725 bRightIndentsCorrected = true;
1726 }
1727 // LAR, EZE update the column
1728 else if(i == GetActLeftColumn())
1729 {
1731 bLeftIndentsCorrected = true;
1732 }
1733 }
1734 }
1736 {
1737 int nLimit;
1738 tools::Long lLeft;
1739 int nStartLimit = mpBorders.size() - 2;
1740 switch(GetDragType())
1741 {
1742 default: ;//prevent warning
1743 OSL_FAIL("svx::SvxRuler::DragBorders(), unknown drag type!" );
1744 [[fallthrough]];
1745 case RulerType::Border:
1746 if(mxRulerImpl->bIsTableRows)
1747 {
1748 mpBorders[nIndex].nPos += lDiff;
1749 if(bHorz)
1750 {
1751 lLeft = mpBorders[nIndex].nPos;
1752 mxRulerImpl->nTotalDist -= lDiff;
1753 nLimit = nIndex + 1;
1754 }
1755 else
1756 {
1757 lLeft = 0;
1758 nStartLimit = nIndex - 1;
1759 mxRulerImpl->nTotalDist += lDiff;
1760 nLimit = 0;
1761 }
1762 }
1763 else
1764 {
1765 nLimit = nIndex + 1;
1766 mpBorders[nIndex].nPos += lDiff;
1767 lLeft = mpBorders[nIndex].nPos;
1768 mxRulerImpl->nTotalDist -= lDiff;
1769 }
1770 break;
1771 case RulerType::Margin1:
1772 nLimit = 0;
1773 lLeft = mxRulerImpl->lLastLMargin + lDiff;
1774 mxRulerImpl->nTotalDist -= lDiff;
1775 break;
1776 case RulerType::Margin2:
1777 nLimit = 0;
1778 lLeft= 0;
1779 nStartLimit = mpBorders.size() - 2;
1780 mxRulerImpl->nTotalDist += lDiff;
1781 break;
1782 }
1783
1784 for(int i = nStartLimit; i >= nLimit; --i)
1785 {
1786
1787 tools::Long l = mpBorders[i].nPos;
1788 mpBorders[i].nPos =
1789 lLeft +
1790 (mxRulerImpl->nTotalDist * mxRulerImpl->pPercBuf[i]) / 1000 +
1791 mxRulerImpl->pBlockBuf[i];
1792
1793 // RR update the column
1794 if(!mxRulerImpl->bIsTableRows)
1795 {
1796 if(i == GetActRightColumn())
1797 {
1799 bRightIndentsCorrected = true;
1800 }
1801 // LAR, EZE update the column
1802 else if(i == GetActLeftColumn())
1803 {
1805 bLeftIndentsCorrected = true;
1806 }
1807 }
1808 }
1809 if(mxRulerImpl->bIsTableRows)
1810 {
1811 //in vertical tables the left borders have to be moved
1812 if(bHorz)
1813 {
1814 for(int i = 0; i < nIndex; ++i)
1815 mpBorders[i].nPos += lDiff;
1816 AdjustMargin1(lDiff);
1817 }
1818 else
1819 {
1820 //otherwise the right borders are moved
1821 for(int i = mxColumnItem->Count() - 1; i > nIndex; --i)
1822 mpBorders[i].nPos += lDiff;
1823 SetMargin2( GetMargin2() + lDiff, RulerMarginStyle::NONE );
1824 }
1825 }
1826 }
1827 else if(mxRulerImpl->bIsTableRows)
1828 {
1829 //moving rows: if a row is resized all following rows
1830 //have to be moved by the same amount.
1831 //This includes the left border when the table is not limited
1832 //to a lower frame border.
1833 int nLimit;
1834 if(GetDragType()==RulerType::Border)
1835 {
1836 nLimit = nIndex + 1;
1837 mpBorders[nIndex].nPos += lDiff;
1838 }
1839 else
1840 {
1841 nLimit=0;
1842 }
1843 //in vertical tables the left borders have to be moved
1844 if(bHorz)
1845 {
1846 for(int i = 0; i < nIndex; ++i)
1847 {
1848 mpBorders[i].nPos += lDiff;
1849 }
1850 AdjustMargin1(lDiff);
1851 }
1852 else
1853 {
1854 //otherwise the right borders are moved
1855 for(int i = mpBorders.size() - 2; i >= nLimit; --i)
1856 {
1857 mpBorders[i].nPos += lDiff;
1858 }
1859 SetMargin2( GetMargin2() + lDiff, RulerMarginStyle::NONE );
1860 }
1861 }
1862 else
1863 mpBorders[nIndex].nPos += lDiff;
1864 break;
1865 }
1866 case RulerDragSize::N1:
1867 {
1868 lDiff = lPos - mpBorders[nIndex].nPos;
1869 mpBorders[nIndex].nWidth += mpBorders[nIndex].nPos - lPos;
1870 mpBorders[nIndex].nPos = lPos;
1871 break;
1872 }
1873 case RulerDragSize::N2:
1874 {
1875 const tools::Long nOld = mpBorders[nIndex].nWidth;
1876 mpBorders[nIndex].nWidth = lPos - mpBorders[nIndex].nPos;
1877 lDiff = mpBorders[nIndex].nWidth - nOld;
1878 break;
1879 }
1880 }
1881 if(!bRightIndentsCorrected &&
1883 nDragSize != RulerDragSize::N2 &&
1884 !mpIndents.empty() &&
1885 !mxRulerImpl->bIsTableRows)
1886 {
1888 }
1889 else if(!bLeftIndentsCorrected &&
1890 GetActLeftColumn() == nIndex &&
1891 nDragSize != RulerDragSize::N1 &&
1892 !mpIndents.empty())
1893 {
1895 }
1896 SetBorders(mxColumnItem->Count() - 1, mpBorders.data());
1897}
1898
1900{
1901 /* Dragging of object edges */
1902 if(RulerDragSize::Move == GetDragSize())
1903 {
1905
1906 const sal_uInt16 nIdx = GetDragAryPos();
1907 mpObjectBorders[GetObjectBordersOff(nIdx)].nPos = lPosition;
1910
1911 }
1912}
1913
1915{
1916 /* Applying margins; changed by dragging. */
1917 const SfxPoolItem* pItem = nullptr;
1918 sal_uInt16 nId = SID_ATTR_LONG_LRSPACE;
1919
1920 if(bHorz)
1921 {
1922 const tools::Long lOldNull = lLogicNullOffset;
1923 if(mxRulerImpl->lMaxLeftLogic != -1 && nMaxLeft == GetMargin1() + Ruler::GetNullOffset())
1924 {
1925 lLogicNullOffset = mxRulerImpl->lMaxLeftLogic;
1927 }
1928 else
1929 {
1932 }
1933
1935 {
1936 lAppNullOffset += lLogicNullOffset - lOldNull;
1937 }
1938
1939 tools::Long nRight;
1940 if(mxRulerImpl->lMaxRightLogic != -1
1942 {
1943 nRight = GetPageWidth() - mxRulerImpl->lMaxRightLogic;
1944 }
1945 else
1946 {
1947 nRight = std::max(tools::Long(0),
1948 mxPagePosItem->GetWidth() - mxLRSpaceItem->GetLeft() -
1950
1951 nRight = PixelHAdjust( nRight, mxLRSpaceItem->GetRight());
1952 }
1953 mxLRSpaceItem->SetRight(nRight);
1954
1955 pItem = mxLRSpaceItem.get();
1956
1957#ifdef DEBUGLIN
1958 Debug_Impl(pEditWin, *mxLRSpaceItem);
1959#endif // DEBUGLIN
1960
1961 }
1962 else
1963 {
1964 const tools::Long lOldNull = lLogicNullOffset;
1968 mxULSpaceItem->SetUpper(
1971 {
1972 lAppNullOffset += lLogicNullOffset - lOldNull;
1973 }
1974 mxULSpaceItem->SetLower(
1976 std::max(tools::Long(0), mxPagePosItem->GetHeight() -
1977 mxULSpaceItem->GetUpper() -
1979 lAppNullOffset)), mxULSpaceItem->GetLower()));
1980 pItem = mxULSpaceItem.get();
1981 nId = SID_ATTR_LONG_ULSPACE;
1982
1983#ifdef DEBUGLIN
1984 Debug_Impl(pEditWin,*mxULSpaceItem);
1985#endif // DEBUGLIN
1986
1987 }
1988 pBindings->GetDispatcher()->ExecuteList(nId, SfxCallMode::RECORD, { pItem });
1989 if (mxTabStopItem)
1990 UpdateTabs();
1991}
1992
1994{
1995 RulerUnitData aUnitData = GetCurrentRulerUnit();
1996 double aRoundingFactor = aUnitData.nTickUnit / aUnitData.nTick1;
1997
1998 tools::Long lNewValue = OutputDevice::LogicToLogic(Size(lValue, 0), pEditWin->GetMapMode(), GetCurrentMapMode()).Width();
1999 lNewValue = (rtl::math::round(lNewValue / static_cast<double>(aUnitData.nTickUnit) * aRoundingFactor) / aRoundingFactor) * aUnitData.nTickUnit;
2000 return OutputDevice::LogicToLogic(Size(lNewValue, 0), GetCurrentMapMode(), pEditWin->GetMapMode()).Width();
2001}
2002
2004{
2005 /* Applying paragraph settings; changed by dragging. */
2006
2007 tools::Long nLeftFrameMargin = GetLeftFrameMargin();
2008
2009 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2010
2011 tools::Long nNewTxtLeft;
2012 tools::Long nNewFirstLineOffset;
2013 tools::Long nNewRight;
2014
2018
2019 if(mxColumnItem && ((bRTL && !IsActLastColumn(true)) || (!bRTL && !IsActFirstColumn(true))))
2020 {
2021 if(bRTL)
2022 {
2023 tools::Long nRightColumn = GetActRightColumn(true);
2024 tools::Long nRightBorder = ConvertPosLogic(mpBorders[nRightColumn].nPos);
2025 nNewTxtLeft = nRightBorder - nLeftMargin - lAppNullOffset;
2026 }
2027 else
2028 {
2029 tools::Long nLeftColumn = GetActLeftColumn(true);
2030 tools::Long nLeftBorder = ConvertPosLogic(mpBorders[nLeftColumn].nPos + mpBorders[nLeftColumn].nWidth);
2031 nNewTxtLeft = nLeftMargin - nLeftBorder - lAppNullOffset;
2032 }
2033 }
2034 else
2035 {
2036 if(bRTL)
2037 {
2038 tools::Long nRightBorder = ConvertPosLogic(GetMargin2());
2039 nNewTxtLeft = nRightBorder - nLeftMargin - lAppNullOffset;
2040 }
2041 else
2042 {
2043 tools::Long nLeftBorder = ConvertPosLogic(GetMargin1());
2044 nNewTxtLeft = nLeftBorder + nLeftMargin - nLeftFrameMargin - lAppNullOffset;
2045 }
2046 }
2047
2048 if(bRTL)
2049 nNewFirstLineOffset = nLeftMargin - nFirstLine - lAppNullOffset;
2050 else
2051 nNewFirstLineOffset = nFirstLine - nLeftMargin - lAppNullOffset;
2052
2053 if(mxColumnItem && ((!bRTL && !IsActLastColumn(true)) || (bRTL && !IsActFirstColumn(true))))
2054 {
2055 if(bRTL)
2056 {
2057 tools::Long nLeftColumn = GetActLeftColumn(true);
2058 tools::Long nLeftBorder = ConvertPosLogic(mpBorders[nLeftColumn].nPos + mpBorders[nLeftColumn].nWidth);
2059 nNewRight = nRightMargin - nLeftBorder - lAppNullOffset;
2060 }
2061 else
2062 {
2063 tools::Long nRightColumn = GetActRightColumn(true);
2064 tools::Long nRightBorder = ConvertPosLogic(mpBorders[nRightColumn].nPos);
2065 nNewRight = nRightBorder - nRightMargin - lAppNullOffset;
2066 }
2067 }
2068 else
2069 {
2070 if(bRTL)
2071 {
2072 tools::Long nLeftBorder = ConvertPosLogic(GetMargin1());
2073 nNewRight = nLeftBorder + nRightMargin - nLeftFrameMargin - lAppNullOffset;
2074 }
2075 else
2076 {
2077 tools::Long nRightBorder = ConvertPosLogic(GetMargin2());
2078 nNewRight = nRightBorder - nRightMargin - lAppNullOffset;
2079 }
2080 }
2081
2082 if (mbSnapping)
2083 {
2084 nNewTxtLeft = RoundToCurrentMapMode(nNewTxtLeft);
2085 nNewFirstLineOffset = RoundToCurrentMapMode(nNewFirstLineOffset);
2086 nNewRight = RoundToCurrentMapMode(nNewRight);
2087 }
2088
2089 mxParaItem->SetTextFirstLineOffset(sal::static_int_cast<short>(nNewFirstLineOffset));
2090 mxParaItem->SetTextLeft(nNewTxtLeft);
2091 mxParaItem->SetRight(nNewRight);
2092
2093 sal_uInt16 nParagraphId = bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL;
2094 pBindings->GetDispatcher()->ExecuteList(nParagraphId, SfxCallMode::RECORD,
2095 { mxParaItem.get() });
2096 UpdateTabs();
2097}
2098
2100{
2101 /* Apply tab settings, changed by dragging. */
2102 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2103 const sal_uInt16 nCoreIdx = GetDragAryPos();
2104 if(IsDragDelete())
2105 {
2106 mxTabStopItem->Remove(nCoreIdx);
2107 }
2110 {
2111 SvxTabStopItem *pItem = new SvxTabStopItem(mxTabStopItem->Which());
2112 //remove default tab stops
2113 for ( sal_uInt16 i = 0; i < pItem->Count(); )
2114 {
2115 if ( SvxTabAdjust::Default == (*pItem)[i].GetAdjustment() )
2116 {
2117 pItem->Remove(i);
2118 continue;
2119 }
2120 ++i;
2121 }
2122
2123 sal_uInt16 j;
2124 for(j = 0; j < nCoreIdx; ++j)
2125 {
2126 pItem->Insert(mxTabStopItem->At(j));
2127 }
2128 for(; j < mxTabStopItem->Count(); ++j)
2129 {
2130 SvxTabStop aTabStop = mxTabStopItem->At(j);
2131 aTabStop.GetTabPos() = PixelHAdjust(
2134 aTabStop.GetTabPos());
2135 pItem->Insert(aTabStop);
2136 }
2137 mxTabStopItem.reset(pItem);
2138 }
2139 else if( mxTabStopItem->Count() == 0 )
2140 return;
2141 else
2142 {
2143 SvxTabStop aTabStop = mxTabStopItem->At(nCoreIdx);
2144 if( mxRulerImpl->lMaxRightLogic != -1 &&
2145 mpTabs[nCoreIdx + TAB_GAP].nPos + Ruler::GetNullOffset() == nMaxRight )
2146 {
2147 // Set tab pos exactly at the right indent
2148 tools::Long nTmpLeftIndentLogic
2150 if (mxRulerImpl->bIsTabsRelativeToIndent && mxParaItem)
2151 {
2152 nTmpLeftIndentLogic += bRTL ? mxParaItem->GetRight() : mxParaItem->GetLeft();
2153 }
2154 aTabStop.GetTabPos()
2155 = mxRulerImpl->lMaxRightLogic - lLogicNullOffset - nTmpLeftIndentLogic;
2156 }
2157 else
2158 {
2159 if(bRTL)
2160 {
2161 //#i24363# tab stops relative to indent
2162 const tools::Long nTmpLeftIndent = mxRulerImpl->bIsTabsRelativeToIndent ?
2163 GetLeftIndent() :
2165
2166 tools::Long nNewPosition = ConvertHPosLogic(nTmpLeftIndent - mpTabs[nCoreIdx + TAB_GAP].nPos);
2167 aTabStop.GetTabPos() = PixelHAdjust(nNewPosition - lAppNullOffset, aTabStop.GetTabPos());
2168 }
2169 else
2170 {
2171 //#i24363# tab stops relative to indent
2172 const tools::Long nTmpLeftIndent = mxRulerImpl->bIsTabsRelativeToIndent ?
2173 GetLeftIndent() :
2175
2176 tools::Long nNewPosition = ConvertHPosLogic(mpTabs[nCoreIdx + TAB_GAP].nPos - nTmpLeftIndent);
2177 aTabStop.GetTabPos() = PixelHAdjust(nNewPosition - lAppNullOffset, aTabStop.GetTabPos());
2178 }
2179 }
2180 mxTabStopItem->Remove(nCoreIdx);
2181 mxTabStopItem->Insert(aTabStop);
2182 }
2183 sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
2184 pBindings->GetDispatcher()->ExecuteList(nTabStopId, SfxCallMode::RECORD,
2185 { mxTabStopItem.get() });
2186 UpdateTabs();
2187}
2188
2190{
2191 /* Applying (table) column settings; changed by dragging. */
2192 if(mxColumnItem->IsTable())
2193 {
2194 tools::Long lValue = GetFrameLeft();
2195 if(lValue != mxRulerImpl->nColLeftPix)
2196 {
2197 tools::Long nLeft = PixelHAdjust(
2198 ConvertHPosLogic(lValue) -
2200 mxColumnItem->GetLeft());
2201 mxColumnItem->SetLeft(nLeft);
2202 }
2203
2204 lValue = GetMargin2();
2205
2206 if(lValue != mxRulerImpl->nColRightPix)
2207 {
2208 tools::Long nWidthOrHeight = bHorz ? mxPagePosItem->GetWidth() : mxPagePosItem->GetHeight();
2209 tools::Long nRight = PixelHAdjust(
2210 nWidthOrHeight -
2211 mxColumnItem->GetLeft() -
2212 ConvertHPosLogic(lValue) -
2214 mxColumnItem->GetRight() );
2215 mxColumnItem->SetRight(nRight);
2216 }
2217 }
2218
2219 for(sal_uInt16 i = 0; i < mxColumnItem->Count() - 1; ++i)
2220 {
2221 tools::Long& nEnd = mxColumnItem->At(i).nEnd;
2222 nEnd = PixelHAdjust(
2224 mxColumnItem->At(i).nEnd);
2225 tools::Long& nStart = mxColumnItem->At(i + 1).nStart;
2226 nStart = PixelHAdjust(
2228 mpBorders[i].nWidth) -
2230 mxColumnItem->At(i + 1).nStart);
2231 // It may be that, due to the PixelHAdjust readjustment to old values,
2232 // the width becomes < 0. This we readjust.
2233 if( nEnd > nStart )
2234 nStart = nEnd;
2235 }
2236
2237#ifdef DEBUGLIN
2238 Debug_Impl(pEditWin,*mxColumnItem);
2239#endif // DEBUGLIN
2240
2241 SfxBoolItem aFlag(SID_RULER_ACT_LINE_ONLY,
2243
2244 sal_uInt16 nColId = mxRulerImpl->bIsTableRows ? (bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL) :
2245 (bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
2246
2247 pBindings->GetDispatcher()->ExecuteList(nColId, SfxCallMode::RECORD,
2248 { mxColumnItem.get(), &aFlag });
2249}
2250
2252{
2253 /* Applying object settings, changed by dragging. */
2254
2255 // to the page margin
2256 tools::Long nMargin = mxLRSpaceItem ? mxLRSpaceItem->GetLeft() : 0;
2257 tools::Long nStartX = PixelAdjust(
2259 nMargin -
2261 mxObjectItem->GetStartX());
2262 mxObjectItem->SetStartX(nStartX);
2263
2264 tools::Long nEndX = PixelAdjust(
2266 nMargin -
2268 mxObjectItem->GetEndX());
2269 mxObjectItem->SetEndX(nEndX);
2270
2271 nMargin = mxULSpaceItem ? mxULSpaceItem->GetUpper() : 0;
2272 tools::Long nStartY = PixelAdjust(
2274 nMargin -
2276 mxObjectItem->GetStartY());
2277 mxObjectItem->SetStartY(nStartY);
2278
2279 tools::Long nEndY = PixelAdjust(
2281 nMargin -
2283 mxObjectItem->GetEndY());
2284 mxObjectItem->SetEndY(nEndY);
2285
2286 pBindings->GetDispatcher()->ExecuteList(SID_RULER_OBJECT,
2287 SfxCallMode::RECORD, { mxObjectItem.get() });
2288}
2289
2291{
2292 /*
2293 Preparation proportional dragging, and it is calculated based on the
2294 proportional share of the total width in parts per thousand.
2295 */
2296 mxRulerImpl->nTotalDist = GetMargin2();
2297 switch(eType)
2298 {
2299 case RulerType::Margin2:
2300 case RulerType::Margin1:
2301 case RulerType::Border:
2302 {
2303 DBG_ASSERT(mxColumnItem, "no ColumnItem");
2304
2305 mxRulerImpl->SetPercSize(mxColumnItem->Count());
2306
2307 tools::Long lPos;
2308 tools::Long lWidth=0;
2309 sal_uInt16 nStart;
2310 sal_uInt16 nIdx=GetDragAryPos();
2311 tools::Long lActWidth=0;
2312 tools::Long lActBorderSum;
2313 tools::Long lOrigLPos;
2314
2315 if(eType != RulerType::Border)
2316 {
2317 lOrigLPos = GetMargin1();
2318 nStart = 0;
2319 lActBorderSum = 0;
2320 }
2321 else
2322 {
2323 if(mxRulerImpl->bIsTableRows &&!bHorz)
2324 {
2325 lOrigLPos = GetMargin1();
2326 nStart = 0;
2327 }
2328 else
2329 {
2330 lOrigLPos = mpBorders[nIdx].nPos + mpBorders[nIdx].nWidth;
2331 nStart = 1;
2332 }
2333 lActBorderSum = mpBorders[nIdx].nWidth;
2334 }
2335
2336 //in horizontal mode the percentage value has to be
2337 //calculated on a "current change" position base
2338 //because the height of the table changes while dragging
2339 if(mxRulerImpl->bIsTableRows && RulerType::Border == eType)
2340 {
2341 sal_uInt16 nStartBorder;
2342 sal_uInt16 nEndBorder;
2343 if(bHorz)
2344 {
2345 nStartBorder = nIdx + 1;
2346 nEndBorder = mxColumnItem->Count() - 1;
2347 }
2348 else
2349 {
2350 nStartBorder = 0;
2351 nEndBorder = nIdx;
2352 }
2353
2354 lWidth = mpBorders[nIdx].nPos;
2355 if(bHorz)
2356 lWidth = GetMargin2() - lWidth;
2357 mxRulerImpl->nTotalDist = lWidth;
2358 lPos = mpBorders[nIdx].nPos;
2359
2360 for(sal_uInt16 i = nStartBorder; i < nEndBorder; ++i)
2361 {
2362 if(bHorz)
2363 {
2364 lActWidth += mpBorders[i].nPos - lPos;
2365 lPos = mpBorders[i].nPos + mpBorders[i].nWidth;
2366 }
2367 else
2368 lActWidth = mpBorders[i].nPos;
2369 mxRulerImpl->pPercBuf[i] = static_cast<sal_uInt16>((lActWidth * 1000)
2370 / mxRulerImpl->nTotalDist);
2371 mxRulerImpl->pBlockBuf[i] = static_cast<sal_uInt16>(lActBorderSum);
2372 lActBorderSum += mpBorders[i].nWidth;
2373 }
2374 }
2375 else
2376 {
2377 lPos = lOrigLPos;
2378 for(sal_uInt16 ii = nStart; ii < mxColumnItem->Count() - 1; ++ii)
2379 {
2380 lWidth += mpBorders[ii].nPos - lPos;
2381 lPos = mpBorders[ii].nPos + mpBorders[ii].nWidth;
2382 }
2383
2384 lWidth += GetMargin2() - lPos;
2385 mxRulerImpl->nTotalDist = lWidth;
2386 lPos = lOrigLPos;
2387
2388 for(sal_uInt16 i = nStart; i < mxColumnItem->Count() - 1; ++i)
2389 {
2390 lActWidth += mpBorders[i].nPos - lPos;
2391 lPos = mpBorders[i].nPos + mpBorders[i].nWidth;
2392 mxRulerImpl->pPercBuf[i] = static_cast<sal_uInt16>((lActWidth * 1000)
2393 / mxRulerImpl->nTotalDist);
2394 mxRulerImpl->pBlockBuf[i] = static_cast<sal_uInt16>(lActBorderSum);
2395 lActBorderSum += mpBorders[i].nWidth;
2396 }
2397 }
2398 }
2399 break;
2400 case RulerType::Tab:
2401 {
2402 const sal_uInt16 nIdx = GetDragAryPos()+TAB_GAP;
2403 mxRulerImpl->nTotalDist -= mpTabs[nIdx].nPos;
2404 mxRulerImpl->SetPercSize(nTabCount);
2405 for(sal_uInt16 n=0;n<=nIdx;mxRulerImpl->pPercBuf[n++]=0) ;
2406 for(sal_uInt16 i = nIdx+1; i < nTabCount; ++i)
2407 {
2408 const tools::Long nDelta = mpTabs[i].nPos - mpTabs[nIdx].nPos;
2409 mxRulerImpl->pPercBuf[i] = static_cast<sal_uInt16>((nDelta * 1000) / mxRulerImpl->nTotalDist);
2410 }
2411 break;
2412 }
2413 default: break;
2414 }
2415}
2416
2418{
2419 /*
2420 Eval Drag Modifier
2421 Shift: move linear
2422 Control: move proportional
2423 Shift + Control: Table: only current line
2424 Alt: disable snapping
2425 Alt + Shift: coarse snapping
2426 */
2427
2428 sal_uInt16 nModifier = GetDragModifier();
2429 if(mxRulerImpl->bIsTableRows)
2430 {
2431 //rows can only be moved in one way, additionally current column is possible
2432 if(nModifier == KEY_SHIFT)
2433 nModifier = 0;
2434 }
2435
2436 switch(nModifier)
2437 {
2438 case KEY_SHIFT:
2440 break;
2441 case KEY_MOD2 | KEY_SHIFT:
2442 mbCoarseSnapping = true;
2443 break;
2444 case KEY_MOD2:
2445 mbSnapping = false;
2446 break;
2447 case KEY_MOD1:
2448 {
2449 const RulerType eType = GetDragType();
2451 if( RulerType::Tab == eType ||
2452 ( ( RulerType::Border == eType ||
2453 RulerType::Margin1 == eType ||
2454 RulerType::Margin2 == eType ) &&
2455 mxColumnItem ) )
2456 {
2458 }
2459 }
2460 break;
2461 case KEY_MOD1 | KEY_SHIFT:
2462 if( GetDragType() != RulerType::Margin1 &&
2463 GetDragType() != RulerType::Margin2 )
2464 {
2466 }
2467 break;
2468 }
2469}
2470
2472{
2473 /* Override handler SV; sets Tab per dispatcher call */
2474 Ruler::Click();
2475 if( bActive )
2476 {
2477 pBindings->Update( SID_RULER_LR_MIN_MAX );
2478 pBindings->Update( SID_ATTR_LONG_ULSPACE );
2479 pBindings->Update( SID_ATTR_LONG_LRSPACE );
2480 pBindings->Update( SID_RULER_PAGE_POS );
2481 pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
2482 pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
2483 pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
2484 pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
2485 pBindings->Update( SID_RULER_OBJECT );
2486 pBindings->Update( SID_RULER_PROTECT );
2487 pBindings->Update( SID_ATTR_PARA_LRSPACE_VERTICAL );
2488 }
2489 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2490 if(!(mxTabStopItem &&
2492 return;
2493
2494 bool bContentProtected = mxRulerImpl->aProtectItem->IsContentProtected();
2495 if( bContentProtected ) return;
2496 const tools::Long lPos = GetClickPos();
2497 if(!((bRTL && lPos < std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos > GetRightIndent()) ||
2498 (!bRTL && lPos > std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos < GetRightIndent())))
2499 return;
2500
2501 //convert position in left-to-right text
2502 tools::Long nTabPos;
2503//#i24363# tab stops relative to indent
2504 if(bRTL)
2505 nTabPos = ( mxRulerImpl->bIsTabsRelativeToIndent ?
2506 GetLeftIndent() :
2508 lPos;
2509 else
2510 nTabPos = lPos -
2511 ( mxRulerImpl->bIsTabsRelativeToIndent ?
2512 GetLeftIndent() :
2514
2515 SvxTabStop aTabStop(ConvertHPosLogic(nTabPos),
2517 mxTabStopItem->Insert(aTabStop);
2518 UpdateTabs();
2519}
2520
2522{
2523 /*
2524 Calculates the limits for dragging; which are in pixels relative to the
2525 page edge
2526 */
2527 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
2529 mxRulerImpl->lMaxLeftLogic=mxRulerImpl->lMaxRightLogic=-1;
2530 switch(GetDragType())
2531 {
2532 case RulerType::Margin1:
2533 { // left edge of the surrounding Frame
2534 // DragPos - NOf between left - right
2535 mxRulerImpl->lMaxLeftLogic = GetLeftMin();
2536 nMaxLeft=ConvertSizePixel(mxRulerImpl->lMaxLeftLogic);
2537
2538 if (!mxColumnItem || mxColumnItem->Count() == 1)
2539 {
2540 if(bRTL)
2541 {
2542 nMaxRight = lNullPix - GetRightIndent() +
2543 std::max(GetFirstLineIndent(), GetLeftIndent()) -
2544 glMinFrame;
2545 }
2546 else
2547 {
2548 nMaxRight = lNullPix + GetRightIndent() -
2549 std::max(GetFirstLineIndent(), GetLeftIndent()) -
2550 glMinFrame;
2551 }
2552 }
2553 else if(mxRulerImpl->bIsTableRows)
2554 {
2555 //top border is not moveable when table rows are displayed
2556 // protection of content means the margin is not moveable
2557 if(bHorz && !mxRulerImpl->aProtectItem->IsContentProtected())
2558 {
2559 nMaxLeft = mpBorders[0].nMinPos + lNullPix;
2561 nMaxRight = GetRightIndent() + lNullPix -
2562 (mxColumnItem->Count() - 1 ) * glMinFrame;
2563 else
2564 nMaxRight = mpBorders[0].nPos - glMinFrame + lNullPix;
2565 }
2566 else
2567 nMaxLeft = nMaxRight = lNullPix;
2568 }
2569 else
2570 {
2572 {
2573 nMaxRight=lNullPix+CalcPropMaxRight();
2574 }
2576 {
2578 GetPageWidth() - (
2579 (mxColumnItem->IsTable() && mxLRSpaceItem)
2580 ? mxLRSpaceItem->GetRight() : 0))
2581 - GetMargin2() + GetMargin1();
2582 }
2583 else
2584 {
2585 nMaxRight = lNullPix - glMinFrame;
2586 if (mxColumnItem->IsFirstAct())
2587 {
2588 if(bRTL)
2589 {
2590 nMaxRight += std::min(
2591 mpBorders[0].nPos,
2593 }
2594 else
2595 {
2596 nMaxRight += std::min(
2598 std::max(GetFirstLineIndent(), GetLeftIndent()));
2599 }
2600 }
2601 else if ( mxColumnItem->Count() > 1 )
2602 {
2603 nMaxRight += mpBorders[0].nPos;
2604 }
2605 else
2606 {
2608 }
2609 // Do not drag the left table edge over the edge of the page
2610 if(mxLRSpaceItem && mxColumnItem->IsTable())
2611 {
2613 if(nTmp>nMaxLeft)
2614 nMaxLeft=nTmp;
2615 }
2616 }
2617 }
2618 break;
2619 }
2620 case RulerType::Margin2:
2621 { // right edge of the surrounding Frame
2622 mxRulerImpl->lMaxRightLogic
2624 nMaxRight = ConvertSizePixel(mxRulerImpl->lMaxRightLogic);
2625
2626 if (!mxColumnItem)
2627 {
2628 if(bRTL)
2629 {
2632 glMinFrame + lNullPix;
2633 }
2634 else
2635 {
2638 glMinFrame + lNullPix;
2639 }
2640 }
2641 else if(mxRulerImpl->bIsTableRows)
2642 {
2643 // get the bottom move range from the last border position - only available for rows!
2644 // protection of content means the margin is not moveable
2645 if(bHorz || mxRulerImpl->aProtectItem->IsContentProtected())
2646 {
2647 nMaxLeft = nMaxRight = mpBorders[mxColumnItem->Count() - 1].nMaxPos + lNullPix;
2648 }
2649 else
2650 {
2652 {
2653 nMaxLeft = (mxColumnItem->Count()) * glMinFrame + lNullPix;
2654 }
2655 else
2656 {
2657 if(mxColumnItem->Count() > 1)
2658 nMaxLeft = mpBorders[mxColumnItem->Count() - 2].nPos + glMinFrame + lNullPix;
2659 else
2660 nMaxLeft = glMinFrame + lNullPix;
2661 }
2662 if(mxColumnItem->Count() > 1)
2663 nMaxRight = mpBorders[mxColumnItem->Count() - 2].nMaxPos + lNullPix;
2664 else
2665 nMaxRight -= GetRightIndent() - lNullPix;
2666 }
2667 }
2668 else
2669 {
2670 nMaxLeft = glMinFrame + lNullPix;
2671 if(IsActLastColumn() || mxColumnItem->Count() < 2 ) //If last active column
2672 {
2673 if(bRTL)
2674 {
2675 nMaxLeft = glMinFrame + lNullPix + GetMargin2() +
2676 GetRightIndent() - std::max(GetFirstLineIndent(),
2677 GetLeftIndent());
2678 }
2679 else
2680 {
2681 nMaxLeft = glMinFrame + lNullPix + GetMargin2() -
2682 GetRightIndent() + std::max(GetFirstLineIndent(),
2683 GetLeftIndent());
2684 }
2685 }
2686 if( mxColumnItem->Count() >= 2 )
2687 {
2688 tools::Long nNewMaxLeft =
2689 glMinFrame + lNullPix +
2690 mpBorders[mxColumnItem->Count() - 2].nPos +
2691 mpBorders[mxColumnItem->Count() - 2].nWidth;
2692 nMaxLeft = std::max(nMaxLeft, nNewMaxLeft);
2693 }
2694
2695 }
2696 break;
2697 }
2698 case RulerType::Border:
2699 { // Table, column (Modifier)
2700 const sal_uInt16 nIdx = GetDragAryPos();
2701 switch(GetDragSize())
2702 {
2703 case RulerDragSize::N1 :
2704 {
2705 nMaxRight = mpBorders[nIdx].nPos +
2706 mpBorders[nIdx].nWidth + lNullPix;
2707
2708 if(0 == nIdx)
2709 nMaxLeft = lNullPix;
2710 else
2711 nMaxLeft = mpBorders[nIdx - 1].nPos + mpBorders[nIdx - 1].nWidth + lNullPix;
2712 if (mxColumnItem && nIdx == mxColumnItem->GetActColumn())
2713 {
2714 if(bRTL)
2715 {
2716 nMaxLeft += mpBorders[nIdx].nPos +
2717 GetRightIndent() - std::max(GetFirstLineIndent(),
2718 GetLeftIndent());
2719 }
2720 else
2721 {
2722 nMaxLeft += mpBorders[nIdx].nPos -
2723 GetRightIndent() + std::max(GetFirstLineIndent(),
2724 GetLeftIndent());
2725 }
2726 if(0 != nIdx)
2727 nMaxLeft -= mpBorders[nIdx-1].nPos +
2728 mpBorders[nIdx-1].nWidth;
2729 }
2732 break;
2733 }
2734 case RulerDragSize::Move:
2735 {
2736 if (mxColumnItem)
2737 {
2738 //nIdx contains the position of the currently moved item
2739 //next visible separator on the left
2740 sal_uInt16 nLeftCol=GetActLeftColumn(false, nIdx);
2741 //next visible separator on the right
2742 sal_uInt16 nRightCol=GetActRightColumn(false, nIdx);
2743 //next separator on the left - regardless if visible or not
2744 sal_uInt16 nActLeftCol=GetActLeftColumn();
2745 //next separator on the right - regardless if visible or not
2746 sal_uInt16 nActRightCol=GetActRightColumn();
2747 if(mxColumnItem->IsTable())
2748 {
2750 {
2751 //the current row/column should be modified only
2752 //then the next/previous visible border position
2753 //marks the min/max positions
2754 nMaxLeft = nLeftCol == USHRT_MAX ?
2755 0 :
2756 mpBorders[nLeftCol].nPos;
2757 //rows can always be increased without a limit
2758 if(mxRulerImpl->bIsTableRows)
2759 nMaxRight = mpBorders[nIdx].nMaxPos;
2760 else
2761 nMaxRight = nRightCol == USHRT_MAX ?
2762 GetMargin2():
2763 mpBorders[nRightCol].nPos;
2764 nMaxLeft += lNullPix;
2765 nMaxRight += lNullPix;
2766 }
2767 else
2768 {
2770 nMaxLeft = (nIdx + 1) * glMinFrame + lNullPix;
2771 else
2772 nMaxLeft = mpBorders[nIdx].nMinPos + lNullPix;
2775 {
2776 if(mxRulerImpl->bIsTableRows)
2777 {
2778 if(bHorz)
2779 nMaxRight = GetRightIndent() + lNullPix -
2780 (mxColumnItem->Count() - nIdx - 1) * glMinFrame;
2781 else
2782 nMaxRight = mpBorders[nIdx].nMaxPos + lNullPix;
2783 }
2784 else
2785 nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
2786 }
2787 else
2788 nMaxRight = mpBorders[nIdx].nMaxPos + lNullPix;
2789 }
2792
2793 }
2794 else
2795 {
2796 if(nLeftCol==USHRT_MAX)
2797 nMaxLeft=lNullPix;
2798 else
2799 nMaxLeft = mpBorders[nLeftCol].nPos +
2800 mpBorders[nLeftCol].nWidth + lNullPix;
2801
2802 if(nActRightCol == nIdx)
2803 {
2804 if(bRTL)
2805 {
2806 nMaxLeft += mpBorders[nIdx].nPos +
2807 GetRightIndent() - std::max(GetFirstLineIndent(),
2808 GetLeftIndent());
2809 if(nActLeftCol!=USHRT_MAX)
2810 nMaxLeft -= mpBorders[nActLeftCol].nPos +
2811 mpBorders[nActLeftCol].nWidth;
2812 }
2813 else
2814 {
2815 nMaxLeft += mpBorders[nIdx].nPos -
2816 GetRightIndent() + std::max(GetFirstLineIndent(),
2817 GetLeftIndent());
2818 if(nActLeftCol!=USHRT_MAX)
2819 nMaxLeft -= mpBorders[nActLeftCol].nPos +
2820 mpBorders[nActLeftCol].nWidth;
2821 }
2822 }
2825
2826 // nMaxRight
2827 // linear / proportional move
2830 {
2831 nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
2832 }
2834 {
2835 nMaxRight = lNullPix + GetMargin2() - GetMargin1() +
2836 (mpBorders.size() - nIdx - 1) * glMinFrame;
2837 }
2838 else
2839 {
2840 if(nRightCol==USHRT_MAX)
2841 { // last column
2842 nMaxRight = GetMargin2() + lNullPix;
2843 if(IsActLastColumn())
2844 {
2845 if(bRTL)
2846 {
2847 nMaxRight -=
2849 std::max(GetFirstLineIndent(),
2850 GetLeftIndent());
2851 }
2852 else
2853 {
2854 nMaxRight -=
2856 std::max(GetFirstLineIndent(),
2857 GetLeftIndent());
2858 }
2859 nMaxRight += mpBorders[nIdx].nPos +
2860 mpBorders[nIdx].nWidth;
2861 }
2862 }
2863 else
2864 {
2865 nMaxRight = lNullPix + mpBorders[nRightCol].nPos;
2866 sal_uInt16 nNotHiddenRightCol =
2867 GetActRightColumn(true, nIdx);
2868
2869 if( nActLeftCol == nIdx )
2870 {
2871 tools::Long nBorder = nNotHiddenRightCol ==
2872 USHRT_MAX ?
2873 GetMargin2() :
2874 mpBorders[nNotHiddenRightCol].nPos;
2875 if(bRTL)
2876 {
2878 std::max(GetFirstLineIndent(),
2879 GetLeftIndent());
2880 }
2881 else
2882 {
2884 std::max(GetFirstLineIndent(),
2885 GetLeftIndent());
2886 }
2887 nMaxRight += mpBorders[nIdx].nPos +
2888 mpBorders[nIdx].nWidth;
2889 }
2890 }
2892 nMaxRight -= mpBorders[nIdx].nWidth;
2893 }
2894 }
2895 }
2896 // ObjectItem
2897 else
2898 {
2899 nMaxLeft = LONG_MIN;
2901 }
2902 break;
2903 }
2904 case RulerDragSize::N2:
2905 if (mxColumnItem)
2906 {
2907 nMaxLeft = lNullPix + mpBorders[nIdx].nPos;
2908 if(nIdx == mxColumnItem->Count()-2) { // last column
2909 nMaxRight = GetMargin2() + lNullPix;
2910 if(mxColumnItem->IsLastAct()) {
2911 nMaxRight -=
2913 std::max(GetFirstLineIndent(),
2914 GetLeftIndent());
2915 nMaxRight += mpBorders[nIdx].nPos +
2916 mpBorders[nIdx].nWidth;
2917 }
2918 }
2919 else {
2920 nMaxRight = lNullPix + mpBorders[nIdx+1].nPos;
2921 if(mxColumnItem->GetActColumn()-1 == nIdx) {
2922 nMaxRight -= mpBorders[nIdx+1].nPos - GetRightIndent() +
2923 std::max(GetFirstLineIndent(),
2924 GetLeftIndent());
2925 nMaxRight += mpBorders[nIdx].nPos +
2926 mpBorders[nIdx].nWidth;
2927 }
2928 }
2930 nMaxRight -= mpBorders[nIdx].nWidth;
2931 break;
2932 }
2933 }
2935 break;
2936 }
2937 case RulerType::Indent:
2938 {
2939 const sal_uInt16 nIdx = GetDragAryPos();
2940 switch(nIdx) {
2943 {
2944 if(bRTL)
2945 {
2946 nMaxLeft = lNullPix + GetRightIndent();
2947
2948 if(mxColumnItem && !mxColumnItem->IsFirstAct())
2949 nMaxLeft += mpBorders[mxColumnItem->GetActColumn()-1].nPos +
2950 mpBorders[mxColumnItem->GetActColumn()-1].nWidth;
2951 nMaxRight = lNullPix + GetMargin2();
2952
2953 // Dragging along
2954 if((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
2956 {
2959 else
2961 }
2962 }
2963 else
2964 {
2965 nMaxLeft = lNullPix;
2966
2967 if(mxColumnItem && !mxColumnItem->IsFirstAct())
2968 nMaxLeft += mpBorders[mxColumnItem->GetActColumn()-1].nPos +
2969 mpBorders[mxColumnItem->GetActColumn()-1].nWidth;
2970 nMaxRight = lNullPix + GetRightIndent() - glMinFrame;
2971
2972 // Dragging along
2973 if((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
2975 {
2978 else
2980 }
2981 }
2982 }
2983 break;
2985 {
2986 if(bRTL)
2987 {
2988 nMaxLeft = lNullPix;
2989 nMaxRight = lNullPix + std::min(GetFirstLineIndent(), GetLeftIndent()) - glMinFrame;
2990 if (mxColumnItem)
2991 {
2992 sal_uInt16 nRightCol=GetActRightColumn( true );
2993 if(!IsActLastColumn( true ))
2994 nMaxRight += mpBorders[nRightCol].nPos;
2995 else
2996 nMaxRight += GetMargin2();
2997 }
2998 else
2999 {
3000 nMaxLeft += GetMargin1();
3001 }
3003 }
3004 else
3005 {
3006 nMaxLeft = lNullPix +
3007 std::max(GetFirstLineIndent(), GetLeftIndent());
3008 nMaxRight = lNullPix;
3009 if (mxColumnItem)
3010 {
3011 sal_uInt16 nRightCol=GetActRightColumn( true );
3012 if(!IsActLastColumn( true ))
3013 nMaxRight += mpBorders[nRightCol].nPos;
3014 else
3015 nMaxRight += GetMargin2();
3016 }
3017 else
3018 nMaxRight += GetMargin2();
3020 }
3021 }
3022 break;
3023 }
3024 break;
3025 }
3026 case RulerType::Tab: // Tabs (Modifier)
3027 /* left = NOf + Max(LAR, EZ)
3028 right = NOf + RAR */
3029
3030 if (bRTL)
3031 nMaxLeft = lNullPix + GetRightIndent();
3032 else
3033 nMaxLeft = lNullPix + std::min(GetFirstLineIndent(), GetLeftIndent());
3034
3035 mxRulerImpl->lMaxRightLogic = GetLogicRightIndent() + lLogicNullOffset;
3036 nMaxRight = ConvertSizePixel(mxRulerImpl->lMaxRightLogic);
3037 break;
3038 default: ; //prevent warning
3039 }
3040}
3041
3043{
3044 /*
3045 Beginning of a drag operation (SV-handler) evaluates modifier and
3046 calculated values
3047
3048 [Cross-reference]
3049
3050 <SvxRuler::EvalModifier()>
3051 <SvxRuler::CalcMinMax()>
3052 <SvxRuler::EndDrag()>
3053 */
3054 bool bContentProtected = mxRulerImpl->aProtectItem->IsContentProtected();
3055
3056 if(!bValid)
3057 return false;
3058
3059 mxRulerImpl->lLastLMargin = GetMargin1();
3060 mxRulerImpl->lLastRMargin = GetMargin2();
3061
3062 bool bOk = true;
3063
3065 switch(GetDragType())
3066 {
3067 case RulerType::Margin1: // left edge of the surrounding Frame
3068 case RulerType::Margin2: // right edge of the surrounding Frame
3069 if((bHorz && mxLRSpaceItem) || (!bHorz && mxULSpaceItem))
3070 {
3071 if (!mxColumnItem)
3072 EvalModifier();
3073 else
3075 }
3076 else
3077 {
3078 bOk = false;
3079 }
3080 break;
3081 case RulerType::Border: // Table, column (Modifier)
3082 if (mxColumnItem)
3083 {
3084 nDragOffset = 0;
3085 if (!mxColumnItem->IsTable())
3087 EvalModifier();
3088 }
3089 else
3090 nDragOffset = 0;
3091 break;
3092 case RulerType::Indent: // Paragraph indents (Modifier)
3093 {
3094 if( bContentProtected )
3095 return false;
3096 if(INDENT_LEFT_MARGIN == GetDragAryPos() + INDENT_GAP) { // Left paragraph indent
3098 EvalModifier();
3099 }
3100 else
3101 {
3103 }
3105 break;
3106 }
3107 case RulerType::Tab: // Tabs (Modifier)
3108 if( bContentProtected )
3109 return false;
3110 EvalModifier();
3111 mpTabs[0] = mpTabs[GetDragAryPos() + 1];
3112 mpTabs[0].nStyle |= RULER_STYLE_DONTKNOW;
3113 break;
3114 default:
3116 }
3117
3118 if(bOk)
3119 CalcMinMax();
3120
3121 return bOk;
3122}
3123
3125{
3126 /* SV-Draghandler */
3127 if(IsDragCanceled())
3128 {
3129 Ruler::Drag();
3130 return;
3131 }
3132 switch(GetDragType()) {
3133 case RulerType::Margin1: // left edge of the surrounding Frame
3134 DragMargin1();
3135 mxRulerImpl->lLastLMargin = GetMargin1();
3136 break;
3137 case RulerType::Margin2: // right edge of the surrounding Frame
3138 DragMargin2();
3139 mxRulerImpl->lLastRMargin = GetMargin2();
3140 break;
3141 case RulerType::Indent: // Paragraph indents
3142 DragIndents();
3143 break;
3144 case RulerType::Border: // Table, columns
3145 if (mxColumnItem)
3146 DragBorders();
3147 else if (mxObjectItem)
3149 break;
3150 case RulerType::Tab: // Tabs
3151 DragTabs();
3152 break;
3153 default:
3154 break; //prevent warning
3155 }
3156 Ruler::Drag();
3157}
3158
3160{
3161 /*
3162 SV-handler; is called when ending the dragging. Triggers the updating of data
3163 on the application, by calling the respective Apply...() methods to send the
3164 data to the application.
3165 */
3166 const bool bUndo = IsDragCanceled();
3167 const tools::Long lPos = GetDragPos();
3169 lTabPos = -1;
3170
3171 if(!bUndo)
3172 {
3173 switch(GetDragType())
3174 {
3175 case RulerType::Margin1: // upper left edge of the surrounding Frame
3176 case RulerType::Margin2: // lower right edge of the surrounding Frame
3177 {
3178 if (!mxColumnItem || !mxColumnItem->IsTable())
3179 ApplyMargins();
3180
3181 if(mxColumnItem &&
3182 (mxColumnItem->IsTable() ||
3184 ApplyBorders();
3185
3186 }
3187 break;
3188 case RulerType::Border: // Table, columns
3189 if(lInitialDragPos != lPos ||
3190 (mxRulerImpl->bIsTableRows && bHorz)) //special case - the null offset is changed here
3191 {
3192 if (mxColumnItem)
3193 {
3194 ApplyBorders();
3195 if(bHorz)
3196 UpdateTabs();
3197 }
3198 else if (mxObjectItem)
3199 ApplyObject();
3200 }
3201 break;
3202 case RulerType::Indent: // Paragraph indents
3203 if(lInitialDragPos != lPos)
3204 ApplyIndents();
3206 break;
3207 case RulerType::Tab: // Tabs
3208 {
3209 ApplyTabs();
3210 mpTabs[GetDragAryPos()].nStyle &= ~RULER_STYLE_INVISIBLE;
3211 SetTabs(nTabCount, mpTabs.data() + TAB_GAP);
3212 }
3213 break;
3214 default:
3215 break; //prevent warning
3216 }
3217 }
3219
3220 mbCoarseSnapping = false;
3221 mbSnapping = true;
3222
3224 if(bUndo)
3225 {
3226 for(sal_uInt16 i = 0; i < mxRulerImpl->nControllerItems; i++)
3227 {
3228 pCtrlItems[i]->ClearCache();
3229 pCtrlItems[i]->GetBindings().Invalidate(pCtrlItems[i]->GetId());
3230 }
3231 }
3232}
3233
3235{
3236 /* Override SV method, sets the new type for the Default tab. */
3237
3238 // Switch Tab Type
3239 if(mxTabStopItem &&
3241 {
3242 ++nDefTabType;
3245 SetExtraType(RulerExtra::Tab, nDefTabType);
3246 }
3248}
3249
3251{
3252 /*
3253 Report through the bindings that the status update is completed. The ruler
3254 updates its appearance and gets registered again in the bindings.
3255 */
3256
3257 // start update
3258 if (bActive && rHint.GetId() == SfxHintId::UpdateDone)
3259 {
3260 Update();
3262 bValid = true;
3263 bListening = false;
3264 }
3265}
3266
3267void SvxRuler::MenuSelect(std::string_view ident)
3268{
3269 if (ident.empty())
3270 return;
3271 /* Handler of the context menus for switching the unit of measurement */
3273}
3274
3275void SvxRuler::TabMenuSelect(std::string_view rIdent)
3276{
3277 if (rIdent.empty())
3278 return;
3279 sal_Int32 nId = o3tl::toInt32(rIdent);
3280 /* Handler of the tab menu for setting the type */
3281 if (mxTabStopItem && mxTabStopItem->Count() > mxRulerImpl->nIdx)
3282 {
3283 SvxTabStop aTabStop = mxTabStopItem->At(mxRulerImpl->nIdx);
3284 aTabStop.GetAdjustment() = ToAttrTab_Impl(nId - 1);
3285 mxTabStopItem->Remove(mxRulerImpl->nIdx);
3286 mxTabStopItem->Insert(aTabStop);
3287 sal_uInt16 nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
3288 pBindings->GetDispatcher()->ExecuteList(nTabStopId,
3289 SfxCallMode::RECORD, { mxTabStopItem.get() });
3290 UpdateTabs();
3291 mxRulerImpl->nIdx = 0;
3292 }
3293}
3294
3296{
3297 RID_SVXSTR_RULER_TAB_LEFT,
3298 RID_SVXSTR_RULER_TAB_RIGHT,
3299 RID_SVXSTR_RULER_TAB_CENTER,
3300 RID_SVXSTR_RULER_TAB_DECIMAL
3301};
3302
3303void SvxRuler::Command( const CommandEvent& rCommandEvent )
3304{
3305 /* Mouse context menu for switching the unit of measurement */
3306 if ( CommandEventId::ContextMenu == rCommandEvent.GetCommand() )
3307 {
3308 CancelDrag();
3309
3310 tools::Rectangle aRect(rCommandEvent.GetMousePosPixel(), Size(1, 1));
3311 weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
3312 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "svx/ui/rulermenu.ui"));
3313 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
3314
3315 bool bRTL = mxRulerImpl->pTextRTLItem && mxRulerImpl->pTextRTLItem->GetValue();
3316 if ( !mpTabs.empty() &&
3317 RulerType::Tab ==
3318 GetRulerType( rCommandEvent.GetMousePosPixel(), &mxRulerImpl->nIdx ) &&
3319 mpTabs[mxRulerImpl->nIdx + TAB_GAP].nStyle < RULER_TAB_DEFAULT )
3320 {
3321 xMenu->clear();
3322
3323 const Size aSz(ruler_tab_svx.width + 2, ruler_tab_svx.height + 2);
3324 const Point aPt(aSz.Width() / 2, aSz.Height() / 2);
3325
3326 for ( sal_uInt16 i = RULER_TAB_LEFT; i < RULER_TAB_DEFAULT; ++i )
3327 {
3329 xDev->SetOutputSize(aSz);
3330
3331 sal_uInt16 nStyle = bRTL ? i|RULER_TAB_RTL : i;
3332 nStyle |= static_cast<sal_uInt16>(bHorz ? WB_HORZ : WB_VERT);
3333
3334 Color aFillColor(xDev->GetSettings().GetStyleSettings().GetShadowColor());
3335 DrawTab(*xDev, aFillColor, aPt, nStyle);
3336
3337 OString sId(OString::number(i + 1));
3338 xMenu->insert(-1, OUString::fromUtf8(sId), SvxResId(RID_SVXSTR_RULER_TAB[i]),
3339 nullptr, xDev.get(), nullptr, TRISTATE_TRUE);
3340 xMenu->set_active(sId, i == mpTabs[mxRulerImpl->nIdx + TAB_GAP].nStyle);
3341 }
3342 TabMenuSelect(xMenu->popup_at_rect(pPopupParent, aRect));
3343 }
3344 else
3345 {
3346 FieldUnit eUnit = GetUnit();
3347 const int nCount = xMenu->n_children();
3348
3349 bool bReduceMetric = bool(nFlags & SvxRulerSupportFlags::REDUCED_METRIC);
3350 for ( sal_uInt16 i = nCount; i; --i )
3351 {
3352 OString sIdent = xMenu->get_id(i - 1);
3353 FieldUnit eMenuUnit = vcl::EnglishStringToMetric(sIdent);
3354 xMenu->set_active(sIdent, eMenuUnit == eUnit);
3355 if( bReduceMetric )
3356 {
3357 if (eMenuUnit == FieldUnit::M ||
3358 eMenuUnit == FieldUnit::KM ||
3359 eMenuUnit == FieldUnit::FOOT ||
3360 eMenuUnit == FieldUnit::MILE)
3361 {
3362 xMenu->remove(sIdent);
3363 }
3364 else if (( eMenuUnit == FieldUnit::CHAR ) && !bHorz )
3365 {
3366 xMenu->remove(sIdent);
3367 }
3368 else if (( eMenuUnit == FieldUnit::LINE ) && bHorz )
3369 {
3370 xMenu->remove(sIdent);
3371 }
3372 }
3373 }
3374 MenuSelect(xMenu->popup_at_rect(pPopupParent, aRect));
3375 }
3376 }
3377 else
3378 {
3379 Ruler::Command( rCommandEvent );
3380 }
3381}
3382
3384 bool bForceDontConsiderHidden,
3385 sal_uInt16 nAct ) const
3386{
3387 if( nAct == USHRT_MAX )
3388 nAct = mxColumnItem->GetActColumn();
3389 else
3390 nAct++; //To be able to pass on the ActDrag
3391
3392 bool bConsiderHidden = !bForceDontConsiderHidden &&
3394
3395 while( nAct < mxColumnItem->Count() - 1 )
3396 {
3397 if (mxColumnItem->At(nAct).bVisible || bConsiderHidden)
3398 return nAct;
3399 else
3400 nAct++;
3401 }
3402 return USHRT_MAX;
3403}
3404
3406 bool bForceDontConsiderHidden,
3407 sal_uInt16 nAct ) const
3408{
3409 if(nAct == USHRT_MAX)
3410 nAct = mxColumnItem->GetActColumn();
3411
3412 sal_uInt16 nLeftOffset = 1;
3413
3414 bool bConsiderHidden = !bForceDontConsiderHidden &&
3416
3417 while(nAct >= nLeftOffset)
3418 {
3419 if (mxColumnItem->At(nAct - nLeftOffset).bVisible || bConsiderHidden)
3420 return nAct - nLeftOffset;
3421 else
3422 nLeftOffset++;
3423 }
3424 return USHRT_MAX;
3425}
3426
3428 bool bForceDontConsiderHidden,
3429 sal_uInt16 nAct) const
3430{
3431 return GetActRightColumn(bForceDontConsiderHidden, nAct) == USHRT_MAX;
3432}
3433
3435 bool bForceDontConsiderHidden,
3436 sal_uInt16 nAct) const
3437{
3438 return GetActLeftColumn(bForceDontConsiderHidden, nAct) == USHRT_MAX;
3439}
3440
3442{
3443
3445 {
3446 // Remove the minimum width for all affected columns
3447 // starting from the right edge
3448 tools::Long _nMaxRight = GetMargin2() - GetMargin1();
3449
3450 tools::Long lFences = 0;
3451 tools::Long lMinSpace = USHRT_MAX;
3452 tools::Long lOldPos;
3453 tools::Long lColumns = 0;
3454
3455 sal_uInt16 nStart;
3456 if(!mxColumnItem->IsTable())
3457 {
3458 if(nCol == USHRT_MAX)
3459 {
3460 lOldPos = GetMargin1();
3461 nStart = 0;
3462 }
3463 else
3464 {
3465 lOldPos = mpBorders[nCol].nPos + mpBorders[nCol].nWidth;
3466 nStart = nCol + 1;
3467 lFences = mpBorders[nCol].nWidth;
3468 }
3469
3470 for(size_t i = nStart; i < mpBorders.size() - 1; ++i)
3471 {
3472 tools::Long lWidth = mpBorders[i].nPos - lOldPos;
3473 lColumns += lWidth;
3474 if(lWidth < lMinSpace)
3475 lMinSpace = lWidth;
3476 lOldPos = mpBorders[i].nPos + mpBorders[i].nWidth;
3477 lFences += mpBorders[i].nWidth;
3478 }
3479 tools::Long lWidth = GetMargin2() - lOldPos;
3480 lColumns += lWidth;
3481 if(lWidth < lMinSpace)
3482 lMinSpace = lWidth;
3483 }
3484 else
3485 {
3486 sal_uInt16 nActCol;
3487 if(nCol == USHRT_MAX) //CalcMinMax for LeftMargin
3488 {
3489 lOldPos = GetMargin1();
3490 }
3491 else
3492 {
3493 lOldPos = mpBorders[nCol].nPos;
3494 }
3495 lColumns = GetMargin2()-lOldPos;
3496 nActCol = nCol;
3497 lFences = 0;
3498 while(nActCol < mpBorders.size() || nActCol == USHRT_MAX)
3499 {
3500 sal_uInt16 nRight;
3501 if(nActCol == USHRT_MAX)
3502 {
3503 nRight = 0;
3504 while (!(*mxColumnItem)[nRight].bVisible)
3505 {
3506 nRight++;
3507 }
3508 }
3509 else
3510 {
3511 nRight = GetActRightColumn(false, nActCol);
3512 }
3513
3514 tools::Long lWidth;
3515 if(nRight != USHRT_MAX)
3516 {
3517 lWidth = mpBorders[nRight].nPos - lOldPos;
3518 lOldPos = mpBorders[nRight].nPos;
3519 }
3520 else
3521 {
3522 lWidth=GetMargin2() - lOldPos;
3523 }
3524 nActCol = nRight;
3525 if(lWidth < lMinSpace)
3526 lMinSpace = lWidth;
3527 if(nActCol == USHRT_MAX)
3528 break;
3529 }
3530 }
3531
3532 _nMaxRight -= static_cast<tools::Long>(lFences + glMinFrame / static_cast<float>(lMinSpace) * lColumns);
3533 return _nMaxRight;
3534 }
3535 else
3536 {
3537 if(mxColumnItem->IsTable())
3538 {
3539 sal_uInt16 nVisCols = 0;
3540 for(size_t i = GetActRightColumn(false, nCol); i < mpBorders.size();)
3541 {
3542 if ((*mxColumnItem)[i].bVisible)
3543 nVisCols++;
3544 i = GetActRightColumn(false, i);
3545 }
3546 return GetMargin2() - GetMargin1() - (nVisCols + 1) * glMinFrame;
3547 }
3548 else
3549 {
3550 tools::Long lWidth = 0;
3551 for(size_t i = nCol; i < mpBorders.size() - 1; i++)
3552 {
3553 lWidth += glMinFrame + mpBorders[i].nWidth;
3554 }
3555 return GetMargin2() - GetMargin1() - lWidth;
3556 }
3557 }
3558}
3559
3560// Tab stops relative to indent (#i24363#)
3562{
3563 mxRulerImpl->bIsTabsRelativeToIndent = bRel;
3564}
3565
3567{
3568 if (diffValue == 0)
3569 return;
3570
3572 AdjustMargin1(diffValue);
3573 else if (type == RulerChangeType::MARGIN2)
3574 SetMargin2( GetMargin2() - diffValue);
3575 ApplyMargins();
3576}
3577
3578/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
static bool GetLayoutRTL()
static std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false, sal_uInt64 nLOKWindowId=0)
CommandEventId GetCommand() const
const Point & GetMousePosPixel() const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void SetPagePos(tools::Long nOff=0, tools::Long nWidth=0)
virtual void MouseMove(const MouseEvent &rMEvt) override
void Activate() override
const MapMode & GetCurrentMapMode() const
sal_uInt16 GetDragModifier() const
tools::Long GetMargin1() const
void SetTabs(sal_uInt32 n=0, const RulerTab *pTabAry=nullptr)
bool IsDragCanceled() const
void SetNullOffset(tools::Long nPos)
RulerType GetDragType() const
bool IsDrag() const
const RulerSelection & GetHoverSelection() const
void SetWinPos(tools::Long nOff, tools::Long nWidth=0)
void SetMargin2()
tools::Long GetClickPos() const
bool IsDragDelete() const
virtual void EndDrag()
virtual void dispose() override
virtual void Drag()
tools::Long GetNullOffset() const
void SetLeftFrameMargin(tools::Long nPos)
void SetIndents(sal_uInt32 n=0, const RulerIndent *pIndentAry=nullptr)
void CancelDrag()
static void DrawTab(vcl::RenderContext &rRenderContext, const Color &rFillColor, const Point &rPos, sal_uInt16 nStyle)
void SetMargin1()
const RulerUnitData & GetCurrentRulerUnit() const
void SetExtraType(RulerExtra eNewExtraType, sal_uInt16 nStyle=0)
RulerDragSize GetDragSize() const
void SetRightFrameMargin(tools::Long nPos)
void SetBorders(sal_uInt32 n=0, const RulerBorder *pBrdAry=nullptr)
void Deactivate() override
tools::Long GetMargin2() const
FieldUnit GetUnit() const
void SetTextRTL(bool bRTL)
virtual void ExtraDown()
RulerType GetRulerType(const Point &rPos, sal_uInt16 *pAryPos=nullptr)
sal_uInt16 GetDragAryPos() const
void SetUnit(FieldUnit eNewUnit)
tools::Long GetDragPos() const
virtual void Click()
sal_uInt16 EnterRegistrations(const char *pFile=nullptr, int nLine=0)
void LeaveRegistrations(const char *pFile=nullptr, int nLine=0)
void Update(sal_uInt16 nId)
SfxDispatcher * GetDispatcher() const
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
SfxHintId GetId() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
sal_uInt16 Which() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
sal_uInt16 Count() const
Definition: rulritem.cxx:523
virtual SvxProtectItem * Clone(SfxItemPool *pPool=nullptr) const override
void AdjustMargin1(tools::Long lDiff)
Definition: svxruler.cxx:1331
tools::Long ConvertHSizePixel(tools::Long lSize) const
Definition: svxruler.cxx:351
std::unique_ptr< SvxLRSpaceItem > mxBorderItem
Definition: ruler.hxx:94
void UpdateObject()
Definition: svxruler.cxx:783
void DragMargin2()
Definition: svxruler.cxx:1449
virtual void MouseMove(const MouseEvent &rMEvt) override
Definition: svxruler.cxx:518
sal_uInt16 GetObjectBordersOff(sal_uInt16 nIdx) const
Definition: svxruler.cxx:425
void UpdatePage()
Definition: svxruler.cxx:898
std::vector< RulerBorder > mpObjectBorders
Definition: ruler.hxx:119
bool bValid
Definition: ruler.hxx:125
void SetDefTabDist(tools::Long)
Definition: svxruler.cxx:966
tools::Long nMaxRight
Definition: ruler.hxx:124
virtual void Command(const CommandEvent &rCEvt) override
Definition: svxruler.cxx:3303
tools::Long lLogicNullOffset
Definition: ruler.hxx:105
void MenuSelect(std::string_view ident)
Definition: svxruler.cxx:3267
void DrawLine_Impl(tools::Long &lTabPos, int, bool Horizontal)
Definition: svxruler.cxx:1517
UpdateType
Definition: ruler.hxx:226
tools::Long lInitialDragPos
Definition: ruler.hxx:107
void StartListening_Impl()
Definition: svxruler.cxx:632
bool bHorz
Definition: ruler.hxx:104
void ApplyTabs()
Definition: svxruler.cxx:2099
virtual void Drag() override
Definition: svxruler.cxx:3124
void UpdateFrameMinMax(const SfxRectangleItem *pItem)
Definition: svxruler.cxx:655
bool mbSnapping
Definition: ruler.hxx:130
void ApplyIndents()
Definition: svxruler.cxx:2003
tools::Long GetLogicRightIndent() const
Definition: svxruler.cxx:1193
tools::Long GetLeftFrameMargin() const
Definition: svxruler.cxx:1201
void DragBorders()
Definition: svxruler.cxx:1680
sal_uInt16 nDefTabType
Definition: ruler.hxx:110
void UpdateTabs()
Definition: svxruler.cxx:1001
void UpdateParaContents_Impl(tools::Long lDiff, UpdateType)
Definition: svxruler.cxx:1652
tools::Long ConvertPosLogic(tools::Long lPos) const
Definition: svxruler.cxx:391
tools::Long GetRightIndent() const
Definition: svxruler.cxx:1187
tools::Long GetFirstLineIndent() const
Definition: svxruler.cxx:1175
tools::Long PixelVAdjust(tools::Long lPos, tools::Long lPos2) const
Definition: svxruler.cxx:409
void ApplyMargins()
Definition: svxruler.cxx:1914
void CalcMinMax()
Definition: svxruler.cxx:2521
tools::Long RoundToCurrentMapMode(tools::Long lValue) const
Definition: svxruler.cxx:1993
void SetActive(bool bOn=true)
Definition: svxruler.cxx:1630
void ApplyObject()
Definition: svxruler.cxx:2251
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: svxruler.cxx:3250
virtual bool StartDrag() override
Definition: svxruler.cxx:3042
bool mbCoarseSnapping
Definition: ruler.hxx:129
sal_uInt16 nTabBufSize
Definition: ruler.hxx:112
tools::Long GetLeftIndent() const
Definition: svxruler.cxx:1181
bool bListening
Definition: ruler.hxx:126
tools::Long ConvertVSizeLogic(tools::Long lSize) const
Definition: svxruler.cxx:386
tools::Long ConvertPosPixel(tools::Long lPos) const
Definition: svxruler.cxx:361
tools::Long ConvertVPosLogic(tools::Long lPos) const
Definition: svxruler.cxx:376
void DragTabs()
Definition: svxruler.cxx:1574
tools::Long GetLeftMin() const
Definition: svxruler.cxx:1220
tools::Long GetRightMax() const
Definition: svxruler.cxx:1233
virtual ~SvxRuler() override
Definition: svxruler.cxx:280
virtual void Update()
Definition: svxruler.cxx:1140
tools::Long lTabPos
Definition: ruler.hxx:114
void DragMargin1()
Definition: svxruler.cxx:1314
tools::Long GetFrameLeft() const
Definition: svxruler.cxx:1167
bool bActive
Definition: ruler.hxx:127
void UpdateFrame()
Definition: svxruler.cxx:434
std::vector< RulerIndent > mpIndents
Definition: ruler.hxx:117
bool bAppSetNullOffset
Definition: ruler.hxx:103
virtual void ExtraDown() override
Definition: svxruler.cxx:3234
tools::Long GetRightFrameMargin() const
Definition: svxruler.cxx:1247
tools::Long PixelHAdjust(tools::Long lPos, tools::Long lPos2) const
Definition: svxruler.cxx:401
tools::Long nMaxLeft
Definition: ruler.hxx:123
std::unique_ptr< SvxRuler_Impl > mxRulerImpl
Definition: ruler.hxx:101
sal_uInt16 nTabCount
Definition: ruler.hxx:111
tools::Long GetCorrectedDragPos(bool bLeft=true, bool bRight=true)
Definition: svxruler.cxx:1283
std::unique_ptr< SvxColumnItem > mxColumnItem
Definition: ruler.hxx:96
void DragObjectBorder()
Definition: svxruler.cxx:1899
void EvalModifier()
Definition: svxruler.cxx:2417
std::unique_ptr< SvxObjectItem > mxObjectItem
Definition: ruler.hxx:97
sal_uInt16 GetActRightColumn(bool bForceDontConsiderHidden=false, sal_uInt16 nAct=USHRT_MAX) const
Definition: svxruler.cxx:3383
std::unique_ptr< SvxLongLRSpaceItem > mxLRSpaceItem
Definition: ruler.hxx:89
tools::Long ConvertHSizeLogic(tools::Long lSize) const
Definition: svxruler.cxx:381
SvxRulerDragFlags nDragType
Definition: ruler.hxx:109
tools::Long ConvertSizePixel(tools::Long lSize) const
Definition: svxruler.cxx:366
tools::Long MakePositionSticky(tools::Long rValue, tools::Long aPointOfReference, bool aSnapToFrameMargin=true) const
Definition: svxruler.cxx:301
std::unique_ptr< SfxRectangleItem > mxMinMaxItem
Definition: ruler.hxx:90
std::vector< RulerBorder > mpBorders
Definition: ruler.hxx:118
friend class SvxRulerItem
Definition: ruler.hxx:85
void ApplyBorders()
Definition: svxruler.cxx:2189
void UpdateColumns()
Definition: svxruler.cxx:729
void UpdateTextRTL(const SfxBoolItem *pItem)
Definition: svxruler.cxx:687
VclPtr< vcl::Window > pEditWin
Definition: ruler.hxx:99
std::unique_ptr< SvxPagePosSizeItem > mxPagePosItem
Definition: ruler.hxx:95
SfxBindings * pBindings
Definition: ruler.hxx:121
std::vector< RulerTab > mpTabs
Definition: ruler.hxx:116
tools::Long GetPageWidth() const
Definition: svxruler.cxx:1160
std::unique_ptr< SvxTabStopItem > mxTabStopItem
Definition: ruler.hxx:92
void UpdatePara()
Definition: svxruler.cxx:812
tools::Long ConvertHPosLogic(tools::Long lPos) const
Definition: svxruler.cxx:371
tools::Long ConvertVPosPixel(tools::Long lPos) const
Definition: svxruler.cxx:346
bool IsActLastColumn(bool bForceDontConsiderHidden=false, sal_uInt16 nAct=USHRT_MAX) const
Definition: svxruler.cxx:3427
sal_uInt16 GetActLeftColumn(bool bForceDontConsiderHidden=false, sal_uInt16 nAct=USHRT_MAX) const
Definition: svxruler.cxx:3405
virtual void EndDrag() override
Definition: svxruler.cxx:3159
SvxRuler(vcl::Window *pParent, vcl::Window *pEditWin, SvxRulerSupportFlags nRulerFlags, SfxBindings &rBindings, WinBits nWinStyle)
Definition: svxruler.cxx:159
std::unique_ptr< SvxLRSpaceItem > mxParaItem
Definition: ruler.hxx:93
tools::Long ConvertSizeLogic(tools::Long lSize) const
Definition: svxruler.cxx:396
std::vector< std::unique_ptr< SvxRulerItem > > pCtrlItems
Definition: ruler.hxx:87
std::unique_ptr< SvxLongULSpaceItem > mxULSpaceItem
Definition: ruler.hxx:91
tools::Long ConvertVSizePixel(tools::Long lSize) const
Definition: svxruler.cxx:356
void UpdateBorder(const SvxLRSpaceItem *pItem)
Definition: svxruler.cxx:884
void SetValues(RulerChangeType type, tools::Long value)
Definition: svxruler.cxx:3566
tools::Long lAppNullOffset
Definition: ruler.hxx:106
tools::Long nDragOffset
Definition: ruler.hxx:122
void SetNullOffsetLogic(tools::Long lOff)
Definition: svxruler.cxx:1132
void TabMenuSelect(std::string_view rIdent)
Definition: svxruler.cxx:3275
tools::Long ConvertHPosPixel(tools::Long lPos) const
Definition: svxruler.cxx:341
tools::Long CalcPropMaxRight(sal_uInt16 nCol=USHRT_MAX) const
Definition: svxruler.cxx:3441
void PrepareProportional_Impl(RulerType)
Definition: svxruler.cxx:2290
SvxRulerSupportFlags nFlags
Definition: ruler.hxx:108
virtual void Click() override
Definition: svxruler.cxx:2471
tools::Long PixelAdjust(tools::Long lPos, tools::Long lPos2) const
Definition: svxruler.cxx:417
bool IsActFirstColumn(bool bForceDontConsiderHidden=false, sal_uInt16 nAct=USHRT_MAX) const
Definition: svxruler.cxx:3434
tools::Long lDefTabDist
Definition: ruler.hxx:113
void SetTabsRelativeToIndent(bool bRel)
Definition: svxruler.cxx:3561
virtual void dispose() override
Definition: svxruler.cxx:285
void DragIndents()
Definition: svxruler.cxx:1486
sal_uInt16 Count() const
void Remove(const sal_uInt16 nPos, const sal_uInt16 nLen=1)
bool Insert(const SvxTabStop &rTab)
sal_Int32 & GetTabPos()
SvxTabAdjust & GetAdjustment()
void clear()
reference_type * get() const
float GetDPIScaleFactor() const
virtual VclPtr< VirtualDevice > create_virtual_device() const=0
const sal_uInt16 nVisCols
int nCount
#define DBG_ASSERT(sCon, aError)
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
virtual sal_uInt32 GetId() const override
FieldUnit
DocumentType eType
TRISTATE_TRUE
sal_Int32 nIndex
sal_Int64 n
constexpr sal_uInt16 KEY_MOD2
constexpr sal_uInt16 KEY_MOD1
constexpr sal_uInt16 KEY_SHIFT
sal_uInt16 nPos
const long LONG_MAX
NONE
tools::Long const nRightMargin
tools::Long const nBorder
tools::Long const nLeftMargin
int i
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
Count
long Long
FieldUnit EnglishStringToMetric(std::string_view rEnglishMetricString)
weld::Window * GetPopupParent(vcl::Window &rOutWin, tools::Rectangle &rRect)
sal_Int16 nId
constexpr sal_uInt16 RULER_STYLE_DONTKNOW
RulerDragSize
constexpr sal_uInt16 RULER_TAB_CENTER
RulerMarginStyle
constexpr sal_uInt16 RULER_TAB_DEFAULT
constexpr sal_uInt16 RULER_TAB_RIGHT
constexpr sal_uInt16 RULER_STYLE_INVISIBLE
RulerChangeType
Definition: ruler.hxx:45
constexpr sal_uInt16 RULER_TAB_RTL
constexpr sal_uInt16 RULER_TAB_LEFT
SvxRulerSupportFlags
Definition: ruler.hxx:68
SvxRulerDragFlags
Definition: ruler.hxx:51
RulerType
constexpr sal_uInt16 RULER_TAB_DECIMAL
RulerBorderStyle
sal_uInt16 nAryPos
RulerType eType
sal_uInt16 height
sal_uInt16 width
sal_uInt16 DPIScaleFactor
tools::Long nPos
tools::Long nTickUnit
char aUnitStr[8]
tools::Long lMaxRightLogic
Definition: svxruler.cxx:67
void SetPercSize(sal_uInt16 nSize)
Definition: svxruler.cxx:120
tools::Long nTotalDist
Definition: svxruler.cxx:64
sal_uInt16 nPercSize
Definition: svxruler.cxx:63
sal_uInt16 nColRightPix
Definition: svxruler.cxx:75
std::unique_ptr< SvxProtectItem > aProtectItem
Definition: svxruler.cxx:70
tools::Long lOldWinPos
Definition: svxruler.cxx:65
std::unique_ptr< sal_uInt16[]> pPercBuf
Definition: svxruler.cxx:61
tools::Long lMaxLeftLogic
Definition: svxruler.cxx:66
std::unique_ptr< SfxBoolItem > pTextRTLItem
Definition: svxruler.cxx:71
sal_uInt16 nColLeftPix
Definition: svxruler.cxx:74
bool bIsTabsRelativeToIndent
Definition: svxruler.cxx:81
bool bIsTableRows
Definition: svxruler.cxx:79
tools::Long lLastLMargin
Definition: svxruler.cxx:68
sal_uInt16 nIdx
Definition: svxruler.cxx:73
sal_uInt16 nControllerItems
Definition: svxruler.cxx:72
tools::Long lLastRMargin
Definition: svxruler.cxx:69
std::unique_ptr< sal_uInt16[]> pBlockBuf
Definition: svxruler.cxx:62
SvxTabAdjust
constexpr tools::Long glMinFrame
Definition: svxruler.cxx:157
const TranslateId RID_SVXSTR_RULER_TAB[]
Definition: svxruler.cxx:3295
#define GAP
Definition: svxruler.cxx:51
static SvxTabAdjust ToAttrTab_Impl(sal_uInt16 eAdj)
Definition: svxruler.cxx:989
#define INDENT_FIRST_LINE
Definition: svxruler.cxx:55
#define INDENT_RIGHT_MARGIN
Definition: svxruler.cxx:57
#define TAB_FLAG
Definition: svxruler.cxx:1281
static sal_uInt16 ToSvTab_Impl(SvxTabAdjust eAdj)
Definition: svxruler.cxx:975
#define TAB_GAP
Definition: svxruler.cxx:53
#define OBJECT_BORDER_COUNT
Definition: svxruler.cxx:52
static RulerTabData ruler_tab_svx
Definition: svxruler.cxx:100
#define INDENT_LEFT_MARGIN
Definition: svxruler.cxx:56
#define INDENT_GAP
Definition: svxruler.cxx:54
#define CTRL_ITEM_COUNT
Definition: svxruler.cxx:50
#define NEG_FLAG
Definition: svxruler.cxx:1279
#define INDENT_COUNT
Definition: svxruler.cxx:58
static void ModifyTabs_Impl(sal_uInt16 nCount, RulerTab *pTabs, tools::Long lDiff)
Definition: svxruler.cxx:1300
bool bVisible
ResultType type
OUString sId
sal_Int64 WinBits
WinBits const WB_VERT
WinBits const WB_HORZ
WinBits const WB_VSCROLL