Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/hdrcont.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sfx2/dispatch.hxx>
21
#include <vcl/commandevent.hxx>
22
#include <vcl/help.hxx>
23
#include <vcl/ptrstyle.hxx>
24
#include <vcl/settings.hxx>
25
#include <svtools/colorcfg.hxx>
26
#include <osl/diagnose.h>
27
28
#include <tabvwsh.hxx>
29
#include <hdrcont.hxx>
30
#include <dbdata.hxx>
31
#include <scmod.hxx>
32
#include <inputopt.hxx>
33
#include <gridmerg.hxx>
34
#include <document.hxx>
35
#include <markdata.hxx>
36
#include <tabview.hxx>
37
#include <viewdata.hxx>
38
#include <columnspanset.hxx>
39
#include <SheetViewManager.hxx>
40
#include <officecfg/Office/Common.hxx>
41
#include <o3tl/enumrange.hxx>
42
43
0
#define SC_DRAG_MIN     2
44
45
//  passes in paint
46
//  (selection left/right must be first because the continuous lines
47
//  are partly overwritten later)
48
49
namespace
50
{
51
52
enum class HeaderPaintPass
53
{
54
    SelectionBottom,
55
    Bottom,
56
    Text,
57
    LAST = Text
58
};
59
60
}
61
62
ScHeaderControl::ScHeaderControl( vcl::Window* pParent, SelectionEngine* pSelectionEngine,
63
                                  SCCOLROW nNewSize, bool bNewVertical, ScTabView* pTab ) :
64
0
            Window      ( pParent ),
65
0
            pSelEngine  ( pSelectionEngine ),
66
0
            aShowHelpTimer("sc HeaderControl Popover Timer"),
67
0
            bVertical   ( bNewVertical ),
68
0
            nSize       ( nNewSize ),
69
0
            nMarkStart  ( 0 ),
70
0
            nMarkEnd    ( 0 ),
71
0
            bMarkRange  ( false ),
72
0
            bDragging   ( false ),
73
0
            nDragNo     ( 0 ),
74
0
            nDragStart  ( 0 ),
75
0
            nDragPos    ( 0 ),
76
0
            nTipVisible ( nullptr ),
77
0
            bDragMoved  ( false ),
78
0
            bIgnoreMove ( false ),
79
0
            bInRefMode  ( false ),
80
0
            pTabView    ( pTab )
81
0
{
82
    // RTL: no default mirroring for this window, the spreadsheet itself
83
    // is also not mirrored
84
    // mirror the vertical window for correct border drawing
85
    // table layout depends on sheet format, not UI setting, so the
86
    // borders of the vertical window have to be handled manually, too.
87
0
    EnableRTL( false );
88
89
0
    aNormFont = GetFont();
90
0
    aNormFont.SetTransparent( true );       //! hard-set WEIGHT_NORMAL ???
91
92
0
    mnDefaultFontHeight = aNormFont.GetFontHeight();
93
94
0
    aBoldFont = aNormFont;
95
0
    aBoldFont.SetWeight( WEIGHT_BOLD );
96
0
    aAutoFilterFont = aNormFont;
97
98
0
    SetFont(aBoldFont);
99
0
    bBoldSet = true;
100
0
    bAutoFilterSet = false;
101
102
0
    Size aSize = LogicToPixel( Size(
103
0
        GetTextWidth(u"8888"_ustr),
104
0
        GetTextHeight() ) );
105
0
    aSize.AdjustWidth(4 );    // place for highlight border
106
0
    aSize.AdjustHeight(3 );
107
0
    SetSizePixel( aSize );
108
109
0
    nWidth = nSmallWidth = aSize.Width();
110
0
    nBigWidth = LogicToPixel( Size( GetTextWidth(u"8888888"_ustr), 0 ) ).Width() + 5;
111
112
0
    aShowHelpTimer.SetInvokeHandler(LINK(this, ScHeaderControl, ShowDragHelpHdl));
113
0
    aShowHelpTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
114
115
0
    SetBackground();
116
0
}
117
118
void ScHeaderControl::dispose()
119
0
{
120
0
    aShowHelpTimer.Stop();
121
0
    vcl::Window::dispose();
122
0
}
123
124
void ScHeaderControl::SetWidth( tools::Long nNew )
125
0
{
126
0
    OSL_ENSURE( bVertical, "SetWidth works only on row headers" );
127
0
    if ( nNew != nWidth )
128
0
    {
129
0
        Size aSize( nNew, GetSizePixel().Height() );
130
0
        SetSizePixel( aSize );
131
132
0
        nWidth = nNew;
133
134
0
        Invalidate();
135
0
    }
136
0
}
137
138
ScHeaderControl::~ScHeaderControl()
139
0
{
140
0
}
141
142
void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd )
143
0
{
144
0
    bool bLayoutRTL = IsLayoutRTL();
145
0
    tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
146
147
0
    tools::Rectangle aRect( Point(0,0), GetOutputSizePixel() );
148
0
    if ( bVertical )
149
0
    {
150
0
        aRect.SetTop( GetScrPos( nStart )-nLayoutSign );      // extra pixel for line at top of selection
151
0
        aRect.SetBottom( GetScrPos( nEnd+1 )-nLayoutSign );
152
0
    }
153
0
    else
154
0
    {
155
0
        aRect.SetLeft( GetScrPos( nStart )-nLayoutSign );     // extra pixel for line left of selection
156
0
        aRect.SetRight( GetScrPos( nEnd+1 )-nLayoutSign );
157
0
    }
158
0
    Invalidate(aRect);
159
0
}
160
161
void ScHeaderControl::SetMark( bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd )
162
0
{
163
0
    bool bEnabled = ScModule::get()->GetInputOptions().GetMarkHeader(); //! cache?
164
0
    if (!bEnabled)
165
0
        bNewSet = false;
166
167
0
    bool bOldSet       = bMarkRange;
168
0
    SCCOLROW nOldStart = nMarkStart;
169
0
    SCCOLROW nOldEnd   = nMarkEnd;
170
0
    PutInOrder( nNewStart, nNewEnd );
171
0
    bMarkRange = bNewSet;
172
0
    nMarkStart = nNewStart;
173
0
    nMarkEnd   = nNewEnd;
174
175
    //  Paint
176
177
0
    if ( bNewSet )
178
0
    {
179
0
        if ( bOldSet )
180
0
        {
181
0
            if ( nNewStart == nOldStart )
182
0
            {
183
0
                if ( nNewEnd != nOldEnd )
184
0
                    DoPaint( std::min( nNewEnd, nOldEnd ) + 1, std::max( nNewEnd, nOldEnd ) );
185
0
            }
186
0
            else if ( nNewEnd == nOldEnd )
187
0
                DoPaint( std::min( nNewStart, nOldStart ), std::max( nNewStart, nOldStart ) - 1 );
188
0
            else if ( nNewStart > nOldEnd || nNewEnd < nOldStart )
189
0
            {
190
                //  two areas
191
0
                DoPaint( nOldStart, nOldEnd );
192
0
                DoPaint( nNewStart, nNewEnd );
193
0
            }
194
0
            else //  somehow overlapping... (it is not often)
195
0
                DoPaint( std::min( nNewStart, nOldStart ), std::max( nNewEnd, nOldEnd ) );
196
0
        }
197
0
        else
198
0
            DoPaint( nNewStart, nNewEnd );      //  completely new selection
199
0
    }
200
0
    else if ( bOldSet )
201
0
        DoPaint( nOldStart, nOldEnd );          //  cancel selection
202
0
}
203
204
tools::Long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo ) const
205
0
{
206
0
    tools::Long nScrPos;
207
208
0
    tools::Long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1;
209
0
    if (nEntryNo >= nSize)
210
0
        nScrPos = nMax;
211
0
    else
212
0
    {
213
0
        nScrPos = 0;
214
0
        for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++)
215
0
        {
216
0
            sal_uInt16 nAdd = GetEntrySize(i);
217
0
            if (nAdd)
218
0
                nScrPos += nAdd;
219
0
            else
220
0
            {
221
0
                SCCOLROW nHidden = GetHiddenCount(i);
222
0
                if (nHidden > 0)
223
0
                    i += nHidden - 1;
224
0
            }
225
0
        }
226
0
    }
227
228
0
    if ( IsLayoutRTL() )
229
0
        nScrPos = nMax - nScrPos - 2;
230
231
0
    return nScrPos;
232
0
}
233
234
void ScHeaderControl::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
235
0
{
236
    // It is important for VCL to have few calls, that is why the outer lines are
237
    // grouped together
238
239
0
    const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
240
0
    bool bHighContrast = rStyleSettings.GetHighContrastMode();
241
0
    bool bDark = rStyleSettings.GetFaceColor().IsDark();
242
    // Use the same distinction for bDark as in Window::DrawSelectionBackground
243
244
0
    Color aTextColor = rStyleSettings.GetButtonTextColor();
245
0
    Color aSelTextColor = rStyleSettings.GetHighlightTextColor();
246
0
    Color aAFilterTextColor = rStyleSettings.GetButtonTextColor();
247
0
    aAFilterTextColor.Merge(COL_LIGHTBLUE, bDark ? 150 : 10); // color of filtered row numbers
248
0
    aNormFont.SetColor( aTextColor );
249
0
    aAutoFilterFont.SetColor(aAFilterTextColor);
250
0
    if ( bHighContrast )
251
0
        aBoldFont.SetColor( aTextColor );
252
0
    else
253
0
        aBoldFont.SetColor( aSelTextColor );
254
255
0
    if (bAutoFilterSet)
256
0
        rRenderContext.SetTextColor(aAFilterTextColor);
257
0
    else
258
0
        rRenderContext.SetTextColor((bBoldSet && !bHighContrast) ? aSelTextColor : aTextColor);
259
260
0
    ScModule* mod = ScModule::get();
261
0
    Color aSelLineColor = mod->GetColorConfig().GetColorValue(svtools::CALCCELLFOCUS).nColor;
262
0
    aSelLineColor.Merge( COL_BLACK, 0xe0 );        // darken just a little bit
263
264
0
    bool bLayoutRTL = IsLayoutRTL();
265
0
    tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
266
267
0
    OUString            aString;
268
0
    sal_uInt16          nBarSize;
269
0
    Point               aScrPos;
270
271
0
    if (bVertical)
272
0
        nBarSize = static_cast<sal_uInt16>(GetSizePixel().Width());
273
0
    else
274
0
        nBarSize = static_cast<sal_uInt16>(GetSizePixel().Height());
275
276
0
    SCCOLROW    nPos = GetPos();
277
278
0
    tools::Long nPStart = bVertical ? rRect.Top() : rRect.Left();
279
0
    tools::Long nPEnd = bVertical ? rRect.Bottom() : rRect.Right();
280
281
0
    tools::Long nTransStart = nPEnd + 1;
282
0
    tools::Long nTransEnd = 0;
283
284
0
    tools::Long nInitScrPos = 0;
285
0
    if ( bLayoutRTL )
286
0
    {
287
0
        std::swap(nPStart, nPEnd);
288
0
        std::swap(nTransStart, nTransEnd);
289
0
        if ( bVertical )            // start loops from the end
290
0
            nInitScrPos = GetSizePixel().Height() - 1;
291
0
        else
292
0
            nInitScrPos = GetSizePixel().Width() - 1;
293
0
    }
294
295
    // complete the painting of the outer lines
296
    // first find the end of the last cell
297
298
0
    tools::Long nLineEnd = nInitScrPos - nLayoutSign;
299
300
0
    for (SCCOLROW i=nPos; i<nSize; i++)
301
0
    {
302
0
        sal_uInt16 nSizePix = GetEntrySize( i );
303
0
        if (nSizePix)
304
0
        {
305
0
            nLineEnd += nSizePix * nLayoutSign;
306
307
0
            if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd )
308
0
            {
309
0
                tools::Long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign;
310
0
                if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign )
311
0
                    nTransStart = nLineStart;
312
0
                if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign )
313
0
                    nTransEnd = nLineEnd;
314
0
            }
315
316
0
            if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign )
317
0
            {
318
0
                nLineEnd = nPEnd;
319
0
                break;
320
0
            }
321
0
        }
322
0
        else
323
0
        {
324
0
            SCCOLROW nHidden = GetHiddenCount(i);
325
0
            if (nHidden > 0)
326
0
                i += nHidden - 1;
327
0
        }
328
0
    }
329
330
    //  background is different for entry area and behind the entries
331
332
0
    tools::Rectangle aFillRect;
333
0
    rRenderContext.SetLineColor();
334
335
0
    if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign )
336
0
    {
337
0
        Color aFaceColor(rStyleSettings.GetFaceColor());
338
0
        if (pTabView)
339
0
        {
340
0
            ScViewData& rViewData = pTabView->GetViewData();
341
0
            sc::SheetViewID nSheetViewID = rViewData.GetSheetViewID();
342
0
            if (nSheetViewID >= 0)
343
0
            {
344
0
                auto pSheetManager = rViewData.GetDocument().GetSheetViewManager(rViewData.GetTabNumber());
345
0
                auto pSheetView = pSheetManager->get(nSheetViewID);
346
0
                if (pSheetView->isSynced())
347
0
                    aFaceColor.Merge(COL_LIGHTBLUE, 220);
348
0
                else
349
0
                    aFaceColor.Merge(COL_LIGHTRED, 220);
350
0
            }
351
0
        }
352
0
        if (bDark)
353
0
            aFaceColor.IncreaseLuminance(20);
354
0
        else
355
0
            aFaceColor.DecreaseLuminance(20);
356
0
        rRenderContext.SetFillColor(aFaceColor);
357
0
        if ( bVertical )
358
0
            aFillRect = tools::Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd );
359
0
        else
360
0
            aFillRect = tools::Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 );
361
0
        rRenderContext.DrawRect( aFillRect );
362
0
    }
363
364
0
    if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign )
365
0
    {
366
0
        Color aAppBackgroundColor = mod->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor;
367
0
        rRenderContext.SetFillColor(aAppBackgroundColor);
368
0
        if ( bVertical )
369
0
            aFillRect = tools::Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd );
370
0
        else
371
0
            aFillRect = tools::Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 );
372
0
        rRenderContext.DrawRect( aFillRect );
373
0
    }
374
375
0
    if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign )
376
0
    {
377
0
        if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign )
378
0
        {
379
0
            if (bVertical)
380
0
                aFillRect = tools::Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
381
0
            else
382
0
                aFillRect = tools::Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
383
384
0
            if ( bHighContrast )
385
0
            {
386
0
                if ( bDark )
387
0
                {
388
                    //  solid grey background for dark face color is drawn before lines
389
0
                    rRenderContext.SetLineColor();
390
0
                    rRenderContext.SetFillColor( COL_LIGHTGRAY );
391
0
                    rRenderContext.DrawRect( aFillRect );
392
0
                }
393
0
            }
394
0
            else
395
0
            {
396
                // background for selection
397
0
                rRenderContext.SetLineColor();
398
0
                Color aColor = mod->GetColorConfig().GetColorValue(svtools::CALCCELLFOCUS).nColor;
399
// merging the highlightcolor (which is used if accent does not exist) with the background
400
// fails in many cases such as Breeze Dark (highlight is too close to background) and
401
// Breeze Light (font color is white and not readable anymore)
402
#ifdef MACOSX
403
                aColor.Merge( rStyleSettings.GetFaceColor(), 80 );
404
#endif
405
0
                rRenderContext.SetFillColor( aColor );
406
0
                rRenderContext.DrawRect( aFillRect );
407
0
            }
408
0
        }
409
410
0
        rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
411
0
        if (bVertical)
412
0
        {
413
0
            rRenderContext.DrawLine( Point( 0, nPStart ), Point( 0, nLineEnd ) ); //left
414
0
            rRenderContext.DrawLine( Point( nBarSize-1, nPStart ), Point( nBarSize-1, nLineEnd ) ); //right
415
0
        }
416
0
        else
417
0
        {
418
0
            rRenderContext.DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) ); //bottom
419
0
            rRenderContext.DrawLine( Point( nPStart, 0 ), Point( nLineEnd, 0 ) ); //top
420
0
        }
421
0
    }
422
423
    // tdf#89841 Use blue row numbers when Autofilter selected
424
0
    std::vector<sc::ColRowSpan> aSpans;
425
0
    if (bVertical && pTabView)
426
0
    {
427
0
        SCTAB nTab = pTabView->GetViewData().CurrentTabForData();
428
0
        ScDocument& rDoc = pTabView->GetViewData().GetDocument();
429
430
0
        ScDBData* pDBData = rDoc.GetAnonymousDBData(nTab);
431
0
        if (pDBData && pDBData->HasAutoFilter())
432
0
        {
433
0
            SCSIZE nSelected = 0;
434
0
            SCSIZE nTotal = 0;
435
0
            pDBData->GetFilterSelCount(nSelected, nTotal);
436
0
            if (nTotal > nSelected)
437
0
            {
438
0
                ScRange aRange;
439
0
                pDBData->GetArea(aRange);
440
0
                SCCOLROW nStartRow = static_cast<SCCOLROW>(aRange.aStart.Row());
441
0
                SCCOLROW nEndRow = static_cast<SCCOLROW>(aRange.aEnd.Row());
442
0
                if (pDBData->HasHeader())
443
0
                    nStartRow++;
444
0
                aSpans.push_back(sc::ColRowSpan(nStartRow, nEndRow));
445
0
            }
446
0
        }
447
448
0
        ScDBCollection* pDocColl = rDoc.GetDBCollection();
449
0
        if (!pDocColl->empty())
450
0
        {
451
0
            ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
452
0
            for (const auto& rxDB : rDBs)
453
0
            {
454
0
                if (rxDB->GetTab() == nTab && rxDB->HasAutoFilter())
455
0
                {
456
0
                    SCSIZE nSelected = 0;
457
0
                    SCSIZE nTotal = 0;
458
0
                    rxDB->GetFilterSelCount(nSelected, nTotal);
459
0
                    if (nTotal > nSelected)
460
0
                    {
461
0
                        ScRange aRange;
462
0
                        rxDB->GetArea(aRange);
463
0
                        SCCOLROW nStartRow = static_cast<SCCOLROW>(aRange.aStart.Row());
464
0
                        SCCOLROW nEndRow = static_cast<SCCOLROW>(aRange.aEnd.Row());
465
0
                        if (rxDB->HasHeader())
466
0
                            nStartRow++;
467
0
                        aSpans.push_back(sc::ColRowSpan(nStartRow, nEndRow));
468
0
                    }
469
0
                }
470
0
            }
471
0
        }
472
0
    }
473
474
    //  loop through entries several times to avoid changing the line color too often
475
    //  and to allow merging of lines
476
477
0
    ScGridMerger aGrid( GetOutDev(), 1, 1 );
478
479
0
    for (HeaderPaintPass ePass : o3tl::enumrange<HeaderPaintPass>())
480
0
    {
481
        //  set line color etc. before entry loop
482
0
        switch (ePass)
483
0
        {
484
0
            case HeaderPaintPass::SelectionBottom:
485
                // same as non-selected for high contrast
486
0
                rRenderContext.SetLineColor( bHighContrast ? rStyleSettings.GetShadowColor() : aSelLineColor );
487
0
                break;
488
0
            case HeaderPaintPass::Bottom:
489
0
                rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
490
0
                break;
491
0
            case HeaderPaintPass::Text:
492
                // DrawSelectionBackground is used only for high contrast on light background
493
0
                if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark )
494
0
                {
495
                    //  Transparent selection background is drawn after lines, before text.
496
                    //  Use DrawSelectionBackground to make sure there is a visible
497
                    //  difference. The case of a dark face color, where DrawSelectionBackground
498
                    //  would just paint over the lines, is handled separately (bDark).
499
                    //  Otherwise, GetHighlightColor is used with 80% transparency.
500
                    //  The window's background color (SetBackground) has to be the background
501
                    //  of the cell area, for the contrast comparison in DrawSelectionBackground.
502
503
0
                    tools::Rectangle aTransRect;
504
0
                    if (bVertical)
505
0
                        aTransRect = tools::Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
506
0
                    else
507
0
                        aTransRect = tools::Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
508
0
                    rRenderContext.SetBackground( rStyleSettings.GetFaceColor() );
509
0
                    rRenderContext.DrawSelectionBackground(aTransRect, GetBackgroundColor(), 0, true);
510
0
                    rRenderContext.SetBackground();
511
0
                }
512
0
                break;
513
0
        }
514
515
0
        SCCOLROW nCount = 0;
516
0
        tools::Long nScrPos = nInitScrPos;
517
0
        sal_Int32 nFontHeight = 0;
518
0
        do
519
0
        {
520
0
            if (bVertical)
521
0
                aScrPos = Point( 0, nScrPos );
522
0
            else
523
0
                aScrPos = Point( nScrPos, 0 );
524
525
0
            SCCOLROW    nEntryNo = nCount + nPos;
526
0
            if ( nEntryNo >= nSize )                // rDoc.MaxCol()/rDoc.MaxRow()
527
0
                nScrPos = nPEnd + nLayoutSign;      //  beyond nPEnd -> stop
528
0
            else
529
0
            {
530
0
                sal_uInt16 nSizePix = GetEntrySize( nEntryNo );
531
532
0
                if (nSizePix == 0)
533
0
                {
534
0
                    SCCOLROW nHidden = GetHiddenCount(nEntryNo);
535
0
                    if (nHidden > 0)
536
0
                        nCount += nHidden - 1;
537
0
                }
538
0
                else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign)
539
0
                {
540
0
                    Point aEndPos(aScrPos);
541
0
                    if (bVertical)
542
0
                        aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign );
543
0
                    else
544
0
                        aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 );
545
546
0
                    bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd;
547
0
                    bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd;
548
549
0
                    switch (ePass)
550
0
                    {
551
0
                        case HeaderPaintPass::SelectionBottom:
552
0
                        case HeaderPaintPass::Bottom:
553
0
                            if (ePass == (bNextToMark ? HeaderPaintPass::SelectionBottom : HeaderPaintPass::Bottom))
554
0
                            {
555
0
                                if (bVertical)
556
0
                                    aGrid.AddHorLine(/* here we work in pixels */ true, aScrPos.X(), aEndPos.X(), aEndPos.Y());
557
0
                                else
558
0
                                    aGrid.AddVerLine(/* here we work in pixels */ true, aEndPos.X(), aScrPos.Y(), aEndPos.Y());
559
560
                                //  thick bottom for hidden rows
561
                                //  (drawn directly, without aGrid)
562
0
                                if ( nEntryNo+1 < nSize )
563
0
                                    if ( GetEntrySize(nEntryNo+1)==0 )
564
0
                                    {
565
0
                                        if (bVertical)
566
0
                                            rRenderContext.DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign),
567
0
                                                      Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) );
568
0
                                        else
569
0
                                            rRenderContext.DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()),
570
0
                                                      Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) );
571
0
                                    }
572
0
                            }
573
0
                            break;
574
575
0
                        case HeaderPaintPass::Text:
576
0
                            if ( nSizePix > 1 )     // minimal check for small columns/rows
577
0
                            {
578
0
                                sal_Int32 nCurrentFontHeight = std::min(aEndPos.Y() - aScrPos.Y() + 1, mnDefaultFontHeight);
579
0
                                bool bChangedHeight = false;
580
0
                                if (nFontHeight != nCurrentFontHeight)
581
0
                                {
582
0
                                    nFontHeight = nCurrentFontHeight;
583
0
                                    aNormFont.SetFontHeight(nFontHeight);
584
0
                                    aBoldFont.SetFontHeight(nFontHeight);
585
0
                                    aAutoFilterFont.SetFontHeight(nFontHeight);
586
0
                                    bChangedHeight = true;
587
0
                                }
588
589
0
                                if (bVertical)
590
0
                                {
591
0
                                    bool bAutoFilterPos = false;
592
0
                                    for (const auto& rSpan : aSpans)
593
0
                                    {
594
0
                                        if (nEntryNo >= rSpan.mnStart && nEntryNo <= rSpan.mnEnd)
595
0
                                        {
596
0
                                            bAutoFilterPos = true;
597
0
                                            break;
598
0
                                        }
599
0
                                    }
600
601
0
                                    if (bMark != bBoldSet || bAutoFilterPos != bAutoFilterSet || bChangedHeight)
602
0
                                    {
603
0
                                        if (bMark)
604
0
                                            SetFont(aBoldFont);
605
0
                                        else if (bAutoFilterPos)
606
0
                                            SetFont(aAutoFilterFont);
607
0
                                        else
608
0
                                            SetFont(aNormFont);
609
0
                                        bBoldSet = bMark;
610
0
                                        bAutoFilterSet = bAutoFilterPos && !bMark;
611
0
                                    }
612
0
                                }
613
0
                                else
614
0
                                {
615
0
                                    if (bMark != bBoldSet || bChangedHeight)
616
0
                                    {
617
0
                                        if (bMark)
618
0
                                            SetFont(aBoldFont);
619
0
                                        else
620
0
                                            SetFont(aNormFont);
621
0
                                        bBoldSet = bMark;
622
0
                                    }
623
0
                                }
624
0
                                aString = GetEntryText(nEntryNo);
625
0
                                const bool bRight
626
0
                                    = GetTextWidth(aString) > fabs(aScrPos.X() - aEndPos.X());
627
0
                                DrawTextFlags nDrawTextStyle(
628
0
                                    (bRight ? DrawTextFlags::Right : DrawTextFlags::Center)
629
0
                                    | DrawTextFlags::VCenter | DrawTextFlags::Clip);
630
0
                                tools::Rectangle aRect;
631
0
                                if (!bVertical && bLayoutRTL)
632
0
                                    aRect = tools::Rectangle(aEndPos.X(), aScrPos.Y(), aScrPos.X(),
633
0
                                                             aEndPos.Y());
634
0
                                else
635
0
                                    aRect = tools::Rectangle(aScrPos.X(), aScrPos.Y(), aEndPos.X(),
636
0
                                                             aEndPos.Y());
637
0
                                rRenderContext.DrawText(aRect, aString, nDrawTextStyle);
638
0
                            }
639
0
                            break;
640
0
                    }
641
642
                    // when selecting the complete row/column:
643
                    //  InvertRect( Rectangle( aScrPos, aEndPos ) );
644
0
                }
645
0
                nScrPos += nSizePix * nLayoutSign;      // also if before the visible area
646
0
            }
647
0
            ++nCount;
648
0
        }
649
0
        while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign );
650
651
0
        aGrid.Flush();
652
0
    }
653
0
}
654
655
SCCOLROW ScHeaderControl::GetMousePos(const Point& rPos, bool& rBorder) const
656
0
{
657
0
    bool        bFound = false;
658
0
    SCCOLROW    nPos = GetPos();
659
0
    SCCOLROW    nHitNo = nPos;
660
0
    SCCOLROW    nEntryNo = 1 + nPos;
661
0
    tools::Long    nScrPos;
662
0
    tools::Long    nMousePos = bVertical ? rPos.Y() : rPos.X();
663
0
    tools::Long    nDif;
664
0
    Size    aSize = GetOutputSizePixel();
665
0
    tools::Long    nWinSize = bVertical ? aSize.Height() : aSize.Width();
666
667
0
    bool bLayoutRTL = IsLayoutRTL();
668
0
    tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
669
0
    tools::Long nEndPos = bLayoutRTL ? -1 : nWinSize;
670
671
0
    nScrPos = GetScrPos( nPos ) - nLayoutSign;
672
0
    do
673
0
    {
674
0
        if (nEntryNo > nSize)
675
0
            nScrPos = nEndPos + nLayoutSign;
676
0
        else
677
0
            nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign;      //! GetHiddenCount() ??
678
679
0
        nDif = nMousePos - nScrPos;
680
0
        if (nDif >= -5 && nDif <= 5)
681
0
        {
682
0
            bFound = true;
683
0
            nHitNo=nEntryNo-1;
684
0
        }
685
0
        else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize)
686
0
            nHitNo = nEntryNo;
687
0
        ++nEntryNo;
688
0
    }
689
0
    while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 );
690
691
0
    rBorder = bFound;
692
0
    return nHitNo;
693
0
}
694
695
bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const
696
0
{
697
0
    ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
698
0
    if (!pViewSh)
699
0
        return false;
700
701
0
    ScViewData& rViewData = pViewSh->GetViewData();
702
0
    sal_uInt16 nTab = rViewData.CurrentTabForData();
703
0
    ScDocument& rDoc = rViewData.GetDocument();
704
0
    const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
705
0
    bool bSelectAllowed = true;
706
0
    if ( pProtect && pProtect->isProtected() )
707
0
    {
708
        // This sheet is protected.  Check if a context menu is allowed on this cell.
709
0
        bool bCellsProtected = false;
710
0
        if (bVertical)
711
0
        {
712
            // row header
713
0
            SCROW nRPos = static_cast<SCROW>(nPos);
714
0
            bCellsProtected = rDoc.HasAttrib(0, nRPos, nTab, rDoc.MaxCol(), nRPos, nTab, HasAttrFlags::Protected);
715
0
        }
716
0
        else
717
0
        {
718
            // column header
719
0
            SCCOL nCPos = static_cast<SCCOL>(nPos);
720
0
            bCellsProtected = rDoc.HasAttrib(nCPos, 0, nTab, nCPos, rDoc.MaxRow(), nTab, HasAttrFlags::Protected);
721
0
        }
722
723
0
        bool bSelProtected   = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
724
0
        bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
725
726
0
        if (bCellsProtected)
727
0
            bSelectAllowed = bSelProtected;
728
0
        else
729
0
            bSelectAllowed = bSelUnprotected;
730
0
    }
731
0
    return bSelectAllowed;
732
0
}
733
734
void ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt )
735
0
{
736
0
    if (IsDisabled())
737
0
        return;
738
739
0
    bIgnoreMove = false;
740
0
    SelectWindow();
741
742
0
    bool bIsBorder;
743
0
    SCCOLROW nHitNo = GetMousePos(rMEvt.GetPosPixel(), bIsBorder);
744
0
    if (!IsSelectionAllowed(nHitNo))
745
0
        return;
746
0
    if ( ! rMEvt.IsLeft() )
747
0
        return;
748
0
    if (ScModule::get()->IsFormulaMode())
749
0
    {
750
0
        if( !pTabView )
751
0
            return;
752
0
        SCTAB nTab = pTabView->GetViewData().CurrentTabForData();
753
0
        if( !rMEvt.IsShift() )
754
0
            pTabView->DoneRefMode( rMEvt.IsMod1() );
755
0
        ScDocument& rDoc = pTabView->GetViewData().GetDocument();
756
0
        if( !bVertical )
757
0
        {
758
0
            pTabView->InitRefMode( nHitNo, 0, nTab, SC_REFTYPE_REF );
759
0
            pTabView->UpdateRef( nHitNo, rDoc.MaxRow(), nTab );
760
0
        }
761
0
        else
762
0
        {
763
0
            pTabView->InitRefMode( 0, nHitNo, nTab, SC_REFTYPE_REF );
764
0
            pTabView->UpdateRef( rDoc.MaxCol(), nHitNo, nTab );
765
0
        }
766
0
        bInRefMode = true;
767
0
        return;
768
0
    }
769
0
    if ( bIsBorder && ResizeAllowed() )
770
0
    {
771
0
        nDragNo = nHitNo;
772
0
        sal_uInt16 nClicks = rMEvt.GetClicks();
773
0
        if ( nClicks && nClicks%2==0 )
774
0
        {
775
0
            SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM );
776
0
            SetPointer( PointerStyle::Arrow );
777
0
        }
778
0
        else
779
0
        {
780
0
            if (bVertical)
781
0
                nDragStart = rMEvt.GetPosPixel().Y();
782
0
            else
783
0
                nDragStart = rMEvt.GetPosPixel().X();
784
0
            nDragPos = nDragStart;
785
            // tdf#140833 launch help tip to show after the double click time has expired
786
            // so under gtk the popover isn't active when the double click is processed
787
            // by gtk because under load on wayland the double click is getting handled
788
            // by something else and getting sent to the window underneath our window
789
0
            aShowHelpTimer.Start();
790
0
            DrawInvert( nDragPos );
791
792
0
            StartTracking();
793
0
            bDragging = true;
794
0
            bDragMoved = false;
795
0
        }
796
0
    }
797
0
    else
798
0
    {
799
0
        pSelEngine->SetWindow( this );
800
0
        tools::Rectangle aVis( Point(), GetOutputSizePixel() );
801
0
        if (bVertical)
802
0
        {
803
0
            aVis.SetLeft( LONG_MIN );
804
0
            aVis.SetRight( LONG_MAX );
805
0
        }
806
0
        else
807
0
        {
808
0
            aVis.SetTop( LONG_MIN );
809
0
            aVis.SetBottom( LONG_MAX );
810
0
        }
811
0
        pSelEngine->SetVisibleArea( aVis );
812
813
0
        SetMarking( true );     //  must precede SelMouseButtonDown
814
0
        pSelEngine->SelMouseButtonDown( rMEvt );
815
816
        //  In column/row headers a simple click already is a selection.
817
        //  -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor
818
        //  if the next click is somewhere else with Control key).
819
0
        pSelEngine->SelMouseMove( rMEvt );
820
821
0
        if (IsMouseCaptured())
822
0
        {
823
            // tracking instead of CaptureMouse, so it can be cancelled cleanly
824
            //! someday SelectionEngine itself should call StartTracking!?!
825
0
            ReleaseMouse();
826
0
            StartTracking();
827
0
        }
828
0
    }
829
0
}
830
831
void ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt )
832
0
{
833
0
    if ( IsDisabled() )
834
0
        return;
835
836
0
    if (ScModule* mod = ScModule::get(); mod->IsFormulaMode())
837
0
    {
838
0
        mod->EndReference();
839
0
        bInRefMode = false;
840
0
        return;
841
0
    }
842
843
0
    SetMarking( false );
844
0
    bIgnoreMove = false;
845
846
0
    if ( bDragging )
847
0
    {
848
0
        DrawInvert( nDragPos );
849
0
        ReleaseMouse();
850
0
        HideDragHelp();
851
0
        bDragging = false;
852
853
0
        tools::Long nScrPos    = GetScrPos( nDragNo );
854
0
        tools::Long nMousePos  = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
855
0
        bool bLayoutRTL = IsLayoutRTL();
856
0
        tools::Long nNewWidth  = bLayoutRTL ? ( nScrPos - nMousePos + 1 )
857
0
                                     : ( nMousePos + 2 - nScrPos );
858
859
0
        if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ )
860
0
        {
861
0
            SCCOLROW nStart = 0;
862
0
            SCCOLROW nEnd = nDragNo;
863
0
            while (nNewWidth < 0)
864
0
            {
865
0
                nStart = nDragNo;
866
0
                if (nDragNo>0)
867
0
                {
868
0
                    --nDragNo;
869
0
                    nNewWidth += GetEntrySize( nDragNo );   //! GetHiddenCount() ???
870
0
                }
871
0
                else
872
0
                    nNewWidth = 0;
873
0
            }
874
0
            HideEntries( nStart, nEnd );
875
0
        }
876
0
        else
877
0
        {
878
0
            if (bDragMoved)
879
0
                SetEntrySize( nDragNo, static_cast<sal_uInt16>(nNewWidth) );
880
0
        }
881
0
    }
882
0
    else
883
0
    {
884
0
        pSelEngine->SelMouseButtonUp( rMEvt );
885
0
        ReleaseMouse();
886
0
    }
887
0
}
888
889
void ScHeaderControl::MouseMove( const MouseEvent& rMEvt )
890
0
{
891
0
    if ( IsDisabled() )
892
0
    {
893
0
        SetPointer( PointerStyle::Arrow );
894
0
        return;
895
0
    }
896
897
0
    if (bInRefMode && rMEvt.IsLeft() && ScModule::get()->IsFormulaMode())
898
0
    {
899
0
        if( !pTabView )
900
0
            return;
901
0
        bool bTmp;
902
0
        SCCOLROW nHitNo = GetMousePos(rMEvt.GetPosPixel(), bTmp);
903
0
        SCTAB nTab = pTabView->GetViewData().CurrentTabForData();
904
0
        ScDocument& rDoc = pTabView->GetViewData().GetDocument();
905
0
        if( !bVertical )
906
0
            pTabView->UpdateRef( nHitNo, rDoc.MaxRow(), nTab );
907
0
        else
908
0
            pTabView->UpdateRef( rDoc.MaxCol(), nHitNo, nTab );
909
910
0
        return;
911
0
    }
912
913
0
    if ( bDragging )
914
0
    {
915
0
        tools::Long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
916
0
        if ( nNewPos != nDragPos )
917
0
        {
918
0
            DrawInvert( nDragPos );
919
0
            nDragPos = nNewPos;
920
0
            ShowDragHelp();
921
0
            DrawInvert( nDragPos );
922
923
0
            if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN)
924
0
                bDragMoved = true;
925
0
        }
926
0
    }
927
0
    else
928
0
    {
929
0
        bool bIsBorder;
930
0
        (void)GetMousePos(rMEvt.GetPosPixel(), bIsBorder);
931
932
0
        if ( bIsBorder && rMEvt.GetButtons()==0 && ResizeAllowed() )
933
0
            SetPointer( bVertical ? PointerStyle::VSizeBar : PointerStyle::HSizeBar );
934
0
        else
935
0
            SetPointer( PointerStyle::Arrow );
936
937
0
        if (!bIgnoreMove)
938
0
            pSelEngine->SelMouseMove( rMEvt );
939
0
    }
940
0
}
941
942
void ScHeaderControl::Tracking( const TrackingEvent& rTEvt )
943
0
{
944
    // Distribute the tracking events to the various MouseEvents, because
945
    // SelectionEngine does not know anything about Tracking
946
947
0
    if ( rTEvt.IsTrackingCanceled() )
948
0
        StopMarking();
949
0
    else if ( rTEvt.IsTrackingEnded() )
950
0
        MouseButtonUp( rTEvt.GetMouseEvent() );
951
0
    else
952
0
        MouseMove( rTEvt.GetMouseEvent() );
953
0
}
954
955
void ScHeaderControl::Command( const CommandEvent& rCEvt )
956
0
{
957
0
    CommandEventId nCmd = rCEvt.GetCommand();
958
0
    if ( nCmd == CommandEventId::ContextMenu )
959
0
    {
960
0
        StopMarking();      // finish selection / dragging
961
962
        // execute popup menu
963
964
0
        ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( SfxViewShell::Current() );
965
0
        if ( pViewSh )
966
0
        {
967
0
            if ( rCEvt.IsMouseEvent() )
968
0
            {
969
                // #i18735# select the column/row under the mouse pointer
970
0
                ScViewData& rViewData = pViewSh->GetViewData();
971
972
0
                SelectWindow();     // also deselects drawing objects, stops draw text edit
973
0
                if ( rViewData.HasEditView( rViewData.GetActivePart() ) )
974
0
                    ScModule::get()->InputEnterHandler(); // always end edit mode
975
976
0
                bool bBorder;
977
0
                SCCOLROW nPos = GetMousePos(rCEvt.GetMousePosPixel(), bBorder );
978
0
                if (!IsSelectionAllowed(nPos))
979
                    // Selecting this cell is not allowed, neither is context menu.
980
0
                    return;
981
982
0
                SCTAB nTab = rViewData.CurrentTabForData();
983
0
                ScDocument& rDoc = pViewSh->GetViewData().GetDocument();
984
0
                ScRange aNewRange;
985
0
                if ( bVertical )
986
0
                    aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab,
987
0
                                         rDoc.MaxCol(), sal::static_int_cast<SCROW>(nPos), nTab );
988
0
                else
989
0
                    aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab,
990
0
                                         sal::static_int_cast<SCCOL>(nPos), rDoc.MaxRow(), nTab );
991
992
                // see if any part of the range is already selected
993
0
                ScRangeList aRanges;
994
0
                rViewData.GetMarkData().FillRangeListWithMarks( &aRanges, false );
995
0
                bool bSelected = aRanges.Intersects(aNewRange);
996
997
                // select the range if no part of it was selected
998
0
                if ( !bSelected )
999
0
                    pViewSh->MarkRange( aNewRange );
1000
0
            }
1001
1002
0
            pViewSh->GetDispatcher()->ExecutePopup( bVertical ? u"rowheader"_ustr : u"colheader"_ustr );
1003
0
        }
1004
0
    }
1005
0
    else if ( nCmd == CommandEventId::StartDrag )
1006
0
    {
1007
0
        pSelEngine->Command( rCEvt );
1008
0
    }
1009
0
}
1010
1011
void ScHeaderControl::StopMarking()
1012
0
{
1013
0
    if ( bDragging )
1014
0
    {
1015
0
        DrawInvert( nDragPos );
1016
0
        HideDragHelp();
1017
0
        bDragging = false;
1018
0
    }
1019
1020
0
    SetMarking( false );
1021
0
    bIgnoreMove = true;
1022
1023
    //  don't call pSelEngine->Reset, so selection across the parts of
1024
    //  a split/frozen view is possible
1025
0
    if (IsMouseCaptured())
1026
0
        ReleaseMouse();
1027
0
}
1028
1029
IMPL_LINK_NOARG(ScHeaderControl, ShowDragHelpHdl, Timer*, void)
1030
0
{
1031
0
    ShowDragHelp();
1032
0
}
1033
1034
void ScHeaderControl::ShowDragHelp()
1035
0
{
1036
0
    aShowHelpTimer.Stop();
1037
0
    if (!Help::IsQuickHelpEnabled())
1038
0
        return;
1039
1040
0
    tools::Long nScrPos    = GetScrPos( nDragNo );
1041
0
    bool bLayoutRTL = IsLayoutRTL();
1042
0
    tools::Long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 )
1043
0
                           : ( nDragPos + 2 - nScrPos );
1044
1045
0
    OUString aHelpStr = GetDragHelp( nVal );
1046
0
    Point aPos = OutputToScreenPixel( Point(0,0) );
1047
0
    Size aSize = GetSizePixel();
1048
1049
0
    Point aMousePos = OutputToScreenPixel(GetPointerPosPixel());
1050
1051
0
    tools::Rectangle aRect;
1052
0
    QuickHelpFlags nAlign;
1053
0
    if (!bVertical)
1054
0
    {
1055
        // above
1056
0
        aRect.SetLeft( aMousePos.X() );
1057
0
        aRect.SetTop( aPos.Y() - 4 );
1058
0
        nAlign       = QuickHelpFlags::Bottom|QuickHelpFlags::Center;
1059
0
    }
1060
0
    else
1061
0
    {
1062
        // top right
1063
0
        aRect.SetLeft( aPos.X() + aSize.Width() + 8 );
1064
0
        aRect.SetTop( aMousePos.Y() - 2 );
1065
0
        nAlign       = QuickHelpFlags::Left|QuickHelpFlags::Bottom;
1066
0
    }
1067
1068
0
    aRect.SetRight( aRect.Left() );
1069
0
    aRect.SetBottom( aRect.Top() );
1070
1071
0
    if (nTipVisible)
1072
0
        Help::HidePopover(this, nTipVisible);
1073
0
    nTipVisible = Help::ShowPopover(this, aRect, aHelpStr, nAlign);
1074
0
}
1075
1076
void ScHeaderControl::HideDragHelp()
1077
0
{
1078
0
    aShowHelpTimer.Stop();
1079
0
    if (nTipVisible)
1080
0
    {
1081
0
        Help::HidePopover(this, nTipVisible);
1082
0
        nTipVisible = nullptr;
1083
0
    }
1084
0
}
1085
1086
void ScHeaderControl::RequestHelp( const HelpEvent& rHEvt )
1087
0
{
1088
    //  If the own QuickHelp is displayed, don't let RequestHelp remove it
1089
1090
0
    bool bOwn = bDragging && Help::IsQuickHelpEnabled();
1091
0
    if (!bOwn)
1092
0
        Window::RequestHelp(rHEvt);
1093
0
}
1094
1095
//                  dummies for virtual methods
1096
1097
SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo ) const
1098
0
{
1099
0
    SCCOLROW nHidden = 0;
1100
0
    while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 )
1101
0
    {
1102
0
        ++nEntryNo;
1103
0
        ++nHidden;
1104
0
    }
1105
0
    return nHidden;
1106
0
}
1107
1108
bool ScHeaderControl::IsLayoutRTL() const
1109
0
{
1110
0
    return false;
1111
0
}
1112
1113
bool ScHeaderControl::IsDisabled() const
1114
0
{
1115
0
    return false;
1116
0
}
1117
1118
bool ScHeaderControl::ResizeAllowed() const
1119
0
{
1120
0
    return true;
1121
0
}
1122
1123
void ScHeaderControl::SelectWindow()
1124
0
{
1125
0
}
1126
1127
void ScHeaderControl::DrawInvert( tools::Long /* nDragPos */ )
1128
0
{
1129
0
}
1130
1131
OUString ScHeaderControl::GetDragHelp( tools::Long /* nVal */ )
1132
0
{
1133
0
    return OUString();
1134
0
}
1135
1136
void ScHeaderControl::SetMarking( bool /* bSet */ )
1137
0
{
1138
0
}
1139
1140
void ScHeaderControl::GetMarkRange(SCCOLROW& rStart, SCCOLROW& rEnd) const
1141
0
{
1142
0
    rStart = nMarkStart;
1143
0
    rEnd = nMarkEnd;
1144
0
}
1145
1146
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */