Coverage Report

Created: 2025-11-16 09:57

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