Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/treelist/iconviewimpl.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 <vcl/svapp.hxx>
21
#include <vcl/toolkit/treelistentry.hxx>
22
#include <tools/debug.hxx>
23
#include "iconviewimpl.hxx"
24
25
IconViewImpl::IconViewImpl(IconView* pIconView, SvTreeList* pTreeList, WinBits nWinStyle)
26
0
    : SvImpLBox(pIconView, pTreeList, nWinStyle)
27
0
{
28
0
}
29
30
IconView& IconViewImpl::GetIconView() const
31
0
{
32
0
    assert(m_pView);
33
0
    return static_cast<IconView&>(*m_pView);
34
0
}
35
36
Size IconViewImpl::GetEntrySize(const SvTreeListEntry& entry) const
37
0
{
38
0
    return GetIconView().GetEntrySize(entry);
39
0
}
40
41
void IconViewImpl::IterateVisibleEntryAreas(const IterateEntriesFunc& f, bool fromStartEntry) const
42
0
{
43
0
    tools::Long x = 0, y = 0;
44
0
    short column = 0;
45
0
    const tools::Long rowWidth = m_pView->GetEntryWidth() * GetIconView().GetColumnCount();
46
0
    tools::Long nPrevHeight = 0;
47
0
    for (auto entry = fromStartEntry ? m_pStartEntry : m_pView->FirstVisible(); entry;
48
0
         entry = m_pView->NextVisible(entry))
49
0
    {
50
0
        const Size s = GetEntrySize(*entry);
51
0
        if (x >= rowWidth || entry->IsSeparator())
52
0
        {
53
0
            column = 0;
54
0
            x = 0;
55
0
            y += nPrevHeight;
56
0
        }
57
0
        EntryAreaInfo info{ *entry, column, tools::Rectangle{ Point{ x, y }, s } };
58
0
        const auto result = f(info);
59
0
        if (result == CallbackResult::Stop)
60
0
            return;
61
0
        ++column;
62
0
        x += s.Width();
63
0
        nPrevHeight = s.Height();
64
0
    }
65
0
}
66
67
tools::Long IconViewImpl::GetEntryRow(const SvTreeListEntry* entry) const
68
0
{
69
0
    tools::Long nEntryRow = -1;
70
0
    auto GetRow = [entry, &nEntryRow, row = -1](const EntryAreaInfo& info) mutable
71
0
    {
72
0
        if (info.column == 0 && !info.entry.IsSeparator())
73
0
            ++row;
74
0
        if (&info.entry != entry)
75
0
            return CallbackResult::Continue;
76
0
        nEntryRow = row;
77
0
        return CallbackResult::Stop;
78
0
    };
79
0
    IterateVisibleEntryAreas(GetRow);
80
0
    return nEntryRow;
81
0
}
82
83
void IconViewImpl::SetStartEntry(SvTreeListEntry* entry)
84
0
{
85
0
    const tools::Long max = m_aVerSBar->GetRangeMax() - m_aVerSBar->GetVisibleSize();
86
0
    tools::Long row = -1;
87
0
    auto GetEntryAndRow = [&entry, &row, max, found = entry](const EntryAreaInfo& info) mutable
88
0
    {
89
0
        if (info.column == 0 && !info.entry.IsSeparator())
90
0
        {
91
0
            found = &info.entry;
92
0
            ++row;
93
0
        }
94
0
        if (row >= max || &info.entry == entry)
95
0
        {
96
0
            entry = found;
97
0
            return CallbackResult::Stop;
98
0
        }
99
0
        return CallbackResult::Continue;
100
0
    };
101
0
    IterateVisibleEntryAreas(GetEntryAndRow);
102
103
0
    m_pStartEntry = entry;
104
0
    m_aVerSBar->SetThumbPos(row);
105
0
    m_pView->Invalidate(GetVisibleArea());
106
0
}
107
108
void IconViewImpl::ScrollTo(SvTreeListEntry& rEntry)
109
0
{
110
0
    if (!m_aVerSBar->IsVisible())
111
0
        return;
112
0
    const tools::Long entryRow = GetEntryRow(&rEntry);
113
0
    const tools::Long oldStartRow = m_aVerSBar->GetThumbPos();
114
0
    if (entryRow < oldStartRow)
115
0
        IconViewImpl::SetStartEntry(&rEntry);
116
0
    const tools::Long visibleRows = m_aVerSBar->GetVisibleSize();
117
0
    const tools::Long posRelativeToBottom = entryRow - (oldStartRow + visibleRows) + 1;
118
0
    if (posRelativeToBottom > 0)
119
0
        IconViewImpl::SetStartEntry(GoToNextRow(m_pStartEntry, posRelativeToBottom));
120
0
}
121
122
SvTreeListEntry* IconViewImpl::GoToPrevRow(SvTreeListEntry* pEntry, int nRows) const
123
0
{
124
0
    SvTreeListEntry* pPrev = pEntry;
125
0
    auto FindPrev = [this, pEntry, nRows, &pPrev,
126
0
                     prevs = std::vector<SvTreeListEntry*>()](const EntryAreaInfo& info) mutable
127
0
    {
128
0
        if (info.column == 0 && !info.entry.IsSeparator())
129
0
            prevs.push_back(&info.entry);
130
0
        if (pEntry == &info.entry)
131
0
        {
132
0
            if (prevs.size() > 1)
133
0
            {
134
0
                int i = std::max(0, static_cast<int>(prevs.size()) - nRows - 1);
135
0
                pPrev = prevs[i];
136
0
                for (short column = info.column; column; --column)
137
0
                {
138
0
                    SvTreeListEntry* pNext = m_pView->NextVisible(pPrev);
139
0
                    if (!pNext || pNext->IsSeparator())
140
0
                        break;
141
0
                    pPrev = pNext;
142
0
                }
143
0
            }
144
0
            return CallbackResult::Stop;
145
0
        }
146
0
        return CallbackResult::Continue;
147
0
    };
148
0
    IterateVisibleEntryAreas(FindPrev);
149
150
0
    return pPrev;
151
0
}
152
153
SvTreeListEntry* IconViewImpl::GoToNextRow(SvTreeListEntry* pEntry, int nRows) const
154
0
{
155
0
    SvTreeListEntry* pNext = pEntry;
156
0
    auto FindNext = [pEntry, nRows, &pNext, column = -1](const EntryAreaInfo& info) mutable
157
0
    {
158
0
        if (info.column <= column && !info.entry.IsSeparator())
159
0
        {
160
0
            if (info.column == 0 && --nRows < 0)
161
0
                return CallbackResult::Stop;
162
0
            pNext = &info.entry;
163
0
            if (info.column == column && nRows == 0)
164
0
                return CallbackResult::Stop;
165
0
        }
166
0
        else if (pEntry == &info.entry)
167
0
        {
168
0
            column = info.column;
169
0
        }
170
0
        return CallbackResult::Continue;
171
0
    };
172
0
    IterateVisibleEntryAreas(FindNext);
173
174
0
    return pNext;
175
0
}
176
177
void IconViewImpl::CursorUp()
178
0
{
179
0
    if (!m_pStartEntry)
180
0
        return;
181
182
0
    SvTreeListEntry* pPrevFirstToDraw = GoToPrevRow(m_pStartEntry, 1);
183
184
0
    m_nFlags &= ~LBoxFlags::Filling;
185
0
    ShowCursor( false );
186
0
    SetStartEntry(pPrevFirstToDraw);
187
0
    ShowCursor( true );
188
0
    m_pView->NotifyScrolled();
189
0
}
190
191
void IconViewImpl::CursorDown()
192
0
{
193
0
    if (!m_pStartEntry)
194
0
        return;
195
196
0
    SvTreeListEntry* pNextFirstToDraw = GoToNextRow(m_pStartEntry, 1);
197
198
0
    m_nFlags &= ~LBoxFlags::Filling;
199
0
    ShowCursor( false );
200
0
    SetStartEntry(pNextFirstToDraw);
201
0
    ShowCursor( true );
202
0
    m_pView->NotifyScrolled();
203
0
}
204
205
void IconViewImpl::PageDown( sal_uInt16 nDelta )
206
0
{
207
0
    if( !nDelta )
208
0
        return;
209
210
0
    if (!m_pStartEntry)
211
0
        return;
212
213
0
    SvTreeListEntry* pNext = GoToNextRow(m_pStartEntry, nDelta);
214
215
0
    ShowCursor( false );
216
217
0
    m_nFlags &= ~LBoxFlags::Filling;
218
0
    SetStartEntry(pNext);
219
220
0
    ShowCursor( true );
221
0
}
222
223
void IconViewImpl::PageUp( sal_uInt16 nDelta )
224
0
{
225
0
    if( !nDelta )
226
0
        return;
227
228
0
    if (!m_pStartEntry)
229
0
        return;
230
231
0
    SvTreeListEntry* pPrev = GoToPrevRow(m_pStartEntry, nDelta);
232
233
0
    m_nFlags &= ~LBoxFlags::Filling;
234
0
    ShowCursor( false );
235
236
0
    SetStartEntry(pPrev);
237
238
0
    ShowCursor( true );
239
0
}
240
241
void IconViewImpl::KeyDown( bool bPageDown )
242
0
{
243
0
    if( !m_aVerSBar->IsVisible() )
244
0
        return;
245
246
0
    tools::Long nDelta;
247
0
    if( bPageDown )
248
0
        nDelta = m_aVerSBar->GetPageSize();
249
0
    else
250
0
        nDelta = 1;
251
252
0
    if( nDelta <= 0 )
253
0
        return;
254
255
0
    m_nFlags &= ~LBoxFlags::Filling;
256
257
0
    if( bPageDown )
258
0
        PageDown( static_cast<short>(nDelta) );
259
0
    else
260
0
        CursorDown();
261
0
}
262
263
void IconViewImpl::KeyUp( bool bPageUp )
264
0
{
265
0
    if( !m_aVerSBar->IsVisible() )
266
0
        return;
267
268
0
    tools::Long nDelta;
269
0
    if( bPageUp )
270
0
        nDelta = m_aVerSBar->GetPageSize();
271
0
    else
272
0
        nDelta = 1;
273
274
0
    m_nFlags &= ~LBoxFlags::Filling;
275
276
0
    if( bPageUp )
277
0
        PageUp( static_cast<short>(nDelta) );
278
0
    else
279
0
        CursorUp();
280
0
}
281
282
tools::Long IconViewImpl::GetEntryLine(const SvTreeListEntry* pEntry) const
283
0
{
284
0
    if(!m_pStartEntry )
285
0
        return -1; // invisible position
286
287
0
    return IconViewImpl::GetEntryPosition(pEntry).Y();
288
0
}
289
290
Point IconViewImpl::GetEntryPosition(const SvTreeListEntry* pEntry) const
291
0
{
292
0
    Point result{ -m_pView->GetEntryWidth(), -m_pView->GetEntryHeight() }; // invisible
293
0
    auto FindEntryPos = [pEntry, &result](const EntryAreaInfo& info)
294
0
    {
295
0
        if (pEntry == &info.entry)
296
0
        {
297
0
            result = info.area.TopLeft();
298
0
            return CallbackResult::Stop;
299
0
        }
300
0
        return CallbackResult::Continue;
301
0
    };
302
0
    IterateVisibleEntryAreas(FindEntryPos, true);
303
304
0
    return result;
305
0
}
306
307
// Returns the last entry (in respective row) if position is just past the last entry
308
SvTreeListEntry* IconViewImpl::GetClickedEntry( const Point& rPoint ) const
309
0
{
310
0
    DBG_ASSERT( m_pView->GetModel(), "IconViewImpl::GetClickedEntry: how can this ever happen?" );
311
0
    if ( !m_pView->GetModel() )
312
0
        return nullptr;
313
0
    if( m_pView->GetEntryCount() == 0 || !m_pStartEntry || !m_pView->GetEntryHeight() || !m_pView->GetEntryWidth())
314
0
        return nullptr;
315
316
0
    SvTreeListEntry* pEntry = nullptr;
317
0
    auto FindEntryByPos = [&pEntry, &rPoint](const EntryAreaInfo& info)
318
0
    {
319
0
        if (info.area.Contains(rPoint))
320
0
        {
321
0
            pEntry = &info.entry;
322
0
            return CallbackResult::Stop;
323
0
        }
324
0
        else if (info.area.Top() > rPoint.Y())
325
0
        {
326
0
            return CallbackResult::Stop; // we are already below the clicked row
327
0
        }
328
0
        else if (info.area.Bottom() > rPoint.Y())
329
0
        {
330
0
            pEntry = &info.entry; // Same row; store the entry in case the click is past all entries
331
0
        }
332
0
        return CallbackResult::Continue;
333
0
    };
334
0
    IterateVisibleEntryAreas(FindEntryByPos, true);
335
336
0
    return pEntry;
337
0
}
338
339
bool IconViewImpl::IsEntryInView( SvTreeListEntry* pEntry ) const
340
0
{
341
    // parent collapsed
342
0
    if( !m_pView->IsEntryVisible(pEntry) )
343
0
        return false;
344
345
0
    tools::Long nY = GetEntryLine( pEntry );
346
0
    if( nY < 0 )
347
0
        return false;
348
349
0
    tools::Long height = GetEntrySize(*pEntry).Height();
350
0
    if (nY + height > m_aOutputSize.Height())
351
0
        return false;
352
353
0
    return true;
354
0
}
355
356
void IconViewImpl::AdjustScrollBars( Size& rSize )
357
0
{
358
0
    tools::Long nEntryHeight = m_pView->GetEntryHeight();
359
0
    if( !nEntryHeight )
360
0
        return;
361
362
0
    sal_uInt16 nResult = 0;
363
364
0
    Size aOSize( m_pView->Control::GetOutputSizePixel() );
365
366
0
    const WinBits nWindowStyle = m_pView->GetStyle();
367
0
    bool bVerSBar = ( nWindowStyle & WB_VSCROLL ) != 0;
368
369
    // number of entries visible within the view
370
0
    const tools::Long nVisibleRows = aOSize.Height() / nEntryHeight;
371
0
    m_nVisibleCount = nVisibleRows * GetIconView().GetColumnCount();
372
373
0
    tools::Long nTotalRows = 0;
374
0
    tools::Long totalHeight = 0;
375
0
    auto CountRowsAndHeight = [&nTotalRows, &totalHeight](const EntryAreaInfo& info)
376
0
    {
377
0
        totalHeight = std::max(totalHeight, info.area.Bottom());
378
0
        if (info.column == 0 && !info.entry.IsSeparator())
379
0
            ++nTotalRows;
380
0
        return CallbackResult::Continue;
381
0
    };
382
0
    IterateVisibleEntryAreas(CountRowsAndHeight);
383
384
    // do we need a vertical scrollbar?
385
0
    if( bVerSBar || totalHeight > aOSize.Height())
386
0
    {
387
0
        nResult = 1;
388
0
    }
389
390
    // do we need a Horizontal scrollbar?
391
0
    bool bHorSBar = (nWindowStyle & WB_HSCROLL) != 0;
392
0
    if (bHorSBar || m_pView->GetEntryWidth() > aOSize.Width())
393
0
    {
394
0
        nResult += 2;
395
0
        m_aHorSBar->SetRange(Range(0, m_pView->GetEntryWidth()));
396
0
        m_aHorSBar->SetVisibleSize(aOSize.Width());
397
0
    }
398
399
0
    PositionScrollBars( aOSize, nResult );
400
401
    // adapt Range, VisibleRange etc.
402
403
    // refresh output size, in case we have to scroll
404
0
    tools::Rectangle aRect;
405
0
    aRect.SetSize( aOSize );
406
0
    m_aSelEng.SetVisibleArea( aRect );
407
408
    // vertical scrollbar
409
0
    if( !m_bInVScrollHdl )
410
0
    {
411
0
        m_aVerSBar->SetRange(Range(0, nTotalRows));
412
0
        m_aVerSBar->SetPageSize(nVisibleRows);
413
0
        m_aVerSBar->SetVisibleSize(nVisibleRows);
414
0
    }
415
0
    else
416
0
    {
417
0
        m_nFlags |= LBoxFlags::EndScrollSetVisSize;
418
0
    }
419
420
0
    if( nResult & 0x0001 )
421
0
        m_aVerSBar->Show();
422
0
    else
423
0
        m_aVerSBar->Hide();
424
425
0
    if (nResult & 0x0002)
426
0
        m_aHorSBar->Show();
427
0
    else
428
0
        m_aHorSBar->Hide();
429
430
0
    rSize = aOSize;
431
0
}
432
433
// returns 0 if position is just past the last entry
434
SvTreeListEntry* IconViewImpl::GetEntry( const Point& rPoint ) const
435
0
{
436
0
    if( (m_pView->GetEntryCount() == 0) || !m_pStartEntry ||
437
0
        (rPoint.Y() > m_aOutputSize.Height())
438
0
        || !m_pView->GetEntryHeight()
439
0
        || !m_pView->GetEntryWidth())
440
0
        return nullptr;
441
442
0
    SvTreeListEntry* pEntry = nullptr;
443
0
    auto FindEntryByPos = [&pEntry, &rPoint](const EntryAreaInfo& info)
444
0
    {
445
0
        if (info.area.Contains(rPoint))
446
0
        {
447
0
            pEntry = &info.entry;
448
0
            return CallbackResult::Stop;
449
0
        }
450
0
        else if (info.area.Top() > rPoint.Y())
451
0
        {
452
0
            return CallbackResult::Stop; // we are already below the clicked row
453
0
        }
454
0
        return CallbackResult::Continue;
455
0
    };
456
0
    IterateVisibleEntryAreas(FindEntryByPos, true);
457
458
0
    return pEntry;
459
0
}
460
461
void IconViewImpl::SyncVerThumb()
462
0
{
463
0
    m_aVerSBar->SetThumbPos(GetEntryRow(m_pStartEntry));
464
0
}
465
466
void IconViewImpl::UpdateAll()
467
0
{
468
0
    FindMostRight();
469
0
    AdjustScrollBars(m_aOutputSize);
470
0
    SyncVerThumb();
471
0
    FillView();
472
0
    ShowVerSBar();
473
0
    if( m_bSimpleTravel && m_pCursor && m_pView->HasFocus() )
474
0
        m_pView->Select( m_pCursor );
475
0
    ShowCursor( true );
476
0
    m_pView->Invalidate( GetVisibleArea() );
477
0
}
478
479
void IconViewImpl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
480
0
{
481
0
    if (!m_pView->GetVisibleCount())
482
0
        return;
483
484
0
    m_nFlags |= LBoxFlags::InPaint;
485
486
0
    if (m_nFlags & LBoxFlags::Filling)
487
0
    {
488
0
        SvTreeListEntry* pFirst = m_pView->First();
489
0
        if (pFirst != m_pStartEntry)
490
0
        {
491
0
            ShowCursor(false);
492
0
            m_pStartEntry = m_pView->First();
493
0
            m_aVerSBar->SetThumbPos( 0 );
494
0
            StopUserEvent();
495
0
            ShowCursor(true);
496
0
            m_nCurUserEvent = Application::PostUserEvent(LINK(this, SvImpLBox, MyUserEvent),
497
0
                                                       reinterpret_cast<void*>(1));
498
0
            return;
499
0
        }
500
0
    }
501
502
0
    if (!m_pStartEntry)
503
0
    {
504
0
        m_pStartEntry = m_pView->First();
505
0
    }
506
507
0
    if (!m_pCursor && !mbNoAutoCurEntry)
508
0
    {
509
        // do not select if multiselection or explicit set
510
0
        bool bNotSelect = (m_aSelEng.GetSelectionMode() == SelectionMode::Multiple ) || ((m_nStyle & WB_NOINITIALSELECTION) == WB_NOINITIALSELECTION);
511
0
        SetCursor(m_pStartEntry, bNotSelect);
512
0
    }
513
514
0
    auto PaintEntry = [&rIconView = GetIconView(), &rRect,
515
0
                       &rRenderContext](const EntryAreaInfo& info)
516
0
    {
517
0
        if (!info.area.GetIntersection(rRect).IsEmpty())
518
0
        {
519
0
            rIconView.PaintEntry(info.entry, info.area.Left(), info.area.Top(), rRenderContext);
520
0
        }
521
0
        else if (info.area.Top() > rRect.Bottom())
522
0
        {
523
0
            return CallbackResult::Stop; // we are already below the last visible row
524
0
        }
525
0
        return CallbackResult::Continue;
526
0
    };
527
0
    IterateVisibleEntryAreas(PaintEntry, true);
528
529
0
    m_nFlags &= ~LBoxFlags::DeselectAll;
530
0
    rRenderContext.SetClipRegion();
531
0
    m_nFlags &= ~LBoxFlags::InPaint;
532
0
}
533
534
void IconViewImpl::InvalidateEntry( tools::Long nId ) const
535
0
{
536
0
    if( m_nFlags & LBoxFlags::InPaint )
537
0
        return;
538
0
    if (nId < 0)
539
0
        return;
540
541
    // nId is a Y coordinate of the top of the element, coming from GetEntryLine
542
0
    tools::Rectangle aRect( GetVisibleArea() );
543
0
    if (nId > aRect.Bottom())
544
0
        return;
545
0
    aRect.SetTop(nId); // Invalidate everything below
546
0
    m_pView->Invalidate( aRect );
547
0
}
548
549
bool IconViewImpl::KeyInput( const KeyEvent& rKEvt )
550
0
{
551
0
    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
552
553
0
    if( rKeyCode.IsMod2() )
554
0
        return false; // don't evaluate Alt key
555
556
0
    m_nFlags &= ~LBoxFlags::Filling;
557
558
0
    if( !m_pCursor )
559
0
        m_pCursor = m_pStartEntry;
560
0
    if( !m_pCursor )
561
0
        return false;
562
563
0
    sal_uInt16  aCode = rKeyCode.GetCode();
564
565
0
    bool    bShift = rKeyCode.IsShift();
566
0
    bool    bMod1 = rKeyCode.IsMod1();
567
568
0
    SvTreeListEntry* pNewCursor;
569
570
0
    bool bHandled = true;
571
572
0
    switch( aCode )
573
0
    {
574
0
        case KEY_LEFT:
575
0
            if( !IsEntryInView( m_pCursor ) )
576
0
                MakeVisible( m_pCursor );
577
578
0
            pNewCursor = m_pCursor;
579
0
            do
580
0
            {
581
0
                pNewCursor = m_pView->PrevVisible(pNewCursor);
582
0
            } while( pNewCursor && !IsSelectable(pNewCursor) );
583
584
            // if there is no next entry, take the current one
585
            // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
586
            // the cursor key
587
0
            if (!pNewCursor)
588
0
                pNewCursor = m_pCursor;
589
590
0
            m_aSelEng.CursorPosChanging( bShift, bMod1 );
591
0
            SetCursor( pNewCursor, bMod1 );     // no selection, when Ctrl is on
592
0
            if( !IsEntryInView( pNewCursor ) )
593
0
                KeyUp( false );
594
0
            break;
595
596
0
        case KEY_RIGHT:
597
0
            if( !IsEntryInView( m_pCursor ) )
598
0
                MakeVisible( m_pCursor );
599
600
0
            pNewCursor = m_pCursor;
601
0
            do
602
0
            {
603
0
                pNewCursor = m_pView->NextVisible(pNewCursor);
604
0
            } while( pNewCursor && !IsSelectable(pNewCursor) );
605
606
            // if there is no next entry, take the current one
607
            // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
608
            // the cursor key
609
0
            if ( !pNewCursor && m_pCursor )
610
0
                pNewCursor = m_pCursor;
611
612
0
            if( pNewCursor )
613
0
            {
614
0
                m_aSelEng.CursorPosChanging( bShift, bMod1 );
615
0
                if( IsEntryInView( pNewCursor ) )
616
0
                    SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
617
0
                else
618
0
                {
619
0
                    if( m_pCursor )
620
0
                        m_pView->Select( m_pCursor, false );
621
0
                    KeyDown( false );
622
0
                    SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
623
0
                }
624
0
            }
625
0
            else
626
0
                KeyDown( false );   // because scrollbar range might still
627
                                        // allow scrolling
628
0
            break;
629
630
0
        case KEY_UP:
631
0
        {
632
0
            pNewCursor = GoToPrevRow(m_pCursor, 1);
633
634
0
            if( pNewCursor )
635
0
            {
636
0
                m_aSelEng.CursorPosChanging( bShift, bMod1 );
637
0
                SetCursor( pNewCursor, bMod1 );     // no selection, when Ctrl is on
638
0
                ScrollTo(*pNewCursor);
639
0
            }
640
0
            break;
641
0
        }
642
643
0
        case KEY_DOWN:
644
0
        {
645
0
            pNewCursor = GoToNextRow(m_pCursor, 1);
646
647
0
            if( pNewCursor )
648
0
            {
649
0
                m_aSelEng.CursorPosChanging( bShift, bMod1 );
650
0
                ScrollTo(*pNewCursor);
651
0
                SetCursor(pNewCursor, bMod1); // no selection, when Ctrl is on
652
0
            }
653
0
            else
654
0
                KeyDown( false );   // because scrollbar range might still
655
                                        // allow scrolling
656
0
            break;
657
0
        }
658
659
0
        case KEY_PAGEUP:
660
0
            if (!bMod1)
661
0
            {
662
0
                const sal_uInt16 nDelta = m_aVerSBar->GetPageSize();
663
0
                pNewCursor = GoToPrevRow(m_pCursor, nDelta);
664
665
0
                if (pNewCursor)
666
0
                {
667
0
                    m_aSelEng.CursorPosChanging(bShift, bMod1);
668
0
                    ScrollTo(*pNewCursor);
669
0
                    SetCursor(pNewCursor);
670
0
                }
671
0
            }
672
0
            else
673
0
                bHandled = false;
674
0
            break;
675
676
0
        case KEY_PAGEDOWN:
677
0
            if (!bMod1)
678
0
            {
679
0
                const sal_uInt16 nDelta = m_aVerSBar->GetPageSize();
680
0
                pNewCursor = GoToNextRow(m_pCursor, nDelta);
681
682
0
                if (pNewCursor)
683
0
                {
684
0
                    m_aSelEng.CursorPosChanging(bShift, bMod1);
685
0
                    ScrollTo(*pNewCursor);
686
0
                    SetCursor(pNewCursor);
687
0
                }
688
0
                else
689
0
                    KeyDown(false);
690
0
            }
691
0
            else
692
0
                bHandled = false;
693
0
            break;
694
695
0
        case KEY_RETURN:
696
0
        case KEY_SPACE:
697
0
        {
698
0
            bHandled = !m_pView->aDoubleClickHdl.Call(m_pView);
699
0
            break;
700
0
        }
701
702
0
        case KEY_END:
703
0
        {
704
0
            pNewCursor = m_pView->GetModel()->Last();
705
706
0
            while( pNewCursor && !IsSelectable(pNewCursor) )
707
0
            {
708
0
                pNewCursor = m_pView->PrevVisible(pNewCursor);
709
0
            }
710
711
0
            SetStartEntry(pNewCursor);
712
713
0
            if( pNewCursor && pNewCursor != m_pCursor)
714
0
            {
715
//              SelAllDestrAnch( false );
716
0
                m_aSelEng.CursorPosChanging( bShift, bMod1 );
717
0
                SetCursor( pNewCursor );
718
0
            }
719
720
0
            bHandled = true;
721
722
0
            break;
723
0
        }
724
725
0
        default:
726
0
        {
727
0
            bHandled = false;
728
0
            break;
729
0
        }
730
0
    }
731
732
0
    if(!bHandled)
733
0
        return SvImpLBox::KeyInput( rKEvt );
734
735
0
    return true;
736
0
}
737
738
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */