1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 <sfx2/viewsh.hxx>
40 #include <editeng/editids.hrc>
41 #include <editeng/tstpitem.hxx>
42 #include <editeng/lrspitem.hxx>
43 #include <editeng/protitem.hxx>
44 #include <osl/diagnose.h>
45 #include <rtl/math.hxx>
46 #include <o3tl/string_view.hxx>
47 #include <svl/itemset.hxx>
48 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
49 #include <tools/json_writer.hxx>
50 #include <tools/UnitConversion.hxx>
51 #include <comphelper/lok.hxx>
52 #include "rlrcitem.hxx"
53 #include <com/sun/star/frame/XFrame.hpp>
54 #include <com/sun/star/lang/XServiceInfo.hpp>
55 #include <sfx2/viewfrm.hxx>
60 #define CTRL_ITEM_COUNT 14
62 #define OBJECT_BORDER_COUNT 4
65 #define INDENT_FIRST_LINE 2
66 #define INDENT_LEFT_MARGIN 3
67 #define INDENT_RIGHT_MARGIN 4
68 #define INDENT_COUNT 3 //without the first two old values
70 struct SvxRuler_Impl
{
71 std::unique_ptr
<sal_uInt16
[]> pPercBuf
;
72 std::unique_ptr
<sal_uInt16
[]> pBlockBuf
;
74 tools::Long nTotalDist
;
75 tools::Long lOldWinPos
;
76 tools::Long lMaxLeftLogic
;
77 tools::Long lMaxRightLogic
;
78 tools::Long lLastLMargin
;
79 tools::Long lLastRMargin
;
80 std::unique_ptr
<SvxProtectItem
> aProtectItem
;
81 std::unique_ptr
<SfxBoolItem
> pTextRTLItem
;
82 sal_uInt16 nControllerItems
;
84 sal_uInt16 nColLeftPix
;
85 sal_uInt16 nColRightPix
; // Pixel values for left / right edge
86 // For columns; buffered to prevent
87 // recalculation errors
88 // May be has to be widen for future values
89 bool bIsTableRows
: 1; // mxColumnItem contains table rows instead of columns
90 //#i24363# tab stops relative to indent
91 bool bIsTabsRelativeToIndent
: 1; // Tab stops relative to paragraph indent?
92 // false means relative to SvxRuler::GetLeftFrameMargin()
95 nPercSize(0), nTotalDist(0),
96 lOldWinPos(0), lMaxLeftLogic(0), lMaxRightLogic(0),
97 lLastLMargin(0), lLastRMargin(0),
98 aProtectItem(std::make_unique
<SvxProtectItem
>(SID_RULER_PROTECT
)),
99 nControllerItems(0), nIdx(0),
100 nColLeftPix(0), nColRightPix(0),
102 bIsTabsRelativeToIndent(true)
106 void SetPercSize(sal_uInt16 nSize
);
110 static RulerTabData ruler_tab_svx
=
112 0, // DPIScaleFactor to be set
113 7, // ruler_tab_width
114 6, // ruler_tab_height
115 0, // ruler_tab_height2
116 0, // ruler_tab_width2
117 0, // ruler_tab_cwidth
118 0, // ruler_tab_cwidth2
119 0, // ruler_tab_cwidth3
120 0, // ruler_tab_cwidth4
121 0, // ruler_tab_dheight
122 0, // ruler_tab_dheight2
123 0, // ruler_tab_dwidth
124 0, // ruler_tab_dwidth2
125 0, // ruler_tab_dwidth3
126 0, // ruler_tab_dwidth4
127 0 // ruler_tab_textoff
130 void SvxRuler_Impl::SetPercSize(sal_uInt16 nSize
)
132 if(nSize
> nPercSize
)
135 pPercBuf
.reset( new sal_uInt16
[nPercSize
] );
136 pBlockBuf
.reset( new sal_uInt16
[nPercSize
] );
138 size_t nSize2
= sizeof(sal_uInt16
) * nPercSize
;
139 memset(pPercBuf
.get(), 0, nSize2
);
140 memset(pBlockBuf
.get(), 0, nSize2
);
143 // Constructor of the ruler
145 // SID_ATTR_ULSPACE, SID_ATTR_LRSPACE
146 // expects as parameter SvxULSpaceItem for page edge
147 // (either left/right or top/bottom)
148 // Ruler: SetMargin1, SetMargin2
150 // SID_RULER_PAGE_POS
151 // expects as parameter the initial value of the page and page width
155 // expects: SvxTabStopItem
158 // SID_ATTR_PARA_LRSPACE
159 // left, right paragraph edge in H-ruler
163 // Table borders, columns
164 // expects: something like SwTabCols
167 constexpr tools::Long glMinFrame
= 5; // minimal frame width in pixels
170 vcl::Window
* pParent
, // StarView Parent
171 vcl::Window
* pWin
, // Output window: is used for conversion
172 // logical units <-> pixels
173 SvxRulerSupportFlags flags
, // Display flags, see ruler.hxx
174 SfxBindings
&rBindings
, // associated Bindings
175 WinBits nWinStyle
) : // StarView WinBits
176 Ruler(pParent
, nWinStyle
),
177 pCtrlItems(CTRL_ITEM_COUNT
),
179 mxRulerImpl(new SvxRuler_Impl
),
180 bAppSetNullOffset(false), // Is the 0-offset of the ruler set by the application?
182 lAppNullOffset(LONG_MAX
),
185 nDragType(SvxRulerDragFlags::NONE
),
186 nDefTabType(RULER_TAB_LEFT
),
191 mpBorders(1), // due to one column tables
192 pBindings(&rBindings
),
199 mbCoarseSnapping(false),
202 /* Constructor; Initialize data buffer; controller items are created */
204 rBindings
.EnterRegistrations();
206 // Create Supported Items
210 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_RULER_LR_MIN_MAX
, *this, rBindings
));
211 if((nWinStyle
& WB_VSCROLL
) == WB_VSCROLL
)
214 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_ATTR_LONG_ULSPACE
, *this, rBindings
));
219 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_ATTR_LONG_LRSPACE
, *this, rBindings
));
223 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_RULER_PAGE_POS
, *this, rBindings
));
225 if(nFlags
& SvxRulerSupportFlags::TABS
)
227 sal_uInt16 nTabStopId
= bHorz
? SID_ATTR_TABSTOP
: SID_ATTR_TABSTOP_VERTICAL
;
228 pCtrlItems
[i
++].reset(new SvxRulerItem(nTabStopId
, *this, rBindings
));
229 SetExtraType(RulerExtra::Tab
, nDefTabType
);
232 if(nFlags
& (SvxRulerSupportFlags::PARAGRAPH_MARGINS
|SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL
))
235 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_ATTR_PARA_LRSPACE
, *this, rBindings
));
237 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_ATTR_PARA_LRSPACE_VERTICAL
, *this, rBindings
));
239 mpIndents
.resize(5 + INDENT_GAP
);
241 for(RulerIndent
& rIndent
: mpIndents
)
244 rIndent
.nStyle
= RulerIndentStyle::Top
;
247 mpIndents
[0].nStyle
= RulerIndentStyle::Top
;
248 mpIndents
[1].nStyle
= RulerIndentStyle::Top
;
249 mpIndents
[INDENT_FIRST_LINE
].nStyle
= RulerIndentStyle::Top
;
250 mpIndents
[INDENT_LEFT_MARGIN
].nStyle
= RulerIndentStyle::Bottom
;
251 mpIndents
[INDENT_RIGHT_MARGIN
].nStyle
= RulerIndentStyle::Bottom
;
254 if( (nFlags
& SvxRulerSupportFlags::BORDERS
) == SvxRulerSupportFlags::BORDERS
)
256 pCtrlItems
[i
++].reset(new SvxRulerItem(bHorz
? SID_RULER_BORDERS
: SID_RULER_BORDERS_VERTICAL
, *this, rBindings
));
257 pCtrlItems
[i
++].reset(new SvxRulerItem(bHorz
? SID_RULER_ROWS
: SID_RULER_ROWS_VERTICAL
, *this, rBindings
));
260 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_RULER_TEXT_RIGHT_TO_LEFT
, *this, rBindings
));
262 if( (nFlags
& SvxRulerSupportFlags::OBJECT
) == SvxRulerSupportFlags::OBJECT
)
264 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_RULER_OBJECT
, *this, rBindings
));
265 mpObjectBorders
.resize(OBJECT_BORDER_COUNT
);
266 for(sal_uInt16 nBorder
= 0; nBorder
< OBJECT_BORDER_COUNT
; ++nBorder
)
268 mpObjectBorders
[nBorder
].nPos
= 0;
269 mpObjectBorders
[nBorder
].nWidth
= 0;
270 mpObjectBorders
[nBorder
].nStyle
= RulerBorderStyle::Moveable
;
274 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_RULER_PROTECT
, *this, rBindings
));
275 pCtrlItems
[i
++].reset(new SvxRulerItem(SID_RULER_BORDER_DISTANCE
, *this, rBindings
));
276 mxRulerImpl
->nControllerItems
=i
;
278 if( (nFlags
& SvxRulerSupportFlags::SET_NULLOFFSET
) == SvxRulerSupportFlags::SET_NULLOFFSET
)
279 SetExtraType(RulerExtra::NullOffset
);
281 rBindings
.LeaveRegistrations();
283 ruler_tab_svx
.DPIScaleFactor
= pParent
->GetDPIScaleFactor();
284 ruler_tab_svx
.height
*= ruler_tab_svx
.DPIScaleFactor
;
285 ruler_tab_svx
.width
*= ruler_tab_svx
.DPIScaleFactor
;
288 SvxRuler::~SvxRuler()
293 void SvxRuler::dispose()
295 /* Destructor ruler; release internal buffer */
297 EndListening(*pBindings
);
299 pBindings
->EnterRegistrations();
303 pBindings
->LeaveRegistrations();
309 tools::Long
SvxRuler::MakePositionSticky(tools::Long aPosition
, tools::Long aPointOfReference
, bool aSnapToFrameMargin
) const
311 tools::Long aPointOfReferencePixel
= ConvertHPosPixel(aPointOfReference
);
312 tools::Long aLeftFramePosition
= ConvertHPosPixel(GetLeftFrameMargin());
313 tools::Long aRightFramePosition
= ConvertHPosPixel(GetRightFrameMargin());
315 double aTick
= GetCurrentRulerUnit().nTick1
;
317 if (mbCoarseSnapping
)
318 aTick
= GetCurrentRulerUnit().nTick2
;
320 tools::Long aTickPixel
= pEditWin
->LogicToPixel(Size(aTick
, 0), GetCurrentMapMode()).Width();
322 double aHalfTick
= aTick
/ 2.0;
323 double aHalfTickPixel
= aTickPixel
/ 2.0;
325 if (aSnapToFrameMargin
)
327 if (aPosition
> aLeftFramePosition
- aHalfTickPixel
&& aPosition
< aLeftFramePosition
+ aHalfTickPixel
)
328 return aLeftFramePosition
;
330 if (aPosition
> aRightFramePosition
- aHalfTickPixel
&& aPosition
< aRightFramePosition
+ aHalfTickPixel
)
331 return aRightFramePosition
;
337 // Move "coordinate system" to frame position so ticks are calculated correctly
338 tools::Long aTranslatedPosition
= aPosition
- aPointOfReferencePixel
;
339 // Convert position to current selected map mode
340 tools::Long aPositionLogic
= pEditWin
->PixelToLogic(Size(aTranslatedPosition
, 0), GetCurrentMapMode()).Width();
341 // Normalize -- snap to nearest tick
342 aPositionLogic
= rtl::math::round((aPositionLogic
+ aHalfTick
) / aTick
) * aTick
;
343 // Convert back to pixels
344 aPosition
= pEditWin
->LogicToPixel(Size(aPositionLogic
, 0), GetCurrentMapMode()).Width();
345 // Move "coordinate system" back to original position
346 return aPosition
+ aPointOfReferencePixel
;
349 tools::Long
SvxRuler::ConvertHPosPixel(tools::Long nVal
) const
351 return pEditWin
->LogicToPixel(Size(nVal
, 0)).Width();
354 tools::Long
SvxRuler::ConvertVPosPixel(tools::Long nVal
) const
356 return pEditWin
->LogicToPixel(Size(0, nVal
)).Height();
359 tools::Long
SvxRuler::ConvertHSizePixel(tools::Long nVal
) const
361 return pEditWin
->LogicToPixel(Size(nVal
, 0)).Width();
364 tools::Long
SvxRuler::ConvertVSizePixel(tools::Long nVal
) const
366 return pEditWin
->LogicToPixel(Size(0, nVal
)).Height();
369 tools::Long
SvxRuler::ConvertPosPixel(tools::Long nVal
) const
371 return bHorz
? ConvertHPosPixel(nVal
): ConvertVPosPixel(nVal
);
374 tools::Long
SvxRuler::ConvertSizePixel(tools::Long nVal
) const
376 return bHorz
? ConvertHSizePixel(nVal
): ConvertVSizePixel(nVal
);
379 inline tools::Long
SvxRuler::ConvertHPosLogic(tools::Long nVal
) const
381 return pEditWin
->PixelToLogic(Size(nVal
, 0)).Width();
384 inline tools::Long
SvxRuler::ConvertVPosLogic(tools::Long nVal
) const
386 return pEditWin
->PixelToLogic(Size(0, nVal
)).Height();
389 inline tools::Long
SvxRuler::ConvertHSizeLogic(tools::Long nVal
) const
391 return pEditWin
->PixelToLogic(Size(nVal
, 0)).Width();
394 inline tools::Long
SvxRuler::ConvertVSizeLogic(tools::Long nVal
) const
396 return pEditWin
->PixelToLogic(Size(0, nVal
)).Height();
399 inline tools::Long
SvxRuler::ConvertPosLogic(tools::Long nVal
) const
401 return bHorz
? ConvertHPosLogic(nVal
): ConvertVPosLogic(nVal
);
404 inline tools::Long
SvxRuler::ConvertSizeLogic(tools::Long nVal
) const
406 return bHorz
? ConvertHSizeLogic(nVal
): ConvertVSizeLogic(nVal
);
409 tools::Long
SvxRuler::PixelHAdjust(tools::Long nVal
, tools::Long nValOld
) const
411 if(ConvertHSizePixel(nVal
) != ConvertHSizePixel(nValOld
))
417 tools::Long
SvxRuler::PixelVAdjust(tools::Long nVal
, tools::Long nValOld
) const
419 if(ConvertVSizePixel(nVal
) != ConvertVSizePixel(nValOld
))
425 tools::Long
SvxRuler::PixelAdjust(tools::Long nVal
, tools::Long nValOld
) const
427 if(ConvertSizePixel(nVal
) != ConvertSizePixel(nValOld
))
433 inline sal_uInt16
SvxRuler::GetObjectBordersOff(sal_uInt16 nIdx
) const
435 return bHorz
? nIdx
: nIdx
+ 2;
439 Update Upper Left edge.
440 Items are translated into the representation of the ruler.
442 void SvxRuler::UpdateFrame()
444 const RulerMarginStyle nMarginStyle
=
445 ( mxRulerImpl
->aProtectItem
->IsSizeProtected() ||
446 mxRulerImpl
->aProtectItem
->IsPosProtected() ) ?
447 RulerMarginStyle::NONE
: RulerMarginStyle::Sizeable
;
449 if(mxLRSpaceItem
&& mxPagePosItem
)
451 // if no initialization by default app behavior
452 const tools::Long nOld
= lLogicNullOffset
;
453 lLogicNullOffset
= mxColumnItem
? mxColumnItem
->GetLeft() : mxLRSpaceItem
->GetLeft();
455 if(bAppSetNullOffset
)
457 lAppNullOffset
+= lLogicNullOffset
- nOld
;
460 if(!bAppSetNullOffset
|| lAppNullOffset
== LONG_MAX
)
462 Ruler::SetNullOffset(ConvertHPosPixel(lLogicNullOffset
));
463 SetMargin1(0, nMarginStyle
);
468 SetMargin1(ConvertHPosPixel(lAppNullOffset
), nMarginStyle
);
471 tools::Long lRight
= 0;
473 // evaluate the table right edge of the table
474 if(mxColumnItem
&& mxColumnItem
->IsTable())
475 lRight
= mxColumnItem
->GetRight();
477 lRight
= mxLRSpaceItem
->GetRight();
479 tools::Long aWidth
= mxPagePosItem
->GetWidth() - lRight
- lLogicNullOffset
+ lAppNullOffset
;
480 tools::Long aWidthPixel
= ConvertHPosPixel(aWidth
);
482 SetMargin2(aWidthPixel
, nMarginStyle
);
484 else if(mxULSpaceItem
&& mxPagePosItem
)
486 // relative the upper edge of the surrounding frame
487 const tools::Long nOld
= lLogicNullOffset
;
488 lLogicNullOffset
= mxColumnItem
? mxColumnItem
->GetLeft() : mxULSpaceItem
->GetUpper();
490 if(bAppSetNullOffset
)
492 lAppNullOffset
+= lLogicNullOffset
- nOld
;
495 if(!bAppSetNullOffset
|| lAppNullOffset
== LONG_MAX
)
497 Ruler::SetNullOffset(ConvertVPosPixel(lLogicNullOffset
));
499 SetMargin1(0, nMarginStyle
);
503 SetMargin1(ConvertVPosPixel(lAppNullOffset
), nMarginStyle
);
506 tools::Long lLower
= mxColumnItem
? mxColumnItem
->GetRight() : mxULSpaceItem
->GetLower();
507 tools::Long nMargin2
= mxPagePosItem
->GetHeight() - lLower
- lLogicNullOffset
+ lAppNullOffset
;
508 tools::Long nMargin2Pixel
= ConvertVPosPixel(nMargin2
);
510 SetMargin2(nMargin2Pixel
, nMarginStyle
);
514 // turns off the view
521 mxRulerImpl
->nColLeftPix
= static_cast<sal_uInt16
>(ConvertSizePixel(mxColumnItem
->GetLeft()));
522 mxRulerImpl
->nColRightPix
= static_cast<sal_uInt16
>(ConvertSizePixel(mxColumnItem
->GetRight()));
526 void SvxRuler::MouseMove( const MouseEvent
& rMEvt
)
530 pBindings
->Update( SID_RULER_LR_MIN_MAX
);
531 pBindings
->Update( SID_ATTR_LONG_ULSPACE
);
532 pBindings
->Update( SID_ATTR_LONG_LRSPACE
);
533 pBindings
->Update( SID_RULER_PAGE_POS
);
534 pBindings
->Update( bHorz
? SID_ATTR_TABSTOP
: SID_ATTR_TABSTOP_VERTICAL
);
535 pBindings
->Update( bHorz
? SID_ATTR_PARA_LRSPACE
: SID_ATTR_PARA_LRSPACE_VERTICAL
);
536 pBindings
->Update( bHorz
? SID_RULER_BORDERS
: SID_RULER_BORDERS_VERTICAL
);
537 pBindings
->Update( bHorz
? SID_RULER_ROWS
: SID_RULER_ROWS_VERTICAL
);
538 pBindings
->Update( SID_RULER_OBJECT
);
539 pBindings
->Update( SID_RULER_PROTECT
);
542 Ruler::MouseMove( rMEvt
);
544 RulerSelection aSelection
= GetHoverSelection();
546 if (aSelection
.eType
== RulerType::DontKnow
)
548 SetQuickHelpText(u
""_ustr
);
552 RulerUnitData aUnitData
= GetCurrentRulerUnit();
553 double aRoundingFactor
= aUnitData
.nTickUnit
/ aUnitData
.nTick1
;
554 sal_Int32 aNoDecimalPlaces
= 1 + std::ceil(std::log10(aRoundingFactor
));
555 OUString sUnit
= OUString::createFromAscii(aUnitData
.aUnitStr
);
557 switch (aSelection
.eType
)
559 case RulerType::Indent
:
564 tools::Long nIndex
= aSelection
.nAryPos
+ INDENT_GAP
;
566 tools::Long nIndentValue
= 0.0;
567 if (nIndex
== INDENT_LEFT_MARGIN
)
568 nIndentValue
= mxParaItem
->ResolveTextLeft({});
569 else if (nIndex
== INDENT_FIRST_LINE
)
570 nIndentValue
= mxParaItem
->ResolveTextFirstLineOffset({});
571 else if (nIndex
== INDENT_RIGHT_MARGIN
)
572 nIndentValue
= mxParaItem
->ResolveRight({});
574 double fValue
= OutputDevice::LogicToLogic(Size(nIndentValue
, 0), pEditWin
->GetMapMode(), GetCurrentMapMode()).Width();
575 fValue
= rtl::math::round(fValue
/ aUnitData
.nTickUnit
, aNoDecimalPlaces
);
577 SetQuickHelpText(OUString::number(fValue
) + " " + sUnit
);
580 case RulerType::Border
:
582 if (mxColumnItem
== nullptr)
585 SvxColumnItem
& aColumnItem
= *mxColumnItem
;
587 if (aSelection
.nAryPos
+ 1 >= aColumnItem
.Count())
590 double fStart
= OutputDevice::LogicToLogic(Size(aColumnItem
[aSelection
.nAryPos
].nEnd
, 0), pEditWin
->GetMapMode(), GetCurrentMapMode()).Width();
591 fStart
= rtl::math::round(fStart
/ aUnitData
.nTickUnit
, aNoDecimalPlaces
);
592 double fEnd
= OutputDevice::LogicToLogic(Size(aColumnItem
[aSelection
.nAryPos
+ 1].nStart
, 0), pEditWin
->GetMapMode(), GetCurrentMapMode()).Width();
593 fEnd
= rtl::math::round(fEnd
/ aUnitData
.nTickUnit
, aNoDecimalPlaces
);
596 OUString::number(fStart
) + " " + sUnit
+ " - " +
597 OUString::number(fEnd
) + " " + sUnit
);
600 case RulerType::Margin1
:
602 tools::Long nLeft
= 0.0;
604 nLeft
= mxLRSpaceItem
->GetLeft();
605 else if (mxULSpaceItem
)
606 nLeft
= mxULSpaceItem
->GetUpper();
610 double fValue
= OutputDevice::LogicToLogic(Size(nLeft
, 0), pEditWin
->GetMapMode(), GetCurrentMapMode()).Width();
611 fValue
= rtl::math::round(fValue
/ aUnitData
.nTickUnit
, aNoDecimalPlaces
);
612 SetQuickHelpText(OUString::number(fValue
) + " " + sUnit
);
616 case RulerType::Margin2
:
618 tools::Long nRight
= 0.0;
620 nRight
= mxLRSpaceItem
->GetRight();
621 else if (mxULSpaceItem
)
622 nRight
= mxULSpaceItem
->GetLower();
626 double fValue
= OutputDevice::LogicToLogic(Size(nRight
, 0), pEditWin
->GetMapMode(), GetCurrentMapMode()).Width();
627 fValue
= rtl::math::round(fValue
/ aUnitData
.nTickUnit
, aNoDecimalPlaces
);
628 SetQuickHelpText(OUString::number(fValue
) + " " + sUnit
);
634 SetQuickHelpText(u
""_ustr
);
640 void SvxRuler::StartListening_Impl()
645 StartListening(*pBindings
);
650 void SvxRuler::UpdateFrame(const SvxLongLRSpaceItem
*pItem
) // new value LRSpace
652 /* Store new value LRSpace; delete old ones if possible */
656 mxLRSpaceItem
.reset(new SvxLongLRSpaceItem(*pItem
));
658 mxLRSpaceItem
.reset();
659 StartListening_Impl();
663 void SvxRuler::UpdateFrameMinMax(const SfxRectangleItem
*pItem
) // value for MinMax
665 /* Set new value for MinMax; delete old ones if possible */
669 mxMinMaxItem
.reset(new SfxRectangleItem(*pItem
));
671 mxMinMaxItem
.reset();
676 void SvxRuler::UpdateFrame(const SvxLongULSpaceItem
*pItem
) // new value
678 /* Update Right/bottom margin */
679 if(bActive
&& !bHorz
)
682 mxULSpaceItem
.reset(new SvxLongULSpaceItem(*pItem
));
684 mxULSpaceItem
.reset();
685 StartListening_Impl();
689 void SvxRuler::Update( const SvxProtectItem
* pItem
)
692 mxRulerImpl
->aProtectItem
.reset(pItem
->Clone());
695 void SvxRuler::UpdateTextRTL(const SfxBoolItem
* pItem
)
699 mxRulerImpl
->pTextRTLItem
.reset();
701 mxRulerImpl
->pTextRTLItem
.reset(new SfxBoolItem(*pItem
));
702 SetTextRTL(mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue());
703 StartListening_Impl();
707 void SvxRuler::Update(
708 const SvxColumnItem
*pItem
, // new value
709 sal_uInt16 nSID
) //Slot Id to identify NULL items
711 /* Set new value for column view */
717 mxColumnItem
.reset(new SvxColumnItem(*pItem
));
718 mxRulerImpl
->bIsTableRows
= (pItem
->Which() == SID_RULER_ROWS
|| pItem
->Which() == SID_RULER_ROWS_VERTICAL
);
719 if(!bHorz
&& !mxRulerImpl
->bIsTableRows
)
720 mxColumnItem
->SetWhich(SID_RULER_BORDERS_VERTICAL
);
722 else if(mxColumnItem
&& mxColumnItem
->Which() == nSID
)
723 //there are two groups of column items table/frame columns and table rows
724 //both can occur in vertical or horizontal mode
725 //the horizontal ruler handles the SID_RULER_BORDERS and SID_RULER_ROWS_VERTICAL
726 //and the vertical handles SID_RULER_BORDERS_VERTICAL and SID_RULER_ROWS
727 //if mxColumnItem is already set with one of the ids then a NULL pItem argument
730 mxColumnItem
.reset();
731 mxRulerImpl
->bIsTableRows
= false;
733 StartListening_Impl();
737 void SvxRuler::UpdateColumns()
739 /* Update column view */
740 if(mxColumnItem
&& mxColumnItem
->Count() > 1)
742 mpBorders
.resize(mxColumnItem
->Count());
744 RulerBorderStyle nStyleFlags
= RulerBorderStyle::Variable
;
746 bool bProtectColumns
=
747 mxRulerImpl
->aProtectItem
->IsSizeProtected() ||
748 mxRulerImpl
->aProtectItem
->IsPosProtected();
750 if( !bProtectColumns
)
752 nStyleFlags
|= RulerBorderStyle::Moveable
;
753 if( !mxColumnItem
->IsTable() )
754 nStyleFlags
|= RulerBorderStyle::Sizeable
;
757 sal_uInt16 nBorders
= mxColumnItem
->Count();
759 if(!mxRulerImpl
->bIsTableRows
)
762 for(sal_uInt16 i
= 0; i
< nBorders
; ++i
)
764 mpBorders
[i
].nStyle
= nStyleFlags
;
765 if(!mxColumnItem
->At(i
).bVisible
)
766 mpBorders
[i
].nStyle
|= RulerBorderStyle::Invisible
;
768 mpBorders
[i
].nPos
= ConvertPosPixel(mxColumnItem
->At(i
).nEnd
+ lAppNullOffset
);
770 if(mxColumnItem
->Count() == i
+ 1)
772 //with table rows the end of the table is contained in the
773 //column item but it has no width!
774 mpBorders
[i
].nWidth
= 0;
778 mpBorders
[i
].nWidth
= ConvertSizePixel(mxColumnItem
->At(i
+ 1).nStart
- mxColumnItem
->At(i
).nEnd
);
780 mpBorders
[i
].nMinPos
= ConvertPosPixel(mxColumnItem
->At(i
).nEndMin
+ lAppNullOffset
);
781 mpBorders
[i
].nMaxPos
= ConvertPosPixel(mxColumnItem
->At(i
).nEndMax
+ lAppNullOffset
);
783 SetBorders(mxColumnItem
->Count() - 1, mpBorders
.data());
791 void SvxRuler::UpdateObject()
793 /* Update view of object representation */
796 DBG_ASSERT(!mpObjectBorders
.empty(), "no Buffer");
797 // !! to the page margin
798 tools::Long nMargin
= mxLRSpaceItem
? mxLRSpaceItem
->GetLeft() : 0;
799 mpObjectBorders
[0].nPos
=
800 ConvertPosPixel(mxObjectItem
->GetStartX() -
801 nMargin
+ lAppNullOffset
);
802 mpObjectBorders
[1].nPos
=
803 ConvertPosPixel(mxObjectItem
->GetEndX() - nMargin
+ lAppNullOffset
);
804 nMargin
= mxULSpaceItem
? mxULSpaceItem
->GetUpper() : 0;
805 mpObjectBorders
[2].nPos
=
806 ConvertPosPixel(mxObjectItem
->GetStartY() -
807 nMargin
+ lAppNullOffset
);
808 mpObjectBorders
[3].nPos
=
809 ConvertPosPixel(mxObjectItem
->GetEndY() - nMargin
+ lAppNullOffset
);
811 const sal_uInt16 nOffset
= GetObjectBordersOff(0);
812 SetBorders(2, mpObjectBorders
.data() + nOffset
);
820 void SvxRuler::UpdatePara()
823 /* Update the view for paragraph indents:
824 Left margin, first line indent, right margin paragraph update
825 mpIndents[0] = Buffer for old intent
826 mpIndents[1] = Buffer for old intent
827 mpIndents[INDENT_FIRST_LINE] = first line indent
828 mpIndents[INDENT_LEFT_MARGIN] = left margin
829 mpIndents[INDENT_RIGHT_MARGIN] = right margin
832 // Dependence on PagePosItem
833 if (mxParaItem
&& mxPagePosItem
&& !mxObjectItem
)
835 bool bRTLText
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
836 // First-line indent is negative to the left paragraph margin
837 tools::Long nLeftFrameMargin
= GetLeftFrameMargin();
838 tools::Long nRightFrameMargin
= GetRightFrameMargin();
839 SetLeftFrameMargin(ConvertHPosPixel(nLeftFrameMargin
));
840 SetRightFrameMargin(ConvertHPosPixel(nRightFrameMargin
));
842 tools::Long leftMargin
;
843 tools::Long leftFirstLine
;
844 tools::Long rightMargin
;
848 leftMargin
= nRightFrameMargin
- mxParaItem
->ResolveTextLeft({}) + lAppNullOffset
;
849 leftFirstLine
= leftMargin
- mxParaItem
->ResolveTextFirstLineOffset({});
850 rightMargin
= nLeftFrameMargin
+ mxParaItem
->ResolveRight({}) + lAppNullOffset
;
854 leftMargin
= nLeftFrameMargin
+ mxParaItem
->ResolveTextLeft({}) + lAppNullOffset
;
855 leftFirstLine
= leftMargin
+ mxParaItem
->ResolveTextFirstLineOffset({});
856 rightMargin
= nRightFrameMargin
- mxParaItem
->ResolveRight({}) + lAppNullOffset
;
859 mpIndents
[INDENT_LEFT_MARGIN
].nPos
= ConvertHPosPixel(leftMargin
);
860 mpIndents
[INDENT_FIRST_LINE
].nPos
= ConvertHPosPixel(leftFirstLine
);
861 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
= ConvertHPosPixel(rightMargin
);
863 mpIndents
[INDENT_FIRST_LINE
].bInvisible
= mxParaItem
->IsAutoFirst();
865 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
869 if(!mpIndents
.empty())
871 mpIndents
[INDENT_FIRST_LINE
].nPos
= 0;
872 mpIndents
[INDENT_LEFT_MARGIN
].nPos
= 0;
873 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
= 0;
875 SetIndents(); // turn off
879 void SvxRuler::UpdatePara(const SvxLRSpaceItem
*pItem
) // new value of paragraph indents
881 /* Store new value of paragraph indents */
885 mxParaItem
.reset(new SvxLRSpaceItem(*pItem
));
888 StartListening_Impl();
892 void SvxRuler::UpdateBorder(const SvxLRSpaceItem
* pItem
)
894 /* Border distance */
898 mxBorderItem
.reset(new SvxLRSpaceItem(*pItem
));
900 mxBorderItem
.reset();
902 StartListening_Impl();
906 void SvxRuler::UpdatePage()
908 /* Update view of position and width of page */
911 // all objects are automatically adjusted
915 pEditWin
->LogicToPixel(mxPagePosItem
->GetPos()).X(),
916 pEditWin
->LogicToPixel(Size(mxPagePosItem
->GetWidth(), 0)).
922 pEditWin
->LogicToPixel(mxPagePosItem
->GetPos()).Y(),
923 pEditWin
->LogicToPixel(Size(0, mxPagePosItem
->GetHeight())).
926 if(bAppSetNullOffset
)
927 SetNullOffset(ConvertSizePixel(-lAppNullOffset
+ lLogicNullOffset
));
934 tools::Long lPos
= 0;
935 Point aOwnPos
= GetPosPixel();
936 Point aEdtWinPos
= pEditWin
->GetPosPixel();
937 if( AllSettings::GetLayoutRTL() && bHorz
)
939 //#i73321# in RTL the window and the ruler is not mirrored but the
940 // influence of the vertical ruler is inverted
941 Size aOwnSize
= GetSizePixel();
942 Size aEdtWinSize
= pEditWin
->GetSizePixel();
943 lPos
= aOwnSize
.Width() - aEdtWinSize
.Width();
944 lPos
-= (aEdtWinPos
- aOwnPos
).X();
948 Point
aPos(aEdtWinPos
- aOwnPos
);
949 lPos
= bHorz
? aPos
.X() : aPos
.Y();
952 // Unfortunately, we get the offset of the edit window to the ruler never
953 // through a status message. So we set it ourselves if necessary.
954 if(lPos
!= mxRulerImpl
->lOldWinPos
)
956 mxRulerImpl
->lOldWinPos
=lPos
;
961 void SvxRuler::Update(const SvxPagePosSizeItem
*pItem
) // new value of page attributes
963 /* Store new value of page attributes */
967 mxPagePosItem
.reset(new SvxPagePosSizeItem(*pItem
));
969 mxPagePosItem
.reset();
970 StartListening_Impl();
974 void SvxRuler::SetDefTabDist(tools::Long inDefTabDist
) // New distance for DefaultTabs in App-Metrics
976 if (lAppNullOffset
== LONG_MAX
)
977 UpdateFrame(); // hack: try to get lAppNullOffset initialized
978 /* New distance is set for DefaultTabs */
979 lDefTabDist
= inDefTabDist
;
986 static sal_uInt16
ToSvTab_Impl(SvxTabAdjust eAdj
)
988 /* Internal conversion routine between SV-Tab.-Enum and Svx */
990 case SvxTabAdjust::Left
: return RULER_TAB_LEFT
;
991 case SvxTabAdjust::Right
: return RULER_TAB_RIGHT
;
992 case SvxTabAdjust::Decimal
: return RULER_TAB_DECIMAL
;
993 case SvxTabAdjust::Center
: return RULER_TAB_CENTER
;
994 case SvxTabAdjust::Default
: return RULER_TAB_DEFAULT
;
995 default: ; //prevent warning
1000 static SvxTabAdjust
ToAttrTab_Impl(sal_uInt16 eAdj
)
1003 case RULER_TAB_LEFT
: return SvxTabAdjust::Left
;
1004 case RULER_TAB_RIGHT
: return SvxTabAdjust::Right
;
1005 case RULER_TAB_DECIMAL
: return SvxTabAdjust::Decimal
;
1006 case RULER_TAB_CENTER
: return SvxTabAdjust::Center
;
1007 case RULER_TAB_DEFAULT
: return SvxTabAdjust::Default
;
1009 return SvxTabAdjust::Left
;
1012 void SvxRuler::UpdateTabs()
1017 if (mxPagePosItem
&& mxParaItem
&& mxTabStopItem
&& !mxObjectItem
)
1019 // buffer for DefaultTabStop
1020 // Distance last Tab <-> Right paragraph margin / DefaultTabDist
1021 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
1023 const tools::Long nLeftFrameMargin
= GetLeftFrameMargin();
1024 const tools::Long nRightFrameMargin
= GetRightFrameMargin();
1026 //#i24363# tab stops relative to indent
1027 const tools::Long nParaItemTxtLeft
= mxParaItem
->ResolveTextLeft({});
1029 const tools::Long lParaIndent
= nLeftFrameMargin
+ nParaItemTxtLeft
;
1030 const tools::Long lRightMargin
= nRightFrameMargin
- nParaItemTxtLeft
;
1032 const tools::Long lLastTab
= mxTabStopItem
->Count()
1033 ? ConvertHPosPixel(mxTabStopItem
->At(mxTabStopItem
->Count() - 1).GetTabPos())
1035 const tools::Long lPosPixel
= ConvertHPosPixel(lParaIndent
) + lLastTab
;
1036 const tools::Long lRightIndent
1037 = ConvertHPosPixel(nRightFrameMargin
- mxParaItem
->ResolveRight({}));
1039 tools::Long lCurrentDefTabDist
= lDefTabDist
;
1040 if(mxTabStopItem
->GetDefaultDistance())
1041 lCurrentDefTabDist
= mxTabStopItem
->GetDefaultDistance();
1042 tools::Long nDefTabDist
= ConvertHPosPixel(lCurrentDefTabDist
);
1044 const sal_uInt16 nDefTabBuf
= lPosPixel
> lRightIndent
|| lLastTab
> lRightIndent
|| nDefTabDist
== 0
1046 : static_cast<sal_uInt16
>( (lRightIndent
- lPosPixel
) / nDefTabDist
);
1048 if(mxTabStopItem
->Count() + TAB_GAP
+ nDefTabBuf
> nTabBufSize
)
1050 // 10 (GAP) in stock
1051 nTabBufSize
= mxTabStopItem
->Count() + TAB_GAP
+ nDefTabBuf
+ GAP
;
1052 mpTabs
.resize(nTabBufSize
);
1058 const tools::Long lParaIndentPix
= ConvertSizePixel(lParaIndent
);
1060 tools::Long lTabStartLogic
= (mxRulerImpl
->bIsTabsRelativeToIndent
? lParaIndent
: nLeftFrameMargin
)
1064 lTabStartLogic
= lParaIndent
+ lRightMargin
- lTabStartLogic
;
1066 tools::Long lLastTabOffsetLogic
= 0;
1067 for(j
= 0; j
< mxTabStopItem
->Count(); ++j
)
1069 const SvxTabStop
* pTab
= &mxTabStopItem
->At(j
);
1070 lLastTabOffsetLogic
= pTab
->GetTabPos();
1071 tools::Long lPos
= lTabStartLogic
+ (bRTL
? -lLastTabOffsetLogic
: lLastTabOffsetLogic
);
1072 mpTabs
[nTabCount
+ TAB_GAP
].nPos
= ConvertHPosPixel(lPos
);
1073 mpTabs
[nTabCount
+ TAB_GAP
].nStyle
= ToSvTab_Impl(pTab
->GetAdjustment());
1077 // Adjust to previous-to-first default tab stop
1078 lLastTabOffsetLogic
-= lLastTabOffsetLogic
% lCurrentDefTabDist
;
1080 // fill the rest with default Tabs
1081 for (j
= 0; j
< nDefTabBuf
; ++j
)
1083 //simply add the default distance to the last position
1084 lLastTabOffsetLogic
+= lCurrentDefTabDist
;
1087 mpTabs
[nTabCount
+ TAB_GAP
].nPos
=
1088 ConvertHPosPixel(lTabStartLogic
- lLastTabOffsetLogic
);
1089 if (mpTabs
[nTabCount
+ TAB_GAP
].nPos
<= lParaIndentPix
)
1094 mpTabs
[nTabCount
+ TAB_GAP
].nPos
=
1095 ConvertHPosPixel(lTabStartLogic
+ lLastTabOffsetLogic
);
1096 if (mpTabs
[nTabCount
+ TAB_GAP
].nPos
>= lRightIndent
)
1100 mpTabs
[nTabCount
+ TAB_GAP
].nStyle
= RULER_TAB_DEFAULT
;
1103 SetTabs(nTabCount
, mpTabs
.data() + TAB_GAP
);
1104 DBG_ASSERT(nTabCount
+ TAB_GAP
<= nTabBufSize
, "BufferSize too small");
1112 void SvxRuler::Update(const SvxTabStopItem
*pItem
) // new value for tabs
1114 /* Store new value for tabs; delete old ones if possible */
1120 mxTabStopItem
.reset(new SvxTabStopItem(*pItem
));
1122 mxTabStopItem
->SetWhich(SID_ATTR_TABSTOP_VERTICAL
);
1126 mxTabStopItem
.reset();
1128 StartListening_Impl();
1131 void SvxRuler::Update(const SvxObjectItem
*pItem
) // new value for objects
1133 /* Store new value for objects */
1137 mxObjectItem
.reset(new SvxObjectItem(*pItem
));
1139 mxObjectItem
.reset();
1140 StartListening_Impl();
1144 void SvxRuler::SetNullOffsetLogic(tools::Long lVal
) // Setting of the logic NullOffsets
1146 lAppNullOffset
= lLogicNullOffset
- lVal
;
1147 bAppSetNullOffset
= true;
1148 Ruler::SetNullOffset(ConvertSizePixel(lVal
));
1152 void SvxRuler::CreateJsonNotification(tools::JsonWriter
& rJsonWriter
)
1154 tools::Long nMargin1
= 0;
1155 tools::Long nMargin2
= 0;
1156 tools::Long nNullOffset
= 0;
1157 tools::Long nPageOffset
= 0;
1158 tools::Long nPageWidthHeight
= 0;
1160 bool bWriter
= false;
1162 // Determine if we are a Ruler for Writer or not
1163 if (SfxViewFrame
* pFrame
= SfxViewFrame::Current())
1165 uno::Reference
<frame::XFrame
> xFrame
= pFrame
->GetFrame().GetFrameInterface();
1166 uno::Reference
<frame::XModel
> xModel
= xFrame
->getController()->getModel();
1167 uno::Reference
<lang::XServiceInfo
> xSI(xModel
, uno::UNO_QUERY
);
1170 bWriter
= xSI
->supportsService("com.sun.star.text.TextDocument")
1171 || xSI
->supportsService("com.sun.star.text.WebDocument")
1172 || xSI
->supportsService("com.sun.star.text.GlobalDocument");
1178 // In Writer the ruler values need to be converted first from pixel to twips (default logical unit) and then to 100thmm
1179 nMargin1
= convertTwipToMm100(ConvertPosLogic(GetMargin1()));
1180 nMargin2
= convertTwipToMm100(ConvertPosLogic(GetMargin2()));
1181 nNullOffset
= convertTwipToMm100(ConvertPosLogic(GetNullOffset()));
1182 nPageOffset
= convertTwipToMm100(ConvertPosLogic(GetPageOffset()));
1183 nPageWidthHeight
= convertTwipToMm100(GetPageWidth());
1187 // Only convert from pixel to default logical unit, which is 100thmm for Impress
1188 nMargin1
= ConvertPosLogic(GetMargin1());
1189 nMargin2
= ConvertPosLogic(GetMargin2());
1190 nPageOffset
= ConvertPosLogic(GetPageOffset());
1192 // In LOKit API we expect the ruler 0,0 coordinate is where the document starts.
1193 // In Impress and Draw the ruler 0,0 is where the canvas starts, not where the document starts.
1194 // The margin to the document is 1 document width (on the left and right) and 0.5 document height
1195 // (on the top and bottom).
1196 // So the canvas width = 3 * document width, canvas height = 2 * document height
1199 nPageWidthHeight
= GetPageWidth() / 3;
1200 nNullOffset
= ConvertPosLogic(GetNullOffset()) - nPageWidthHeight
;
1204 nPageWidthHeight
= GetPageWidth() / 2;
1205 nNullOffset
= ConvertPosLogic(GetNullOffset()) - (nPageWidthHeight
/ 2);
1209 rJsonWriter
.put("margin1", nMargin1
);
1210 rJsonWriter
.put("margin2", nMargin2
);
1211 rJsonWriter
.put("leftOffset", nNullOffset
);
1212 rJsonWriter
.put("pageOffset", nPageOffset
);
1213 rJsonWriter
.put("pageWidth", nPageWidthHeight
);
1216 auto tabsNode
= rJsonWriter
.startNode("tabs");
1218 // The RulerTab array elements that GetTabs() returns have their nPos field in twips. So these
1219 // too are actual mm100.
1220 for (auto const& tab
: GetTabs())
1222 auto tabNode
= rJsonWriter
.startNode("");
1223 rJsonWriter
.put("position", convertTwipToMm100(tab
.nPos
));
1224 rJsonWriter
.put("style", tab
.nStyle
);
1228 RulerUnitData aUnitData
= GetCurrentRulerUnit();
1229 rJsonWriter
.put("unit", aUnitData
.aUnitStr
);
1232 void SvxRuler::NotifyKit()
1234 if (!comphelper::LibreOfficeKit::isActive())
1236 SfxViewShell
* pViewShell
= SfxViewShell::Current();
1240 tools::JsonWriter aJsonWriter
;
1241 CreateJsonNotification(aJsonWriter
);
1242 OString pJsonData
= aJsonWriter
.finishAndGetAsOString();
1243 LibreOfficeKitCallbackType eType
= isHorizontal() ? LOK_CALLBACK_RULER_UPDATE
: LOK_CALLBACK_VERTICAL_RULER_UPDATE
;
1244 pViewShell
->libreOfficeKitViewCallback(eType
, pJsonData
);
1247 void SvxRuler::Update()
1249 /* Perform update of view */
1255 if(nFlags
& SvxRulerSupportFlags::OBJECT
)
1260 if(nFlags
& (SvxRulerSupportFlags::PARAGRAPH_MARGINS
| SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL
))
1263 if(nFlags
& SvxRulerSupportFlags::TABS
)
1269 tools::Long
SvxRuler::GetPageWidth() const
1273 return bHorz
? mxPagePosItem
->GetWidth() : mxPagePosItem
->GetHeight();
1276 inline tools::Long
SvxRuler::GetFrameLeft() const
1278 /* Get Left margin in Pixels */
1279 return bAppSetNullOffset
?
1280 GetMargin1() + ConvertSizePixel(lLogicNullOffset
) :
1281 Ruler::GetNullOffset();
1284 tools::Long
SvxRuler::GetFirstLineIndent() const
1286 /* Get First-line indent in pixels */
1287 return mxParaItem
? mpIndents
[INDENT_FIRST_LINE
].nPos
: GetMargin1();
1290 tools::Long
SvxRuler::GetLeftIndent() const
1292 /* Get Left paragraph margin in Pixels */
1293 return mxParaItem
? mpIndents
[INDENT_LEFT_MARGIN
].nPos
: GetMargin1();
1296 tools::Long
SvxRuler::GetRightIndent() const
1298 /* Get Right paragraph margin in Pixels */
1299 return mxParaItem
? mpIndents
[INDENT_RIGHT_MARGIN
].nPos
: GetMargin2();
1302 tools::Long
SvxRuler::GetLogicRightIndent() const
1304 /* Get Right paragraph margin in Logic */
1305 return mxParaItem
? GetRightFrameMargin() - mxParaItem
->ResolveRight({})
1306 : GetRightFrameMargin();
1309 // Left margin in App values, is either the margin (= 0) or the left edge of
1310 // the column that is set in the column attribute as current column.
1311 tools::Long
SvxRuler::GetLeftFrameMargin() const
1313 // #126721# for some unknown reason the current column is set to 0xffff
1314 DBG_ASSERT(!mxColumnItem
|| mxColumnItem
->GetActColumn() < mxColumnItem
->Count(),
1315 "issue #126721# - invalid current column!");
1316 tools::Long nLeft
= 0;
1318 mxColumnItem
->Count() &&
1319 mxColumnItem
->IsConsistent())
1321 nLeft
= mxColumnItem
->GetActiveColumnDescription().nStart
;
1324 if (mxBorderItem
&& (!mxColumnItem
|| mxColumnItem
->IsTable()))
1325 nLeft
+= mxBorderItem
->ResolveLeft({});
1330 inline tools::Long
SvxRuler::GetLeftMin() const
1332 DBG_ASSERT(mxMinMaxItem
, "no MinMax value set");
1336 return mxMinMaxItem
->GetValue().Left();
1338 return mxMinMaxItem
->GetValue().Top();
1343 inline tools::Long
SvxRuler::GetRightMax() const
1345 DBG_ASSERT(mxMinMaxItem
, "no MinMax value set");
1349 return mxMinMaxItem
->GetValue().Right();
1351 return mxMinMaxItem
->GetValue().Bottom();
1357 tools::Long
SvxRuler::GetRightFrameMargin() const
1359 /* Get right frame margin (in logical units) */
1362 if (!IsActLastColumn(true))
1364 return mxColumnItem
->At(GetActRightColumn(true)).nEnd
;
1368 tools::Long lResult
= lLogicNullOffset
;
1370 // If possible deduct right table entry
1371 if(mxColumnItem
&& mxColumnItem
->IsTable())
1372 lResult
+= mxColumnItem
->GetRight();
1373 else if(bHorz
&& mxLRSpaceItem
)
1374 lResult
+= mxLRSpaceItem
->GetRight();
1375 else if(!bHorz
&& mxULSpaceItem
)
1376 lResult
+= mxULSpaceItem
->GetLower();
1378 if (bHorz
&& mxBorderItem
&& (!mxColumnItem
|| mxColumnItem
->IsTable()))
1379 lResult
+= mxBorderItem
->ResolveRight({});
1382 lResult
= mxPagePosItem
->GetWidth() - lResult
;
1384 lResult
= mxPagePosItem
->GetHeight() - lResult
;
1389 #define NEG_FLAG ( (nFlags & SvxRulerSupportFlags::NEGATIVE_MARGINS) == \
1390 SvxRulerSupportFlags::NEGATIVE_MARGINS )
1391 #define TAB_FLAG ( mxColumnItem && mxColumnItem->IsTable() )
1393 tools::Long
SvxRuler::GetCorrectedDragPos( bool bLeft
, bool bRight
)
1396 Corrects the position within the calculated limits. The limit values are in
1397 pixels relative to the page edge.
1400 const tools::Long lNullPix
= Ruler::GetNullOffset();
1401 tools::Long lDragPos
= GetDragPos() + lNullPix
;
1402 bool bHoriRows
= bHorz
&& mxRulerImpl
->bIsTableRows
;
1403 if((bLeft
|| bHoriRows
) && lDragPos
< nMaxLeft
)
1404 lDragPos
= nMaxLeft
;
1405 else if((bRight
||bHoriRows
) && lDragPos
> nMaxRight
)
1406 lDragPos
= nMaxRight
;
1407 return lDragPos
- lNullPix
;
1410 static void ModifyTabs_Impl( sal_uInt16 nCount
, // Number of Tabs
1411 RulerTab
* pTabs
, // Tab buffer
1412 tools::Long lDiff
) // difference to be added
1414 /* Helper function, move all the tabs by a fixed value */
1417 for(sal_uInt16 i
= 0; i
< nCount
; ++i
)
1419 pTabs
[i
].nPos
+= lDiff
;
1424 void SvxRuler::DragMargin1()
1426 /* Dragging the left edge of frame */
1427 tools::Long aDragPosition
= GetCorrectedDragPos( !TAB_FLAG
|| !NEG_FLAG
);
1429 aDragPosition
= MakePositionSticky(aDragPosition
, GetRightFrameMargin(), false);
1431 // Check if position changed
1432 if (aDragPosition
== 0)
1435 DrawLine_Impl(lTabPos
, ( TAB_FLAG
&& NEG_FLAG
) ? 3 : 7, bHorz
);
1436 if (mxColumnItem
&& (nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
))
1438 AdjustMargin1(aDragPosition
);
1441 void SvxRuler::AdjustMargin1(tools::Long lInputDiff
)
1443 const tools::Long nOld
= bAppSetNullOffset
? GetMargin1(): GetNullOffset();
1444 const tools::Long lDragPos
= lInputDiff
;
1446 bool bProtectColumns
=
1447 mxRulerImpl
->aProtectItem
->IsSizeProtected() ||
1448 mxRulerImpl
->aProtectItem
->IsPosProtected();
1450 const RulerMarginStyle nMarginStyle
=
1451 bProtectColumns
? RulerMarginStyle::NONE
: RulerMarginStyle::Sizeable
;
1453 if(!bAppSetNullOffset
)
1455 tools::Long lDiff
= lDragPos
;
1456 SetNullOffset(nOld
+ lDiff
);
1457 if (!mxColumnItem
|| !(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_LINEAR
))
1459 SetMargin2( GetMargin2() - lDiff
, nMarginStyle
);
1461 if (!mxColumnItem
&& !mxObjectItem
&& mxParaItem
)
1463 // Right indent of the old position
1464 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
-= lDiff
;
1465 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1469 mpObjectBorders
[GetObjectBordersOff(0)].nPos
-= lDiff
;
1470 mpObjectBorders
[GetObjectBordersOff(1)].nPos
-= lDiff
;
1471 SetBorders(2, mpObjectBorders
.data() + GetObjectBordersOff(0));
1475 for(sal_uInt16 i
= 0; i
< mxColumnItem
->Count()-1; ++i
)
1476 mpBorders
[i
].nPos
-= lDiff
;
1477 SetBorders(mxColumnItem
->Count()-1, mpBorders
.data());
1478 if(mxColumnItem
->IsFirstAct())
1480 // Right indent of the old position
1483 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
-= lDiff
;
1484 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1491 mpIndents
[INDENT_FIRST_LINE
].nPos
-= lDiff
;
1492 mpIndents
[INDENT_LEFT_MARGIN
].nPos
-= lDiff
;
1493 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
-= lDiff
;
1494 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1497 if(mxTabStopItem
&& (nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)
1498 &&!IsActFirstColumn())
1500 ModifyTabs_Impl(nTabCount
+ TAB_GAP
, mpTabs
.data(), -lDiff
);
1501 SetTabs(nTabCount
, mpTabs
.data() + TAB_GAP
);
1508 tools::Long lDiff
= lDragPos
- nOld
;
1509 SetMargin1(nOld
+ lDiff
, nMarginStyle
);
1513 & (SvxRulerDragFlags::OBJECT_SIZE_LINEAR
1514 | SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)))
1516 if (!mxColumnItem
&& !mxObjectItem
&& mxParaItem
)
1518 // Left indent of the old position
1519 mpIndents
[INDENT_FIRST_LINE
].nPos
+= lDiff
;
1520 mpIndents
[INDENT_LEFT_MARGIN
].nPos
+= lDiff
;
1521 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1526 for(sal_uInt16 i
= 0; i
< mxColumnItem
->Count() - 1; ++i
)
1527 mpBorders
[i
].nPos
+= lDiff
;
1528 SetBorders(mxColumnItem
->Count() - 1, mpBorders
.data());
1529 if (mxColumnItem
->IsFirstAct())
1531 // Left indent of the old position
1534 mpIndents
[INDENT_FIRST_LINE
].nPos
+= lDiff
;
1535 mpIndents
[INDENT_LEFT_MARGIN
].nPos
+= lDiff
;
1536 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1543 mpIndents
[INDENT_FIRST_LINE
].nPos
+= lDiff
;
1544 mpIndents
[INDENT_LEFT_MARGIN
].nPos
+= lDiff
;
1545 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
+= lDiff
;
1546 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1552 ModifyTabs_Impl(nTabCount
+ TAB_GAP
, mpTabs
.data(), lDiff
);
1553 SetTabs(nTabCount
, mpTabs
.data() + TAB_GAP
);
1559 void SvxRuler::DragMargin2()
1561 /* Dragging the right edge of frame */
1562 tools::Long aDragPosition
= GetCorrectedDragPos( true, !TAB_FLAG
|| !NEG_FLAG
);
1563 aDragPosition
= MakePositionSticky(aDragPosition
, GetLeftFrameMargin(), false);
1564 tools::Long lDiff
= aDragPosition
- GetMargin2();
1566 // Check if position changed
1570 if( mxRulerImpl
->bIsTableRows
&&
1573 (nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
))
1578 bool bProtectColumns
=
1579 mxRulerImpl
->aProtectItem
->IsSizeProtected() ||
1580 mxRulerImpl
->aProtectItem
->IsPosProtected();
1582 const RulerMarginStyle nMarginStyle
= bProtectColumns
? RulerMarginStyle::NONE
: RulerMarginStyle::Sizeable
;
1584 SetMargin2( aDragPosition
, nMarginStyle
);
1586 // Right indent of the old position
1587 if ((!mxColumnItem
|| IsActLastColumn()) && mxParaItem
)
1589 mpIndents
[INDENT_FIRST_LINE
].nPos
+= lDiff
;
1590 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1593 DrawLine_Impl(lTabPos
, ( TAB_FLAG
&& NEG_FLAG
) ? 5 : 7, bHorz
);
1596 void SvxRuler::DragIndents()
1598 /* Dragging the paragraph indents */
1599 tools::Long aDragPosition
= NEG_FLAG
? GetDragPos() : GetCorrectedDragPos();
1600 const sal_uInt16 nIndex
= GetDragAryPos() + INDENT_GAP
;
1602 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
1604 if(nIndex
== INDENT_RIGHT_MARGIN
)
1605 aDragPosition
= MakePositionSticky(aDragPosition
, bRTL
? GetLeftFrameMargin() : GetRightFrameMargin());
1607 aDragPosition
= MakePositionSticky(aDragPosition
, bRTL
? GetRightFrameMargin() : GetLeftFrameMargin());
1609 const tools::Long lDiff
= mpIndents
[nIndex
].nPos
- aDragPosition
;
1611 // Check if position changed
1615 if((nIndex
== INDENT_FIRST_LINE
|| nIndex
== INDENT_LEFT_MARGIN
) &&
1616 !(nDragType
& SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY
))
1618 mpIndents
[INDENT_FIRST_LINE
].nPos
-= lDiff
;
1621 mpIndents
[nIndex
].nPos
= aDragPosition
;
1623 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1624 DrawLine_Impl(lTabPos
, 1, bHorz
);
1627 void SvxRuler::DrawLine_Impl(tools::Long
& lTabPosition
, int nNew
, bool bHorizontal
)
1630 Output routine for the ledger line when moving tabs, tables and other
1635 const tools::Long nHeight
= pEditWin
->GetOutDev()->GetOutputSize().Height();
1636 Point aZero
= pEditWin
->GetMapMode().GetOrigin();
1637 if(lTabPosition
!= -1)
1639 pEditWin
->InvertTracking(
1640 tools::Rectangle( Point(lTabPosition
, -aZero
.Y()),
1641 Point(lTabPosition
, -aZero
.Y() + nHeight
)),
1642 ShowTrackFlags::Split
| ShowTrackFlags::Clip
);
1646 tools::Long nDrapPosition
= GetCorrectedDragPos( ( nNew
& 4 ) != 0, ( nNew
& 2 ) != 0 );
1647 nDrapPosition
= MakePositionSticky(nDrapPosition
, GetLeftFrameMargin());
1648 lTabPosition
= ConvertHSizeLogic( nDrapPosition
+ GetNullOffset() );
1650 lTabPosition
+= mxPagePosItem
->GetPos().X();
1651 pEditWin
->InvertTracking(
1652 tools::Rectangle( Point(lTabPosition
, -aZero
.Y()),
1653 Point(lTabPosition
, -aZero
.Y() + nHeight
) ),
1654 ShowTrackFlags::Clip
| ShowTrackFlags::Split
);
1659 const tools::Long nWidth
= pEditWin
->GetOutDev()->GetOutputSize().Width();
1660 Point aZero
= pEditWin
->GetMapMode().GetOrigin();
1661 if(lTabPosition
!= -1)
1663 pEditWin
->InvertTracking(
1664 tools::Rectangle( Point(-aZero
.X(), lTabPosition
),
1665 Point(-aZero
.X() + nWidth
, lTabPosition
)),
1666 ShowTrackFlags::Split
| ShowTrackFlags::Clip
);
1671 tools::Long nDrapPosition
= GetCorrectedDragPos();
1672 nDrapPosition
= MakePositionSticky(nDrapPosition
, GetLeftFrameMargin());
1673 lTabPosition
= ConvertVSizeLogic(nDrapPosition
+ GetNullOffset());
1675 lTabPosition
+= mxPagePosItem
->GetPos().Y();
1676 pEditWin
->InvertTracking(
1677 tools::Rectangle( Point(-aZero
.X(), lTabPosition
),
1678 Point(-aZero
.X()+nWidth
, lTabPosition
)),
1679 ShowTrackFlags::Clip
| ShowTrackFlags::Split
);
1684 void SvxRuler::DragTabs()
1686 /* Dragging of Tabs */
1687 tools::Long aDragPosition
= GetCorrectedDragPos(true, false);
1688 aDragPosition
= MakePositionSticky(aDragPosition
, GetLeftFrameMargin());
1690 sal_uInt16 nIdx
= GetDragAryPos() + TAB_GAP
;
1691 tools::Long nDiff
= aDragPosition
- mpTabs
[nIdx
].nPos
;
1695 DrawLine_Impl(lTabPos
, 7, bHorz
);
1697 if(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_LINEAR
)
1700 for(sal_uInt16 i
= nIdx
; i
< nTabCount
; ++i
)
1702 mpTabs
[i
].nPos
+= nDiff
;
1704 if(mpTabs
[i
].nPos
> GetMargin2())
1705 mpTabs
[nIdx
].nStyle
|= RULER_STYLE_INVISIBLE
;
1707 mpTabs
[nIdx
].nStyle
&= ~RULER_STYLE_INVISIBLE
;
1710 else if(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)
1712 mxRulerImpl
->nTotalDist
-= nDiff
;
1713 mpTabs
[nIdx
].nPos
= aDragPosition
;
1714 for(sal_uInt16 i
= nIdx
+1; i
< nTabCount
; ++i
)
1716 if(mpTabs
[i
].nStyle
& RULER_TAB_DEFAULT
)
1717 // can be canceled at the DefaultTabs
1719 tools::Long nDelta
= mxRulerImpl
->nTotalDist
* mxRulerImpl
->pPercBuf
[i
];
1721 mpTabs
[i
].nPos
= mpTabs
[nIdx
].nPos
+ nDelta
;
1722 if(mpTabs
[i
].nPos
+ GetNullOffset() > nMaxRight
)
1723 mpTabs
[i
].nStyle
|= RULER_STYLE_INVISIBLE
;
1725 mpTabs
[i
].nStyle
&= ~RULER_STYLE_INVISIBLE
;
1730 mpTabs
[nIdx
].nPos
= aDragPosition
;
1734 mpTabs
[nIdx
].nStyle
|= RULER_STYLE_INVISIBLE
;
1736 mpTabs
[nIdx
].nStyle
&= ~RULER_STYLE_INVISIBLE
;
1737 SetTabs(nTabCount
, mpTabs
.data() + TAB_GAP
);
1740 void SvxRuler::SetActive(bool bOn
)
1750 pBindings
->EnterRegistrations();
1752 for(sal_uInt16 i
=0;i
<mxRulerImpl
->nControllerItems
;i
++)
1753 pCtrlItems
[i
]->ReBind();
1755 for(sal_uInt16 j
=0;j
<mxRulerImpl
->nControllerItems
;j
++)
1756 pCtrlItems
[j
]->UnBind();
1757 pBindings
->LeaveRegistrations();
1762 void SvxRuler::UpdateParaContents_Impl(
1763 tools::Long lDifference
,
1764 UpdateType eType
) // Art (all, left or right)
1766 /* Helper function; carry Tabs and Paragraph Margins */
1769 case UpdateType::MoveRight
:
1770 mpIndents
[INDENT_RIGHT_MARGIN
].nPos
+= lDifference
;
1772 case UpdateType::MoveLeft
:
1774 mpIndents
[INDENT_FIRST_LINE
].nPos
+= lDifference
;
1775 mpIndents
[INDENT_LEFT_MARGIN
].nPos
+= lDifference
;
1776 if (!mpTabs
.empty())
1778 for(sal_uInt16 i
= 0; i
< nTabCount
+TAB_GAP
; ++i
)
1780 mpTabs
[i
].nPos
+= lDifference
;
1782 SetTabs(nTabCount
, mpTabs
.data() + TAB_GAP
);
1787 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
1790 void SvxRuler::DragBorders()
1792 /* Dragging of Borders (Tables and other columns) */
1793 bool bLeftIndentsCorrected
= false;
1794 bool bRightIndentsCorrected
= false;
1797 if(GetDragType() == RulerType::Border
)
1799 DrawLine_Impl(lTabPos
, 7, bHorz
);
1800 nIndex
= GetDragAryPos();
1807 RulerDragSize nDragSize
= GetDragSize();
1808 tools::Long lDiff
= 0;
1810 // the drag position has to be corrected to be able to prevent borders from passing each other
1811 tools::Long lPos
= MakePositionSticky(GetCorrectedDragPos(), GetLeftFrameMargin());
1815 case RulerDragSize::Move
:
1817 if(GetDragType() == RulerType::Border
)
1818 lDiff
= lPos
- nDragOffset
- mpBorders
[nIndex
].nPos
;
1820 lDiff
= GetDragType() == RulerType::Margin1
? lPos
- mxRulerImpl
->lLastLMargin
: lPos
- mxRulerImpl
->lLastRMargin
;
1822 if(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_LINEAR
)
1824 tools::Long nRight
= GetMargin2() - glMinFrame
; // Right limiters
1825 for(int i
= mpBorders
.size() - 2; i
>= nIndex
; --i
)
1827 tools::Long l
= mpBorders
[i
].nPos
;
1828 mpBorders
[i
].nPos
+= lDiff
;
1829 mpBorders
[i
].nPos
= std::min(mpBorders
[i
].nPos
, nRight
- mpBorders
[i
].nWidth
);
1830 nRight
= mpBorders
[i
].nPos
- glMinFrame
;
1831 // RR update the column
1832 if(i
== GetActRightColumn())
1834 UpdateParaContents_Impl(mpBorders
[i
].nPos
- l
, UpdateType::MoveRight
);
1835 bRightIndentsCorrected
= true;
1837 // LAR, EZE update the column
1838 else if(i
== GetActLeftColumn())
1840 UpdateParaContents_Impl(mpBorders
[i
].nPos
- l
, UpdateType::MoveLeft
);
1841 bLeftIndentsCorrected
= true;
1845 else if(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)
1849 int nStartLimit
= mpBorders
.size() - 2;
1850 switch(GetDragType())
1852 default: ;//prevent warning
1853 OSL_FAIL("svx::SvxRuler::DragBorders(), unknown drag type!" );
1855 case RulerType::Border
:
1856 if(mxRulerImpl
->bIsTableRows
)
1858 mpBorders
[nIndex
].nPos
+= lDiff
;
1861 lLeft
= mpBorders
[nIndex
].nPos
;
1862 mxRulerImpl
->nTotalDist
-= lDiff
;
1863 nLimit
= nIndex
+ 1;
1868 nStartLimit
= nIndex
- 1;
1869 mxRulerImpl
->nTotalDist
+= lDiff
;
1875 nLimit
= nIndex
+ 1;
1876 mpBorders
[nIndex
].nPos
+= lDiff
;
1877 lLeft
= mpBorders
[nIndex
].nPos
;
1878 mxRulerImpl
->nTotalDist
-= lDiff
;
1881 case RulerType::Margin1
:
1883 lLeft
= mxRulerImpl
->lLastLMargin
+ lDiff
;
1884 mxRulerImpl
->nTotalDist
-= lDiff
;
1886 case RulerType::Margin2
:
1889 nStartLimit
= mpBorders
.size() - 2;
1890 mxRulerImpl
->nTotalDist
+= lDiff
;
1894 for(int i
= nStartLimit
; i
>= nLimit
; --i
)
1897 tools::Long l
= mpBorders
[i
].nPos
;
1900 (mxRulerImpl
->nTotalDist
* mxRulerImpl
->pPercBuf
[i
]) / 1000 +
1901 mxRulerImpl
->pBlockBuf
[i
];
1903 // RR update the column
1904 if(!mxRulerImpl
->bIsTableRows
)
1906 if(i
== GetActRightColumn())
1908 UpdateParaContents_Impl(mpBorders
[i
].nPos
- l
, UpdateType::MoveRight
);
1909 bRightIndentsCorrected
= true;
1911 // LAR, EZE update the column
1912 else if(i
== GetActLeftColumn())
1914 UpdateParaContents_Impl(mpBorders
[i
].nPos
- l
, UpdateType::MoveLeft
);
1915 bLeftIndentsCorrected
= true;
1919 if(mxRulerImpl
->bIsTableRows
)
1921 //in vertical tables the left borders have to be moved
1924 for(int i
= 0; i
< nIndex
; ++i
)
1925 mpBorders
[i
].nPos
+= lDiff
;
1926 AdjustMargin1(lDiff
);
1930 //otherwise the right borders are moved
1931 for(int i
= mxColumnItem
->Count() - 1; i
> nIndex
; --i
)
1932 mpBorders
[i
].nPos
+= lDiff
;
1933 SetMargin2( GetMargin2() + lDiff
, RulerMarginStyle::NONE
);
1937 else if(mxRulerImpl
->bIsTableRows
)
1939 //moving rows: if a row is resized all following rows
1940 //have to be moved by the same amount.
1941 //This includes the left border when the table is not limited
1942 //to a lower frame border.
1944 if(GetDragType()==RulerType::Border
)
1946 nLimit
= nIndex
+ 1;
1947 mpBorders
[nIndex
].nPos
+= lDiff
;
1953 //in vertical tables the left borders have to be moved
1956 for(int i
= 0; i
< nIndex
; ++i
)
1958 mpBorders
[i
].nPos
+= lDiff
;
1960 AdjustMargin1(lDiff
);
1964 //otherwise the right borders are moved
1965 for(int i
= mpBorders
.size() - 2; i
>= nLimit
; --i
)
1967 mpBorders
[i
].nPos
+= lDiff
;
1969 SetMargin2( GetMargin2() + lDiff
, RulerMarginStyle::NONE
);
1973 mpBorders
[nIndex
].nPos
+= lDiff
;
1976 case RulerDragSize::N1
:
1978 lDiff
= lPos
- mpBorders
[nIndex
].nPos
;
1979 mpBorders
[nIndex
].nWidth
+= mpBorders
[nIndex
].nPos
- lPos
;
1980 mpBorders
[nIndex
].nPos
= lPos
;
1983 case RulerDragSize::N2
:
1985 const tools::Long nOld
= mpBorders
[nIndex
].nWidth
;
1986 mpBorders
[nIndex
].nWidth
= lPos
- mpBorders
[nIndex
].nPos
;
1987 lDiff
= mpBorders
[nIndex
].nWidth
- nOld
;
1991 if(!bRightIndentsCorrected
&&
1992 GetActRightColumn() == nIndex
&&
1993 nDragSize
!= RulerDragSize::N2
&&
1994 !mpIndents
.empty() &&
1995 !mxRulerImpl
->bIsTableRows
)
1997 UpdateParaContents_Impl(lDiff
, UpdateType::MoveRight
);
1999 else if(!bLeftIndentsCorrected
&&
2000 GetActLeftColumn() == nIndex
&&
2001 nDragSize
!= RulerDragSize::N1
&&
2004 UpdateParaContents_Impl(lDiff
, UpdateType::MoveLeft
);
2006 SetBorders(mxColumnItem
->Count() - 1, mpBorders
.data());
2009 void SvxRuler::DragObjectBorder()
2011 /* Dragging of object edges */
2012 if(RulerDragSize::Move
== GetDragSize())
2014 const tools::Long lPosition
= MakePositionSticky(GetCorrectedDragPos(), GetLeftFrameMargin());
2016 const sal_uInt16 nIdx
= GetDragAryPos();
2017 mpObjectBorders
[GetObjectBordersOff(nIdx
)].nPos
= lPosition
;
2018 SetBorders(2, mpObjectBorders
.data() + GetObjectBordersOff(0));
2019 DrawLine_Impl(lTabPos
, 7, bHorz
);
2024 void SvxRuler::ApplyMargins()
2026 /* Applying margins; changed by dragging. */
2027 const SfxPoolItem
* pItem
= nullptr;
2028 sal_uInt16 nId
= SID_ATTR_LONG_LRSPACE
;
2032 const tools::Long lOldNull
= lLogicNullOffset
;
2033 if(mxRulerImpl
->lMaxLeftLogic
!= -1 && nMaxLeft
== GetMargin1() + Ruler::GetNullOffset())
2035 lLogicNullOffset
= mxRulerImpl
->lMaxLeftLogic
;
2036 mxLRSpaceItem
->SetLeft(lLogicNullOffset
);
2040 lLogicNullOffset
= ConvertHPosLogic(GetFrameLeft()) - lAppNullOffset
;
2041 mxLRSpaceItem
->SetLeft(PixelHAdjust(lLogicNullOffset
, mxLRSpaceItem
->GetLeft()));
2044 if(bAppSetNullOffset
)
2046 lAppNullOffset
+= lLogicNullOffset
- lOldNull
;
2050 if(mxRulerImpl
->lMaxRightLogic
!= -1
2051 && nMaxRight
== GetMargin2() + Ruler::GetNullOffset())
2053 nRight
= GetPageWidth() - mxRulerImpl
->lMaxRightLogic
;
2057 nRight
= std::max(tools::Long(0),
2058 mxPagePosItem
->GetWidth() - mxLRSpaceItem
->GetLeft() -
2059 (ConvertHPosLogic(GetMargin2()) - lAppNullOffset
));
2061 nRight
= PixelHAdjust( nRight
, mxLRSpaceItem
->GetRight());
2063 mxLRSpaceItem
->SetRight(nRight
);
2065 pItem
= mxLRSpaceItem
.get();
2068 Debug_Impl(pEditWin
, *mxLRSpaceItem
);
2074 const tools::Long lOldNull
= lLogicNullOffset
;
2076 ConvertVPosLogic(GetFrameLeft()) -
2078 mxULSpaceItem
->SetUpper(
2079 PixelVAdjust(lLogicNullOffset
, mxULSpaceItem
->GetUpper()));
2080 if(bAppSetNullOffset
)
2082 lAppNullOffset
+= lLogicNullOffset
- lOldNull
;
2084 mxULSpaceItem
->SetLower(
2086 std::max(tools::Long(0), mxPagePosItem
->GetHeight() -
2087 mxULSpaceItem
->GetUpper() -
2088 (ConvertVPosLogic(GetMargin2()) -
2089 lAppNullOffset
)), mxULSpaceItem
->GetLower()));
2090 pItem
= mxULSpaceItem
.get();
2091 nId
= SID_ATTR_LONG_ULSPACE
;
2094 Debug_Impl(pEditWin
,*mxULSpaceItem
);
2098 pBindings
->GetDispatcher()->ExecuteList(nId
, SfxCallMode::RECORD
, { pItem
});
2103 tools::Long
SvxRuler::RoundToCurrentMapMode(tools::Long lValue
) const
2105 RulerUnitData aUnitData
= GetCurrentRulerUnit();
2106 double aRoundingFactor
= aUnitData
.nTickUnit
/ aUnitData
.nTick1
;
2108 tools::Long lNewValue
= OutputDevice::LogicToLogic(Size(lValue
, 0), pEditWin
->GetMapMode(), GetCurrentMapMode()).Width();
2109 lNewValue
= (rtl::math::round(lNewValue
/ static_cast<double>(aUnitData
.nTickUnit
) * aRoundingFactor
) / aRoundingFactor
) * aUnitData
.nTickUnit
;
2110 return OutputDevice::LogicToLogic(Size(lNewValue
, 0), GetCurrentMapMode(), pEditWin
->GetMapMode()).Width();
2113 void SvxRuler::ApplyIndents()
2115 /* Applying paragraph settings; changed by dragging. */
2117 tools::Long nLeftFrameMargin
= GetLeftFrameMargin();
2119 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
2121 tools::Long nNewTxtLeft
;
2122 tools::Long nNewFirstLineOffset
;
2123 tools::Long nNewRight
;
2125 tools::Long nFirstLine
= ConvertPosLogic(mpIndents
[INDENT_FIRST_LINE
].nPos
);
2126 tools::Long nLeftMargin
= ConvertPosLogic(mpIndents
[INDENT_LEFT_MARGIN
].nPos
);
2127 tools::Long nRightMargin
= ConvertPosLogic(mpIndents
[INDENT_RIGHT_MARGIN
].nPos
);
2129 if(mxColumnItem
&& ((bRTL
&& !IsActLastColumn(true)) || (!bRTL
&& !IsActFirstColumn(true))))
2133 tools::Long nRightColumn
= GetActRightColumn(true);
2134 tools::Long nRightBorder
= ConvertPosLogic(mpBorders
[nRightColumn
].nPos
);
2135 nNewTxtLeft
= nRightBorder
- nLeftMargin
- lAppNullOffset
;
2139 tools::Long nLeftColumn
= GetActLeftColumn(true);
2140 tools::Long nLeftBorder
= ConvertPosLogic(mpBorders
[nLeftColumn
].nPos
+ mpBorders
[nLeftColumn
].nWidth
);
2141 nNewTxtLeft
= nLeftMargin
- nLeftBorder
- lAppNullOffset
;
2148 tools::Long nRightBorder
= ConvertPosLogic(GetMargin2());
2149 nNewTxtLeft
= nRightBorder
- nLeftMargin
- lAppNullOffset
;
2153 tools::Long nLeftBorder
= ConvertPosLogic(GetMargin1());
2154 nNewTxtLeft
= nLeftBorder
+ nLeftMargin
- nLeftFrameMargin
- lAppNullOffset
;
2159 nNewFirstLineOffset
= nLeftMargin
- nFirstLine
- lAppNullOffset
;
2161 nNewFirstLineOffset
= nFirstLine
- nLeftMargin
- lAppNullOffset
;
2163 if(mxColumnItem
&& ((!bRTL
&& !IsActLastColumn(true)) || (bRTL
&& !IsActFirstColumn(true))))
2167 tools::Long nLeftColumn
= GetActLeftColumn(true);
2168 tools::Long nLeftBorder
= ConvertPosLogic(mpBorders
[nLeftColumn
].nPos
+ mpBorders
[nLeftColumn
].nWidth
);
2169 nNewRight
= nRightMargin
- nLeftBorder
- lAppNullOffset
;
2173 tools::Long nRightColumn
= GetActRightColumn(true);
2174 tools::Long nRightBorder
= ConvertPosLogic(mpBorders
[nRightColumn
].nPos
);
2175 nNewRight
= nRightBorder
- nRightMargin
- lAppNullOffset
;
2182 tools::Long nLeftBorder
= ConvertPosLogic(GetMargin1());
2183 nNewRight
= nLeftBorder
+ nRightMargin
- nLeftFrameMargin
- lAppNullOffset
;
2187 tools::Long nRightBorder
= ConvertPosLogic(GetMargin2());
2188 nNewRight
= nRightBorder
- nRightMargin
- lAppNullOffset
;
2194 nNewTxtLeft
= RoundToCurrentMapMode(nNewTxtLeft
);
2195 nNewFirstLineOffset
= RoundToCurrentMapMode(nNewFirstLineOffset
);
2196 nNewRight
= RoundToCurrentMapMode(nNewRight
);
2199 mxParaItem
->SetTextFirstLineOffset(SvxIndentValue::twips(nNewFirstLineOffset
));
2200 mxParaItem
->SetTextLeft(SvxIndentValue::twips(nNewTxtLeft
));
2201 mxParaItem
->SetRight(SvxIndentValue::twips(nNewRight
));
2203 sal_uInt16 nParagraphId
= bHorz
? SID_ATTR_PARA_LRSPACE
: SID_ATTR_PARA_LRSPACE_VERTICAL
;
2204 pBindings
->GetDispatcher()->ExecuteList(nParagraphId
, SfxCallMode::RECORD
,
2205 { mxParaItem
.get() });
2209 void SvxRuler::ApplyTabs()
2211 /* Apply tab settings, changed by dragging. */
2212 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
2213 const sal_uInt16 nCoreIdx
= GetDragAryPos();
2216 mxTabStopItem
->Remove(nCoreIdx
);
2218 else if(SvxRulerDragFlags::OBJECT_SIZE_LINEAR
& nDragType
||
2219 SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
& nDragType
)
2221 SvxTabStopItem
*pItem
= new SvxTabStopItem(mxTabStopItem
->Which());
2222 //remove default tab stops
2223 for ( sal_uInt16 i
= 0; i
< pItem
->Count(); )
2225 if ( SvxTabAdjust::Default
== (*pItem
)[i
].GetAdjustment() )
2234 for(j
= 0; j
< nCoreIdx
; ++j
)
2236 pItem
->Insert(mxTabStopItem
->At(j
));
2238 for(; j
< mxTabStopItem
->Count(); ++j
)
2240 SvxTabStop aTabStop
= mxTabStopItem
->At(j
);
2241 aTabStop
.GetTabPos() = PixelHAdjust(
2243 mpTabs
[j
+ TAB_GAP
].nPos
- GetLeftIndent()) - lAppNullOffset
,
2244 aTabStop
.GetTabPos());
2245 pItem
->Insert(aTabStop
);
2247 mxTabStopItem
.reset(pItem
);
2249 else if( mxTabStopItem
->Count() == 0 )
2253 SvxTabStop aTabStop
= mxTabStopItem
->At(nCoreIdx
);
2254 if( mxRulerImpl
->lMaxRightLogic
!= -1 &&
2255 mpTabs
[nCoreIdx
+ TAB_GAP
].nPos
+ Ruler::GetNullOffset() == nMaxRight
)
2257 // Set tab pos exactly at the right indent
2258 tools::Long nTmpLeftIndentLogic
2259 = lAppNullOffset
+ (bRTL
? GetRightFrameMargin() : GetLeftFrameMargin());
2260 if (mxRulerImpl
->bIsTabsRelativeToIndent
&& mxParaItem
)
2263 += bRTL
? mxParaItem
->ResolveRight({}) : mxParaItem
->ResolveTextLeft({});
2265 aTabStop
.GetTabPos()
2266 = mxRulerImpl
->lMaxRightLogic
- lLogicNullOffset
- nTmpLeftIndentLogic
;
2272 //#i24363# tab stops relative to indent
2273 const tools::Long nTmpLeftIndent
= mxRulerImpl
->bIsTabsRelativeToIndent
?
2275 ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset
);
2277 tools::Long nNewPosition
= ConvertHPosLogic(nTmpLeftIndent
- mpTabs
[nCoreIdx
+ TAB_GAP
].nPos
);
2278 aTabStop
.GetTabPos() = PixelHAdjust(nNewPosition
- lAppNullOffset
, aTabStop
.GetTabPos());
2282 //#i24363# tab stops relative to indent
2283 const tools::Long nTmpLeftIndent
= mxRulerImpl
->bIsTabsRelativeToIndent
?
2285 ConvertHPosPixel( GetLeftFrameMargin() + lAppNullOffset
);
2287 tools::Long nNewPosition
= ConvertHPosLogic(mpTabs
[nCoreIdx
+ TAB_GAP
].nPos
- nTmpLeftIndent
);
2288 aTabStop
.GetTabPos() = PixelHAdjust(nNewPosition
- lAppNullOffset
, aTabStop
.GetTabPos());
2291 mxTabStopItem
->Remove(nCoreIdx
);
2292 mxTabStopItem
->Insert(aTabStop
);
2294 sal_uInt16 nTabStopId
= bHorz
? SID_ATTR_TABSTOP
: SID_ATTR_TABSTOP_VERTICAL
;
2295 pBindings
->GetDispatcher()->ExecuteList(nTabStopId
, SfxCallMode::RECORD
,
2296 { mxTabStopItem
.get() });
2300 void SvxRuler::ApplyBorders()
2302 /* Applying (table) column settings; changed by dragging. */
2303 if(mxColumnItem
->IsTable())
2305 tools::Long lValue
= GetFrameLeft();
2306 if(lValue
!= mxRulerImpl
->nColLeftPix
)
2308 tools::Long nLeft
= PixelHAdjust(
2309 ConvertHPosLogic(lValue
) -
2311 mxColumnItem
->GetLeft());
2312 mxColumnItem
->SetLeft(nLeft
);
2315 lValue
= GetMargin2();
2317 if(lValue
!= mxRulerImpl
->nColRightPix
)
2319 tools::Long nWidthOrHeight
= bHorz
? mxPagePosItem
->GetWidth() : mxPagePosItem
->GetHeight();
2320 tools::Long nRight
= PixelHAdjust(
2322 mxColumnItem
->GetLeft() -
2323 ConvertHPosLogic(lValue
) -
2325 mxColumnItem
->GetRight() );
2326 mxColumnItem
->SetRight(nRight
);
2330 for(sal_uInt16 i
= 0; i
< mxColumnItem
->Count() - 1; ++i
)
2332 tools::Long
& nEnd
= mxColumnItem
->At(i
).nEnd
;
2333 nEnd
= PixelHAdjust(
2334 ConvertPosLogic(mpBorders
[i
].nPos
),
2335 mxColumnItem
->At(i
).nEnd
);
2336 tools::Long
& nStart
= mxColumnItem
->At(i
+ 1).nStart
;
2337 nStart
= PixelHAdjust(
2338 ConvertSizeLogic(mpBorders
[i
].nPos
+
2339 mpBorders
[i
].nWidth
) -
2341 mxColumnItem
->At(i
+ 1).nStart
);
2342 // It may be that, due to the PixelHAdjust readjustment to old values,
2343 // the width becomes < 0. This we readjust.
2349 Debug_Impl(pEditWin
,*mxColumnItem
);
2352 SfxBoolItem
aFlag(SID_RULER_ACT_LINE_ONLY
,
2353 bool(nDragType
& SvxRulerDragFlags::OBJECT_ACTLINE_ONLY
));
2355 sal_uInt16 nColId
= mxRulerImpl
->bIsTableRows
? (bHorz
? SID_RULER_ROWS
: SID_RULER_ROWS_VERTICAL
) :
2356 (bHorz
? SID_RULER_BORDERS
: SID_RULER_BORDERS_VERTICAL
);
2358 pBindings
->GetDispatcher()->ExecuteList(nColId
, SfxCallMode::RECORD
,
2359 { mxColumnItem
.get(), &aFlag
});
2362 void SvxRuler::ApplyObject()
2364 /* Applying object settings, changed by dragging. */
2366 // to the page margin
2367 tools::Long nMargin
= mxLRSpaceItem
? mxLRSpaceItem
->GetLeft() : 0;
2368 tools::Long nStartX
= PixelAdjust(
2369 ConvertPosLogic(mpObjectBorders
[0].nPos
) +
2372 mxObjectItem
->GetStartX());
2373 mxObjectItem
->SetStartX(nStartX
);
2375 tools::Long nEndX
= PixelAdjust(
2376 ConvertPosLogic(mpObjectBorders
[1].nPos
) +
2379 mxObjectItem
->GetEndX());
2380 mxObjectItem
->SetEndX(nEndX
);
2382 nMargin
= mxULSpaceItem
? mxULSpaceItem
->GetUpper() : 0;
2383 tools::Long nStartY
= PixelAdjust(
2384 ConvertPosLogic(mpObjectBorders
[2].nPos
) +
2387 mxObjectItem
->GetStartY());
2388 mxObjectItem
->SetStartY(nStartY
);
2390 tools::Long nEndY
= PixelAdjust(
2391 ConvertPosLogic(mpObjectBorders
[3].nPos
) +
2394 mxObjectItem
->GetEndY());
2395 mxObjectItem
->SetEndY(nEndY
);
2397 pBindings
->GetDispatcher()->ExecuteList(SID_RULER_OBJECT
,
2398 SfxCallMode::RECORD
, { mxObjectItem
.get() });
2401 void SvxRuler::PrepareProportional_Impl(RulerType eType
)
2404 Preparation proportional dragging, and it is calculated based on the
2405 proportional share of the total width in parts per thousand.
2407 mxRulerImpl
->nTotalDist
= GetMargin2();
2410 case RulerType::Margin2
:
2411 case RulerType::Margin1
:
2412 case RulerType::Border
:
2414 DBG_ASSERT(mxColumnItem
, "no ColumnItem");
2416 mxRulerImpl
->SetPercSize(mxColumnItem
->Count());
2419 tools::Long lWidth
=0;
2421 sal_uInt16 nIdx
=GetDragAryPos();
2422 tools::Long lActWidth
=0;
2423 tools::Long lActBorderSum
;
2424 tools::Long lOrigLPos
;
2426 if(eType
!= RulerType::Border
)
2428 lOrigLPos
= GetMargin1();
2434 if(mxRulerImpl
->bIsTableRows
&&!bHorz
)
2436 lOrigLPos
= GetMargin1();
2441 lOrigLPos
= mpBorders
[nIdx
].nPos
+ mpBorders
[nIdx
].nWidth
;
2444 lActBorderSum
= mpBorders
[nIdx
].nWidth
;
2447 //in horizontal mode the percentage value has to be
2448 //calculated on a "current change" position base
2449 //because the height of the table changes while dragging
2450 if(mxRulerImpl
->bIsTableRows
&& RulerType::Border
== eType
)
2452 sal_uInt16 nStartBorder
;
2453 sal_uInt16 nEndBorder
;
2456 nStartBorder
= nIdx
+ 1;
2457 nEndBorder
= mxColumnItem
->Count() - 1;
2465 lWidth
= mpBorders
[nIdx
].nPos
;
2467 lWidth
= GetMargin2() - lWidth
;
2468 mxRulerImpl
->nTotalDist
= lWidth
;
2469 lPos
= mpBorders
[nIdx
].nPos
;
2471 for(sal_uInt16 i
= nStartBorder
; i
< nEndBorder
; ++i
)
2475 lActWidth
+= mpBorders
[i
].nPos
- lPos
;
2476 lPos
= mpBorders
[i
].nPos
+ mpBorders
[i
].nWidth
;
2479 lActWidth
= mpBorders
[i
].nPos
;
2480 mxRulerImpl
->pPercBuf
[i
] = static_cast<sal_uInt16
>((lActWidth
* 1000)
2481 / mxRulerImpl
->nTotalDist
);
2482 mxRulerImpl
->pBlockBuf
[i
] = static_cast<sal_uInt16
>(lActBorderSum
);
2483 lActBorderSum
+= mpBorders
[i
].nWidth
;
2489 for(sal_uInt16 ii
= nStart
; ii
< mxColumnItem
->Count() - 1; ++ii
)
2491 lWidth
+= mpBorders
[ii
].nPos
- lPos
;
2492 lPos
= mpBorders
[ii
].nPos
+ mpBorders
[ii
].nWidth
;
2495 lWidth
+= GetMargin2() - lPos
;
2496 mxRulerImpl
->nTotalDist
= lWidth
;
2499 for(sal_uInt16 i
= nStart
; i
< mxColumnItem
->Count() - 1; ++i
)
2501 lActWidth
+= mpBorders
[i
].nPos
- lPos
;
2502 lPos
= mpBorders
[i
].nPos
+ mpBorders
[i
].nWidth
;
2503 mxRulerImpl
->pPercBuf
[i
] = static_cast<sal_uInt16
>((lActWidth
* 1000)
2504 / mxRulerImpl
->nTotalDist
);
2505 mxRulerImpl
->pBlockBuf
[i
] = static_cast<sal_uInt16
>(lActBorderSum
);
2506 lActBorderSum
+= mpBorders
[i
].nWidth
;
2511 case RulerType::Tab
:
2513 const sal_uInt16 nIdx
= GetDragAryPos()+TAB_GAP
;
2514 mxRulerImpl
->nTotalDist
-= mpTabs
[nIdx
].nPos
;
2515 mxRulerImpl
->SetPercSize(nTabCount
);
2516 for(sal_uInt16 n
=0;n
<=nIdx
;mxRulerImpl
->pPercBuf
[n
++]=0) ;
2517 for(sal_uInt16 i
= nIdx
+1; i
< nTabCount
; ++i
)
2519 const tools::Long nDelta
= mpTabs
[i
].nPos
- mpTabs
[nIdx
].nPos
;
2520 mxRulerImpl
->pPercBuf
[i
] = static_cast<sal_uInt16
>((nDelta
* 1000) / mxRulerImpl
->nTotalDist
);
2528 void SvxRuler::EvalModifier()
2533 Control: move proportional
2534 Shift + Control: Table: only current line
2535 Alt: disable snapping
2536 Alt + Shift: coarse snapping
2539 sal_uInt16 nModifier
= GetDragModifier();
2540 if(mxRulerImpl
->bIsTableRows
)
2542 //rows can only be moved in one way, additionally current column is possible
2543 if(nModifier
== KEY_SHIFT
)
2550 nDragType
= SvxRulerDragFlags::OBJECT_SIZE_LINEAR
;
2552 case KEY_MOD2
| KEY_SHIFT
:
2553 mbCoarseSnapping
= true;
2560 const RulerType eType
= GetDragType();
2561 nDragType
= SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
;
2562 if( RulerType::Tab
== eType
||
2563 ( ( RulerType::Border
== eType
||
2564 RulerType::Margin1
== eType
||
2565 RulerType::Margin2
== eType
) &&
2568 PrepareProportional_Impl(eType
);
2572 case KEY_MOD1
| KEY_SHIFT
:
2573 if( GetDragType() != RulerType::Margin1
&&
2574 GetDragType() != RulerType::Margin2
)
2576 nDragType
= SvxRulerDragFlags::OBJECT_ACTLINE_ONLY
;
2582 void SvxRuler::Click()
2584 /* Override handler SV; sets Tab per dispatcher call */
2588 pBindings
->Update( SID_RULER_LR_MIN_MAX
);
2589 pBindings
->Update( SID_ATTR_LONG_ULSPACE
);
2590 pBindings
->Update( SID_ATTR_LONG_LRSPACE
);
2591 pBindings
->Update( SID_RULER_PAGE_POS
);
2592 pBindings
->Update( bHorz
? SID_ATTR_TABSTOP
: SID_ATTR_TABSTOP_VERTICAL
);
2593 pBindings
->Update( bHorz
? SID_ATTR_PARA_LRSPACE
: SID_ATTR_PARA_LRSPACE_VERTICAL
);
2594 pBindings
->Update( bHorz
? SID_RULER_BORDERS
: SID_RULER_BORDERS_VERTICAL
);
2595 pBindings
->Update( bHorz
? SID_RULER_ROWS
: SID_RULER_ROWS_VERTICAL
);
2596 pBindings
->Update( SID_RULER_OBJECT
);
2597 pBindings
->Update( SID_RULER_PROTECT
);
2598 pBindings
->Update( SID_ATTR_PARA_LRSPACE_VERTICAL
);
2600 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
2601 if(!(mxTabStopItem
&&
2602 (nFlags
& SvxRulerSupportFlags::TABS
) == SvxRulerSupportFlags::TABS
))
2605 bool bContentProtected
= mxRulerImpl
->aProtectItem
->IsContentProtected();
2606 if( bContentProtected
) return;
2607 const tools::Long lPos
= GetClickPos();
2608 if(!((bRTL
&& lPos
< std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos
> GetRightIndent()) ||
2609 (!bRTL
&& lPos
> std::min(GetFirstLineIndent(), GetLeftIndent()) && lPos
< GetRightIndent())))
2612 //convert position in left-to-right text
2613 tools::Long nTabPos
;
2614 //#i24363# tab stops relative to indent
2616 nTabPos
= ( mxRulerImpl
->bIsTabsRelativeToIndent
?
2618 ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset
) ) -
2622 ( mxRulerImpl
->bIsTabsRelativeToIndent
?
2624 ConvertHPosPixel( GetLeftFrameMargin() + lAppNullOffset
));
2626 SvxTabStop
aTabStop(ConvertHPosLogic(nTabPos
),
2627 ToAttrTab_Impl(nDefTabType
));
2628 mxTabStopItem
->Insert(aTabStop
);
2632 void SvxRuler::CalcMinMax()
2635 Calculates the limits for dragging; which are in pixels relative to the
2638 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
2639 const tools::Long lNullPix
= ConvertPosPixel(lLogicNullOffset
);
2640 mxRulerImpl
->lMaxLeftLogic
=mxRulerImpl
->lMaxRightLogic
=-1;
2641 switch(GetDragType())
2643 case RulerType::Margin1
:
2644 { // left edge of the surrounding Frame
2645 // DragPos - NOf between left - right
2646 mxRulerImpl
->lMaxLeftLogic
= GetLeftMin();
2647 nMaxLeft
=ConvertSizePixel(mxRulerImpl
->lMaxLeftLogic
);
2649 if (!mxColumnItem
|| mxColumnItem
->Count() == 1)
2653 nMaxRight
= lNullPix
- GetRightIndent() +
2654 std::max(GetFirstLineIndent(), GetLeftIndent()) -
2659 nMaxRight
= lNullPix
+ GetRightIndent() -
2660 std::max(GetFirstLineIndent(), GetLeftIndent()) -
2664 else if(mxRulerImpl
->bIsTableRows
)
2666 //top border is not moveable when table rows are displayed
2667 // protection of content means the margin is not moveable
2668 if(bHorz
&& !mxRulerImpl
->aProtectItem
->IsContentProtected())
2670 nMaxLeft
= mpBorders
[0].nMinPos
+ lNullPix
;
2671 if(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)
2672 nMaxRight
= GetRightIndent() + lNullPix
-
2673 (mxColumnItem
->Count() - 1 ) * glMinFrame
;
2675 nMaxRight
= mpBorders
[0].nPos
- glMinFrame
+ lNullPix
;
2678 nMaxLeft
= nMaxRight
= lNullPix
;
2682 if (nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)
2684 nMaxRight
=lNullPix
+CalcPropMaxRight();
2686 else if (nDragType
& SvxRulerDragFlags::OBJECT_SIZE_LINEAR
)
2688 nMaxRight
= ConvertPosPixel(
2690 (mxColumnItem
->IsTable() && mxLRSpaceItem
)
2691 ? mxLRSpaceItem
->GetRight() : 0))
2692 - GetMargin2() + GetMargin1();
2696 nMaxRight
= lNullPix
- glMinFrame
;
2697 if (mxColumnItem
->IsFirstAct())
2701 nMaxRight
+= std::min(
2703 std::max(GetFirstLineIndent(), GetLeftIndent()) - GetRightIndent());
2707 nMaxRight
+= std::min(
2708 mpBorders
[0].nPos
, GetRightIndent() -
2709 std::max(GetFirstLineIndent(), GetLeftIndent()));
2712 else if ( mxColumnItem
->Count() > 1 )
2714 nMaxRight
+= mpBorders
[0].nPos
;
2718 nMaxRight
+= GetRightIndent() - std::max(GetFirstLineIndent(), GetLeftIndent());
2720 // Do not drag the left table edge over the edge of the page
2721 if(mxLRSpaceItem
&& mxColumnItem
->IsTable())
2723 tools::Long nTmp
=ConvertSizePixel(mxLRSpaceItem
->GetLeft());
2731 case RulerType::Margin2
:
2732 { // right edge of the surrounding Frame
2733 mxRulerImpl
->lMaxRightLogic
2734 = mxMinMaxItem
? GetPageWidth() - GetRightMax() : GetPageWidth();
2735 nMaxRight
= ConvertSizePixel(mxRulerImpl
->lMaxRightLogic
);
2741 nMaxLeft
= GetMargin2() + GetRightIndent() -
2742 std::max(GetFirstLineIndent(),GetLeftIndent()) - GetMargin1()+
2743 glMinFrame
+ lNullPix
;
2747 nMaxLeft
= GetMargin2() - GetRightIndent() +
2748 std::max(GetFirstLineIndent(),GetLeftIndent()) - GetMargin1()+
2749 glMinFrame
+ lNullPix
;
2752 else if(mxRulerImpl
->bIsTableRows
)
2754 // get the bottom move range from the last border position - only available for rows!
2755 // protection of content means the margin is not moveable
2756 if(bHorz
|| mxRulerImpl
->aProtectItem
->IsContentProtected())
2758 nMaxLeft
= nMaxRight
= mpBorders
[mxColumnItem
->Count() - 1].nMaxPos
+ lNullPix
;
2762 if(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)
2764 nMaxLeft
= (mxColumnItem
->Count()) * glMinFrame
+ lNullPix
;
2768 if(mxColumnItem
->Count() > 1)
2769 nMaxLeft
= mpBorders
[mxColumnItem
->Count() - 2].nPos
+ glMinFrame
+ lNullPix
;
2771 nMaxLeft
= glMinFrame
+ lNullPix
;
2773 if(mxColumnItem
->Count() > 1)
2774 nMaxRight
= mpBorders
[mxColumnItem
->Count() - 2].nMaxPos
+ lNullPix
;
2776 nMaxRight
-= GetRightIndent() - lNullPix
;
2781 nMaxLeft
= glMinFrame
+ lNullPix
;
2782 if(IsActLastColumn() || mxColumnItem
->Count() < 2 ) //If last active column
2786 nMaxLeft
= glMinFrame
+ lNullPix
+ GetMargin2() +
2787 GetRightIndent() - std::max(GetFirstLineIndent(),
2792 nMaxLeft
= glMinFrame
+ lNullPix
+ GetMargin2() -
2793 GetRightIndent() + std::max(GetFirstLineIndent(),
2797 if( mxColumnItem
->Count() >= 2 )
2799 tools::Long nNewMaxLeft
=
2800 glMinFrame
+ lNullPix
+
2801 mpBorders
[mxColumnItem
->Count() - 2].nPos
+
2802 mpBorders
[mxColumnItem
->Count() - 2].nWidth
;
2803 nMaxLeft
= std::max(nMaxLeft
, nNewMaxLeft
);
2809 case RulerType::Border
:
2810 { // Table, column (Modifier)
2811 const sal_uInt16 nIdx
= GetDragAryPos();
2812 switch(GetDragSize())
2814 case RulerDragSize::N1
:
2816 nMaxRight
= mpBorders
[nIdx
].nPos
+
2817 mpBorders
[nIdx
].nWidth
+ lNullPix
;
2820 nMaxLeft
= lNullPix
;
2822 nMaxLeft
= mpBorders
[nIdx
- 1].nPos
+ mpBorders
[nIdx
- 1].nWidth
+ lNullPix
;
2823 if (mxColumnItem
&& nIdx
== mxColumnItem
->GetActColumn())
2827 nMaxLeft
+= mpBorders
[nIdx
].nPos
+
2828 GetRightIndent() - std::max(GetFirstLineIndent(),
2833 nMaxLeft
+= mpBorders
[nIdx
].nPos
-
2834 GetRightIndent() + std::max(GetFirstLineIndent(),
2838 nMaxLeft
-= mpBorders
[nIdx
-1].nPos
+
2839 mpBorders
[nIdx
-1].nWidth
;
2841 nMaxLeft
+= glMinFrame
;
2842 nMaxLeft
+= nDragOffset
;
2845 case RulerDragSize::Move
:
2849 //nIdx contains the position of the currently moved item
2850 //next visible separator on the left
2851 sal_uInt16 nLeftCol
=GetActLeftColumn(false, nIdx
);
2852 //next visible separator on the right
2853 sal_uInt16 nRightCol
=GetActRightColumn(false, nIdx
);
2854 //next separator on the left - regardless if visible or not
2855 sal_uInt16 nActLeftCol
=GetActLeftColumn();
2856 //next separator on the right - regardless if visible or not
2857 sal_uInt16 nActRightCol
=GetActRightColumn();
2858 if(mxColumnItem
->IsTable())
2860 if(nDragType
& SvxRulerDragFlags::OBJECT_ACTLINE_ONLY
)
2862 //the current row/column should be modified only
2863 //then the next/previous visible border position
2864 //marks the min/max positions
2865 nMaxLeft
= nLeftCol
== USHRT_MAX
?
2867 mpBorders
[nLeftCol
].nPos
;
2868 //rows can always be increased without a limit
2869 if(mxRulerImpl
->bIsTableRows
)
2870 nMaxRight
= mpBorders
[nIdx
].nMaxPos
;
2872 nMaxRight
= nRightCol
== USHRT_MAX
?
2874 mpBorders
[nRightCol
].nPos
;
2875 nMaxLeft
+= lNullPix
;
2876 nMaxRight
+= lNullPix
;
2880 if(SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
& nDragType
&& !bHorz
&& mxRulerImpl
->bIsTableRows
)
2881 nMaxLeft
= (nIdx
+ 1) * glMinFrame
+ lNullPix
;
2883 nMaxLeft
= mpBorders
[nIdx
].nMinPos
+ lNullPix
;
2884 if((SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
& nDragType
) ||
2885 (SvxRulerDragFlags::OBJECT_SIZE_LINEAR
& nDragType
) )
2887 if(mxRulerImpl
->bIsTableRows
)
2890 nMaxRight
= GetRightIndent() + lNullPix
-
2891 (mxColumnItem
->Count() - nIdx
- 1) * glMinFrame
;
2893 nMaxRight
= mpBorders
[nIdx
].nMaxPos
+ lNullPix
;
2896 nMaxRight
=lNullPix
+CalcPropMaxRight(nIdx
);
2899 nMaxRight
= mpBorders
[nIdx
].nMaxPos
+ lNullPix
;
2901 nMaxLeft
+= glMinFrame
;
2902 nMaxRight
-= glMinFrame
;
2907 if(nLeftCol
==USHRT_MAX
)
2910 nMaxLeft
= mpBorders
[nLeftCol
].nPos
+
2911 mpBorders
[nLeftCol
].nWidth
+ lNullPix
;
2913 if(nActRightCol
== nIdx
)
2917 nMaxLeft
+= mpBorders
[nIdx
].nPos
+
2918 GetRightIndent() - std::max(GetFirstLineIndent(),
2920 if(nActLeftCol
!=USHRT_MAX
)
2921 nMaxLeft
-= mpBorders
[nActLeftCol
].nPos
+
2922 mpBorders
[nActLeftCol
].nWidth
;
2926 nMaxLeft
+= mpBorders
[nIdx
].nPos
-
2927 GetRightIndent() + std::max(GetFirstLineIndent(),
2929 if(nActLeftCol
!=USHRT_MAX
)
2930 nMaxLeft
-= mpBorders
[nActLeftCol
].nPos
+
2931 mpBorders
[nActLeftCol
].nWidth
;
2934 nMaxLeft
+= glMinFrame
;
2935 nMaxLeft
+= nDragOffset
;
2938 // linear / proportional move
2939 if((SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
& nDragType
) ||
2940 (SvxRulerDragFlags::OBJECT_SIZE_LINEAR
& nDragType
) )
2942 nMaxRight
=lNullPix
+CalcPropMaxRight(nIdx
);
2944 else if(SvxRulerDragFlags::OBJECT_SIZE_LINEAR
& nDragType
)
2946 nMaxRight
= lNullPix
+ GetMargin2() - GetMargin1() +
2947 (mpBorders
.size() - nIdx
- 1) * glMinFrame
;
2951 if(nRightCol
==USHRT_MAX
)
2953 nMaxRight
= GetMargin2() + lNullPix
;
2954 if(IsActLastColumn())
2959 GetMargin2() + GetRightIndent() -
2960 std::max(GetFirstLineIndent(),
2966 GetMargin2() - GetRightIndent() +
2967 std::max(GetFirstLineIndent(),
2970 nMaxRight
+= mpBorders
[nIdx
].nPos
+
2971 mpBorders
[nIdx
].nWidth
;
2976 nMaxRight
= lNullPix
+ mpBorders
[nRightCol
].nPos
;
2977 sal_uInt16 nNotHiddenRightCol
=
2978 GetActRightColumn(true, nIdx
);
2980 if( nActLeftCol
== nIdx
)
2982 tools::Long nBorder
= nNotHiddenRightCol
==
2985 mpBorders
[nNotHiddenRightCol
].nPos
;
2988 nMaxRight
-= nBorder
+ GetRightIndent() -
2989 std::max(GetFirstLineIndent(),
2994 nMaxRight
-= nBorder
- GetRightIndent() +
2995 std::max(GetFirstLineIndent(),
2998 nMaxRight
+= mpBorders
[nIdx
].nPos
+
2999 mpBorders
[nIdx
].nWidth
;
3002 nMaxRight
-= glMinFrame
;
3003 nMaxRight
-= mpBorders
[nIdx
].nWidth
;
3010 nMaxLeft
= LONG_MIN
;
3011 nMaxRight
= LONG_MAX
;
3015 case RulerDragSize::N2
:
3018 nMaxLeft
= lNullPix
+ mpBorders
[nIdx
].nPos
;
3019 if(nIdx
== mxColumnItem
->Count()-2) { // last column
3020 nMaxRight
= GetMargin2() + lNullPix
;
3021 if(mxColumnItem
->IsLastAct()) {
3023 GetMargin2() - GetRightIndent() +
3024 std::max(GetFirstLineIndent(),
3026 nMaxRight
+= mpBorders
[nIdx
].nPos
+
3027 mpBorders
[nIdx
].nWidth
;
3031 nMaxRight
= lNullPix
+ mpBorders
[nIdx
+1].nPos
;
3032 if(mxColumnItem
->GetActColumn()-1 == nIdx
) {
3033 nMaxRight
-= mpBorders
[nIdx
+1].nPos
- GetRightIndent() +
3034 std::max(GetFirstLineIndent(),
3036 nMaxRight
+= mpBorders
[nIdx
].nPos
+
3037 mpBorders
[nIdx
].nWidth
;
3040 nMaxRight
-= glMinFrame
;
3041 nMaxRight
-= mpBorders
[nIdx
].nWidth
;
3045 nMaxRight
+= nDragOffset
;
3048 case RulerType::Indent
:
3050 const sal_uInt16 nIdx
= GetDragAryPos();
3052 case INDENT_FIRST_LINE
- INDENT_GAP
:
3053 case INDENT_LEFT_MARGIN
- INDENT_GAP
:
3057 nMaxLeft
= lNullPix
+ GetRightIndent();
3059 if(mxColumnItem
&& !mxColumnItem
->IsFirstAct())
3060 nMaxLeft
+= mpBorders
[mxColumnItem
->GetActColumn()-1].nPos
+
3061 mpBorders
[mxColumnItem
->GetActColumn()-1].nWidth
;
3062 nMaxRight
= lNullPix
+ GetMargin2();
3065 if((INDENT_FIRST_LINE
- INDENT_GAP
) != nIdx
&&
3066 !(nDragType
& SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY
))
3068 if(GetLeftIndent() > GetFirstLineIndent())
3069 nMaxLeft
+= GetLeftIndent() - GetFirstLineIndent();
3071 nMaxRight
-= GetFirstLineIndent() - GetLeftIndent();
3076 nMaxLeft
= lNullPix
;
3078 if(mxColumnItem
&& !mxColumnItem
->IsFirstAct())
3079 nMaxLeft
+= mpBorders
[mxColumnItem
->GetActColumn()-1].nPos
+
3080 mpBorders
[mxColumnItem
->GetActColumn()-1].nWidth
;
3081 nMaxRight
= lNullPix
+ GetRightIndent() - glMinFrame
;
3084 if((INDENT_FIRST_LINE
- INDENT_GAP
) != nIdx
&&
3085 !(nDragType
& SvxRulerDragFlags::OBJECT_LEFT_INDENT_ONLY
))
3087 if(GetLeftIndent() > GetFirstLineIndent())
3088 nMaxLeft
+= GetLeftIndent() - GetFirstLineIndent();
3090 nMaxRight
-= GetFirstLineIndent() - GetLeftIndent();
3095 case INDENT_RIGHT_MARGIN
- INDENT_GAP
:
3099 nMaxLeft
= lNullPix
;
3100 nMaxRight
= lNullPix
+ std::min(GetFirstLineIndent(), GetLeftIndent()) - glMinFrame
;
3103 sal_uInt16 nRightCol
=GetActRightColumn( true );
3104 if(!IsActLastColumn( true ))
3105 nMaxRight
+= mpBorders
[nRightCol
].nPos
;
3107 nMaxRight
+= GetMargin2();
3111 nMaxLeft
+= GetMargin1();
3113 nMaxLeft
+= glMinFrame
;
3117 nMaxLeft
= lNullPix
+
3118 std::max(GetFirstLineIndent(), GetLeftIndent());
3119 nMaxRight
= lNullPix
;
3122 sal_uInt16 nRightCol
=GetActRightColumn( true );
3123 if(!IsActLastColumn( true ))
3124 nMaxRight
+= mpBorders
[nRightCol
].nPos
;
3126 nMaxRight
+= GetMargin2();
3129 nMaxRight
+= GetMargin2();
3130 nMaxLeft
+= glMinFrame
;
3137 case RulerType::Tab
: // Tabs (Modifier)
3138 /* left = NOf + Max(LAR, EZ)
3139 right = NOf + RAR */
3142 nMaxLeft
= lNullPix
+ GetRightIndent();
3144 nMaxLeft
= lNullPix
+ std::min(GetFirstLineIndent(), GetLeftIndent());
3146 mxRulerImpl
->lMaxRightLogic
= GetLogicRightIndent() + lLogicNullOffset
;
3147 nMaxRight
= ConvertSizePixel(mxRulerImpl
->lMaxRightLogic
);
3149 default: ; //prevent warning
3153 bool SvxRuler::StartDrag()
3156 Beginning of a drag operation (SV-handler) evaluates modifier and
3161 <SvxRuler::EvalModifier()>
3162 <SvxRuler::CalcMinMax()>
3163 <SvxRuler::EndDrag()>
3165 bool bContentProtected
= mxRulerImpl
->aProtectItem
->IsContentProtected();
3170 mxRulerImpl
->lLastLMargin
= GetMargin1();
3171 mxRulerImpl
->lLastRMargin
= GetMargin2();
3175 lInitialDragPos
= GetDragPos();
3176 switch(GetDragType())
3178 case RulerType::Margin1
: // left edge of the surrounding Frame
3179 case RulerType::Margin2
: // right edge of the surrounding Frame
3180 if((bHorz
&& mxLRSpaceItem
) || (!bHorz
&& mxULSpaceItem
))
3185 nDragType
= SvxRulerDragFlags::OBJECT
;
3192 case RulerType::Border
: // Table, column (Modifier)
3196 if (!mxColumnItem
->IsTable())
3197 nDragOffset
= GetDragPos() - mpBorders
[GetDragAryPos()].nPos
;
3203 case RulerType::Indent
: // Paragraph indents (Modifier)
3205 if( bContentProtected
)
3207 if(INDENT_LEFT_MARGIN
== GetDragAryPos() + INDENT_GAP
) { // Left paragraph indent
3208 mpIndents
[0] = mpIndents
[INDENT_FIRST_LINE
];
3213 nDragType
= SvxRulerDragFlags::OBJECT
;
3215 mpIndents
[1] = mpIndents
[GetDragAryPos() + INDENT_GAP
];
3218 case RulerType::Tab
: // Tabs (Modifier)
3219 if( bContentProtected
)
3222 mpTabs
[0] = mpTabs
[GetDragAryPos() + 1];
3223 mpTabs
[0].nStyle
|= RULER_STYLE_DONTKNOW
;
3226 nDragType
= SvxRulerDragFlags::NONE
;
3235 void SvxRuler::Drag()
3237 /* SV-Draghandler */
3238 if(IsDragCanceled())
3243 switch(GetDragType()) {
3244 case RulerType::Margin1
: // left edge of the surrounding Frame
3246 mxRulerImpl
->lLastLMargin
= GetMargin1();
3248 case RulerType::Margin2
: // right edge of the surrounding Frame
3250 mxRulerImpl
->lLastRMargin
= GetMargin2();
3252 case RulerType::Indent
: // Paragraph indents
3255 case RulerType::Border
: // Table, columns
3258 else if (mxObjectItem
)
3261 case RulerType::Tab
: // Tabs
3265 break; //prevent warning
3270 void SvxRuler::EndDrag()
3273 SV-handler; is called when ending the dragging. Triggers the updating of data
3274 on the application, by calling the respective Apply...() methods to send the
3275 data to the application.
3277 const bool bUndo
= IsDragCanceled();
3278 const tools::Long lPos
= GetDragPos();
3279 DrawLine_Impl(lTabPos
, 6, bHorz
);
3284 switch(GetDragType())
3286 case RulerType::Margin1
: // upper left edge of the surrounding Frame
3287 case RulerType::Margin2
: // lower right edge of the surrounding Frame
3289 if (!mxColumnItem
|| !mxColumnItem
->IsTable())
3293 (mxColumnItem
->IsTable() ||
3294 (nDragType
& SvxRulerDragFlags::OBJECT_SIZE_PROPORTIONAL
)))
3299 case RulerType::Border
: // Table, columns
3300 if(lInitialDragPos
!= lPos
||
3301 (mxRulerImpl
->bIsTableRows
&& bHorz
)) //special case - the null offset is changed here
3309 else if (mxObjectItem
)
3313 case RulerType::Indent
: // Paragraph indents
3314 if(lInitialDragPos
!= lPos
)
3316 SetIndents(INDENT_COUNT
, mpIndents
.data() + INDENT_GAP
);
3318 case RulerType::Tab
: // Tabs
3321 mpTabs
[GetDragAryPos()].nStyle
&= ~RULER_STYLE_INVISIBLE
;
3322 SetTabs(nTabCount
, mpTabs
.data() + TAB_GAP
);
3326 break; //prevent warning
3329 nDragType
= SvxRulerDragFlags::NONE
;
3331 mbCoarseSnapping
= false;
3337 for(sal_uInt16 i
= 0; i
< mxRulerImpl
->nControllerItems
; i
++)
3339 pCtrlItems
[i
]->ClearCache();
3340 pCtrlItems
[i
]->GetBindings().Invalidate(pCtrlItems
[i
]->GetId());
3345 void SvxRuler::ExtraDown()
3347 /* Override SV method, sets the new type for the Default tab. */
3351 (nFlags
& SvxRulerSupportFlags::TABS
) == SvxRulerSupportFlags::TABS
)
3354 if(RULER_TAB_DEFAULT
== nDefTabType
)
3355 nDefTabType
= RULER_TAB_LEFT
;
3356 SetExtraType(RulerExtra::Tab
, nDefTabType
);
3361 void SvxRuler::Notify(SfxBroadcaster
&, const SfxHint
& rHint
)
3364 Report through the bindings that the status update is completed. The ruler
3365 updates its appearance and gets registered again in the bindings.
3369 if (bActive
&& rHint
.GetId() == SfxHintId::UpdateDone
)
3372 EndListening(*pBindings
);
3378 void SvxRuler::MenuSelect(std::u16string_view ident
)
3382 /* Handler of the context menus for switching the unit of measurement */
3383 SetUnit(vcl::EnglishStringToMetric(ident
));
3386 void SvxRuler::TabMenuSelect(std::u16string_view rIdent
)
3390 sal_Int32 nId
= o3tl::toInt32(rIdent
);
3391 /* Handler of the tab menu for setting the type */
3392 if (mxTabStopItem
&& mxTabStopItem
->Count() > mxRulerImpl
->nIdx
)
3394 SvxTabStop aTabStop
= mxTabStopItem
->At(mxRulerImpl
->nIdx
);
3395 aTabStop
.GetAdjustment() = ToAttrTab_Impl(nId
- 1);
3396 mxTabStopItem
->Remove(mxRulerImpl
->nIdx
);
3397 mxTabStopItem
->Insert(aTabStop
);
3398 sal_uInt16 nTabStopId
= bHorz
? SID_ATTR_TABSTOP
: SID_ATTR_TABSTOP_VERTICAL
;
3399 pBindings
->GetDispatcher()->ExecuteList(nTabStopId
,
3400 SfxCallMode::RECORD
, { mxTabStopItem
.get() });
3402 mxRulerImpl
->nIdx
= 0;
3406 const TranslateId RID_SVXSTR_RULER_TAB
[] =
3408 RID_SVXSTR_RULER_TAB_LEFT
,
3409 RID_SVXSTR_RULER_TAB_RIGHT
,
3410 RID_SVXSTR_RULER_TAB_CENTER
,
3411 RID_SVXSTR_RULER_TAB_DECIMAL
3414 void SvxRuler::Command( const CommandEvent
& rCommandEvent
)
3416 /* Mouse context menu for switching the unit of measurement */
3417 if ( CommandEventId::ContextMenu
== rCommandEvent
.GetCommand() )
3421 tools::Rectangle
aRect(rCommandEvent
.GetMousePosPixel(), Size(1, 1));
3422 weld::Window
* pPopupParent
= weld::GetPopupParent(*this, aRect
);
3423 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(pPopupParent
, u
"svx/ui/rulermenu.ui"_ustr
));
3424 std::unique_ptr
<weld::Menu
> xMenu(xBuilder
->weld_menu(u
"menu"_ustr
));
3426 bool bRTL
= mxRulerImpl
->pTextRTLItem
&& mxRulerImpl
->pTextRTLItem
->GetValue();
3427 if ( !mpTabs
.empty() &&
3429 GetRulerType( rCommandEvent
.GetMousePosPixel(), &mxRulerImpl
->nIdx
) &&
3430 mpTabs
[mxRulerImpl
->nIdx
+ TAB_GAP
].nStyle
< RULER_TAB_DEFAULT
)
3434 const Size
aSz(ruler_tab_svx
.width
+ 2, ruler_tab_svx
.height
+ 2);
3435 const Point
aPt(aSz
.Width() / 2, aSz
.Height() / 2);
3437 for ( sal_uInt16 i
= RULER_TAB_LEFT
; i
< RULER_TAB_DEFAULT
; ++i
)
3439 ScopedVclPtr
<VirtualDevice
> xDev(pPopupParent
->create_virtual_device());
3440 xDev
->SetOutputSize(aSz
);
3442 sal_uInt16 nStyle
= bRTL
? i
|RULER_TAB_RTL
: i
;
3443 nStyle
|= static_cast<sal_uInt16
>(bHorz
? WB_HORZ
: WB_VERT
);
3445 Color
aFillColor(xDev
->GetSettings().GetStyleSettings().GetShadowColor());
3446 DrawTab(*xDev
, aFillColor
, aPt
, nStyle
);
3448 OUString
sId(OUString::number(i
+ 1));
3449 xMenu
->insert(-1, sId
, SvxResId(RID_SVXSTR_RULER_TAB
[i
]),
3450 nullptr, xDev
.get(), nullptr, TRISTATE_TRUE
);
3451 xMenu
->set_active(sId
, i
== mpTabs
[mxRulerImpl
->nIdx
+ TAB_GAP
].nStyle
);
3453 TabMenuSelect(xMenu
->popup_at_rect(pPopupParent
, aRect
));
3457 FieldUnit eUnit
= GetUnit();
3458 const int nCount
= xMenu
->n_children();
3460 bool bReduceMetric
= bool(nFlags
& SvxRulerSupportFlags::REDUCED_METRIC
);
3461 for ( sal_uInt16 i
= nCount
; i
; --i
)
3463 OUString sIdent
= xMenu
->get_id(i
- 1);
3464 FieldUnit eMenuUnit
= vcl::EnglishStringToMetric(sIdent
);
3465 xMenu
->set_active(sIdent
, eMenuUnit
== eUnit
);
3468 if (eMenuUnit
== FieldUnit::M
||
3469 eMenuUnit
== FieldUnit::KM
||
3470 eMenuUnit
== FieldUnit::FOOT
||
3471 eMenuUnit
== FieldUnit::MILE
)
3473 xMenu
->remove(sIdent
);
3475 else if (( eMenuUnit
== FieldUnit::CHAR
) && !bHorz
)
3477 xMenu
->remove(sIdent
);
3479 else if (( eMenuUnit
== FieldUnit::LINE
) && bHorz
)
3481 xMenu
->remove(sIdent
);
3485 MenuSelect(xMenu
->popup_at_rect(pPopupParent
, aRect
));
3490 Ruler::Command( rCommandEvent
);
3494 sal_uInt16
SvxRuler::GetActRightColumn(
3495 bool bForceDontConsiderHidden
,
3496 sal_uInt16 nAct
) const
3498 if( nAct
== USHRT_MAX
)
3499 nAct
= mxColumnItem
->GetActColumn();
3501 nAct
++; //To be able to pass on the ActDrag
3503 bool bConsiderHidden
= !bForceDontConsiderHidden
&&
3504 !(nDragType
& SvxRulerDragFlags::OBJECT_ACTLINE_ONLY
);
3506 while( nAct
< mxColumnItem
->Count() - 1 )
3508 if (mxColumnItem
->At(nAct
).bVisible
|| bConsiderHidden
)
3516 sal_uInt16
SvxRuler::GetActLeftColumn(
3517 bool bForceDontConsiderHidden
,
3518 sal_uInt16 nAct
) const
3520 if(nAct
== USHRT_MAX
)
3521 nAct
= mxColumnItem
->GetActColumn();
3523 sal_uInt16 nLeftOffset
= 1;
3525 bool bConsiderHidden
= !bForceDontConsiderHidden
&&
3526 !(nDragType
& SvxRulerDragFlags::OBJECT_ACTLINE_ONLY
);
3528 while(nAct
>= nLeftOffset
)
3530 if (mxColumnItem
->At(nAct
- nLeftOffset
).bVisible
|| bConsiderHidden
)
3531 return nAct
- nLeftOffset
;
3538 bool SvxRuler::IsActLastColumn(
3539 bool bForceDontConsiderHidden
,
3540 sal_uInt16 nAct
) const
3542 return GetActRightColumn(bForceDontConsiderHidden
, nAct
) == USHRT_MAX
;
3545 bool SvxRuler::IsActFirstColumn(
3546 bool bForceDontConsiderHidden
,
3547 sal_uInt16 nAct
) const
3549 return GetActLeftColumn(bForceDontConsiderHidden
, nAct
) == USHRT_MAX
;
3552 tools::Long
SvxRuler::CalcPropMaxRight(sal_uInt16 nCol
) const
3555 if(!(nDragType
& SvxRulerDragFlags::OBJECT_SIZE_LINEAR
))
3557 // Remove the minimum width for all affected columns
3558 // starting from the right edge
3559 tools::Long _nMaxRight
= GetMargin2() - GetMargin1();
3561 tools::Long lFences
= 0;
3562 tools::Long lMinSpace
= USHRT_MAX
;
3563 tools::Long lOldPos
;
3564 tools::Long lColumns
= 0;
3567 if(!mxColumnItem
->IsTable())
3569 if(nCol
== USHRT_MAX
)
3571 lOldPos
= GetMargin1();
3576 lOldPos
= mpBorders
[nCol
].nPos
+ mpBorders
[nCol
].nWidth
;
3578 lFences
= mpBorders
[nCol
].nWidth
;
3581 for(size_t i
= nStart
; i
< mpBorders
.size() - 1; ++i
)
3583 tools::Long lWidth
= mpBorders
[i
].nPos
- lOldPos
;
3585 if(lWidth
< lMinSpace
)
3587 lOldPos
= mpBorders
[i
].nPos
+ mpBorders
[i
].nWidth
;
3588 lFences
+= mpBorders
[i
].nWidth
;
3590 tools::Long lWidth
= GetMargin2() - lOldPos
;
3592 if(lWidth
< lMinSpace
)
3598 if(nCol
== USHRT_MAX
) //CalcMinMax for LeftMargin
3600 lOldPos
= GetMargin1();
3604 lOldPos
= mpBorders
[nCol
].nPos
;
3606 lColumns
= GetMargin2()-lOldPos
;
3609 while(nActCol
< mpBorders
.size() || nActCol
== USHRT_MAX
)
3612 if(nActCol
== USHRT_MAX
)
3615 while (!(*mxColumnItem
)[nRight
].bVisible
)
3622 nRight
= GetActRightColumn(false, nActCol
);
3626 if(nRight
!= USHRT_MAX
)
3628 lWidth
= mpBorders
[nRight
].nPos
- lOldPos
;
3629 lOldPos
= mpBorders
[nRight
].nPos
;
3633 lWidth
=GetMargin2() - lOldPos
;
3636 if(lWidth
< lMinSpace
)
3638 if(nActCol
== USHRT_MAX
)
3643 _nMaxRight
-= static_cast<tools::Long
>(lFences
+ glMinFrame
/ static_cast<float>(lMinSpace
) * lColumns
);
3648 if(mxColumnItem
->IsTable())
3650 sal_uInt16 nVisCols
= 0;
3651 for(size_t i
= GetActRightColumn(false, nCol
); i
< mpBorders
.size();)
3653 if ((*mxColumnItem
)[i
].bVisible
)
3655 i
= GetActRightColumn(false, i
);
3657 return GetMargin2() - GetMargin1() - (nVisCols
+ 1) * glMinFrame
;
3661 tools::Long lWidth
= 0;
3662 for(size_t i
= nCol
; i
< mpBorders
.size() - 1; i
++)
3664 lWidth
+= glMinFrame
+ mpBorders
[i
].nWidth
;
3666 return GetMargin2() - GetMargin1() - lWidth
;
3671 // Tab stops relative to indent (#i24363#)
3672 void SvxRuler::SetTabsRelativeToIndent( bool bRel
)
3674 mxRulerImpl
->bIsTabsRelativeToIndent
= bRel
;
3677 void SvxRuler::SetValues(RulerChangeType type
, tools::Long diffValue
)
3682 if (type
== RulerChangeType::MARGIN1
)
3683 AdjustMargin1(diffValue
);
3684 else if (type
== RulerChangeType::MARGIN2
)
3685 SetMargin2( GetMargin2() - diffValue
);
3689 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */