Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svtools/source/brwbox/brwbox2.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 <sal/log.hxx>
21
#include <o3tl/safeint.hxx>
22
#include <osl/diagnose.h>
23
#include <tools/debug.hxx>
24
#include <tools/mapunit.hxx>
25
#include <svtools/brwbox.hxx>
26
#include <svtools/brwhead.hxx>
27
#include <svtools/colorcfg.hxx>
28
#include <svtools/scrolladaptor.hxx>
29
#include "datwin.hxx"
30
#include <vcl/commandevent.hxx>
31
#include <vcl/help.hxx>
32
#include <vcl/ptrstyle.hxx>
33
#include <vcl/rendercontext/SystemTextColorFlags.hxx>
34
#include <vcl/settings.hxx>
35
36
#include <tools/multisel.hxx>
37
#include <tools/fract.hxx>
38
#include <algorithm>
39
#include <memory>
40
41
using namespace ::com::sun::star::datatransfer;
42
43
44
void BrowseBox::StartDrag( sal_Int8 /* _nAction */, const Point& /* _rPosPixel */ )
45
0
{
46
    // not interested in this event
47
0
}
48
49
50
sal_Int8 BrowseBox::AcceptDrop( const AcceptDropEvent& _rEvt )
51
0
{
52
0
    AcceptDropEvent aTransformed( _rEvt );
53
0
    aTransformed.maPosPixel = pDataWin->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) );
54
0
    return pDataWin->AcceptDrop( aTransformed );
55
0
}
56
57
58
sal_Int8 BrowseBox::ExecuteDrop( const ExecuteDropEvent& _rEvt )
59
0
{
60
0
    ExecuteDropEvent aTransformed( _rEvt );
61
0
    aTransformed.maPosPixel = pDataWin->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) );
62
0
    return pDataWin->ExecuteDrop( aTransformed );
63
0
}
64
65
66
sal_Int8 BrowseBox::AcceptDrop( const BrowserAcceptDropEvent& )
67
0
{
68
    // not interested in this event
69
0
    return DND_ACTION_NONE;
70
0
}
71
72
73
sal_Int8 BrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& )
74
0
{
75
    // not interested in this event
76
0
    return DND_ACTION_NONE;
77
0
}
78
79
80
const DataFlavorExVector& BrowseBox::GetDataFlavors() const
81
0
{
82
0
    if (pDataWin->bCallingDropCallback)
83
0
        return pDataWin->GetDataFlavorExVector();
84
0
    return GetDataFlavorExVector();
85
0
}
86
87
88
bool BrowseBox::IsDropFormatSupported( SotClipboardFormatId _nFormat ) const
89
0
{
90
0
    if ( pDataWin->bCallingDropCallback )
91
0
        return pDataWin->IsDropFormatSupported( _nFormat );
92
93
0
    return DropTargetHelper::IsDropFormatSupported( _nFormat );
94
0
}
95
96
97
void BrowseBox::Command( const CommandEvent& rEvt )
98
0
{
99
0
    if ( !pDataWin->bInCommand )
100
0
        Control::Command( rEvt );
101
0
}
102
103
104
void BrowseBox::StateChanged( StateChangedType nStateChange )
105
0
{
106
0
    Control::StateChanged( nStateChange );
107
108
0
    if ( StateChangedType::Mirroring == nStateChange )
109
0
    {
110
0
        pDataWin->EnableRTL( IsRTLEnabled() );
111
112
0
        HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
113
0
        if ( pHeaderBar )
114
0
            pHeaderBar->EnableRTL( IsRTLEnabled() );
115
0
        aHScroll->EnableRTL( IsRTLEnabled() );
116
0
        if( pVScroll )
117
0
            pVScroll->EnableRTL( IsRTLEnabled() );
118
0
        Resize();
119
0
    }
120
0
    else if ( StateChangedType::InitShow == nStateChange )
121
0
    {
122
0
        bBootstrapped = true; // must be set first!
123
124
0
        Resize();
125
0
        if ( bMultiSelection )
126
0
            uRow.pSel->SetTotalRange( Range( 0, nRowCount - 1 ) );
127
0
        if ( nRowCount == 0 )
128
0
            nCurRow = BROWSER_ENDOFSELECTION;
129
0
        else if ( nCurRow == BROWSER_ENDOFSELECTION )
130
0
            nCurRow = 0;
131
132
133
0
        if ( HasFocus() )
134
0
        {
135
0
            bSelectionIsVisible = true;
136
0
            bHasFocus = true;
137
0
        }
138
0
        UpdateScrollbars();
139
0
        AutoSizeLastColumn();
140
0
        CursorMoved();
141
0
    }
142
0
    else if (StateChangedType::Zoom == nStateChange)
143
0
    {
144
0
        pDataWin->SetZoom(GetZoom());
145
0
        HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
146
0
        if (pHeaderBar)
147
0
            pHeaderBar->SetZoom(GetZoom());
148
149
        // let the columns calculate their new widths and adjust the header bar
150
0
        for (auto & pCol : mvCols)
151
0
        {
152
0
            pCol->ZoomChanged(GetZoom());
153
0
            if ( pHeaderBar )
154
0
                pHeaderBar->SetItemSize( pCol->GetId(), pCol->Width() );
155
0
        }
156
157
        // all our controls have to be repositioned
158
0
        Resize();
159
0
    }
160
0
    else if (StateChangedType::Enable == nStateChange)
161
0
    {
162
        // do we have a handle column?
163
0
        bool bHandleCol = !mvCols.empty() && (0 == mvCols[ 0 ]->GetId());
164
        // do we have a header bar?
165
0
        bool bHeaderBar(pDataWin->pHeaderBar);
166
167
0
        if  (   nTitleLines
168
0
            &&  (   !bHeaderBar
169
0
                ||  bHandleCol
170
0
                )
171
0
            )
172
            // we draw the text in our header bar in a color dependent on the enabled state. So if this state changed
173
            // -> redraw
174
0
            Invalidate(tools::Rectangle(Point(0, 0), Size(GetOutputSizePixel().Width(), GetTitleHeight() - 1)));
175
0
    }
176
0
}
177
178
179
void BrowseBox::Select()
180
0
{
181
0
}
182
183
184
void BrowseBox::DoubleClick( const BrowserMouseEvent & )
185
0
{
186
0
}
187
188
189
tools::Long BrowseBox::QueryMinimumRowHeight()
190
0
{
191
0
    return CalcZoom( 5 );
192
0
}
193
194
195
void BrowseBox::ImplStartTracking()
196
0
{
197
0
}
198
199
200
void BrowseBox::ImplEndTracking()
201
0
{
202
0
}
203
204
205
void BrowseBox::RowHeightChanged()
206
0
{
207
0
}
208
209
210
void BrowseBox::ColumnResized( sal_uInt16 )
211
0
{
212
0
}
213
214
215
void BrowseBox::ColumnMoved( sal_uInt16 )
216
0
{
217
0
}
218
219
220
void BrowseBox::StartScroll()
221
0
{
222
0
    DoHideCursor();
223
0
}
224
225
226
void BrowseBox::EndScroll()
227
0
{
228
0
    UpdateScrollbars();
229
0
    AutoSizeLastColumn();
230
0
    DoShowCursor();
231
0
}
232
233
234
void BrowseBox::ToggleSelection()
235
0
{
236
237
    // selection highlight-toggling allowed?
238
0
    if ( bHideSelect )
239
0
        return;
240
0
    if ( bNotToggleSel || !IsUpdateMode() || !bSelectionIsVisible )
241
0
        return;
242
243
    // only highlight painted areas!
244
0
    bNotToggleSel = true;
245
246
    // accumulate areas of rows to highlight
247
0
    std::vector<tools::Rectangle> aHighlightList;
248
0
    sal_Int32 nLastRowInRect = 0; // for the CFront
249
250
    // don't highlight handle column
251
0
    BrowserColumn *pFirstCol = mvCols.empty() ? nullptr : mvCols[ 0 ].get();
252
0
    tools::Long nOfsX = (!pFirstCol || pFirstCol->GetId()) ? 0 : pFirstCol->Width();
253
254
    // accumulate old row selection
255
0
    sal_Int32 nBottomRow = nTopRow +
256
0
        pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight();
257
0
    if ( nBottomRow > GetRowCount() && GetRowCount() )
258
0
        nBottomRow = GetRowCount();
259
0
    for ( sal_Int32 nRow = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
260
0
          nRow != BROWSER_ENDOFSELECTION && nRow <= nBottomRow;
261
0
          nRow = bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION )
262
0
    {
263
0
        if ( nRow < nTopRow )
264
0
            continue;
265
266
0
        tools::Rectangle aAddRect(
267
0
            Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
268
0
            Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
269
0
        if ( !aHighlightList.empty() && nLastRowInRect == ( nRow - 1 ) )
270
0
            aHighlightList[ 0 ].Union( aAddRect );
271
0
        else
272
0
            aHighlightList.emplace( aHighlightList.begin(), aAddRect );
273
0
        nLastRowInRect = nRow;
274
0
    }
275
276
    // unhighlight the old selection (if any)
277
0
    while ( !aHighlightList.empty() )
278
0
    {
279
0
        pDataWin->Invalidate( aHighlightList.back() );
280
0
        aHighlightList.pop_back();
281
0
    }
282
283
    // unhighlight old column selection (if any)
284
0
    for ( tools::Long nColId = pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
285
0
          nColId != BROWSER_ENDOFSELECTION;
286
0
          nColId = pColSel->NextSelected() )
287
0
    {
288
0
        tools::Rectangle aRect( GetFieldRectPixel(nCurRow,
289
0
                                           mvCols[ nColId ]->GetId(),
290
0
                                           false ) );
291
0
        aRect.AdjustLeft( -(MIN_COLUMNWIDTH) );
292
0
        aRect.AdjustRight(MIN_COLUMNWIDTH );
293
0
        aRect.SetTop( 0 );
294
0
        aRect.SetBottom( pDataWin->GetOutputSizePixel().Height() );
295
0
        pDataWin->Invalidate( aRect );
296
0
    }
297
298
0
    bNotToggleSel = false;
299
0
}
300
301
302
void BrowseBox::DrawCursor()
303
0
{
304
0
    bool bReallyHide = false;
305
0
    if ( bHideCursor == TRISTATE_INDET )
306
0
    {
307
0
        if ( !GetSelectRowCount() && !GetSelectColumnCount() )
308
0
            bReallyHide = true;
309
0
    }
310
0
    else if ( bHideCursor == TRISTATE_TRUE )
311
0
    {
312
0
        bReallyHide = true;
313
0
    }
314
315
0
    bReallyHide |= !bSelectionIsVisible || !IsUpdateMode() || bScrolling || nCurRow < 0;
316
317
0
    if (PaintCursorIfHiddenOnce())
318
0
        bReallyHide |= ( GetCursorHideCount() > 1 );
319
0
    else
320
0
        bReallyHide |= ( GetCursorHideCount() > 0 );
321
322
    // no cursor on handle column
323
0
    if ( nCurColId == HandleColumnId )
324
0
        nCurColId = GetColumnId(1);
325
326
    // calculate cursor rectangle
327
0
    tools::Rectangle aCursor;
328
0
    if ( bColumnCursor )
329
0
    {
330
0
        aCursor = GetFieldRectPixel( nCurRow, nCurColId, false );
331
0
        aCursor.AdjustLeft( -(MIN_COLUMNWIDTH) );
332
0
        aCursor.AdjustRight(1 );
333
0
        aCursor.AdjustBottom(1 );
334
0
    }
335
0
    else
336
0
        aCursor = tools::Rectangle(
337
0
            Point( ( !mvCols.empty() && mvCols[ 0 ]->GetId() == 0 ) ?
338
0
                        mvCols[ 0 ]->Width() : 0,
339
0
                        (nCurRow - nTopRow) * GetDataRowHeight() + 1 ),
340
0
            Size( pDataWin->GetOutputSizePixel().Width() + 1,
341
0
                  GetDataRowHeight() - 2 ) );
342
0
    if ( bHLines )
343
0
    {
344
0
        if ( !bMultiSelection )
345
0
            aCursor.AdjustTop( -1 );
346
0
        aCursor.AdjustBottom( -1 );
347
0
    }
348
349
0
    if (m_aCursorColor == COL_TRANSPARENT)
350
0
    {
351
        // on these platforms, the StarView focus works correctly
352
0
        if ( bReallyHide )
353
0
            static_cast<Control*>(pDataWin.get())->HideFocus();
354
0
        else
355
0
            static_cast<Control*>(pDataWin.get())->ShowFocus( aCursor );
356
0
    }
357
0
    else
358
0
    {
359
0
        Color rCol = bReallyHide ? pDataWin->GetOutDev()->GetFillColor() : m_aCursorColor;
360
0
        Color aOldFillColor = pDataWin->GetOutDev()->GetFillColor();
361
0
        Color aOldLineColor = pDataWin->GetOutDev()->GetLineColor();
362
0
        pDataWin->GetOutDev()->SetFillColor();
363
0
        pDataWin->GetOutDev()->SetLineColor( rCol );
364
0
        pDataWin->GetOutDev()->DrawRect( aCursor );
365
0
        pDataWin->GetOutDev()->SetLineColor( aOldLineColor );
366
0
        pDataWin->GetOutDev()->SetFillColor( aOldFillColor );
367
0
    }
368
0
}
369
370
371
tools::Long BrowseBox::GetColumnWidth( sal_uInt16 nId ) const
372
0
{
373
374
0
    sal_uInt16 nItemPos = GetColumnPos( nId );
375
0
    if ( nItemPos >= mvCols.size() )
376
0
        return 0;
377
0
    return mvCols[ nItemPos ]->Width();
378
0
}
379
380
381
sal_uInt16 BrowseBox::GetColumnId( sal_uInt16 nPos ) const
382
0
{
383
384
0
    if ( nPos >= mvCols.size() )
385
0
        return BROWSER_INVALIDID;
386
0
    return mvCols[ nPos ]->GetId();
387
0
}
388
389
390
sal_uInt16 BrowseBox::GetColumnPos( sal_uInt16 nId ) const
391
0
{
392
0
    for ( size_t nPos = 0; nPos < mvCols.size(); ++nPos )
393
0
        if ( mvCols[ nPos ]->GetId() == nId )
394
0
            return nPos;
395
0
    return BROWSER_INVALIDID;
396
0
}
397
398
399
bool BrowseBox::IsFrozen( sal_uInt16 nColumnId ) const
400
0
{
401
0
    for (auto const & pCol : mvCols)
402
0
        if ( pCol->GetId() == nColumnId )
403
0
            return pCol->IsFrozen();
404
0
    return false;
405
0
}
406
407
408
void BrowseBox::ExpandRowSelection( const BrowserMouseEvent& rEvt )
409
0
{
410
0
    DoHideCursor();
411
412
    // expand the last selection
413
0
    if ( bMultiSelection )
414
0
    {
415
0
        Range aJustifiedRange( aSelRange );
416
0
        aJustifiedRange.Normalize();
417
418
0
        bool bSelectThis = ( bSelect != aJustifiedRange.Contains( rEvt.GetRow() ) );
419
420
0
        if ( aJustifiedRange.Contains( rEvt.GetRow() ) )
421
0
        {
422
            // down and up
423
0
            while ( rEvt.GetRow() < aSelRange.Max() )
424
0
            {   // ZTC/Mac bug - don't put these statements together!
425
0
                SelectRow( aSelRange.Max(), bSelectThis );
426
0
                --aSelRange.Max();
427
0
            }
428
0
            while ( rEvt.GetRow() > aSelRange.Max() )
429
0
            {   // ZTC/Mac bug - don't put these statements together!
430
0
                SelectRow( aSelRange.Max(), bSelectThis );
431
0
                ++aSelRange.Max();
432
0
            }
433
0
        }
434
0
        else
435
0
        {
436
            // up and down
437
0
            bool bOldSelecting = bSelecting;
438
0
            bSelecting = true;
439
0
            while ( rEvt.GetRow() < aSelRange.Max() )
440
0
            {   // ZTC/Mac bug - don't put these statements together!
441
0
                --aSelRange.Max();
442
0
                if ( !IsRowSelected( aSelRange.Max() ) )
443
0
                {
444
0
                    SelectRow( aSelRange.Max(), bSelectThis );
445
0
                    bSelect = true;
446
0
                }
447
0
            }
448
0
            while ( rEvt.GetRow() > aSelRange.Max() )
449
0
            {   // ZTC/Mac bug - don't put these statements together!
450
0
                ++aSelRange.Max();
451
0
                if ( !IsRowSelected( aSelRange.Max() ) )
452
0
                {
453
0
                    SelectRow( aSelRange.Max(), bSelectThis );
454
0
                    bSelect = true;
455
0
                }
456
0
            }
457
0
            bSelecting = bOldSelecting;
458
0
            if ( bSelect )
459
0
                Select();
460
0
        }
461
0
    }
462
0
    else
463
0
        if (!IsRowSelected(rEvt.GetRow()))
464
0
            SelectRow( rEvt.GetRow() );
465
466
0
    GoToRow( rEvt.GetRow(), false );
467
0
    DoShowCursor();
468
0
}
469
470
471
void BrowseBox::Resize()
472
0
{
473
0
    if ( !bBootstrapped && IsReallyVisible() )
474
0
        BrowseBox::StateChanged( StateChangedType::InitShow );
475
0
    if ( mvCols.empty() )
476
0
    {
477
0
        pDataWin->bResizeOnPaint = true;
478
0
        return;
479
0
    }
480
0
    pDataWin->bResizeOnPaint = false;
481
482
    // calc the size of the scrollbars
483
0
    tools::Long nSBHeight = GetBarHeight();
484
0
    tools::Long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
485
0
    if (IsZoom())
486
0
    {
487
0
        nSBHeight = static_cast<tools::Long>(nSBHeight * static_cast<double>(GetZoom()));
488
0
        nSBWidth = static_cast<tools::Long>(nSBWidth * static_cast<double>(GetZoom()));
489
0
    }
490
491
0
    DoHideCursor();
492
0
    sal_uInt16 nOldVisibleRows = 0;
493
    //fdo#42694, post #i111125# GetDataRowHeight() can be 0
494
0
    if (GetDataRowHeight())
495
0
        nOldVisibleRows = static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
496
497
    // did we need a horizontal scroll bar or is there a Control Area?
498
0
    if ( !pDataWin->bNoHScroll &&
499
0
         ( ( mvCols.size() - FrozenColCount() ) > 1 ) )
500
0
        aHScroll->Show();
501
0
    else
502
0
        aHScroll->Hide();
503
504
    // calculate the size of the data window
505
0
    tools::Long nDataHeight = GetOutputSizePixel().Height() - GetTitleHeight();
506
0
    if ( aHScroll->IsVisible() || ( nControlAreaWidth != USHRT_MAX ) )
507
0
        nDataHeight -= nSBHeight;
508
509
0
    tools::Long nDataWidth = GetOutputSizePixel().Width();
510
0
    if ( pVScroll->IsVisible() )
511
0
        nDataWidth -= nSBWidth;
512
513
    // adjust position and size of data window
514
0
    pDataWin->SetPosSizePixel(
515
0
        Point( 0, GetTitleHeight() ),
516
0
        Size( nDataWidth, nDataHeight ) );
517
518
0
    sal_uInt16 nVisibleRows = 0;
519
520
0
    if (GetDataRowHeight())
521
0
        nVisibleRows = static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
522
523
    // TopRow is unchanged, but the number of visible lines has changed.
524
0
    if ( nVisibleRows != nOldVisibleRows )
525
0
        VisibleRowsChanged(nTopRow, nVisibleRows);
526
527
0
    UpdateScrollbars();
528
529
    // Control-Area
530
0
    tools::Rectangle aInvalidArea( GetControlArea() );
531
0
    aInvalidArea.SetRight( GetOutputSizePixel().Width() );
532
0
    aInvalidArea.SetLeft( 0 );
533
0
    Invalidate( aInvalidArea );
534
535
    // external header-bar
536
0
    HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
537
0
    if ( pHeaderBar )
538
0
    {
539
        // take the handle column into account
540
0
        BrowserColumn *pFirstCol = mvCols[ 0 ].get();
541
0
        tools::Long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
542
0
        pHeaderBar->SetPosSizePixel( Point( nOfsX, 0 ), Size( GetOutputSizePixel().Width() - nOfsX, GetTitleHeight() ) );
543
0
    }
544
545
0
    AutoSizeLastColumn(); // adjust last column width
546
0
    DoShowCursor();
547
0
}
548
549
550
void BrowseBox::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
551
0
{
552
    // initializations
553
0
    if (!bBootstrapped && IsReallyVisible())
554
0
        BrowseBox::StateChanged(StateChangedType::InitShow);
555
0
    if (mvCols.empty())
556
0
        return;
557
558
0
    BrowserColumn *pFirstCol = mvCols[ 0 ].get();
559
0
    bool bHandleCol = pFirstCol && pFirstCol->GetId() == 0;
560
0
    bool bHeaderBar(pDataWin->pHeaderBar);
561
562
    // draw delimitational lines
563
0
    if (!pDataWin->bNoHScroll)
564
0
        rRenderContext.DrawLine(Point(0, aHScroll->GetPosPixel().Y()),
565
0
                                Point(GetOutputSizePixel().Width(),
566
0
                                      aHScroll->GetPosPixel().Y()));
567
568
0
    if (nTitleLines)
569
0
    {
570
0
        if (!bHeaderBar)
571
0
        {
572
0
            rRenderContext.DrawLine(Point(0, GetTitleHeight() - 1),
573
0
                                    Point(GetOutputSizePixel().Width(), GetTitleHeight() - 1));
574
0
        }
575
0
        else if (bHandleCol)
576
0
        {
577
0
            rRenderContext.DrawLine(Point(0, GetTitleHeight() - 1),
578
0
                                    Point(pFirstCol->Width(), GetTitleHeight() - 1));
579
0
        }
580
0
    }
581
582
    // Title Bar
583
    // If there is a handle column and if the  header bar is available, only
584
    // take the HandleColumn into account
585
0
    if (!(nTitleLines && (!bHeaderBar || bHandleCol)))
586
0
        return;
587
588
    // iterate through columns to redraw
589
0
    tools::Long nX = 0;
590
0
    size_t nCol;
591
0
    for (nCol = 0; nCol < mvCols.size() && nX < rRect.Right(); ++nCol)
592
0
    {
593
        // skip invisible columns between frozen and scrollable area
594
0
        if (nCol < nFirstCol && !mvCols[nCol]->IsFrozen())
595
0
            nCol = nFirstCol;
596
597
        // only the handle column?
598
0
        if (bHeaderBar && bHandleCol && nCol > 0)
599
0
            break;
600
601
0
        BrowserColumn* pCol = mvCols[nCol].get();
602
603
        // draw the column and increment position
604
0
        if ( pCol->Width() > 4 )
605
0
        {
606
0
            ButtonFrame aButtonFrame( Point( nX, 0 ),
607
0
                Size( pCol->Width()-1, GetTitleHeight()-1 ),
608
0
                pCol->Title(), !IsEnabled());
609
0
            aButtonFrame.Draw(rRenderContext);
610
0
            rRenderContext.DrawLine(Point(nX + pCol->Width() - 1, 0),
611
0
                                    Point(nX + pCol->Width() - 1, GetTitleHeight() - 1));
612
0
        }
613
0
        else
614
0
        {
615
0
            auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR);
616
0
            rRenderContext.SetFillColor(COL_BLACK);
617
0
            rRenderContext.DrawRect(tools::Rectangle(Point(nX, 0), Size(pCol->Width(), GetTitleHeight() - 1)));
618
0
        }
619
620
        // skip column
621
0
        nX += pCol->Width();
622
0
    }
623
624
    // retouching
625
0
    if ( !bHeaderBar && nCol == mvCols.size() )
626
0
    {
627
0
        const StyleSettings &rSettings = rRenderContext.GetSettings().GetStyleSettings();
628
0
        Color aColFace(rSettings.GetFaceColor());
629
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
630
0
        rRenderContext.SetFillColor(aColFace);
631
0
        rRenderContext.SetLineColor(aColFace);
632
0
        rRenderContext.DrawRect(tools::Rectangle(Point(nX, 0),
633
0
                                          Point(rRect.Right(), GetTitleHeight() - 2 )));
634
0
    }
635
636
0
    if (m_nActualCornerWidth)
637
0
    {
638
0
        const StyleSettings &rSettings = rRenderContext.GetSettings().GetStyleSettings();
639
0
        Color aColFace(rSettings.GetFaceColor());
640
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
641
0
        rRenderContext.SetFillColor(aColFace);
642
0
        rRenderContext.SetLineColor(aColFace);
643
0
        rRenderContext.DrawRect(tools::Rectangle(Point(GetOutputSizePixel().Width() - m_nActualCornerWidth, aHScroll->GetPosPixel().Y()),
644
0
                                                 Size(m_nActualCornerWidth, m_nCornerHeight)));
645
0
    }
646
0
}
647
648
void BrowseBox::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
649
0
{
650
    // we need pixel coordinates
651
0
    Size aRealSize = GetSizePixel();
652
0
    Point aRealPos = pDev->LogicToPixel(rPos);
653
654
0
    if ((aRealSize.Width() < 3) || (aRealSize.Height() < 3))
655
        // we want to have two pixels frame ...
656
0
        return;
657
658
0
    vcl::Font aFont = pDataWin->GetDrawPixelFont( pDev );
659
        // the 'normal' painting uses always the data window as device to output to, so we have to calc the new font
660
        // relative to the data wins current settings
661
662
0
    auto popIt = pDev->ScopedPush();
663
0
    pDev->SetMapMode();
664
0
    pDev->SetFont( aFont );
665
0
    if (nFlags & SystemTextColorFlags::Mono)
666
0
        pDev->SetTextColor(COL_BLACK);
667
0
    else
668
0
        pDev->SetTextColor(pDataWin->GetTextColor());
669
670
    // draw a frame
671
0
    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
672
0
    pDev->SetLineColor(rStyleSettings.GetDarkShadowColor());
673
0
    pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()),
674
0
                   Point(aRealPos.X(), aRealPos.Y() + aRealSize.Height() - 1));
675
0
    pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()),
676
0
                   Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y()));
677
0
    pDev->SetLineColor(rStyleSettings.GetShadowColor());
678
0
    pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + 1),
679
0
                   Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1));
680
0
    pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1),
681
0
                   Point(aRealPos.X() + 1, aRealPos.Y() + aRealSize.Height() - 1));
682
683
0
    HeaderBar* pBar = pDataWin->pHeaderBar;
684
685
    // we're drawing onto a foreign device, so we have to fake the DataRowHeight for the subsequent ImplPaintData
686
    // (as it is based on the settings of our data window, not the foreign device)
687
0
    if (!m_nDataRowHeight)
688
0
        ImpGetDataRowHeight();
689
0
    tools::Long nHeightLogic = PixelToLogic(Size(0, m_nDataRowHeight), MapMode(MapUnit::Map10thMM)).Height();
690
0
    tools::Long nForeignHeightPixel = pDev->LogicToPixel(Size(0, nHeightLogic), MapMode(MapUnit::Map10thMM)).Height();
691
692
0
    tools::Long nOriginalHeight = m_nDataRowHeight;
693
0
    m_nDataRowHeight = nForeignHeightPixel;
694
695
    // this counts for the column widths, too
696
0
    size_t nPos;
697
0
    for ( nPos = 0; nPos < mvCols.size(); ++nPos )
698
0
    {
699
0
        BrowserColumn* pCurrent = mvCols[ nPos ].get();
700
701
0
        tools::Long nWidthLogic = PixelToLogic(Size(pCurrent->Width(), 0), MapMode(MapUnit::Map10thMM)).Width();
702
0
        tools::Long nForeignWidthPixel = pDev->LogicToPixel(Size(nWidthLogic, 0), MapMode(MapUnit::Map10thMM)).Width();
703
704
0
        pCurrent->SetWidth(nForeignWidthPixel, GetZoom());
705
0
        if ( pBar )
706
0
            pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() );
707
0
    }
708
709
    // a smaller area for the content
710
0
    aRealPos.AdjustX( 1 );
711
0
    aRealPos.AdjustY( 1 );
712
0
    aRealSize.AdjustWidth( -2 );
713
0
    aRealSize.AdjustHeight( -2 );
714
715
    // let the header bar draw itself
716
0
    if ( pBar )
717
0
    {
718
        // the title height with respect to the font set for the given device
719
0
        tools::Long nTitleHeight = PixelToLogic(Size(0, GetTitleHeight()), MapMode(MapUnit::Map10thMM)).Height();
720
0
        nTitleHeight = pDev->LogicToPixel(Size(0, nTitleHeight), MapMode(MapUnit::Map10thMM)).Height();
721
722
0
        BrowserColumn* pFirstCol = !mvCols.empty() ? mvCols[ 0 ].get() : nullptr;
723
724
0
        Point aHeaderPos(pFirstCol && (pFirstCol->GetId() == 0) ? pFirstCol->Width() : 0, 0);
725
0
        Size aHeaderSize(aRealSize.Width() - aHeaderPos.X(), nTitleHeight);
726
727
0
        aHeaderPos += aRealPos;
728
            // do this before converting to logics !
729
730
        // the header's draw expects logic coordinates, again
731
0
        aHeaderPos = pDev->PixelToLogic(aHeaderPos);
732
733
0
        Size aOrigSize(pBar->GetSizePixel());
734
0
        pBar->SetSizePixel(aHeaderSize);
735
0
        pBar->Draw(pDev, aHeaderPos, nFlags);
736
0
        pBar->SetSizePixel(aOrigSize);
737
738
        // draw the "upper left cell" (the intersection between the header bar and the handle column)
739
0
        if (pFirstCol && (pFirstCol->GetId() == 0) && (pFirstCol->Width() > 4))
740
0
        {
741
0
            ButtonFrame aButtonFrame( aRealPos,
742
0
                Size( pFirstCol->Width()-1, nTitleHeight-1 ),
743
0
                pFirstCol->Title(), !IsEnabled());
744
0
            aButtonFrame.Draw( *pDev );
745
746
0
            auto popIt2 = pDev->ScopedPush(vcl::PushFlags::LINECOLOR);
747
0
            pDev->SetLineColor( COL_BLACK );
748
749
0
            pDev->DrawLine( Point( aRealPos.X(), aRealPos.Y() + nTitleHeight-1 ),
750
0
               Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) );
751
0
            pDev->DrawLine( Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() ),
752
0
               Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) );
753
0
        }
754
755
0
        aRealPos.AdjustY(aHeaderSize.Height() );
756
0
        aRealSize.AdjustHeight( -(aHeaderSize.Height()) );
757
0
    }
758
759
    // draw our own content (with clipping)
760
0
    vcl::Region aRegion(tools::Rectangle(aRealPos, aRealSize));
761
0
    pDev->SetClipRegion( pDev->PixelToLogic( aRegion ) );
762
763
    // do we have to paint the background
764
0
    bool bBackground = pDataWin->IsControlBackground();
765
0
    if ( bBackground )
766
0
    {
767
0
        tools::Rectangle aRect( aRealPos, aRealSize );
768
0
        pDev->SetFillColor( pDataWin->GetControlBackground() );
769
0
        pDev->DrawRect( aRect );
770
0
    }
771
772
0
    ImplPaintData( *pDev, tools::Rectangle( aRealPos, aRealSize ), true );
773
774
    // restore the column widths/data row height
775
0
    m_nDataRowHeight = nOriginalHeight;
776
0
    for ( nPos = 0; nPos < mvCols.size(); ++nPos )
777
0
    {
778
0
        BrowserColumn* pCurrent = mvCols[ nPos ].get();
779
780
0
        tools::Long nForeignWidthLogic = pDev->PixelToLogic(Size(pCurrent->Width(), 0), MapMode(MapUnit::Map10thMM)).Width();
781
0
        tools::Long nWidthPixel = LogicToPixel(Size(nForeignWidthLogic, 0), MapMode(MapUnit::Map10thMM)).Width();
782
783
0
        pCurrent->SetWidth(nWidthPixel, GetZoom());
784
0
        if ( pBar )
785
0
            pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() );
786
0
    }
787
0
}
788
789
void BrowseBox::ImplPaintData(OutputDevice& _rOut, const tools::Rectangle& _rRect, bool _bForeignDevice)
790
0
{
791
0
    Point aOverallAreaPos = _bForeignDevice ? _rRect.TopLeft() : Point(0,0);
792
0
    Size aOverallAreaSize = _bForeignDevice ? _rRect.GetSize() : pDataWin->GetOutputSizePixel();
793
0
    Point aOverallAreaBRPos = _bForeignDevice ? _rRect.BottomRight() : Point( aOverallAreaSize.Width(), aOverallAreaSize.Height() );
794
795
0
    tools::Long nDataRowHeight = GetDataRowHeight();
796
797
    // compute relative rows to redraw
798
0
    sal_Int32 nRelTopRow = 0;
799
0
    sal_Int32 nRelBottomRow = aOverallAreaSize.Height();
800
0
    if (!_bForeignDevice && nDataRowHeight)
801
0
    {
802
0
        nRelTopRow = static_cast<sal_Int32>((_rRect.Top()) / nDataRowHeight);
803
0
        nRelBottomRow = static_cast<sal_Int32>((_rRect.Bottom()) / nDataRowHeight);
804
0
    }
805
806
    // cache frequently used values
807
0
    Point aPos( aOverallAreaPos.X(), nRelTopRow * nDataRowHeight + aOverallAreaPos.Y() );
808
0
    _rOut.SetLineColor( COL_WHITE );
809
0
    const AllSettings& rAllSets = _rOut.GetSettings();
810
0
    const StyleSettings &rSettings = rAllSets.GetStyleSettings();
811
0
    const Color &rHighlightTextColor = rSettings.GetHighlightTextColor();
812
0
    const Color &rHighlightFillColor = rSettings.GetHighlightColor();
813
0
    Color aOldTextColor = _rOut.GetTextColor();
814
0
    Color aOldFillColor = _rOut.GetFillColor();
815
0
    Color aOldLineColor = _rOut.GetLineColor();
816
0
    tools::Long nHLineX = 0 == mvCols[ 0 ]->GetId() ? mvCols[ 0 ]->Width() : 0;
817
0
    nHLineX += aOverallAreaPos.X();
818
819
0
    Color aDelimiterLineColor( ::svtools::ColorConfig().GetColorValue( ::svtools::CALCGRID ).nColor );
820
821
    // redraw the invalid fields
822
0
    for ( sal_Int32 nRelRow = nRelTopRow;
823
0
          nRelRow <= nRelBottomRow && nTopRow+nRelRow < nRowCount;
824
0
          ++nRelRow, aPos.AdjustY(nDataRowHeight ) )
825
0
    {
826
        // get row
827
        // check valid area, to be on the safe side:
828
0
        DBG_ASSERT( static_cast<sal_uInt16>(nTopRow+nRelRow) < nRowCount, "BrowseBox::ImplPaintData: invalid seek" );
829
0
        if ( (nTopRow+tools::Long(nRelRow)) < 0 || static_cast<sal_uInt16>(nTopRow+nRelRow) >= nRowCount )
830
0
            continue;
831
832
        // prepare row
833
0
        sal_Int32 nRow = nTopRow+nRelRow;
834
0
        if ( !SeekRow( nRow) ) {
835
0
            OSL_FAIL("BrowseBox::ImplPaintData: SeekRow failed");
836
0
        }
837
0
        _rOut.SetClipRegion();
838
0
        aPos.setX( aOverallAreaPos.X() );
839
840
841
        // #73325# don't paint the row outside the painting rectangle (DG)
842
        // prepare auto-highlight
843
0
        tools::Rectangle aRowRect( Point( _rRect.Left(), aPos.Y() ),
844
0
                Size( _rRect.GetSize().Width(), nDataRowHeight ) );
845
846
0
        bool bRowSelected   =   !bHideSelect
847
0
                            &&  IsRowSelected( nRow );
848
0
        if ( bRowSelected )
849
0
        {
850
0
            _rOut.SetTextColor( rHighlightTextColor );
851
0
            _rOut.SetFillColor( rHighlightFillColor );
852
0
            _rOut.SetLineColor();
853
0
            _rOut.DrawRect( aRowRect );
854
0
        }
855
856
        // iterate through columns to redraw
857
0
        size_t nCol;
858
0
        for ( nCol = 0; nCol < mvCols.size(); ++nCol )
859
0
        {
860
            // get column
861
0
            BrowserColumn *pCol = mvCols[ nCol ].get();
862
863
            // at end of invalid area
864
0
            if ( aPos.X() >= _rRect.Right() )
865
0
                break;
866
867
            // skip invisible columns between frozen and scrollable area
868
0
            if ( nCol < nFirstCol && !pCol->IsFrozen() )
869
0
            {
870
0
                nCol = nFirstCol;
871
0
                pCol = (nCol < mvCols.size() ) ? mvCols[ nCol ].get() : nullptr;
872
0
                if (!pCol)
873
0
                {   // FS - 21.05.99 - 66325
874
                    // actually this has been fixed elsewhere (in the right place),
875
                    // but let's make sure...
876
0
                    OSL_FAIL("BrowseBox::PaintData : nFirstCol is probably invalid !");
877
0
                    break;
878
0
                }
879
0
            }
880
881
            // prepare Column-AutoHighlight
882
0
            bool bColAutoHighlight  =   bColumnCursor
883
0
                                    &&  IsColumnSelected( pCol->GetId() );
884
0
            if ( bColAutoHighlight )
885
0
            {
886
0
                _rOut.SetClipRegion();
887
0
                _rOut.SetTextColor( rHighlightTextColor );
888
0
                _rOut.SetFillColor( rHighlightFillColor );
889
0
                _rOut.SetLineColor();
890
0
                tools::Rectangle aFieldRect( aPos,
891
0
                        Size( pCol->Width(), nDataRowHeight ) );
892
0
                _rOut.DrawRect( aFieldRect );
893
0
            }
894
895
0
            if (!m_bFocusOnlyCursor && (pCol->GetId() == GetCurColumnId()) && (nRow == GetCurRow()))
896
0
                DrawCursor();
897
898
            // draw a single field.
899
            // else something is drawn to, e.g. handle column
900
0
            if (pCol->Width())
901
0
            {
902
                // clip the column's output to the field area
903
0
                if (_bForeignDevice)
904
0
                {   // (not necessary if painting onto the data window)
905
0
                    Size aFieldSize(pCol->Width(), nDataRowHeight);
906
907
0
                    if (aPos.X() + aFieldSize.Width() > aOverallAreaBRPos.X())
908
0
                        aFieldSize.setWidth( aOverallAreaBRPos.X() - aPos.X() );
909
910
0
                    if (aPos.Y() + aFieldSize.Height() > aOverallAreaBRPos.Y() + 1)
911
0
                    {
912
                        // for non-handle cols we don't clip vertically : we just don't draw the cell if the line isn't completely visible
913
0
                        if (pCol->GetId() != 0)
914
0
                            continue;
915
0
                        aFieldSize.setHeight( aOverallAreaBRPos.Y() + 1 - aPos.Y() );
916
0
                    }
917
918
0
                    vcl::Region aClipToField(tools::Rectangle(aPos, aFieldSize));
919
0
                    _rOut.SetClipRegion(aClipToField);
920
0
                }
921
0
                pCol->Draw( *this, _rOut, aPos );
922
0
                if (_bForeignDevice)
923
0
                    _rOut.SetClipRegion();
924
0
            }
925
926
            // reset Column-auto-highlight
927
0
            if ( bColAutoHighlight )
928
0
            {
929
0
                _rOut.SetTextColor( aOldTextColor );
930
0
                _rOut.SetFillColor( aOldFillColor );
931
0
                _rOut.SetLineColor( aOldLineColor );
932
0
            }
933
934
            // skip column
935
0
            aPos.AdjustX(pCol->Width() );
936
0
        }
937
938
        // reset auto-highlight
939
0
        if ( bRowSelected )
940
0
        {
941
0
            _rOut.SetTextColor( aOldTextColor );
942
0
            _rOut.SetFillColor( aOldFillColor );
943
0
            _rOut.SetLineColor( aOldLineColor );
944
0
        }
945
946
0
        if ( bHLines )
947
0
        {
948
            // draw horizontal delimitation lines
949
0
            _rOut.SetClipRegion();
950
0
            auto popIt = _rOut.ScopedPush(vcl::PushFlags::LINECOLOR);
951
0
            _rOut.SetLineColor( aDelimiterLineColor );
952
0
            tools::Long nY = aPos.Y() + nDataRowHeight - 1;
953
0
            if (nY <= aOverallAreaBRPos.Y())
954
0
                _rOut.DrawLine( Point( nHLineX, nY ),
955
0
                                Point( bVLines
956
0
                                        ? std::min(tools::Long(aPos.X() - 1), aOverallAreaBRPos.X())
957
0
                                        : aOverallAreaBRPos.X(),
958
0
                                      nY ) );
959
0
        }
960
0
    }
961
962
0
    if (aPos.Y() > aOverallAreaBRPos.Y() + 1)
963
0
        aPos.setY( aOverallAreaBRPos.Y() + 1 );
964
        // needed for some of the following drawing
965
966
    // retouching
967
0
    _rOut.SetClipRegion();
968
0
    aOldLineColor = _rOut.GetLineColor();
969
0
    aOldFillColor = _rOut.GetFillColor();
970
0
    _rOut.SetFillColor( rSettings.GetFaceColor() );
971
0
    if ( !mvCols.empty() && ( mvCols[ 0 ]->GetId() == 0 ) && ( aPos.Y() <= _rRect.Bottom() ) )
972
0
    {
973
        // fill rectangle gray below handle column
974
        // DG: fill it only until the end of the drawing rect and not to the end, as this may overpaint handle columns
975
0
        _rOut.SetLineColor( COL_BLACK );
976
0
        _rOut.DrawRect( tools::Rectangle(
977
0
            Point( aOverallAreaPos.X() - 1, aPos.Y() - 1 ),
978
0
            Point( aOverallAreaPos.X() + mvCols[ 0 ]->Width() - 1,
979
0
                   _rRect.Bottom() + 1) ) );
980
0
    }
981
0
    _rOut.SetFillColor( aOldFillColor );
982
983
    // draw vertical delimitational line between frozen and scrollable cols
984
0
    _rOut.SetLineColor( COL_BLACK );
985
0
    tools::Long nFrozenWidth = GetFrozenWidth()-1;
986
0
    _rOut.DrawLine( Point( aOverallAreaPos.X() + nFrozenWidth, aPos.Y() ),
987
0
                   Point( aOverallAreaPos.X() + nFrozenWidth, bHLines
988
0
                            ? aPos.Y() - 1
989
0
                            : aOverallAreaBRPos.Y() ) );
990
991
    // draw vertical delimitational lines?
992
0
    if ( bVLines )
993
0
    {
994
0
        _rOut.SetLineColor( aDelimiterLineColor );
995
0
        Point aVertPos( aOverallAreaPos.X() - 1, aOverallAreaPos.Y() );
996
0
        tools::Long nDeltaY = aOverallAreaBRPos.Y();
997
0
        for ( size_t nCol = 0; nCol < mvCols.size(); ++nCol )
998
0
        {
999
            // get column
1000
0
            BrowserColumn *pCol = mvCols[ nCol ].get();
1001
1002
            // skip invisible columns between frozen and scrollable area
1003
0
            if ( nCol < nFirstCol && !pCol->IsFrozen() )
1004
0
            {
1005
0
                nCol = nFirstCol;
1006
0
                pCol = mvCols[ nCol ].get();
1007
0
            }
1008
1009
            // skip column
1010
0
            aVertPos.AdjustX(pCol->Width() );
1011
1012
            // at end of invalid area
1013
            // invalid area is first reached when X > Right
1014
            // and not >=
1015
0
            if ( aVertPos.X() > _rRect.Right() )
1016
0
                break;
1017
1018
            // draw a single line
1019
0
            if ( pCol->GetId() != 0 )
1020
0
                _rOut.DrawLine( aVertPos, Point( aVertPos.X(),
1021
0
                               bHLines
1022
0
                                ? aPos.Y() - 1
1023
0
                                : aPos.Y() + nDeltaY ) );
1024
0
        }
1025
0
    }
1026
1027
0
    _rOut.SetLineColor( aOldLineColor );
1028
0
}
1029
1030
void BrowseBox::PaintData( vcl::Window const & rWin, vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
1031
0
{
1032
0
    if (!bBootstrapped && IsReallyVisible())
1033
0
        BrowseBox::StateChanged(StateChangedType::InitShow);
1034
1035
    // initializations
1036
0
    if (mvCols.empty() || !rWin.IsUpdateMode())
1037
0
        return;
1038
0
    if (pDataWin->bResizeOnPaint)
1039
0
        Resize();
1040
    // MI: who was that? Window::Update();
1041
1042
0
    ImplPaintData(rRenderContext, rRect, false);
1043
0
}
1044
1045
void BrowseBox::UpdateScrollbars()
1046
0
{
1047
1048
0
    if ( !bBootstrapped || !IsUpdateMode() )
1049
0
        return;
1050
1051
    // protect against recursion
1052
0
    if ( pDataWin->bInUpdateScrollbars )
1053
0
    {
1054
0
        pDataWin->bHadRecursion = true;
1055
0
        return;
1056
0
    }
1057
0
    pDataWin->bInUpdateScrollbars = true;
1058
1059
    // the size of the corner window (and the width of the VSB/height of the HSB)
1060
0
    m_nCornerHeight = GetBarHeight();
1061
0
    m_nCornerWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
1062
0
    if (IsZoom())
1063
0
    {
1064
0
        m_nCornerHeight = static_cast<tools::Long>(m_nCornerHeight * static_cast<double>(GetZoom()));
1065
0
        m_nCornerWidth = static_cast<tools::Long>(m_nCornerWidth * static_cast<double>(GetZoom()));
1066
0
    }
1067
1068
0
    bool bNeedsVScroll = false;
1069
0
    sal_Int32 nMaxRows = 0;
1070
0
    if (GetDataRowHeight())
1071
0
    {
1072
        // needs VScroll?
1073
0
        nMaxRows = (pDataWin->GetSizePixel().Height()) / GetDataRowHeight();
1074
0
        bNeedsVScroll =    pDataWin->bAutoVScroll
1075
0
                            ?   nTopRow || ( nRowCount > nMaxRows )
1076
0
                            :   !pDataWin->bNoVScroll;
1077
0
    }
1078
0
    Size aDataWinSize = pDataWin->GetSizePixel();
1079
0
    if ( !bNeedsVScroll )
1080
0
    {
1081
0
        if ( pVScroll->IsVisible() )
1082
0
        {
1083
0
            pVScroll->Hide();
1084
0
            Size aNewSize( aDataWinSize );
1085
0
            aNewSize.setWidth( GetOutputSizePixel().Width() );
1086
0
            aDataWinSize = aNewSize;
1087
0
        }
1088
0
    }
1089
0
    else if ( !pVScroll->IsVisible() )
1090
0
    {
1091
0
        Size aNewSize( aDataWinSize );
1092
0
        aNewSize.setWidth( GetOutputSizePixel().Width() - m_nCornerWidth );
1093
0
        aDataWinSize = aNewSize;
1094
0
    }
1095
1096
    // needs HScroll?
1097
0
    sal_uInt16 nLastCol = GetColumnAtXPosPixel( aDataWinSize.Width() - 1 );
1098
1099
0
    sal_uInt16 nFrozenCols = FrozenColCount();
1100
0
    bool bNeedsHScroll =    pDataWin->bAutoHScroll
1101
0
                        ?   ( nFirstCol > nFrozenCols ) || ( nLastCol <= mvCols.size() )
1102
0
                        :   !pDataWin->bNoHScroll;
1103
0
    if ( !bNeedsHScroll )
1104
0
    {
1105
0
        if ( aHScroll->IsVisible() )
1106
0
        {
1107
0
            aHScroll->Hide();
1108
0
        }
1109
0
        aDataWinSize.setHeight( GetOutputSizePixel().Height() - GetTitleHeight() );
1110
0
        if ( nControlAreaWidth != USHRT_MAX )
1111
0
            aDataWinSize.AdjustHeight( -sal_Int32(m_nCornerHeight) );
1112
0
    }
1113
0
    else if ( !aHScroll->IsVisible() )
1114
0
    {
1115
0
        Size aNewSize( aDataWinSize );
1116
0
        aNewSize.setHeight( GetOutputSizePixel().Height() - GetTitleHeight() - m_nCornerHeight );
1117
0
        aDataWinSize = aNewSize;
1118
0
    }
1119
1120
    // adjust position and Width of horizontal scrollbar
1121
0
    tools::Long nHScrX = nControlAreaWidth == USHRT_MAX
1122
0
        ? 0
1123
0
        : nControlAreaWidth;
1124
1125
0
    aHScroll->SetPosSizePixel(
1126
0
        Point( nHScrX, GetOutputSizePixel().Height() - m_nCornerHeight ),
1127
0
        Size( aDataWinSize.Width() - nHScrX, m_nCornerHeight ) );
1128
1129
    // total scrollable columns
1130
0
    short nScrollCols = short(mvCols.size()) - static_cast<short>(nFrozenCols);
1131
1132
    // visible columns
1133
0
    short nVisibleHSize = nLastCol == BROWSER_INVALIDID
1134
0
        ? static_cast<short>( mvCols.size() - nFirstCol )
1135
0
        : static_cast<short>( nLastCol - nFirstCol );
1136
1137
0
    if (nVisibleHSize)
1138
0
    {
1139
0
        short nRange = std::max( nScrollCols, short(0) );
1140
0
        aHScroll->SetVisibleSize( nVisibleHSize );
1141
0
        aHScroll->SetRange( Range( 0, nRange ));
1142
0
    }
1143
0
    else
1144
0
    {
1145
        // ensure scrollbar is shown as fully filled
1146
0
        aHScroll->SetVisibleSize(1);
1147
0
        aHScroll->SetRange(Range(0, 1));
1148
0
    }
1149
0
    if ( bNeedsHScroll && !aHScroll->IsVisible() )
1150
0
        aHScroll->Show();
1151
1152
    // adjust position and height of vertical scrollbar
1153
0
    pVScroll->SetPageSize( nMaxRows );
1154
1155
0
    if ( nTopRow > nRowCount )
1156
0
    {
1157
0
        nTopRow = nRowCount - 1;
1158
0
        OSL_FAIL("BrowseBox: nTopRow > nRowCount");
1159
0
    }
1160
1161
0
    if ( pVScroll->GetThumbPos() != nTopRow )
1162
0
        pVScroll->SetThumbPos( nTopRow );
1163
0
    tools::Long nVisibleSize = std::min( std::min( nRowCount, nMaxRows ), (nRowCount-nTopRow) );
1164
0
    pVScroll->SetVisibleSize( nVisibleSize ? nVisibleSize : 1 );
1165
0
    pVScroll->SetRange( Range( 0, nRowCount ) );
1166
0
    pVScroll->SetPosSizePixel(
1167
0
        Point( aDataWinSize.Width(), GetTitleHeight() ),
1168
0
        Size( m_nCornerWidth, aDataWinSize.Height()) );
1169
0
    tools::Long nLclDataRowHeight = GetDataRowHeight();
1170
0
    if ( nLclDataRowHeight > 0 && nRowCount < tools::Long( aDataWinSize.Height() / nLclDataRowHeight ) )
1171
0
        ScrollRows( -nTopRow );
1172
0
    if ( bNeedsVScroll && !pVScroll->IsVisible() )
1173
0
        pVScroll->Show();
1174
1175
0
    pDataWin->SetPosSizePixel(
1176
0
        Point( 0, GetTitleHeight() ),
1177
0
        aDataWinSize );
1178
1179
    // needs corner-window?
1180
    // (do that AFTER positioning BOTH scrollbars)
1181
0
    m_nActualCornerWidth = 0;
1182
0
    if (aHScroll->IsVisible() && pVScroll && pVScroll->IsVisible() )
1183
0
    {
1184
        // if we have both scrollbars, the corner window fills the point of intersection of these two
1185
0
        m_nActualCornerWidth = m_nCornerWidth;
1186
0
    }
1187
0
    else if ( !aHScroll->IsVisible() && ( nControlAreaWidth != USHRT_MAX ) )
1188
0
    {
1189
        // if we have no horizontal scrollbar, but a control area, we need the corner window to
1190
        // fill the space between the control are and the right border
1191
0
        m_nActualCornerWidth = GetOutputSizePixel().Width() - nControlAreaWidth;
1192
0
    }
1193
1194
    // scroll headerbar, if necessary
1195
0
    if ( pDataWin->pHeaderBar )
1196
0
    {
1197
0
        tools::Long nWidth = 0;
1198
0
        for ( size_t nCol = 0;
1199
0
              nCol < mvCols.size() && nCol < nFirstCol;
1200
0
              ++nCol )
1201
0
        {
1202
            // not the handle column
1203
0
            if ( mvCols[ nCol ]->GetId() )
1204
0
                nWidth += mvCols[ nCol ]->Width();
1205
0
        }
1206
1207
0
        pDataWin->pHeaderBar->SetOffset( nWidth );
1208
0
    }
1209
1210
0
    pDataWin->bInUpdateScrollbars = false;
1211
0
    if ( pDataWin->bHadRecursion )
1212
0
    {
1213
0
        pDataWin->bHadRecursion = false;
1214
0
        UpdateScrollbars();
1215
0
    }
1216
0
}
1217
1218
1219
void BrowseBox::SetUpdateMode( bool bUpdate )
1220
0
{
1221
1222
0
    bool bWasUpdate = IsUpdateMode();
1223
0
    if ( bWasUpdate == bUpdate )
1224
0
        return;
1225
1226
0
    Control::SetUpdateMode( bUpdate );
1227
    // If WB_CLIPCHILDREN is st at the BrowseBox (to minimize flicker),
1228
    // the data window is not invalidated by SetUpdateMode.
1229
0
    if( bUpdate )
1230
0
        pDataWin->Invalidate();
1231
0
    pDataWin->SetUpdateMode( bUpdate );
1232
1233
1234
0
    if ( bUpdate )
1235
0
    {
1236
0
        if ( bBootstrapped )
1237
0
        {
1238
0
            UpdateScrollbars();
1239
0
            AutoSizeLastColumn();
1240
0
        }
1241
0
        DoShowCursor();
1242
0
    }
1243
0
    else
1244
0
        DoHideCursor();
1245
0
}
1246
1247
1248
bool BrowseBox::GetUpdateMode() const
1249
0
{
1250
1251
0
    return pDataWin->IsUpdateMode();
1252
0
}
1253
1254
1255
tools::Long BrowseBox::GetFrozenWidth() const
1256
0
{
1257
1258
0
    tools::Long nWidth = 0;
1259
0
    for ( size_t nCol = 0;
1260
0
          nCol < mvCols.size() && mvCols[ nCol ]->IsFrozen();
1261
0
          ++nCol )
1262
0
        nWidth += mvCols[ nCol ]->Width();
1263
0
    return nWidth;
1264
0
}
1265
1266
void BrowseBox::ColumnInserted( sal_uInt16 nPos )
1267
0
{
1268
0
    if ( pColSel )
1269
0
        pColSel->Insert( nPos );
1270
0
    UpdateScrollbars();
1271
0
}
1272
1273
sal_uInt16 BrowseBox::FrozenColCount() const
1274
0
{
1275
0
    std::size_t nCol;
1276
0
    for ( nCol = 0;
1277
0
          nCol < mvCols.size() && mvCols[ nCol ]->IsFrozen();
1278
0
          ++nCol )
1279
0
        /* empty loop */;
1280
0
    return nCol; //TODO: BrowserColumns::size_type -> sal_uInt16!
1281
0
}
1282
1283
IMPL_LINK(BrowseBox, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
1284
0
{
1285
0
    auto nCurScrollRow = nTopRow;
1286
0
    auto nPos = rScrollbar.adjustment_get_value();
1287
0
    ScrollRows(nPos - nCurScrollRow);
1288
1289
0
    bool bShowTooltip = ((m_nCurrentMode & BrowserMode::TRACKING_TIPS) == BrowserMode::TRACKING_TIPS);
1290
0
    if (bShowTooltip &&
1291
0
        rScrollbar.get_scroll_type() == ScrollType::Drag &&
1292
0
        Help::IsQuickHelpEnabled())
1293
0
    {
1294
0
        OUString aTip = OUString::number(nPos) + "/";
1295
0
        if (!pDataWin->GetRealRowCount().isEmpty())
1296
0
            aTip += pDataWin->GetRealRowCount();
1297
0
        else
1298
0
            aTip += OUString::number(rScrollbar.adjustment_get_upper());
1299
0
        tools::Rectangle aRect(GetPointerPosPixel(), Size(GetTextWidth(aTip), GetTextHeight()));
1300
0
        Help::ShowQuickHelp(this, aRect, aTip);
1301
0
    }
1302
0
}
1303
1304
IMPL_LINK(BrowseBox, HorzScrollHdl, weld::Scrollbar&, rScrollbar, void)
1305
0
{
1306
0
    auto nCurScrollCol = nFirstCol - FrozenColCount();
1307
0
    ScrollColumns(rScrollbar.adjustment_get_value() - nCurScrollCol);
1308
0
}
1309
1310
IMPL_LINK( BrowseBox, StartDragHdl, HeaderBar*, pBar, void )
1311
0
{
1312
0
    pBar->SetDragSize( pDataWin->GetOutputSizePixel().Height() );
1313
0
}
1314
1315
// usually only the first column was resized
1316
void BrowseBox::MouseButtonDown( const MouseEvent& rEvt )
1317
0
{
1318
1319
0
    GrabFocus();
1320
1321
    // only mouse events in the title-line are supported
1322
0
    const Point &rEvtPos = rEvt.GetPosPixel();
1323
0
    if ( rEvtPos.Y() >= GetTitleHeight() )
1324
0
        return;
1325
1326
0
    tools::Long nX = 0;
1327
0
    tools::Long nWidth = GetOutputSizePixel().Width();
1328
0
    for ( size_t nCol = 0; nCol < mvCols.size() && nX < nWidth; ++nCol )
1329
0
    {
1330
        // is this column visible?
1331
0
        BrowserColumn *pCol = mvCols[ nCol ].get();
1332
0
        if ( pCol->IsFrozen() || nCol >= nFirstCol )
1333
0
        {
1334
            // compute right end of column
1335
0
            tools::Long nR = nX + pCol->Width() - 1;
1336
1337
            // at the end of a column (and not handle column)?
1338
0
            if ( pCol->GetId() && std::abs( nR - rEvtPos.X() ) < 2 )
1339
0
            {
1340
                // start resizing the column
1341
0
                bResizing = true;
1342
0
                nResizeCol = nCol;
1343
0
                nDragX = nResizeX = rEvtPos.X();
1344
0
                SetPointer( PointerStyle::HSplit );
1345
0
                CaptureMouse();
1346
0
                pDataWin->GetOutDev()->DrawLine( Point( nDragX, 0 ),
1347
0
                    Point( nDragX, pDataWin->GetSizePixel().Height() ) );
1348
0
                nMinResizeX = nX + MIN_COLUMNWIDTH;
1349
0
                return;
1350
0
            }
1351
0
            else if ( nX < rEvtPos.X() && nR > rEvtPos.X() )
1352
0
            {
1353
0
                MouseButtonDown( BrowserMouseEvent(
1354
0
                    this, rEvt, -1, nCol, pCol->GetId(), tools::Rectangle() ) );
1355
0
                return;
1356
0
            }
1357
0
            nX = nR + 1;
1358
0
        }
1359
0
    }
1360
1361
    // event occurred out of data area
1362
0
    if ( rEvt.IsRight() )
1363
0
        pDataWin->Command(
1364
0
            CommandEvent( Point( 1, LONG_MAX ), CommandEventId::ContextMenu, true ) );
1365
0
    else
1366
0
        SetNoSelection();
1367
0
}
1368
1369
1370
void BrowseBox::MouseMove( const MouseEvent& rEvt )
1371
0
{
1372
0
    SAL_INFO("svtools", "BrowseBox::MouseMove( MouseEvent )" );
1373
1374
0
    PointerStyle aNewPointer = PointerStyle::Arrow;
1375
1376
0
    sal_uInt16 nX = 0;
1377
0
    for ( size_t nCol = 0;
1378
0
          nCol < mvCols.size() &&
1379
0
            ( nX + mvCols[ nCol ]->Width() ) < GetOutputSizePixel().Width();
1380
0
          ++nCol )
1381
        // is this column visible?
1382
0
        if ( mvCols[ nCol ]->IsFrozen() || nCol >= nFirstCol )
1383
0
        {
1384
            // compute right end of column
1385
0
            BrowserColumn *pCol = mvCols[ nCol ].get();
1386
0
            sal_uInt16 nR = static_cast<sal_uInt16>(nX + pCol->Width() - 1);
1387
1388
            // show resize-pointer?
1389
0
            if ( bResizing || ( pCol->GetId() &&
1390
0
                 std::abs( static_cast<tools::Long>(nR) - rEvt.GetPosPixel().X() ) < MIN_COLUMNWIDTH ) )
1391
0
            {
1392
0
                aNewPointer = PointerStyle::HSplit;
1393
0
                if ( bResizing )
1394
0
                {
1395
                    // delete old auxiliary line
1396
0
                    pDataWin->HideTracking() ;
1397
1398
                    // check allowed width and new delta
1399
0
                    nDragX = std::max( rEvt.GetPosPixel().X(), nMinResizeX );
1400
0
                    tools::Long nDeltaX = nDragX - nResizeX;
1401
0
                    sal_uInt16 nId = GetColumnId(nResizeCol);
1402
0
                    tools::Long nOldWidth = GetColumnWidth(nId);
1403
0
                    nDragX = nOldWidth + nDeltaX + nResizeX - nOldWidth;
1404
1405
                    // draw new auxiliary line
1406
0
                    pDataWin->ShowTracking( tools::Rectangle( Point( nDragX, 0 ),
1407
0
                            Size( 1, pDataWin->GetSizePixel().Height() ) ),
1408
0
                            ShowTrackFlags::Split|ShowTrackFlags::TrackWindow );
1409
0
                }
1410
1411
0
            }
1412
1413
0
            nX = nR + 1;
1414
0
        }
1415
1416
0
    SetPointer( aNewPointer );
1417
0
}
1418
1419
1420
void BrowseBox::MouseButtonUp( const MouseEvent & rEvt )
1421
0
{
1422
1423
0
    if ( bResizing )
1424
0
    {
1425
        // delete auxiliary line
1426
0
        pDataWin->HideTracking();
1427
1428
        // width changed?
1429
0
        nDragX = std::max( rEvt.GetPosPixel().X(), nMinResizeX );
1430
0
        if ( (nDragX - nResizeX) != mvCols[ nResizeCol ]->Width() )
1431
0
        {
1432
            // resize column
1433
0
            tools::Long nMaxX = pDataWin->GetSizePixel().Width();
1434
0
            nDragX = std::min( nDragX, nMaxX );
1435
0
            tools::Long nDeltaX = nDragX - nResizeX;
1436
0
            sal_uInt16 nId = GetColumnId(nResizeCol);
1437
0
            SetColumnWidth( GetColumnId(nResizeCol), GetColumnWidth(nId) + nDeltaX );
1438
0
            ColumnResized( nId );
1439
0
        }
1440
1441
        // end action
1442
0
        SetPointer( PointerStyle::Arrow );
1443
0
        ReleaseMouse();
1444
0
        bResizing = false;
1445
0
    }
1446
0
    else
1447
0
        MouseButtonUp( BrowserMouseEvent( pDataWin,
1448
0
                MouseEvent( Point( rEvt.GetPosPixel().X(),
1449
0
                        rEvt.GetPosPixel().Y() - pDataWin->GetPosPixel().Y() ),
1450
0
                    rEvt.GetClicks(), rEvt.GetMode(), rEvt.GetButtons(),
1451
0
                    rEvt.GetModifier() ) ) );
1452
0
}
1453
1454
1455
static bool bExtendedMode = false;
1456
static bool bFieldMode = false;
1457
1458
void BrowseBox::MouseButtonDown( const BrowserMouseEvent& rEvt )
1459
0
{
1460
1461
0
    GrabFocus();
1462
1463
    // adjust selection while and after double-click
1464
0
    if ( rEvt.GetClicks() == 2 )
1465
0
    {
1466
0
        SetNoSelection();
1467
0
        if ( rEvt.GetRow() >= 0 )
1468
0
        {
1469
0
            GoToRow( rEvt.GetRow() );
1470
0
            SelectRow( rEvt.GetRow(), true, false );
1471
0
        }
1472
0
        else
1473
0
        {
1474
0
            if ( bColumnCursor && rEvt.GetColumn() != 0 )
1475
0
            {
1476
0
                if ( rEvt.GetColumn() < mvCols.size() )
1477
0
                    SelectColumnPos( rEvt.GetColumn(), true, false);
1478
0
            }
1479
0
        }
1480
0
        DoubleClick( rEvt );
1481
0
    }
1482
    // selections
1483
0
    else if ( ( rEvt.GetMode() & ( MouseEventModifiers::SELECT | MouseEventModifiers::SIMPLECLICK ) ) &&
1484
0
         ( bColumnCursor || rEvt.GetRow() >= 0 ) )
1485
0
    {
1486
0
        if ( rEvt.GetClicks() == 1 )
1487
0
        {
1488
            // initialise flags
1489
0
            bHit            = false;
1490
1491
            // selection out of range?
1492
0
            if ( rEvt.GetRow() >= nRowCount ||
1493
0
                 rEvt.GetColumnId() == BROWSER_INVALIDID )
1494
0
            {
1495
0
                SetNoSelection();
1496
0
                return;
1497
0
            }
1498
1499
            // while selecting, no cursor
1500
0
            bSelecting = true;
1501
0
            DoHideCursor();
1502
1503
            // DataRow?
1504
0
            if ( rEvt.GetRow() >= 0 )
1505
0
            {
1506
                // line selection?
1507
0
                if ( rEvt.GetColumnId() == HandleColumnId || !bColumnCursor )
1508
0
                {
1509
0
                    if ( bMultiSelection )
1510
0
                    {
1511
                        // remove column-selection, if exists
1512
0
                        if ( pColSel && pColSel->GetSelectCount() )
1513
0
                        {
1514
0
                            ToggleSelection();
1515
0
                            if ( bMultiSelection )
1516
0
                                uRow.pSel->SelectAll(false);
1517
0
                            else
1518
0
                                uRow.nSel = BROWSER_ENDOFSELECTION;
1519
0
                            if ( pColSel )
1520
0
                                pColSel->SelectAll(false);
1521
0
                            bSelect = true;
1522
0
                        }
1523
1524
                        // expanding mode?
1525
0
                        if ( rEvt.GetMode() & MouseEventModifiers::RANGESELECT )
1526
0
                        {
1527
                            // select the further touched rows too
1528
0
                            bSelect = true;
1529
0
                            ExpandRowSelection( rEvt );
1530
0
                            return;
1531
0
                        }
1532
1533
                        // click in the selected area?
1534
0
                        else if ( IsRowSelected( rEvt.GetRow() ) )
1535
0
                        {
1536
                            // wait for Drag&Drop
1537
0
                            bHit = true;
1538
0
                            bExtendedMode = bool( rEvt.GetMode() & MouseEventModifiers::MULTISELECT );
1539
0
                            return;
1540
0
                        }
1541
1542
                        // extension mode?
1543
0
                        else if ( rEvt.GetMode() & MouseEventModifiers::MULTISELECT )
1544
0
                        {
1545
                            // determine the new selection range
1546
                            // and selection/deselection
1547
0
                            aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
1548
0
                            SelectRow( rEvt.GetRow(),
1549
0
                                    !uRow.pSel->IsSelected( rEvt.GetRow() ) );
1550
0
                            bSelect = true;
1551
0
                            return;
1552
0
                        }
1553
0
                    }
1554
1555
                    // select directly
1556
0
                    SetNoSelection();
1557
0
                    GoToRow( rEvt.GetRow() );
1558
0
                    SelectRow( rEvt.GetRow() );
1559
0
                    aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
1560
0
                    bSelect = true;
1561
0
                }
1562
0
                else // Column/Field-Selection
1563
0
                {
1564
                    // click in selected column
1565
0
                    if ( IsColumnSelected( rEvt.GetColumn() ) ||
1566
0
                         IsRowSelected( rEvt.GetRow() ) )
1567
0
                    {
1568
0
                        bHit = true;
1569
0
                        bFieldMode = true;
1570
0
                        return;
1571
0
                    }
1572
1573
0
                    SetNoSelection();
1574
0
                    GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
1575
0
                    bSelect = true;
1576
0
                }
1577
0
            }
1578
0
            else
1579
0
            {
1580
0
                if ( bMultiSelection && rEvt.GetColumnId() == HandleColumnId )
1581
0
                {
1582
                    // toggle all-selection
1583
0
                    if ( uRow.pSel->GetSelectCount() > ( GetRowCount() / 2 ) )
1584
0
                        SetNoSelection();
1585
0
                    else
1586
0
                        SelectAll();
1587
0
                }
1588
0
                else
1589
0
                    SelectColumnPos( GetColumnPos(rEvt.GetColumnId()), true, false);
1590
0
            }
1591
1592
            // turn cursor on again, if necessary
1593
0
            bSelecting = false;
1594
0
            DoShowCursor();
1595
0
            if ( bSelect )
1596
0
                Select();
1597
0
        }
1598
0
    }
1599
0
}
1600
1601
1602
void BrowseBox::MouseButtonUp( const BrowserMouseEvent &rEvt )
1603
0
{
1604
1605
    // D&D was possible, but did not occur
1606
0
    if ( bHit )
1607
0
    {
1608
0
        aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
1609
0
        if ( bExtendedMode )
1610
0
            SelectRow( rEvt.GetRow(), false );
1611
0
        else
1612
0
        {
1613
0
            SetNoSelection();
1614
0
            if ( bFieldMode )
1615
0
                GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
1616
0
            else
1617
0
            {
1618
0
                GoToRow( rEvt.GetRow() );
1619
0
                SelectRow( rEvt.GetRow() );
1620
0
            }
1621
0
        }
1622
0
        bSelect = true;
1623
0
        bExtendedMode = false;
1624
0
        bFieldMode = false;
1625
0
        bHit = false;
1626
0
    }
1627
1628
    // activate cursor
1629
0
    if ( bSelecting )
1630
0
    {
1631
0
        bSelecting = false;
1632
0
        DoShowCursor();
1633
0
        if ( bSelect )
1634
0
            Select();
1635
0
    }
1636
0
}
1637
1638
1639
void BrowseBox::KeyInput( const KeyEvent& rEvt )
1640
0
{
1641
0
    if ( !ProcessKey( rEvt ) )
1642
0
        Control::KeyInput( rEvt );
1643
0
}
1644
1645
1646
bool BrowseBox::ProcessKey( const KeyEvent& rEvt )
1647
0
{
1648
1649
0
    sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
1650
0
    bool       bShift = rEvt.GetKeyCode().IsShift();
1651
0
    bool       bCtrl = rEvt.GetKeyCode().IsMod1();
1652
0
    bool       bAlt = rEvt.GetKeyCode().IsMod2();
1653
1654
0
    BrowserDispatchId eId = BrowserDispatchId::NONE;
1655
1656
0
    if ( !bAlt && !bCtrl && !bShift )
1657
0
    {
1658
0
        switch ( nCode )
1659
0
        {
1660
0
            case KEY_DOWN:
1661
0
                eId = BrowserDispatchId::CURSORDOWN;
1662
0
                break;
1663
0
            case KEY_UP:
1664
0
                eId = BrowserDispatchId::CURSORUP;
1665
0
                break;
1666
0
            case KEY_HOME:
1667
0
                eId = BrowserDispatchId::CURSORHOME;
1668
0
                break;
1669
0
            case KEY_END:
1670
0
                eId = BrowserDispatchId::CURSOREND;
1671
0
                break;
1672
0
            case KEY_TAB:
1673
0
                if ( !bColumnCursor )
1674
0
                    break;
1675
0
                [[fallthrough]];
1676
0
            case KEY_RIGHT:
1677
0
                eId = BrowserDispatchId::CURSORRIGHT;
1678
0
                break;
1679
0
            case KEY_LEFT:
1680
0
                eId = BrowserDispatchId::CURSORLEFT;
1681
0
                break;
1682
0
            case KEY_SPACE:
1683
0
                eId = BrowserDispatchId::SELECT;
1684
0
                break;
1685
0
        }
1686
0
        if (BrowserDispatchId::NONE != eId)
1687
0
            SetNoSelection();
1688
1689
0
        switch ( nCode )
1690
0
        {
1691
0
            case KEY_PAGEDOWN:
1692
0
                eId = BrowserDispatchId::CURSORPAGEDOWN;
1693
0
                break;
1694
0
            case KEY_PAGEUP:
1695
0
                eId = BrowserDispatchId::CURSORPAGEUP;
1696
0
                break;
1697
0
        }
1698
0
    }
1699
1700
0
    if ( !bAlt && !bCtrl && bShift )
1701
0
        switch ( nCode )
1702
0
        {
1703
0
            case KEY_DOWN:
1704
0
                eId = BrowserDispatchId::SELECTDOWN;
1705
0
                break;
1706
0
            case KEY_UP:
1707
0
                eId = BrowserDispatchId::SELECTUP;
1708
0
                break;
1709
0
            case KEY_TAB:
1710
0
                if ( !bColumnCursor )
1711
0
                    break;
1712
0
                eId = BrowserDispatchId::CURSORLEFT;
1713
0
                break;
1714
0
            case KEY_HOME:
1715
0
                eId = BrowserDispatchId::SELECTHOME;
1716
0
                break;
1717
0
            case KEY_END:
1718
0
                eId = BrowserDispatchId::SELECTEND;
1719
0
                break;
1720
0
        }
1721
1722
1723
0
    if ( !bAlt && bCtrl && !bShift )
1724
0
        switch ( nCode )
1725
0
        {
1726
0
            case KEY_DOWN:
1727
0
                eId = BrowserDispatchId::CURSORDOWN;
1728
0
                break;
1729
0
            case KEY_UP:
1730
0
                eId = BrowserDispatchId::CURSORUP;
1731
0
                break;
1732
0
            case KEY_PAGEDOWN:
1733
0
                eId = BrowserDispatchId::CURSORENDOFFILE;
1734
0
                break;
1735
0
            case KEY_PAGEUP:
1736
0
                eId = BrowserDispatchId::CURSORTOPOFFILE;
1737
0
                break;
1738
0
            case KEY_HOME:
1739
0
                eId = BrowserDispatchId::CURSORTOPOFSCREEN;
1740
0
                break;
1741
0
            case KEY_END:
1742
0
                eId = BrowserDispatchId::CURSORENDOFSCREEN;
1743
0
                break;
1744
0
            case KEY_SPACE:
1745
0
                eId = BrowserDispatchId::ENHANCESELECTION;
1746
0
                break;
1747
0
            case KEY_LEFT:
1748
0
                eId = BrowserDispatchId::MOVECOLUMNLEFT;
1749
0
                break;
1750
0
            case KEY_RIGHT:
1751
0
                eId = BrowserDispatchId::MOVECOLUMNRIGHT;
1752
0
                break;
1753
0
        }
1754
1755
0
    if (eId != BrowserDispatchId::NONE)
1756
0
        Dispatch( eId );
1757
0
    return eId != BrowserDispatchId::NONE;
1758
0
}
1759
1760
void BrowseBox::ChildFocusIn()
1761
0
{
1762
0
}
1763
1764
void BrowseBox::ChildFocusOut()
1765
0
{
1766
0
}
1767
1768
void BrowseBox::Dispatch(BrowserDispatchId eId)
1769
0
{
1770
1771
0
    tools::Long nRowsOnPage = pDataWin->GetSizePixel().Height() / GetDataRowHeight();
1772
1773
0
    switch (eId)
1774
0
    {
1775
0
        case BrowserDispatchId::SELECTCOLUMN:
1776
0
            if ( ColCount() )
1777
0
                SelectColumnId( GetCurColumnId() );
1778
0
            break;
1779
1780
0
        case BrowserDispatchId::CURSORDOWN:
1781
0
            if ( ( GetCurRow() + 1 ) < nRowCount )
1782
0
                GoToRow( GetCurRow() + 1, false );
1783
0
            break;
1784
0
        case BrowserDispatchId::CURSORUP:
1785
0
            if ( GetCurRow() > 0 )
1786
0
                GoToRow( GetCurRow() - 1, false );
1787
0
            break;
1788
0
        case BrowserDispatchId::SELECTHOME:
1789
0
            if ( GetRowCount() )
1790
0
            {
1791
0
                DoHideCursor();
1792
0
                for ( sal_Int32 nRow = GetCurRow(); nRow >= 0; --nRow )
1793
0
                    SelectRow( nRow );
1794
0
                GoToRow( 0, true );
1795
0
                DoShowCursor();
1796
0
            }
1797
0
            break;
1798
0
        case BrowserDispatchId::SELECTEND:
1799
0
            if ( GetRowCount() )
1800
0
            {
1801
0
                DoHideCursor();
1802
0
                sal_Int32 nRows = GetRowCount();
1803
0
                for ( sal_Int32 nRow = GetCurRow(); nRow < nRows; ++nRow )
1804
0
                    SelectRow( nRow );
1805
0
                GoToRow( GetRowCount() - 1, true );
1806
0
                DoShowCursor();
1807
0
            }
1808
0
            break;
1809
0
        case BrowserDispatchId::SELECTDOWN:
1810
0
        {
1811
0
            if ( GetRowCount() && ( GetCurRow() + 1 ) < nRowCount )
1812
0
            {
1813
                // deselect the current row, if it isn't the first
1814
                // and there is no other selected row above
1815
0
                sal_Int32 nRow = GetCurRow();
1816
0
                bool bLocalSelect = ( !IsRowSelected( nRow ) ||
1817
0
                                 GetSelectRowCount() == 1 || IsRowSelected( nRow - 1 ) );
1818
0
                SelectRow( nRow, bLocalSelect );
1819
0
                bool bDone = GoToRow( GetCurRow() + 1, false );
1820
0
                if ( bDone )
1821
0
                    SelectRow( GetCurRow() );
1822
0
            }
1823
0
            else
1824
0
                ScrollRows( 1 );
1825
0
            break;
1826
0
        }
1827
0
        case BrowserDispatchId::SELECTUP:
1828
0
            if ( GetRowCount() )
1829
0
            {
1830
                // deselect the current row, if it isn't the first
1831
                // and there is no other selected row under
1832
0
                sal_Int32 nRow = GetCurRow();
1833
0
                bool bLocalSelect = ( !IsRowSelected( nRow ) ||
1834
0
                                 GetSelectRowCount() == 1 || IsRowSelected( nRow + 1 ) );
1835
0
                SelectRow( nCurRow, bLocalSelect );
1836
0
                bool bDone = GoToRow( nRow - 1, false );
1837
0
                if ( bDone )
1838
0
                    SelectRow( GetCurRow() );
1839
0
            }
1840
0
            break;
1841
0
        case BrowserDispatchId::CURSORPAGEDOWN:
1842
0
            ScrollRows( nRowsOnPage );
1843
0
            break;
1844
0
        case BrowserDispatchId::CURSORPAGEUP:
1845
0
            ScrollRows( -nRowsOnPage );
1846
0
            break;
1847
0
        case BrowserDispatchId::CURSOREND:
1848
0
            if ( bColumnCursor )
1849
0
            {
1850
0
                sal_uInt16 nNewId = GetColumnId(ColCount() -1);
1851
0
                nNewId != HandleColumnId && GoToColumnId( nNewId );
1852
0
                break;
1853
0
            }
1854
0
            [[fallthrough]];
1855
0
        case BrowserDispatchId::CURSORENDOFFILE:
1856
0
            GoToRow( nRowCount - 1, false );
1857
0
            break;
1858
0
        case BrowserDispatchId::CURSORRIGHT:
1859
0
            if ( bColumnCursor )
1860
0
            {
1861
0
                sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) + 1;
1862
0
                sal_uInt16 nNewId = GetColumnId( nNewPos );
1863
0
                if (nNewId != BROWSER_INVALIDID)    // At end of row ?
1864
0
                    GoToColumnId( nNewId );
1865
0
                else
1866
0
                {
1867
0
                    sal_uInt16 nColId = GetColumnId(0);
1868
0
                    if ( nColId == BROWSER_INVALIDID || nColId == HandleColumnId )
1869
0
                        nColId = GetColumnId(1);
1870
0
                    if ( GetRowCount() )
1871
0
                    {
1872
0
                        if ( nCurRow < GetRowCount() - 1 )
1873
0
                        {
1874
0
                            GoToRowColumnId( nCurRow + 1, nColId );
1875
0
                        }
1876
0
                    }
1877
0
                    else if ( ColCount() )
1878
0
                        GoToColumnId( nColId );
1879
0
                }
1880
0
            }
1881
0
            else
1882
0
                ScrollColumns( 1 );
1883
0
            break;
1884
0
        case BrowserDispatchId::CURSORHOME:
1885
0
            if ( bColumnCursor )
1886
0
            {
1887
0
                sal_uInt16 nNewId = GetColumnId(1);
1888
0
                if (nNewId != HandleColumnId)
1889
0
                {
1890
0
                    GoToColumnId( nNewId );
1891
0
                }
1892
0
                break;
1893
0
            }
1894
0
            [[fallthrough]];
1895
0
        case BrowserDispatchId::CURSORTOPOFFILE:
1896
0
            GoToRow( 0, false );
1897
0
            break;
1898
0
        case BrowserDispatchId::CURSORLEFT:
1899
0
            if ( bColumnCursor )
1900
0
            {
1901
0
                sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) - 1;
1902
0
                sal_uInt16 nNewId = GetColumnId( nNewPos );
1903
0
                if (nNewId != HandleColumnId)
1904
0
                    GoToColumnId( nNewId );
1905
0
                else
1906
0
                {
1907
0
                    if ( GetRowCount() )
1908
0
                    {
1909
0
                        if (nCurRow > 0)
1910
0
                        {
1911
0
                            GoToRowColumnId(nCurRow - 1, GetColumnId(ColCount() -1));
1912
0
                        }
1913
0
                    }
1914
0
                    else if ( ColCount() )
1915
0
                        GoToColumnId( GetColumnId(ColCount() -1) );
1916
0
                }
1917
0
            }
1918
0
            else
1919
0
                ScrollColumns( -1 );
1920
0
            break;
1921
0
        case BrowserDispatchId::ENHANCESELECTION:
1922
0
            if ( GetRowCount() )
1923
0
                SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ) );
1924
0
            break;
1925
0
        case BrowserDispatchId::SELECT:
1926
0
            if ( GetRowCount() )
1927
0
                SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), false );
1928
0
            break;
1929
0
        case BrowserDispatchId::MOVECOLUMNLEFT:
1930
0
        case BrowserDispatchId::MOVECOLUMNRIGHT:
1931
0
            { // check if column moving is allowed
1932
0
                BrowserHeader* pHeaderBar = pDataWin->pHeaderBar;
1933
0
                if ( pHeaderBar && pHeaderBar->IsDragable() )
1934
0
                {
1935
0
                    sal_uInt16 nColId = GetCurColumnId();
1936
0
                    bool bColumnSelected = IsColumnSelected(nColId);
1937
0
                    sal_uInt16 nNewPos = GetColumnPos(nColId);
1938
0
                    bool bMoveAllowed = false;
1939
0
                    if (BrowserDispatchId::MOVECOLUMNLEFT == eId && nNewPos > 1)
1940
0
                    {
1941
0
                        --nNewPos;
1942
0
                        bMoveAllowed = true;
1943
0
                    }
1944
0
                    else if (BrowserDispatchId::MOVECOLUMNRIGHT == eId && nNewPos < (ColCount() - 1))
1945
0
                    {
1946
0
                        ++nNewPos;
1947
0
                        bMoveAllowed = true;
1948
0
                    }
1949
1950
0
                    if ( bMoveAllowed )
1951
0
                    {
1952
0
                        SetColumnPos( nColId, nNewPos );
1953
0
                        ColumnMoved( nColId );
1954
0
                        MakeFieldVisible(GetCurRow(), nColId);
1955
0
                        if ( bColumnSelected )
1956
0
                            SelectColumnId(nColId);
1957
0
                    }
1958
0
                }
1959
0
            }
1960
0
            break;
1961
0
        default:
1962
0
            break;
1963
0
    }
1964
0
}
1965
1966
1967
void BrowseBox::SetCursorColor(const Color& _rCol)
1968
0
{
1969
0
    if (_rCol == m_aCursorColor)
1970
0
        return;
1971
1972
    // ensure the cursor is hidden
1973
0
    DoHideCursor();
1974
0
    if (!m_bFocusOnlyCursor)
1975
0
        DoHideCursor();
1976
1977
0
    m_aCursorColor = _rCol;
1978
1979
0
    if (!m_bFocusOnlyCursor)
1980
0
        DoShowCursor();
1981
0
    DoShowCursor();
1982
0
}
1983
1984
tools::Rectangle BrowseBox::calcHeaderRect(bool _bIsColumnBar)
1985
0
{
1986
0
    Point aTopLeft;
1987
0
    tools::Long nWidth;
1988
0
    tools::Long nHeight;
1989
0
    if ( _bIsColumnBar )
1990
0
    {
1991
0
        nWidth = pDataWin->GetOutputSizePixel().Width();
1992
0
        nHeight = GetDataRowHeight();
1993
0
    }
1994
0
    else
1995
0
    {
1996
0
        aTopLeft.setY( GetDataRowHeight() );
1997
0
        nWidth = GetColumnWidth(0);
1998
0
        nHeight = GetWindowExtentsAbsolute().GetHeight() - aTopLeft.Y() - GetControlArea().GetSize().Height();
1999
0
    }
2000
0
    return tools::Rectangle(aTopLeft,Size(nWidth,nHeight));
2001
0
}
2002
2003
tools::Rectangle BrowseBox::calcTableRect()
2004
0
{
2005
0
    tools::Rectangle aRect(GetWindowExtentsAbsolute());
2006
0
    aRect.SetPos(Point(0, 0));
2007
0
    tools::Rectangle aRowBar = calcHeaderRect(false);
2008
2009
0
    tools::Long nX = aRowBar.Right() - aRect.Left();
2010
0
    tools::Long nY = aRowBar.Top() - aRect.Top();
2011
0
    Size aSize(aRect.GetSize());
2012
2013
0
    return tools::Rectangle(aRowBar.TopRight(), Size(aSize.Width() - nX, aSize.Height() - nY - GetBarHeight()) );
2014
0
}
2015
2016
tools::Rectangle BrowseBox::calcFieldRectPixel(sal_Int32 _nRowId, sal_uInt16 _nColId, bool /*_bIsHeader*/)
2017
0
{
2018
0
    return GetFieldRectPixel(_nRowId, _nColId, true);
2019
0
}
2020
2021
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */