LibreOffice Module svtools (master) 1
brwbox1.cxx
Go to the documentation of this file.
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 <svtools/brwbox.hxx>
21#include <svtools/brwhead.hxx>
23#include <o3tl/numeric.hxx>
24#include <o3tl/safeint.hxx>
25#include "datwin.hxx"
26#include <tools/debug.hxx>
27#include <tools/fract.hxx>
28#include <sal/log.hxx>
30#include <vcl/svapp.hxx>
31#include <vcl/weld.hxx>
32
33#include <algorithm>
34#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
35#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
36#include <com/sun/star/accessibility/AccessibleEventId.hpp>
37#include <tools/multisel.hxx>
38#include "brwimpl.hxx"
39
40
41#define SCROLL_FLAGS (ScrollFlags::Clip | ScrollFlags::NoChildren)
42
43using namespace com::sun::star::accessibility::AccessibleEventId;
44using namespace com::sun::star::accessibility::AccessibleTableModelChangeType;
45using com::sun::star::accessibility::AccessibleTableModelChange;
46using namespace ::com::sun::star::uno;
47using namespace svt;
48
49namespace
50{
51 void disposeAndClearHeaderCell(::svt::BrowseBoxImpl::THeaderCellMap& _rHeaderCell)
52 {
53 ::std::for_each(
54 _rHeaderCell.begin(),
55 _rHeaderCell.end(),
57 );
58 _rHeaderCell.clear();
59 }
60}
61
63{
64 SAL_INFO("svtools", "BrowseBox:ConstructImpl " << this );
65 bMultiSelection = false;
66 pColSel = nullptr;
67 pVScroll = nullptr;
69 m_pImpl.reset( new ::svt::BrowseBoxImpl() );
70
71 InitSettings_Impl( this );
73
74 bBootstrapped = false;
76 nTitleLines = 1;
77 nFirstCol = 0;
78 nTopRow = 0;
80 nCurColId = 0;
81 nResizeX = 0;
82 nMinResizeX = 0;
83 nDragX = 0;
84 nResizeCol = 0;
85 bResizing = false;
86 bSelect = false;
87 bSelecting = false;
88 bScrolling = false;
89 bSelectionIsVisible = false;
90 bNotToggleSel = false;
91 bRowDividerDrag = false;
92 bHit = false;
94 bHideSelect = false;
96 nRowCount = 0;
97 m_bFocusOnlyCursor = true;
100 nControlAreaWidth = USHRT_MAX;
102
103 aHScroll->SetLineSize(1);
104 aHScroll->SetScrollHdl( LINK( this, BrowseBox, HorzScrollHdl ) );
105 pDataWin->Show();
106
107 SetMode( nMode );
110 pDataWin->nCursorHidden =
111 ( bHasFocus ? 0 : 1 ) + ( GetUpdateMode() ? 0 : 1 );
112}
113
114// we're just measuring the "real" NavigationBar
116{
117private:
118 std::unique_ptr<weld::Label> m_xRecordText;
119 std::unique_ptr<weld::Entry> m_xAbsolute;
120 std::unique_ptr<weld::Label> m_xRecordOf;
121 std::unique_ptr<weld::Label> m_xRecordCount;
122public:
124 : InterimItemWindow(pParent, "svx/ui/navigationbar.ui", "NavigationBar")
125 , m_xRecordText(m_xBuilder->weld_label("recordtext"))
126 , m_xAbsolute(m_xBuilder->weld_entry("entry-noframe"))
127 , m_xRecordOf(m_xBuilder->weld_label("recordof"))
128 , m_xRecordCount(m_xBuilder->weld_label("recordcount"))
129 {
130 vcl::Font aApplFont(Application::GetSettings().GetStyleSettings().GetToolFont());
131 m_xAbsolute->set_font(aApplFont);
132 m_xRecordText->set_font(aApplFont);
133 m_xRecordOf->set_font(aApplFont);
134 m_xRecordCount->set_font(aApplFont);
135
137 }
138
139 virtual void dispose() override
140 {
141 m_xRecordCount.reset();
142 m_xRecordOf.reset();
143 m_xAbsolute.reset();
144 m_xRecordText.reset();
146 }
147};
148
150{
152 if (!m_bNavigationBar)
153 return nScrollBarSize;
154
155 // tdf#115941 because some platforms have things like overlay scrollbars, take a max
156 // of a statusbar height and a scrollbar height as the control area height
157
158 // (we can't ask the scrollbars for their size cause if we're zoomed they still have to be
159 // resized - which is done in UpdateScrollbars)
160 return std::max(aStatusBarHeight->GetSizePixel().Height(), nScrollBarSize);
161}
162
164 :Control( pParent, nBits | WB_3DLOOK )
165 ,DragSourceHelper( this )
166 ,DropTargetHelper( this )
167 ,aHScroll( VclPtr<ScrollAdaptor>::Create(this, true) )
168 // see NavigationBar ctor, here we just want to know its height
169 ,aStatusBarHeight(VclPtr<MeasureStatusBar>::Create(this))
170 ,m_nCornerHeight(0)
171 ,m_nCornerWidth(0)
172 ,m_nActualCornerWidth(0)
173 ,m_bNavigationBar(false)
174{
175 ConstructImpl( nMode );
176}
177
179{
180 disposeOnce();
181}
182
184{
185 if (m_pImpl->m_pAccessible )
186 {
187 disposeAndClearHeaderCell(m_pImpl->m_aColHeaderCellMap);
188 disposeAndClearHeaderCell(m_pImpl->m_aRowHeaderCellMap);
189 m_pImpl->m_pAccessible->dispose();
190 m_pImpl->m_pAccessible = nullptr;
191 }
192}
193
195{
196 SAL_INFO("svtools", "BrowseBox:dispose " << this );
197
199
200 Hide();
201 pDataWin->pHeaderBar.disposeAndClear();
206
207 // free columns-space
208 mvCols.clear();
209 pColSel.reset();
210 if ( bMultiSelection )
211 delete uRow.pSel;
212 DragSourceHelper::dispose();
213 DropTargetHelper::dispose();
215}
216
217
219{
220 return pDataWin->nCursorHidden;
221}
222
223
225{
226 if (!pDataWin)
227 return;
228 short nHiddenCount = --pDataWin->nCursorHidden;
230 {
231 if (1 == nHiddenCount)
232 DrawCursor();
233 }
234 else
235 {
236 if (0 == nHiddenCount)
237 DrawCursor();
238 }
239}
240
241
243{
244 short nHiddenCount = ++pDataWin->nCursorHidden;
246 {
247 if (2 == nHiddenCount)
248 DrawCursor();
249 }
250 else
251 {
252 if (1 == nHiddenCount)
253 DrawCursor();
254 }
255}
256
257
258void BrowseBox::SetRealRowCount( const OUString &rRealRowCount )
259{
260 pDataWin->aRealRowCount = rRealRowCount;
261}
262
263
264void BrowseBox::SetFont( const vcl::Font& rNewFont )
265{
266 pDataWin->SetFont( rNewFont );
268}
269
271{
272 return pDataWin->GetFont();
273}
274
275sal_uLong BrowseBox::GetDefaultColumnWidth( const OUString& _rText ) const
276{
277 return pDataWin->GetTextWidth( _rText ) + pDataWin->GetTextWidth(OUString('0')) * 4;
278}
279
280
282{
283
284#if OSL_DEBUG_LEVEL > 0
285 OSL_ENSURE( ColCount() == 0 || mvCols[0]->GetId() != HandleColumnId , "BrowseBox::InsertHandleColumn: there is already a handle column" );
286 {
287 for (auto const & col : mvCols)
288 OSL_ENSURE( col->GetId() != HandleColumnId, "BrowseBox::InsertHandleColumn: there is a non-Handle column with handle ID" );
289 }
290#endif
291
292 mvCols.insert( mvCols.begin(), std::unique_ptr<BrowserColumn>(new BrowserColumn( 0, OUString(), nWidth, GetZoom() )) );
293 FreezeColumn( 0 );
294
295 // adjust headerbar
296 if ( pDataWin->pHeaderBar )
297 {
298 pDataWin->pHeaderBar->SetPosSizePixel(
299 Point(nWidth, 0),
301 );
302 }
303
304 ColumnInserted( 0 );
305}
306
307
308void BrowseBox::InsertDataColumn( sal_uInt16 nItemId, const OUString& rText,
309 tools::Long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos )
310{
311
312 OSL_ENSURE( nItemId != HandleColumnId, "BrowseBox::InsertDataColumn: nItemId is HandleColumnId" );
313 OSL_ENSURE( nItemId != BROWSER_INVALIDID, "BrowseBox::InsertDataColumn: nItemId is reserved value BROWSER_INVALIDID" );
314
315#if OSL_DEBUG_LEVEL > 0
316 {
317 for (auto const& col : mvCols)
318 OSL_ENSURE( col->GetId() != nItemId, "BrowseBox::InsertDataColumn: duplicate column Id" );
319 }
320#endif
321
322 if ( nPos < mvCols.size() )
323 {
324 mvCols.emplace( mvCols.begin() + nPos, new BrowserColumn( nItemId, rText, nWidth, GetZoom() ) );
325 }
326 else
327 {
328 mvCols.emplace_back( new BrowserColumn( nItemId, rText, nWidth, GetZoom() ) );
329 }
330 if ( nCurColId == 0 )
331 nCurColId = nItemId;
332
333 if ( pDataWin->pHeaderBar )
334 {
335 // Handle column not in the header bar
336 sal_uInt16 nHeaderPos = nPos;
337 if (nHeaderPos != HEADERBAR_APPEND && GetColumnId(0) == HandleColumnId )
338 nHeaderPos--;
339 pDataWin->pHeaderBar->InsertItem(
340 nItemId, rText, nWidth, nBits, nHeaderPos );
341 }
343}
344
346{
347 sal_uInt16 nSelectedColId = BROWSER_INVALIDID;
348 if ( pColSel && pColSel->GetSelectCount() )
349 {
350 DoHideCursor();
352 tools::Long nSelected = pColSel->FirstSelected();
353 if (nSelected != static_cast<tools::Long>(SFX_ENDOFSELECTION))
354 nSelectedColId = mvCols[nSelected]->GetId();
355 pColSel->SelectAll(false);
356 }
357 return nSelectedColId;
358}
359
360void BrowseBox::SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)
361{
362 if ( pColSel && _nSelectedColumnId != BROWSER_INVALIDID )
363 {
364 pColSel->Select( GetColumnPos( _nSelectedColumnId ) );
366 SAL_INFO("svtools", "BrowseBox::SetToggledSelectedColumn " << this );
367 DoShowCursor();
368 }
369}
370
371void BrowseBox::FreezeColumn( sal_uInt16 nItemId )
372{
373 // get the position in the current array
374 size_t nItemPos = GetColumnPos( nItemId );
375 if ( nItemPos >= mvCols.size() )
376 // not available!
377 return;
378
379 // doesn't the state change?
380 if ( mvCols[ nItemPos ]->IsFrozen() )
381 return;
382
383 // remark the column selection
384 sal_uInt16 nSelectedColId = ToggleSelectedColumn();
385
386 // to be moved?
387 if ( nItemPos != 0 && !mvCols[ nItemPos-1 ]->IsFrozen() )
388 {
389 // move to the right of the last frozen column
390 sal_uInt16 nFirstScrollable = FrozenColCount();
391 std::unique_ptr<BrowserColumn> pColumn = std::move(mvCols[ nItemPos ]);
392 mvCols.erase( mvCols.begin() + nItemPos );
393 nItemPos = nFirstScrollable;
394 mvCols.insert( mvCols.begin() + nItemPos, std::move(pColumn) );
395 }
396
397 // adjust the number of the first scrollable and visible column
398 if ( nFirstCol <= nItemPos )
399 nFirstCol = nItemPos + 1;
400
401 // toggle the freeze-state of the column
402 mvCols[ nItemPos ]->Freeze();
403
404 // align the scrollbar-range
406
407 // repaint
409 pDataWin->Invalidate();
410
411 // remember the column selection
412 SetToggledSelectedColumn(nSelectedColId);
413}
414
415
416void BrowseBox::SetColumnPos( sal_uInt16 nColumnId, sal_uInt16 nPos )
417{
418 // never set pos of the handle column
419 if ( nColumnId == HandleColumnId )
420 return;
421
422 // get the position in the current array
423 sal_uInt16 nOldPos = GetColumnPos( nColumnId );
424 if ( nOldPos >= mvCols.size() )
425 // not available!
426 return;
427
428 // does the state change?
429 if (nOldPos == nPos)
430 return;
431
432 // remark the column selection
433 sal_uInt16 nSelectedColId = ToggleSelectedColumn();
434
435 // determine old column area
436 Size aDataWinSize( pDataWin->GetSizePixel() );
437 if ( pDataWin->pHeaderBar )
438 aDataWinSize.AdjustHeight(pDataWin->pHeaderBar->GetSizePixel().Height() );
439
440 tools::Rectangle aFromRect( GetFieldRect( nColumnId) );
441 aFromRect.AdjustRight(2*MIN_COLUMNWIDTH );
442
443 sal_uInt16 nNextPos = nOldPos + 1;
444 if ( nOldPos > nPos )
445 nNextPos = nOldPos - 1;
446
447 BrowserColumn *pNextCol = mvCols[ nNextPos ].get();
448 tools::Rectangle aNextRect(GetFieldRect( pNextCol->GetId() ));
449
450 // move column internally
451 {
452 std::unique_ptr<BrowserColumn> pTemp = std::move(mvCols[nOldPos]);
453 mvCols.erase( mvCols.begin() + nOldPos );
454 mvCols.insert( mvCols.begin() + nPos, std::move(pTemp) );
455 }
456
457 // determine new column area
458 tools::Rectangle aToRect( GetFieldRect( nColumnId ) );
459 aToRect.AdjustRight(2*MIN_COLUMNWIDTH );
460
461 // do scroll, let redraw
462 if( pDataWin->GetBackground().IsScrollable() )
463 {
464 tools::Long nScroll = -aFromRect.GetWidth();
465 tools::Rectangle aScrollArea;
466 if ( nOldPos > nPos )
467 {
468 tools::Long nFrozenWidth = GetFrozenWidth();
469 if ( aToRect.Left() < nFrozenWidth )
470 aToRect.SetLeft( nFrozenWidth );
471 aScrollArea = tools::Rectangle(Point(aToRect.Left(),0),
472 Point(aNextRect.Right(),aDataWinSize.Height()));
473 nScroll *= -1; // reverse direction
474 }
475 else
476 aScrollArea = tools::Rectangle(Point(aNextRect.Left(),0),
477 Point(aToRect.Right(),aDataWinSize.Height()));
478
479 pDataWin->Scroll( nScroll, 0, aScrollArea );
480 aToRect.SetTop( 0 );
481 aToRect.SetBottom( aScrollArea.Bottom() );
482 Invalidate( aToRect );
483 }
484 else
485 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
486
487 // adjust header bar positions
488 if ( pDataWin->pHeaderBar )
489 {
490 sal_uInt16 nNewPos = nPos;
491 if ( GetColumnId(0) == HandleColumnId )
492 --nNewPos;
493 pDataWin->pHeaderBar->MoveItem(nColumnId,nNewPos);
494 }
495 // remember the column selection
496 SetToggledSelectedColumn(nSelectedColId);
497
498 if ( !isAccessibleAlive() )
499 return;
500
503 Any( AccessibleTableModelChange(
504 COLUMNS_REMOVED,
505 -1,
506 -1,
507 nOldPos,
508 nOldPos
509 )
510 ),
511 Any()
512 );
513
516 Any( AccessibleTableModelChange(
517 COLUMNS_INSERTED,
518 -1,
519 -1,
520 nPos,
521 nPos
522 )
523 ),
524 Any()
525 );
526
527}
528
529
530void BrowseBox::SetColumnTitle( sal_uInt16 nItemId, const OUString& rTitle )
531{
532
533 // never set title of the handle-column
534 if ( nItemId == HandleColumnId )
535 return;
536
537 // get the position in the current array
538 sal_uInt16 nItemPos = GetColumnPos( nItemId );
539 if ( nItemPos >= mvCols.size() )
540 // not available!
541 return;
542
543 // does the state change?
544 BrowserColumn *pCol = mvCols[ nItemPos ].get();
545 if ( pCol->Title() == rTitle )
546 return;
547
548 OUString sOld(pCol->Title());
549
550 pCol->Title() = rTitle;
551
552 // adjust headerbar column
553 if ( pDataWin->pHeaderBar )
554 pDataWin->pHeaderBar->SetItemText( nItemId, rTitle );
555 else
556 {
557 // redraw visible columns
558 if ( GetUpdateMode() && ( pCol->IsFrozen() || nItemPos > nFirstCol ) )
561 }
562
563 if ( isAccessibleAlive() )
564 {
566 Any( rTitle ),
567 Any( sOld )
568 );
569 }
570}
571
572
573void BrowseBox::SetColumnWidth( sal_uInt16 nItemId, sal_uLong nWidth )
574{
575
576 // get the position in the current array
577 size_t nItemPos = GetColumnPos( nItemId );
578 if ( nItemPos >= mvCols.size() )
579 return;
580
581 // does the state change?
582 if ( nWidth < LONG_MAX && mvCols[ nItemPos ]->Width() == nWidth )
583 return;
584
585 tools::Long nOldWidth = mvCols[ nItemPos ]->Width();
586
587 // adjust last column, if necessary
588 if ( IsVisible() && nItemPos == mvCols.size() - 1 )
589 {
590 tools::Long nMaxWidth = pDataWin->GetSizePixel().Width();
591 nMaxWidth -= pDataWin->bAutoSizeLastCol
592 ? GetFieldRect(nItemId).Left()
593 : GetFrozenWidth();
594 if ( pDataWin->bAutoSizeLastCol || nWidth > o3tl::make_unsigned(nMaxWidth) )
595 {
596 nWidth = nMaxWidth > 16 ? nMaxWidth : nOldWidth;
597 }
598 }
599
600 // OV
601 // In AutoSizeLastColumn(), we call SetColumnWidth with nWidth==0xffff.
602 // Thus, check here, if the width has actually changed.
603 if( static_cast<sal_uLong>(nOldWidth) == nWidth )
604 return;
605
606 // do we want to display the change immediately?
607 bool bUpdate = GetUpdateMode() &&
608 ( mvCols[ nItemPos ]->IsFrozen() || nItemPos >= nFirstCol );
609
610 if ( bUpdate )
611 {
612 // Selection hidden
613 DoHideCursor();
617 }
618
619 // set width
620 mvCols[ nItemPos ]->SetWidth(nWidth, GetZoom());
621
622 // scroll and invalidate
623 if ( bUpdate )
624 {
625 // get X-Pos of the column changed
626 tools::Long nX = 0;
627 for ( size_t nCol = 0; nCol < nItemPos; ++nCol )
628 {
629 BrowserColumn *pCol = mvCols[ nCol ].get();
630 if ( pCol->IsFrozen() || nCol >= nFirstCol )
631 nX += pCol->Width();
632 }
633
634 // actually scroll+invalidate
635 pDataWin->GetOutDev()->SetClipRegion();
636 bool bSelVis = bSelectionIsVisible;
637 bSelectionIsVisible = false;
639 {
640
641 tools::Rectangle aScrRect( nX + std::min( static_cast<sal_uLong>(nOldWidth), nWidth ), 0,
642 GetSizePixel().Width() , // the header is longer than the datawin
643 pDataWin->GetPosPixel().Y() - 1 );
644 Control::Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
645 aScrRect.SetBottom( pDataWin->GetSizePixel().Height() );
646 pDataWin->Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
647 tools::Rectangle aInvRect( nX, 0, nX + std::max( nWidth, static_cast<sal_uLong>(nOldWidth) ), USHRT_MAX );
648 Control::Invalidate( aInvRect, InvalidateFlags::NoChildren );
649 pDataWin->Invalidate( aInvRect );
650 }
651 else
652 {
653 Control::Invalidate( InvalidateFlags::NoChildren );
654 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
655 }
656
657
660 bSelectionIsVisible = bSelVis;
662 DoShowCursor();
663 }
665
666 // adjust headerbar column
667 if ( pDataWin->pHeaderBar )
668 pDataWin->pHeaderBar->SetItemSize(
669 nItemId ? nItemId : USHRT_MAX - 1, nWidth );
670
671 // adjust last column
672 if ( nItemPos != mvCols.size() - 1 )
674}
675
676
678{
679 if ( pDataWin->bAutoSizeLastCol &&
680 pDataWin->GetUpdateMode() )
681 {
682 sal_uInt16 nId = GetColumnId( static_cast<sal_uInt16>(mvCols.size()) - 1 );
685 }
686}
687
688
689void BrowseBox::RemoveColumn( sal_uInt16 nItemId )
690{
691
692 // get column position
693 sal_uInt16 nPos = GetColumnPos(nItemId);
694 if ( nPos >= ColCount() )
695 // not available
696 return;
697
698 // correct column selection
699 if ( pColSel )
700 pColSel->Remove( nPos );
701
702 // correct column cursor
703 if ( nCurColId == nItemId )
704 nCurColId = 0;
705
706 // delete column
707 mvCols.erase( mvCols.begin() + nPos );
708 if ( nFirstCol >= nPos && nFirstCol > FrozenColCount() )
709 {
710 OSL_ENSURE(nFirstCol > 0,"FirstCol must be greater zero!");
711 --nFirstCol;
712 }
713
714 // handlecolumn not in headerbar
715 if (nItemId)
716 {
717 if ( pDataWin->pHeaderBar )
718 pDataWin->pHeaderBar->RemoveItem( nItemId );
719 }
720 else
721 {
722 // adjust headerbar
723 if ( pDataWin->pHeaderBar )
724 {
725 pDataWin->pHeaderBar->SetPosSizePixel(
726 Point(0, 0),
728 );
729 }
730 }
731
732 // correct vertical scrollbar
734
735 // trigger repaint, if necessary
736 if ( GetUpdateMode() )
737 {
738 pDataWin->Invalidate();
740 if ( pDataWin->bAutoSizeLastCol && nPos ==ColCount() )
742 }
743
744 if ( !isAccessibleAlive() )
745 return;
746
749 Any( AccessibleTableModelChange(COLUMNS_REMOVED,
750 -1,
751 -1,
752 nPos,
753 nPos
754 )
755 ),
756 Any()
757 );
758
760 CHILD,
761 Any(),
763 true
764 );
765}
766
767
769{
770 size_t nOldCount = mvCols.size();
771
772 // remove all columns
773 mvCols.clear();
774
775 // correct column selection
776 if ( pColSel )
777 {
778 pColSel->SelectAll(false);
779 pColSel->SetTotalRange( Range( 0, 0 ) );
780 }
781
782 // correct column cursor
783 nCurColId = 0;
784 nFirstCol = 0;
785
786 if ( pDataWin->pHeaderBar )
787 pDataWin->pHeaderBar->Clear( );
788
789 // correct vertical scrollbar
791
792 // trigger repaint if necessary
793 if ( GetUpdateMode() )
794 {
795 pDataWin->Invalidate();
797 }
798
799 if ( !isAccessibleAlive() )
800 return;
801
802 if ( mvCols.size() == nOldCount )
803 return;
804
805 // all columns should be removed, so we remove the column header bar and append it again
806 // to avoid to notify every column remove
808 CHILD,
809 Any(),
810 Any(m_pImpl->getAccessibleHeaderBar(AccessibleBrowseBoxObjType::ColumnHeaderBar))
811 );
812
813 // and now append it again
815 CHILD,
816 Any(m_pImpl->getAccessibleHeaderBar(AccessibleBrowseBoxObjType::ColumnHeaderBar)),
817 Any()
818 );
819
820 // notify a table model change
823 Any ( AccessibleTableModelChange( COLUMNS_REMOVED,
824 -1,
825 -1,
826 0,
827 nOldCount
828 )
829 ),
830 Any()
831 );
832}
833
834
835OUString BrowseBox::GetColumnTitle( sal_uInt16 nId ) const
836{
837
838 sal_uInt16 nItemPos = GetColumnPos( nId );
839 if ( nItemPos >= mvCols.size() )
840 return OUString();
841 return mvCols[ nItemPos ]->Title();
842}
843
844sal_Int32 BrowseBox::GetRowCount() const
845{
846 return nRowCount;
847}
848
849sal_uInt16 BrowseBox::ColCount() const
850{
851 return static_cast<sal_uInt16>(mvCols.size());
852}
853
855{
856 BrowseBox *pThis = const_cast<BrowseBox*>(this);
857 pThis->m_nDataRowHeight = pThis->CalcReverseZoom(pDataWin->GetTextHeight() + 4);
858 pThis->Resize();
859 pDataWin->Invalidate();
860 return m_nDataRowHeight;
861}
862
864{
865
867 Resize();
868 pDataWin->Invalidate();
869}
870
871void BrowseBox::SetTitleLines( sal_uInt16 nLines )
872{
873
874 nTitleLines = nLines;
875}
876
877sal_Int32 BrowseBox::ScrollColumns( sal_Int32 nCols )
878{
879
880 if ( nFirstCol + nCols < 0 ||
881 o3tl::make_unsigned(nFirstCol + nCols) >= mvCols.size() )
882 return 0;
883
884 // implicitly hides cursor while scrolling
885 StartScroll();
886 bScrolling = true;
887 bool bScrollable = pDataWin->GetBackground().IsScrollable();
888 bool bInvalidateView = false;
889
890 // scrolling one column to the right?
891 if ( nCols == 1 )
892 {
893 // update internal value and scrollbar
894 ++nFirstCol;
895 aHScroll->SetThumbPos( nFirstCol - FrozenColCount() );
896
897 if ( !bScrollable )
898 {
899 bInvalidateView = true;
900 }
901 else
902 {
903 tools::Long nDelta = mvCols[ nFirstCol-1 ]->Width();
904 tools::Long nFrozenWidth = GetFrozenWidth();
905
906 tools::Rectangle aScrollRect( Point( nFrozenWidth + nDelta, 0 ),
907 Size ( GetOutputSizePixel().Width() - nFrozenWidth - nDelta,
908 GetTitleHeight() - 1
909 ) );
910
911 // scroll the header bar area (if there is no dedicated HeaderBar control)
912 if ( !pDataWin->pHeaderBar && nTitleLines )
913 {
914 // actually scroll
915 Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
916
917 // invalidate the area of the column which was scrolled out to the left hand side
918 tools::Rectangle aInvalidateRect( aScrollRect );
919 aInvalidateRect.SetLeft( nFrozenWidth );
920 aInvalidateRect.SetRight( nFrozenWidth + nDelta - 1 );
921 Invalidate( aInvalidateRect );
922 }
923
924 // scroll the data-area
925 aScrollRect.SetBottom( pDataWin->GetOutputSizePixel().Height() );
926
927 // actually scroll
928 pDataWin->Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
929
930 // invalidate the area of the column which was scrolled out to the left hand side
931 aScrollRect.SetLeft( nFrozenWidth );
932 aScrollRect.SetRight( nFrozenWidth + nDelta - 1 );
933 pDataWin->Invalidate( aScrollRect );
934 }
935 }
936
937 // scrolling one column to the left?
938 else if ( nCols == -1 )
939 {
940 --nFirstCol;
941 aHScroll->SetThumbPos( nFirstCol - FrozenColCount() );
942
943 if ( !bScrollable )
944 {
945 bInvalidateView = true;
946 }
947 else
948 {
949 tools::Long nDelta = mvCols[ nFirstCol ]->Width();
950 tools::Long nFrozenWidth = GetFrozenWidth();
951
952 tools::Rectangle aScrollRect( Point( nFrozenWidth, 0 ),
953 Size ( GetOutputSizePixel().Width() - nFrozenWidth,
954 GetTitleHeight() - 1
955 ) );
956
957 // scroll the header bar area (if there is no dedicated HeaderBar control)
958 if ( !pDataWin->pHeaderBar && nTitleLines )
959 {
960 Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
961 }
962
963 // scroll the data-area
964 aScrollRect.SetBottom( pDataWin->GetOutputSizePixel().Height() );
965 pDataWin->Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
966 }
967 }
968 else
969 {
970 if ( GetUpdateMode() )
971 {
973 Point( GetFrozenWidth(), 0 ),
975 pDataWin->Invalidate( tools::Rectangle(
976 Point( GetFrozenWidth(), 0 ),
977 pDataWin->GetSizePixel() ) );
978 }
979
980 nFirstCol = nFirstCol + static_cast<sal_uInt16>(nCols);
981 aHScroll->SetThumbPos( nFirstCol - FrozenColCount() );
982 }
983
984 // adjust external headerbar, if necessary
985 if ( pDataWin->pHeaderBar )
986 {
987 tools::Long nWidth = 0;
988 for ( size_t nCol = 0;
989 nCol < mvCols.size() && nCol < nFirstCol;
990 ++nCol )
991 {
992 // not the handle column
993 if ( mvCols[ nCol ]->GetId() )
994 nWidth += mvCols[ nCol ]->Width();
995 }
996
997 pDataWin->pHeaderBar->SetOffset( nWidth );
998 }
999
1000 if( bInvalidateView )
1001 {
1002 Control::Invalidate( InvalidateFlags::NoChildren );
1003 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
1004 }
1005
1006 // implicitly show cursor after scrolling
1007 if ( nCols )
1008 {
1009 pDataWin->Update();
1011 }
1012 bScrolling = false;
1013 EndScroll();
1014
1015 return nCols;
1016}
1017
1018
1019sal_Int32 BrowseBox::ScrollRows( sal_Int32 nRows )
1020{
1021 // compute new top row
1022 sal_Int32 nTmpMin = std::min( static_cast<sal_Int32>(nTopRow + nRows), static_cast<sal_Int32>(nRowCount - 1) );
1023
1024 sal_Int32 nNewTopRow = std::max<sal_Int32>( nTmpMin, 0 );
1025
1026 if ( nNewTopRow == nTopRow )
1027 return 0;
1028
1029 sal_uInt16 nVisibleRows =
1030 static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1031
1032 VisibleRowsChanged(nNewTopRow, nVisibleRows);
1033
1034 // compute new top row again (nTopRow might have changed!)
1035 nTmpMin = std::min( static_cast<tools::Long>(nTopRow + nRows), static_cast<tools::Long>(nRowCount - 1) );
1036
1037 nNewTopRow = std::max<tools::Long>( nTmpMin, 0 );
1038
1039 StartScroll();
1040
1041 // scroll area on screen and/or repaint
1042 tools::Long nDeltaY = GetDataRowHeight() * ( nNewTopRow - nTopRow );
1043 sal_Int32 nOldTopRow = nTopRow;
1044 nTopRow = nNewTopRow;
1045
1046 if ( GetUpdateMode() )
1047 {
1048 pVScroll->SetRange( Range( 0L, nRowCount ) );
1049 pVScroll->SetThumbPos( nTopRow );
1050
1051 if( pDataWin->GetBackground().IsScrollable() &&
1052 std::abs( nDeltaY ) > 0 &&
1053 std::abs( nDeltaY ) < pDataWin->GetSizePixel().Height() )
1054 {
1055 pDataWin->Scroll( 0, static_cast<short>(-nDeltaY), SCROLL_FLAGS );
1056 }
1057 else
1058 pDataWin->Invalidate();
1059
1060 if ( nTopRow - nOldTopRow )
1061 pDataWin->Update();
1062 }
1063
1064 EndScroll();
1065
1066 return nTopRow - nOldTopRow;
1067}
1068
1069
1070void BrowseBox::RowModified( sal_Int32 nRow, sal_uInt16 nColId )
1071{
1072
1073 if ( !GetUpdateMode() )
1074 return;
1075
1076 tools::Rectangle aRect;
1077 if ( nColId == BROWSER_INVALIDID )
1078 // invalidate the whole row
1079 aRect = tools::Rectangle( Point( 0, (nRow-nTopRow) * GetDataRowHeight() ),
1080 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1081 else
1082 {
1083 // invalidate the specific field
1084 aRect = GetFieldRectPixel( nRow, nColId, false );
1085 }
1086 pDataWin->Invalidate( aRect );
1087}
1088
1089
1091{
1092 // adjust the total number of rows
1093 DoHideCursor();
1094 sal_Int32 nOldRowCount = nRowCount;
1095 nRowCount = 0;
1096 if(bMultiSelection)
1097 {
1098 assert(uRow.pSel);
1099 uRow.pSel->Reset();
1100 }
1101 else
1104 nTopRow = 0;
1105 nCurColId = 0;
1106
1107 // nFirstCol may not be reset, else the scrolling code will become confused.
1108 // nFirstCol may only be changed when adding or deleting columns
1109 // nFirstCol = 0; -> wrong!
1110 aHScroll->SetThumbPos( 0 );
1111 pVScroll->SetThumbPos( 0 );
1112
1113 Invalidate();
1116 DoShowCursor();
1117 CursorMoved();
1118
1119 if ( !isAccessibleAlive() )
1120 return;
1121
1122 // all rows should be removed, so we remove the row header bar and append it again
1123 // to avoid to notify every row remove
1124 if ( nOldRowCount == nRowCount )
1125 return;
1126
1128 CHILD,
1129 Any(),
1130 Any( m_pImpl->getAccessibleHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar ) )
1131 );
1132
1133 // and now append it again
1135 CHILD,
1136 Any( m_pImpl->getAccessibleHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar ) ),
1137 Any()
1138 );
1139
1140 // notify a table model change
1143 Any( AccessibleTableModelChange(ROWS_REMOVED,
1144 0,
1145 nOldRowCount,
1146 -1,
1147 -1)
1148 ),
1149 Any()
1150 );
1151}
1152
1153void BrowseBox::RowInserted( sal_Int32 nRow, sal_Int32 nNumRows, bool bDoPaint, bool bKeepSelection )
1154{
1155
1156 if (nRow < 0)
1157 nRow = 0;
1158 else if (nRow > nRowCount) // maximal = nRowCount
1159 nRow = nRowCount;
1160
1161 if ( nNumRows <= 0 )
1162 return;
1163
1164 // adjust total row count
1165 bool bLastRow = nRow >= nRowCount;
1166 nRowCount += nNumRows;
1167
1168 DoHideCursor();
1169
1170 // must we paint the new rows?
1171 sal_Int32 nOldCurRow = nCurRow;
1172 Size aSz = pDataWin->GetOutputSizePixel();
1173 if ( bDoPaint && nRow >= nTopRow &&
1174 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1175 {
1176 tools::Long nY = (nRow-nTopRow) * GetDataRowHeight();
1177 if ( !bLastRow )
1178 {
1179 // scroll down the rows behind the new row
1180 pDataWin->GetOutDev()->SetClipRegion();
1181 if( pDataWin->GetBackground().IsScrollable() )
1182 {
1183 pDataWin->Scroll( 0, GetDataRowHeight() * nNumRows,
1184 tools::Rectangle( Point( 0, nY ),
1185 Size( aSz.Width(), aSz.Height() - nY ) ),
1186 SCROLL_FLAGS );
1187 }
1188 else
1189 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
1190 }
1191 else
1192 // scroll would cause a repaint, so we must explicitly invalidate
1193 pDataWin->Invalidate( tools::Rectangle( Point( 0, nY ),
1194 Size( aSz.Width(), nNumRows * GetDataRowHeight() ) ) );
1195 }
1196
1197 // correct top row if necessary
1198 if ( nRow < nTopRow )
1199 nTopRow += nNumRows;
1200
1201 // adjust the selection
1202 if ( bMultiSelection )
1203 uRow.pSel->Insert( nRow, nNumRows );
1204 else if ( uRow.nSel != BROWSER_ENDOFSELECTION && nRow <= uRow.nSel )
1205 uRow.nSel += nNumRows;
1206
1207 // adjust the cursor
1209 GoToRow( 0, false, bKeepSelection );
1210 else if ( nRow <= nCurRow )
1211 {
1212 nCurRow += nNumRows;
1213 GoToRow( nCurRow, false, bKeepSelection );
1214 }
1215
1216 // adjust the vertical scrollbar
1217 if ( bDoPaint )
1218 {
1221 }
1222
1223 DoShowCursor();
1224 // notify accessible that rows were inserted
1225 if ( isAccessibleAlive() )
1226 {
1229 Any( AccessibleTableModelChange(
1230 ROWS_INSERTED,
1231 nRow,
1232 nRow + nNumRows,
1233 -1,
1234 -1
1235 )
1236 ),
1237 Any()
1238 );
1239
1240 for (tools::Long i = nRow+1 ; i <= nRowCount ; ++i)
1241 {
1243 CHILD,
1245 Any(),
1246 false
1247 );
1248 }
1249 }
1250
1251 if ( nCurRow != nOldCurRow )
1252 CursorMoved();
1253
1254 DBG_ASSERT(nRowCount > 0,"BrowseBox: nRowCount <= 0");
1255 DBG_ASSERT(nCurRow >= 0,"BrowseBox: nCurRow < 0");
1256 DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1257}
1258
1259
1260void BrowseBox::RowRemoved( sal_Int32 nRow, sal_Int32 nNumRows, bool bDoPaint )
1261{
1262
1263 if ( nRow < 0 )
1264 nRow = 0;
1265 else if ( nRow >= nRowCount )
1266 nRow = nRowCount - 1;
1267
1268 if ( nNumRows <= 0 )
1269 return;
1270
1271 if ( nRowCount <= 0 )
1272 return;
1273
1274 if ( bDoPaint )
1275 {
1276 // hide cursor and selection
1277 SAL_INFO("svtools", "BrowseBox::HideCursor " << this );
1278 ToggleSelection();
1279 DoHideCursor();
1280 }
1281
1282 // adjust total row count
1283 nRowCount -= nNumRows;
1284 if (nRowCount < 0) nRowCount = 0;
1285 sal_Int32 nOldCurRow = nCurRow;
1286
1287 // adjust the selection
1288 if ( bMultiSelection )
1289 // uRow.pSel->Remove( nRow, nNumRows );
1290 for ( tools::Long i = 0; i < nNumRows; i++ )
1291 uRow.pSel->Remove( nRow );
1292 else if ( nRow < uRow.nSel && uRow.nSel >= nNumRows )
1293 uRow.nSel -= nNumRows;
1294 else if ( nRow <= uRow.nSel )
1295 uRow.nSel = BROWSER_ENDOFSELECTION;
1296
1297 // adjust the cursor
1298 if ( nRowCount == 0 ) // don't compare nRowCount with nNumRows as nNumRows already was subtracted from nRowCount
1299 nCurRow = BROWSER_ENDOFSELECTION;
1300 else if ( nRow < nCurRow )
1301 {
1302 nCurRow -= std::min( nCurRow - nRow, nNumRows );
1303 // with the above nCurRow points a) to the first row after the removed block or b) to the same line
1304 // as before, but moved up nNumRows
1305 // case a) needs an additional correction if the last n lines were deleted, as 'the first row after the
1306 // removed block' is an invalid position then
1307 // FS - 09/28/99 - 68429
1308 if (nCurRow == nRowCount)
1309 --nCurRow;
1310 }
1311 else if( nRow == nCurRow && nCurRow == nRowCount )
1312 nCurRow = nRowCount-1;
1313
1314 // is the deleted row visible?
1315 Size aSz = pDataWin->GetOutputSizePixel();
1316 if ( nRow >= nTopRow &&
1317 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1318 {
1319 if ( bDoPaint )
1320 {
1321 // scroll up the rows behind the deleted row
1322 // if there are Rows behind
1323 if (nRow < nRowCount)
1324 {
1325 tools::Long nY = (nRow-nTopRow) * GetDataRowHeight();
1326 pDataWin->GetOutDev()->SetClipRegion();
1327 if( pDataWin->GetBackground().IsScrollable() )
1328 {
1329 pDataWin->Scroll( 0, - static_cast<short>(GetDataRowHeight()) * nNumRows,
1330 tools::Rectangle( Point( 0, nY ), Size( aSz.Width(),
1331 aSz.Height() - nY + nNumRows*GetDataRowHeight() ) ),
1332 SCROLL_FLAGS );
1333 }
1334 else
1335 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
1336 }
1337 else
1338 {
1339 // Repaint the Rect of the deleted row
1340 tools::Rectangle aRect(
1341 Point( 0, (nRow-nTopRow)*GetDataRowHeight() ),
1342 Size( pDataWin->GetSizePixel().Width(),
1343 nNumRows * GetDataRowHeight() ) );
1344 pDataWin->Invalidate( aRect );
1345 }
1346 }
1347 }
1348 // is the deleted row above of the visible area?
1349 else if ( nRow < nTopRow )
1350 nTopRow = nTopRow >= nNumRows ? nTopRow-nNumRows : 0;
1351
1352 if ( bDoPaint )
1353 {
1354 // reshow cursor and selection
1355 ToggleSelection();
1356 SAL_INFO("svtools", "BrowseBox::ShowCursor " << this );
1357 DoShowCursor();
1358
1359 // adjust the vertical scrollbar
1360 UpdateScrollbars();
1361 AutoSizeLastColumn();
1362 }
1363
1364 if ( isAccessibleAlive() )
1365 {
1366 if ( nRowCount == 0 )
1367 {
1368 // all columns should be removed, so we remove the column header bar and append it again
1369 // to avoid to notify every column remove
1370 commitBrowseBoxEvent(
1371 CHILD,
1372 Any(),
1373 Any( m_pImpl->getAccessibleHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar ) )
1374 );
1375
1376 // and now append it again
1377 commitBrowseBoxEvent(
1378 CHILD,
1379 Any(m_pImpl->getAccessibleHeaderBar(AccessibleBrowseBoxObjType::RowHeaderBar)),
1380 Any()
1381 );
1382 commitBrowseBoxEvent(
1383 CHILD,
1384 Any(),
1385 Any( m_pImpl->getAccessibleTable() )
1386 );
1387
1388 // and now append it again
1389 commitBrowseBoxEvent(
1390 CHILD,
1391 Any( m_pImpl->getAccessibleTable() ),
1392 Any()
1393 );
1394 }
1395 else
1396 {
1397 commitTableEvent(
1398 TABLE_MODEL_CHANGED,
1399 Any( AccessibleTableModelChange(
1400 ROWS_REMOVED,
1401 nRow,
1402 nRow + nNumRows,
1403 -1,
1404 -1
1405 )
1406 ),
1407 Any()
1408 );
1409
1410 for (tools::Long i = nRow+1 ; i <= (nRow+nNumRows) ; ++i)
1411 {
1412 commitHeaderBarEvent(
1413 CHILD,
1414 Any(),
1415 Any( CreateAccessibleRowHeader( i ) ),
1416 false
1417 );
1418 }
1419 }
1420 }
1421
1422 if ( nOldCurRow != nCurRow )
1423 CursorMoved();
1424
1425 DBG_ASSERT(nRowCount >= 0,"BrowseBox: nRowCount < 0");
1426 DBG_ASSERT(nCurRow >= 0 || nRowCount == 0,"BrowseBox: nCurRow < 0 && nRowCount != 0");
1427 DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1428}
1429
1430
1431bool BrowseBox::GoToRow( sal_Int32 nRow)
1432{
1433 return GoToRow(nRow, false);
1434}
1435
1436
1437bool BrowseBox::GoToRow( sal_Int32 nRow, bool bRowColMove, bool bKeepSelection )
1438{
1439 sal_Int32 nOldCurRow = nCurRow;
1440
1441 // nothing to do?
1442 if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) )
1443 return true;
1444
1445 // out of range?
1446 if ( nRow < 0 || nRow >= nRowCount )
1447 return false;
1448
1449 // not allowed?
1450 if ( !bRowColMove && !IsCursorMoveAllowed( nRow, nCurColId ) )
1451 return false;
1452
1453 // compute the last visible row
1454 Size aSz( pDataWin->GetSizePixel() );
1455 sal_uInt16 nVisibleRows = sal_uInt16( aSz.Height() / GetDataRowHeight() - 1 );
1456 sal_Int32 nLastRow = nTopRow + nVisibleRows;
1457
1458 // suspend Updates
1459 pDataWin->EnterUpdateLock();
1460
1461 // remove old highlight, if necessary
1462 if ( !bMultiSelection && !bKeepSelection )
1463 ToggleSelection();
1464 DoHideCursor();
1465
1466 // must we scroll?
1467 bool bWasVisible = bSelectionIsVisible;
1468 if (! bMultiSelection)
1469 {
1470 if( !bKeepSelection )
1471 bSelectionIsVisible = false;
1472 }
1473 if ( nRow < nTopRow )
1474 ScrollRows( nRow - nTopRow );
1475 else if ( nRow > nLastRow )
1476 ScrollRows( nRow - nLastRow );
1477 bSelectionIsVisible = bWasVisible;
1478
1479 // adjust cursor (selection) and thumb
1480 if ( GetUpdateMode() )
1481 pVScroll->SetThumbPos( nTopRow );
1482
1483 // relative positioning (because nCurRow might have changed in the meantime)!
1484 if (nCurRow != BROWSER_ENDOFSELECTION )
1485 nCurRow = nCurRow + (nRow - nOldCurRow);
1486
1487 // make sure that the current position is valid
1488 if (nCurRow == BROWSER_ENDOFSELECTION && nRowCount > 0)
1489 nCurRow = 0;
1490 else if ( nCurRow >= nRowCount )
1491 nCurRow = nRowCount - 1;
1492 aSelRange = Range( nCurRow, nCurRow );
1493
1494 // display new highlight if necessary
1495 if ( !bMultiSelection && !bKeepSelection )
1496 uRow.nSel = nRow;
1497
1498 // resume Updates
1499 pDataWin->LeaveUpdateLock();
1500
1501 // Cursor+Highlight
1502 if ( !bMultiSelection && !bKeepSelection)
1503 ToggleSelection();
1504 DoShowCursor();
1505 if ( !bRowColMove && nOldCurRow != nCurRow )
1506 CursorMoved();
1507
1508 if ( !bMultiSelection && !bKeepSelection )
1509 {
1510 if ( !bSelecting )
1511 Select();
1512 else
1513 bSelect = true;
1514 }
1515 return true;
1516}
1517
1518
1519bool BrowseBox::GoToColumnId( sal_uInt16 nColId)
1520{
1521 return GoToColumnId(nColId, true);
1522}
1523
1524
1525bool BrowseBox::GoToColumnId( sal_uInt16 nColId, bool bMakeVisible, bool bRowColMove)
1526{
1527 if (!bColumnCursor)
1528 return false;
1529
1530 // allowed?
1531 if (!bRowColMove && !IsCursorMoveAllowed( nCurRow, nColId ) )
1532 return false;
1533
1534 if ( nColId != nCurColId || (bMakeVisible && !IsFieldVisible(nCurRow, nColId, true)))
1535 {
1536 sal_uInt16 nNewPos = GetColumnPos(nColId);
1537 BrowserColumn* pColumn = (nNewPos < mvCols.size()) ? mvCols[ nNewPos ].get() : nullptr;
1538 DBG_ASSERT( pColumn, "no column object - invalid id?" );
1539 if ( !pColumn )
1540 return false;
1541
1542 DoHideCursor();
1543 nCurColId = nColId;
1544
1545 bool bScrolled = false;
1546
1547 sal_uInt16 nFirstPos = nFirstCol;
1548 sal_uInt16 nWidth = static_cast<sal_uInt16>(pColumn->Width());
1549 sal_uInt16 nLastPos = GetColumnAtXPosPixel(
1550 pDataWin->GetSizePixel().Width()-nWidth );
1551 sal_uInt16 nFrozen = FrozenColCount();
1552 if ( bMakeVisible && nLastPos &&
1553 nNewPos >= nFrozen && ( nNewPos < nFirstPos || nNewPos > nLastPos ) )
1554 {
1555 if ( nNewPos < nFirstPos )
1556 ScrollColumns( nNewPos-nFirstPos );
1557 else if ( nNewPos > nLastPos )
1558 ScrollColumns( nNewPos-nLastPos );
1559 bScrolled = true;
1560 }
1561
1562 DoShowCursor();
1563 if (!bRowColMove)
1564 {
1565 //try to move to nCurRow, nColId
1566 CursorMoveAttempt aAttempt(nCurRow, nColId, bScrolled);
1567 //Detect if we are already in a call to BrowseBox::GoToColumnId
1568 //but the attempt is impossible and we are simply recursing
1569 //into BrowseBox::GoToColumnId with the same impossible to
1570 //fulfill conditions
1571 if (m_aGotoStack.empty() || aAttempt != m_aGotoStack.top())
1572 {
1573 m_aGotoStack.push(aAttempt);
1574 CursorMoved();
1575 m_aGotoStack.pop();
1576 }
1577 }
1578 return true;
1579 }
1580 return true;
1581}
1582
1583
1584bool BrowseBox::GoToRowColumnId( sal_Int32 nRow, sal_uInt16 nColId )
1585{
1586
1587 // out of range?
1588 if ( nRow < 0 || nRow >= nRowCount )
1589 return false;
1590
1591 if (!bColumnCursor)
1592 return false;
1593
1594 // nothing to do ?
1595 if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) &&
1596 nColId == nCurColId && IsFieldVisible(nCurRow, nColId, true))
1597 return true;
1598
1599 // allowed?
1600 if (!IsCursorMoveAllowed(nRow, nColId))
1601 return false;
1602
1603 DoHideCursor();
1604 bool bMoved = GoToRow(nRow, true) && GoToColumnId(nColId, true, true);
1605 DoShowCursor();
1606
1607 if (bMoved)
1608 CursorMoved();
1609
1610 return bMoved;
1611}
1612
1613
1614void BrowseBox::SetNoSelection()
1615{
1616
1617 // is there no selection
1618 if ( ( !pColSel || !pColSel->GetSelectCount() ) &&
1619 ( ( !bMultiSelection && uRow.nSel == BROWSER_ENDOFSELECTION ) ||
1620 ( bMultiSelection && !uRow.pSel->GetSelectCount() ) ) )
1621 // nothing to do
1622 return;
1623
1624 SAL_INFO("svtools", "BrowseBox::HideCursor " << this );
1625 ToggleSelection();
1626
1627 // unselect all
1628 if ( bMultiSelection )
1629 uRow.pSel->SelectAll(false);
1630 else
1631 uRow.nSel = BROWSER_ENDOFSELECTION;
1632 if ( pColSel )
1633 pColSel->SelectAll(false);
1634 if ( !bSelecting )
1635 Select();
1636 else
1637 bSelect = true;
1638
1639 // restore screen
1640 SAL_INFO("svtools", "BrowseBox::ShowCursor " << this );
1641
1642 if ( isAccessibleAlive() )
1643 {
1644 commitTableEvent(
1645 SELECTION_CHANGED,
1646 Any(),
1647 Any()
1648 );
1649 }
1650}
1651
1652
1653void BrowseBox::SelectAll()
1654{
1655
1656 if ( !bMultiSelection )
1657 return;
1658
1659 SAL_INFO("svtools", "BrowseBox::HideCursor " << this );
1660 ToggleSelection();
1661
1662 // select all rows
1663 if ( pColSel )
1664 pColSel->SelectAll(false);
1665 uRow.pSel->SelectAll();
1666
1667 // don't highlight handle column
1668 BrowserColumn *pFirstCol = mvCols[ 0 ].get();
1669 tools::Long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1670
1671 // highlight the row selection
1672 if ( !bHideSelect )
1673 {
1674 tools::Rectangle aHighlightRect;
1675 sal_uInt16 nVisibleRows =
1676 static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1677 for ( sal_Int32 nRow = std::max<sal_Int32>( nTopRow, uRow.pSel->FirstSelected() );
1678 nRow != BROWSER_ENDOFSELECTION && nRow < nTopRow + nVisibleRows;
1679 nRow = uRow.pSel->NextSelected() )
1680 aHighlightRect.Union( tools::Rectangle(
1681 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1682 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) ) );
1683 pDataWin->Invalidate( aHighlightRect );
1684 }
1685
1686 if ( !bSelecting )
1687 Select();
1688 else
1689 bSelect = true;
1690
1691 // restore screen
1692 SAL_INFO("svtools", "BrowseBox::ShowCursor " << this );
1693
1694 if ( !isAccessibleAlive() )
1695 return;
1696
1697 commitTableEvent(
1698 SELECTION_CHANGED,
1699 Any(),
1700 Any()
1701 );
1702 commitHeaderBarEvent(
1703 SELECTION_CHANGED,
1704 Any(),
1705 Any(),
1706 true
1707 ); // column header event
1708
1709 commitHeaderBarEvent(
1710 SELECTION_CHANGED,
1711 Any(),
1712 Any(),
1713 false
1714 ); // row header event
1715}
1716
1717
1718void BrowseBox::SelectRow( sal_Int32 nRow, bool _bSelect, bool bExpand )
1719{
1720
1721 if ( !bMultiSelection )
1722 {
1723 // deselecting is impossible, selecting via cursor
1724 if ( _bSelect )
1725 GoToRow(nRow, false);
1726 return;
1727 }
1728
1729 SAL_INFO("svtools", "BrowseBox::HideCursor " << this );
1730
1731 // remove old selection?
1732 if ( !bExpand || !bMultiSelection )
1733 {
1734 ToggleSelection();
1735 if ( bMultiSelection )
1736 uRow.pSel->SelectAll(false);
1737 else
1738 uRow.nSel = BROWSER_ENDOFSELECTION;
1739 if ( pColSel )
1740 pColSel->SelectAll(false);
1741 }
1742
1743 // set new selection
1744 if ( !bHideSelect
1745 && ( ( bMultiSelection
1746 && uRow.pSel->GetTotalRange().Max() >= nRow
1747 && uRow.pSel->Select( nRow, _bSelect )
1748 )
1749 || ( !bMultiSelection
1750 && ( uRow.nSel = nRow ) != BROWSER_ENDOFSELECTION )
1751 )
1752 )
1753 {
1754 // don't highlight handle column
1755 BrowserColumn *pFirstCol = mvCols[ 0 ].get();
1756 tools::Long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1757
1758 // highlight only newly selected part
1759 tools::Rectangle aRect(
1760 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1761 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1762 pDataWin->Invalidate( aRect );
1763 }
1764
1765 if ( !bSelecting )
1766 Select();
1767 else
1768 bSelect = true;
1769
1770 // restore screen
1771 SAL_INFO("svtools", "BrowseBox::ShowCursor " << this );
1772
1773 if ( !isAccessibleAlive() )
1774 return;
1775
1776 commitTableEvent(
1777 SELECTION_CHANGED,
1778 Any(),
1779 Any()
1780 );
1781 commitHeaderBarEvent(
1782 SELECTION_CHANGED,
1783 Any(),
1784 Any(),
1785 false
1786 ); // row header event
1787}
1788
1789
1790sal_Int32 BrowseBox::GetSelectRowCount() const
1791{
1792
1793 return bMultiSelection ? uRow.pSel->GetSelectCount() :
1794 uRow.nSel == BROWSER_ENDOFSELECTION ? 0 : 1;
1795}
1796
1797
1798void BrowseBox::SelectColumnPos( sal_uInt16 nNewColPos, bool _bSelect, bool bMakeVisible )
1799{
1800
1801 if ( !bColumnCursor || nNewColPos == BROWSER_INVALIDID )
1802 return;
1803
1804 if ( !bMultiSelection )
1805 {
1806 if ( _bSelect )
1807 GoToColumnId( mvCols[ nNewColPos ]->GetId(), bMakeVisible );
1808 return;
1809 }
1810 else
1811 {
1812 if ( !GoToColumnId( mvCols[ nNewColPos ]->GetId(), bMakeVisible ) )
1813 return;
1814 }
1815
1816 SAL_INFO("svtools", "BrowseBox::HideCursor " << this );
1817 ToggleSelection();
1818 if ( bMultiSelection )
1819 uRow.pSel->SelectAll(false);
1820 else
1821 uRow.nSel = BROWSER_ENDOFSELECTION;
1822 pColSel->SelectAll(false);
1823
1824 if ( pColSel->Select( nNewColPos, _bSelect ) )
1825 {
1826 // GoToColumnId( mvCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
1827
1828 // only highlight painted areas
1829 pDataWin->Update();
1830 tools::Rectangle aFieldRectPix( GetFieldRectPixel( nCurRow, nCurColId, false ) );
1831 tools::Rectangle aRect(
1832 Point( aFieldRectPix.Left() - MIN_COLUMNWIDTH, 0 ),
1833 Size( mvCols[ nNewColPos ]->Width(),
1834 pDataWin->GetOutputSizePixel().Height() ) );
1835 pDataWin->Invalidate( aRect );
1836 if ( !bSelecting )
1837 Select();
1838 else
1839 bSelect = true;
1840
1841 if ( isAccessibleAlive() )
1842 {
1843 commitTableEvent(
1844 SELECTION_CHANGED,
1845 Any(),
1846 Any()
1847 );
1848 commitHeaderBarEvent(
1849 SELECTION_CHANGED,
1850 Any(),
1851 Any(),
1852 true
1853 ); // column header event
1854 }
1855 }
1856
1857 // restore screen
1858 SAL_INFO("svtools", "BrowseBox::ShowCursor " << this );
1859}
1860
1861
1862sal_uInt16 BrowseBox::GetSelectColumnCount() const
1863{
1864
1865 // while bAutoSelect (==!pColSel), 1 if any rows (yes rows!) else none
1866 return pColSel ? static_cast<sal_uInt16>(pColSel->GetSelectCount()) :
1867 nCurRow >= 0 ? 1 : 0;
1868}
1869
1870
1871sal_Int32 BrowseBox::FirstSelectedColumn( ) const
1872{
1873 return pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
1874}
1875
1876
1877sal_Int32 BrowseBox::FirstSelectedRow()
1878{
1879
1880 return bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
1881}
1882
1883
1884sal_Int32 BrowseBox::NextSelectedRow()
1885{
1886
1887 return bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION;
1888}
1889
1890
1891sal_Int32 BrowseBox::LastSelectedRow()
1892{
1893
1894 return bMultiSelection ? uRow.pSel->LastSelected() : uRow.nSel;
1895}
1896
1897
1898bool BrowseBox::IsRowSelected( sal_Int32 nRow ) const
1899{
1900
1901 return bMultiSelection ? uRow.pSel->IsSelected(nRow) : nRow == uRow.nSel;
1902}
1903
1904
1905bool BrowseBox::IsColumnSelected( sal_uInt16 nColumnId ) const
1906{
1907
1908 return pColSel ? pColSel->IsSelected( GetColumnPos(nColumnId) ) :
1909 nCurColId == nColumnId;
1910}
1911
1912
1913void BrowseBox::MakeFieldVisible
1914(
1915 sal_Int32 nRow, // line number of the field (starting with 0)
1916 sal_uInt16 nColId // column ID of the field
1917)
1918
1919/* [Description]
1920
1921 Makes visible the field described in 'nRow' and 'nColId' by scrolling
1922 accordingly.
1923
1924*/
1925
1926{
1927 if (!pDataWin)
1928 return;
1929
1930 Size aTestSize = pDataWin->GetSizePixel();
1931
1932 if ( !bBootstrapped || aTestSize.IsEmpty() )
1933 return;
1934
1935 // is it visible already?
1936 bool bVisible = IsFieldVisible( nRow, nColId, true/*bComplete*/ );
1937 if ( bVisible )
1938 return;
1939
1940 // calculate column position, field rectangle and painting area
1941 sal_uInt16 nColPos = GetColumnPos( nColId );
1942 tools::Rectangle aFieldRect = GetFieldRectPixel( nRow, nColId, false );
1943 tools::Rectangle aDataRect( Point(0, 0), pDataWin->GetSizePixel() );
1944
1945 // positioned outside on the left?
1946 if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
1947 // => scroll to the right
1948 ScrollColumns( nColPos - nFirstCol );
1949
1950 // while outside on the right
1951 while ( aDataRect.Right() < aFieldRect.Right() )
1952 {
1953 // => scroll to the left
1954 if ( ScrollColumns( 1 ) != 1 )
1955 // no more need to scroll
1956 break;
1957 aFieldRect = GetFieldRectPixel( nRow, nColId, false );
1958 }
1959
1960 // positioned outside above?
1961 if ( nRow < nTopRow )
1962 // scroll further to the bottom
1963 ScrollRows( nRow - nTopRow );
1964
1965 // positioned outside below?
1966 sal_Int32 nBottomRow = nTopRow + GetVisibleRows();
1967 // decrement nBottomRow to make it the number of the last visible line
1968 // (count starts with 0!).
1969 // Example: BrowseBox contains exactly one entry. nBottomRow := 0 + 1 - 1
1970 if( nBottomRow )
1971 nBottomRow--;
1972
1973 if ( nRow > nBottomRow )
1974 // scroll further to the top
1975 ScrollRows( nRow - nBottomRow );
1976}
1977
1978
1979bool BrowseBox::IsFieldVisible( sal_Int32 nRow, sal_uInt16 nColumnId,
1980 bool bCompletely ) const
1981{
1982
1983 // hidden by frozen column?
1984 sal_uInt16 nColPos = GetColumnPos( nColumnId );
1985 if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
1986 return false;
1987
1988 tools::Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
1989 if ( aRect.IsEmpty() )
1990 return false;
1991
1992 // get the visible area
1993 tools::Rectangle aOutRect( Point(0, 0), pDataWin->GetOutputSizePixel() );
1994
1995 if ( bCompletely )
1996 // test if the field is completely visible
1997 return aOutRect.Contains( aRect );
1998 else
1999 // test if the field is partly of completely visible
2000 return !aOutRect.Intersection( aRect ).IsEmpty();
2001}
2002
2003
2004tools::Rectangle BrowseBox::GetFieldRectPixel( sal_Int32 nRow, sal_uInt16 nColumnId,
2005 bool bRelToBrowser) const
2006{
2007
2008 // get the rectangle relative to DataWin
2009 tools::Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2010 if ( aRect.IsEmpty() )
2011 return aRect;
2012
2013 // adjust relative to BrowseBox's output area
2014 Point aTopLeft( aRect.TopLeft() );
2015 if ( bRelToBrowser )
2016 {
2017 aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2018 aTopLeft = ScreenToOutputPixel( aTopLeft );
2019 }
2020
2021 return tools::Rectangle( aTopLeft, aRect.GetSize() );
2022}
2023
2024
2025tools::Rectangle BrowseBox::GetRowRectPixel( sal_Int32 nRow ) const
2026{
2027
2028 // get the rectangle relative to DataWin
2029 tools::Rectangle aRect;
2030 if ( nTopRow > nRow )
2031 // row is above visible area
2032 return aRect;
2033 aRect = tools::Rectangle(
2034 Point( 0, GetDataRowHeight() * (nRow-nTopRow) ),
2035 Size( pDataWin->GetOutputSizePixel().Width(), GetDataRowHeight() ) );
2036 if ( aRect.Top() > pDataWin->GetOutputSizePixel().Height() )
2037 // row is below visible area
2038 return aRect;
2039
2040 // adjust relative to BrowseBox's output area
2041 Point aTopLeft( aRect.TopLeft() );
2042 aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2043 aTopLeft = ScreenToOutputPixel( aTopLeft );
2044
2045 return tools::Rectangle( aTopLeft, aRect.GetSize() );
2046}
2047
2048
2049tools::Rectangle BrowseBox::ImplFieldRectPixel( sal_Int32 nRow, sal_uInt16 nColumnId ) const
2050{
2051
2052 // compute the X-coordinate relative to DataWin by accumulation
2053 tools::Long nColX = 0;
2054 sal_uInt16 nFrozenCols = FrozenColCount();
2055 size_t nCol;
2056 for ( nCol = 0;
2057 nCol < mvCols.size() && mvCols[ nCol ]->GetId() != nColumnId;
2058 ++nCol )
2059 if ( mvCols[ nCol ]->IsFrozen() || nCol >= nFirstCol )
2060 nColX += mvCols[ nCol ]->Width();
2061
2062 if ( nCol >= mvCols.size() || ( nCol >= nFrozenCols && nCol < nFirstCol ) )
2063 return tools::Rectangle();
2064
2065 // compute the Y-coordinate relative to DataWin
2066 tools::Long nRowY = GetDataRowHeight();
2067 if ( nRow != BROWSER_ENDOFSELECTION ) // #105497# OJ
2068 nRowY = ( nRow - nTopRow ) * GetDataRowHeight();
2069
2070 // assemble the Rectangle relative to DataWin
2071 return tools::Rectangle(
2072 Point( nColX + MIN_COLUMNWIDTH, nRowY ),
2073 Size( (mvCols[nCol]->Width() == LONG_MAX
2074 ? LONG_MAX - (nColX + MIN_COLUMNWIDTH) : mvCols[ nCol ]->Width() - 2*MIN_COLUMNWIDTH),
2075 GetDataRowHeight() - 1 ) );
2076}
2077
2078
2079sal_Int32 BrowseBox::GetRowAtYPosPixel( tools::Long nY, bool bRelToBrowser ) const
2080{
2081
2082 // compute the Y-coordinate
2083 if ( bRelToBrowser )
2084 {
2085 Point aDataTopLeft = pDataWin->OutputToScreenPixel( Point(0, 0) );
2086 Point aTopLeft = OutputToScreenPixel( Point(0, 0) );
2087 nY -= aDataTopLeft.Y() - aTopLeft.Y();
2088 }
2089
2090 // no row there (e.g. in the header)
2091 if ( nY < 0 || nY >= pDataWin->GetOutputSizePixel().Height() )
2092 return -1;
2093
2094 return nY / GetDataRowHeight() + nTopRow;
2095}
2096
2097
2098tools::Rectangle BrowseBox::GetFieldRect( sal_uInt16 nColumnId ) const
2099{
2100
2101 return GetFieldRectPixel( nCurRow, nColumnId );
2102}
2103
2104
2105sal_uInt16 BrowseBox::GetColumnAtXPosPixel( tools::Long nX ) const
2106{
2107
2108 // accumulate the widths of the visible columns
2109 tools::Long nColX = 0;
2110 for ( size_t nCol = 0; nCol < mvCols.size(); ++nCol )
2111 {
2112 BrowserColumn *pCol = mvCols[ nCol ].get();
2113 if ( pCol->IsFrozen() || nCol >= nFirstCol )
2114 nColX += pCol->Width();
2115
2116 if ( nColX > nX )
2117 return nCol;
2118 }
2119
2120 return BROWSER_INVALIDID;
2121}
2122
2123bool BrowseBox::ReserveControlArea(sal_uInt16 nWidth)
2124{
2125 if (nWidth != nControlAreaWidth)
2126 {
2127 OSL_ENSURE(nWidth,"Control area of 0 is not allowed, Use USHRT_MAX instead!");
2128 nControlAreaWidth = nWidth;
2129 UpdateScrollbars();
2130 return true;
2131 }
2132 return false;
2133}
2134
2135tools::Rectangle BrowseBox::GetControlArea() const
2136{
2137 auto nHeight = aHScroll->GetSizePixel().Height();
2138 auto nEndRight = aHScroll->GetPosPixel().X();
2139
2140 return tools::Rectangle(
2141 Point( 0, GetOutputSizePixel().Height() - nHeight ),
2142 Size( nEndRight, nHeight ) );
2143}
2144
2145void BrowseBox::SetMode( BrowserMode nMode )
2146{
2147
2148 pDataWin->bAutoHScroll = BrowserMode::AUTO_HSCROLL == ( nMode & BrowserMode::AUTO_HSCROLL );
2149 pDataWin->bAutoVScroll = BrowserMode::AUTO_VSCROLL == ( nMode & BrowserMode::AUTO_VSCROLL );
2150 pDataWin->bNoHScroll = BrowserMode::NO_HSCROLL == ( nMode & BrowserMode::NO_HSCROLL );
2151 pDataWin->bNoVScroll = BrowserMode::NO_VSCROLL == ( nMode & BrowserMode::NO_VSCROLL );
2152
2153 DBG_ASSERT( !( pDataWin->bAutoHScroll && pDataWin->bNoHScroll ),
2154 "BrowseBox::SetMode: AutoHScroll *and* NoHScroll?" );
2155 DBG_ASSERT( !( pDataWin->bAutoVScroll && pDataWin->bNoVScroll ),
2156 "BrowseBox::SetMode: AutoVScroll *and* NoVScroll?" );
2157 if ( pDataWin->bAutoHScroll )
2158 pDataWin->bNoHScroll = false;
2159 if ( pDataWin->bAutoVScroll )
2160 pDataWin->bNoVScroll = false;
2161
2162 if ( pDataWin->bNoHScroll )
2163 aHScroll->Hide();
2164
2165 nControlAreaWidth = USHRT_MAX;
2166
2167 tools::Long nOldRowSel = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
2168 MultiSelection *pOldRowSel = bMultiSelection ? uRow.pSel : nullptr;
2169
2170 pVScroll.disposeAndClear();
2171
2172 bMultiSelection = bool( nMode & BrowserMode::MULTISELECTION );
2173 bColumnCursor = bool( nMode & BrowserMode::COLUMNSELECTION );
2174 bKeepHighlight = bool( nMode & BrowserMode::KEEPHIGHLIGHT );
2175
2176 bHideSelect = ((nMode & BrowserMode::HIDESELECT) == BrowserMode::HIDESELECT);
2177 // default: do not hide the cursor at all (untaken scrolling and such)
2178 bHideCursor = TRISTATE_FALSE;
2179
2180 if ( BrowserMode::HIDECURSOR == ( nMode & BrowserMode::HIDECURSOR ) )
2181 {
2182 bHideCursor = TRISTATE_TRUE;
2183 }
2184
2185 m_bFocusOnlyCursor = ((nMode & BrowserMode::CURSOR_WO_FOCUS) == BrowserMode::NONE);
2186
2187 bHLines = ( nMode & BrowserMode::HLINES ) == BrowserMode::HLINES;
2188 bVLines = ( nMode & BrowserMode::VLINES ) == BrowserMode::VLINES;
2189
2190 pVScroll = VclPtr<ScrollAdaptor>::Create(this, false);
2191 pVScroll->SetLineSize( 1 );
2192 pVScroll->SetPageSize(1);
2193 pVScroll->SetScrollHdl( LINK( this, BrowseBox, VertScrollHdl ) );
2194
2195 pDataWin->bAutoSizeLastCol =
2196 BrowserMode::AUTOSIZE_LASTCOL == ( nMode & BrowserMode::AUTOSIZE_LASTCOL );
2197
2198 // create a headerbar. what happens, if a headerbar has to be created and
2199 // there already are columns?
2200 if ( BrowserMode::HEADERBAR_NEW == ( nMode & BrowserMode::HEADERBAR_NEW ) )
2201 {
2202 if (!pDataWin->pHeaderBar)
2203 pDataWin->pHeaderBar = CreateHeaderBar( this );
2204 }
2205 else
2206 {
2207 pDataWin->pHeaderBar.disposeAndClear();
2208 }
2209
2210 if ( bColumnCursor )
2211 {
2212 if (!pColSel)
2213 pColSel.reset(new MultiSelection);
2214 pColSel->SetTotalRange( Range( 0, mvCols.size()-1 ) );
2215 }
2216 else
2217 {
2218 pColSel.reset();
2219 }
2220
2221 if ( bMultiSelection )
2222 {
2223 if ( pOldRowSel )
2224 uRow.pSel = pOldRowSel;
2225 else
2226 uRow.pSel = new MultiSelection;
2227 }
2228 else
2229 {
2230 uRow.nSel = nOldRowSel;
2231 delete pOldRowSel;
2232 }
2233
2234 if ( bBootstrapped )
2235 {
2236 StateChanged( StateChangedType::InitShow );
2237 if ( bMultiSelection && !pOldRowSel &&
2238 nOldRowSel != BROWSER_ENDOFSELECTION )
2239 uRow.pSel->Select( nOldRowSel );
2240 }
2241
2242 if ( pDataWin )
2243 pDataWin->Invalidate();
2244
2245 // no cursor on handle column
2246 if ( nCurColId == HandleColumnId )
2247 nCurColId = GetColumnId( 1 );
2248
2249 m_nCurrentMode = nMode;
2250}
2251
2252
2253void BrowseBox::VisibleRowsChanged( sal_Int32, sal_uInt16 )
2254{
2255
2256 // old behavior: automatically correct NumRows:
2257 if ( nRowCount < GetRowCount() )
2258 {
2259 RowInserted(nRowCount,GetRowCount() - nRowCount, false);
2260 }
2261 else if ( nRowCount > GetRowCount() )
2262 {
2263 RowRemoved(nRowCount-(nRowCount - GetRowCount()),nRowCount - GetRowCount(), false);
2264 }
2265}
2266
2267
2268bool BrowseBox::IsCursorMoveAllowed( sal_Int32, sal_uInt16 ) const
2269
2270/* [Description]
2271
2272 This virtual method is always called before the cursor is moved directly.
2273 By means of 'return false', we avoid doing this if e.g. a record
2274 contradicts any rules.
2275
2276 This method is not called, if the cursor movement results from removing or
2277 deleting a row/column (thus, in cases where only a "cursor correction" happens).
2278
2279 The base implementation currently always returns true.
2280*/
2281
2282{
2283 return true;
2284}
2285
2286
2287tools::Long BrowseBox::GetDataRowHeight() const
2288{
2289 return CalcZoom(m_nDataRowHeight ? m_nDataRowHeight : ImpGetDataRowHeight());
2290}
2291
2292
2293VclPtr<BrowserHeader> BrowseBox::CreateHeaderBar( BrowseBox* pParent )
2294{
2295 VclPtr<BrowserHeader> pNewBar = VclPtr<BrowserHeader>::Create( pParent );
2296 pNewBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2297 return pNewBar;
2298}
2299
2300void BrowseBox::SetHeaderBar( BrowserHeader* pHeaderBar )
2301{
2302 pDataWin->pHeaderBar.disposeAndClear();
2303 pDataWin->pHeaderBar = pHeaderBar;
2304 pDataWin->pHeaderBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2305}
2306
2307tools::Long BrowseBox::GetTitleHeight() const
2308{
2309 tools::Long nHeight;
2310 // ask the header bar for the text height (if possible), as the header bar's font is adjusted with
2311 // our (and the header's) zoom factor
2312 HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
2313 if ( pHeaderBar )
2314 nHeight = pHeaderBar->GetTextHeight();
2315 else
2316 nHeight = GetTextHeight();
2317
2318 return nTitleLines ? nTitleLines * nHeight + 4 : 0;
2319}
2320
2321tools::Long BrowseBox::CalcReverseZoom(tools::Long nVal) const
2322{
2323 if (IsZoom())
2324 {
2325 const Fraction& rZoom = GetZoom();
2326 double n = static_cast<double>(nVal);
2327 n *= static_cast<double>(rZoom.GetDenominator());
2328 if (!rZoom.GetNumerator())
2329 throw o3tl::divide_by_zero();
2330 n /= static_cast<double>(rZoom.GetNumerator());
2331 nVal = n>0 ? static_cast<tools::Long>(n + 0.5) : -static_cast<tools::Long>(-n + 0.5);
2332 }
2333
2334 return nVal;
2335}
2336
2337void BrowseBox::CursorMoved()
2338{
2339 // before implementing more here, please adjust the EditBrowseBox
2340
2341 if ( isAccessibleAlive() && HasFocus() )
2342 commitTableEvent(
2343 ACTIVE_DESCENDANT_CHANGED,
2344 Any( CreateAccessibleCell( GetCurRow(),GetColumnPos( GetCurColumnId() ) ) ),
2345 Any()
2346 );
2347}
2348
2349void BrowseBox::LoseFocus()
2350{
2351 SAL_INFO("svtools", "BrowseBox::LoseFocus " << this );
2352
2353 if ( bHasFocus )
2354 {
2355 SAL_INFO("svtools", "BrowseBox::HideCursor " << this );
2356 DoHideCursor();
2357
2358 if ( !bKeepHighlight )
2359 {
2360 ToggleSelection();
2361 bSelectionIsVisible = false;
2362 }
2363
2364 bHasFocus = false;
2365 }
2366 Control::LoseFocus();
2367}
2368
2369
2370void BrowseBox::GetFocus()
2371{
2372 SAL_INFO("svtools", "BrowseBox::GetFocus " << this );
2373
2374 if ( !bHasFocus )
2375 {
2376 if ( !bSelectionIsVisible )
2377 {
2378 bSelectionIsVisible = true;
2379 if ( bBootstrapped )
2380 ToggleSelection();
2381 }
2382
2383 bHasFocus = true;
2384 DoShowCursor();
2385 }
2386 Control::GetFocus();
2387}
2388
2389
2390sal_uInt16 BrowseBox::GetVisibleRows() const
2391{
2392 return static_cast<sal_uInt16>((pDataWin->GetOutputSizePixel().Height() - 1 )/ GetDataRowHeight() + 1);
2393}
2394
2395BrowserDataWin& BrowseBox::GetDataWindow() const
2396{
2397 return *pDataWin;
2398}
2399
2400/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define SCROLL_FLAGS
Definition: brwbox1.cxx:41
constexpr sal_Int32 BROWSER_ENDOFSELECTION
Definition: brwbox.hxx:56
#define BROWSER_INVALIDID
Definition: brwbox.hxx:55
BrowserMode
Definition: brwbox.hxx:59
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
void SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)
Definition: brwbox1.cxx:360
SVT_DLLPRIVATE void AutoSizeLastColumn()
Definition: brwbox1.cxx:677
void StartScroll()
Definition: brwbox2.cxx:218
tools::Long GetDataRowHeight() const
Definition: brwbox1.cxx:2287
sal_uInt16 GetColumnId(sal_uInt16 nPos) const
Definition: brwbox2.cxx:379
virtual void GetFocus() override
Definition: brwbox1.cxx:2370
virtual void dispose() override
Definition: brwbox1.cxx:194
SVT_DLLPRIVATE sal_uInt16 FrozenColCount() const
Definition: brwbox2.cxx:1279
void SetRealRowCount(const OUString &rRealRowCount)
Definition: brwbox1.cxx:258
virtual void CursorMoved()
Definition: brwbox1.cxx:2337
void Clear()
Definition: brwbox1.cxx:1090
VclPtr< BrowserDataWin > pDataWin
Definition: brwbox.hxx:270
bool bSelectionIsVisible
select or deselect
Definition: brwbox.hxx:306
void InsertDataColumn(sal_uInt16 nItemId, const OUString &rText, tools::Long nSize, HeaderBarItemBits nBits=HeaderBarItemBits::STDSTYLE, sal_uInt16 nPos=HEADERBAR_APPEND)
Definition: brwbox1.cxx:308
tools::Long GetTitleHeight() const
Definition: brwbox1.cxx:2307
tools::Long nResizeX
Definition: brwbox.hxx:299
bool bMultiSelection
Definition: brwbox.hxx:282
SVT_DLLPRIVATE void ColumnInserted(sal_uInt16 nPos)
Definition: brwbox2.cxx:1272
VclPtr< ScrollAdaptor > pVScroll
Definition: brwbox.hxx:271
virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleColumnHeader(sal_uInt16 nColumnPos) override
Creates the accessible object of a column header.
Definition: brwbox3.cxx:139
bool bHideSelect
Definition: brwbox.hxx:310
tools::Long nMinResizeX
Definition: brwbox.hxx:300
sal_uInt16 nResizeCol
Definition: brwbox.hxx:302
tools::Long m_nDataRowHeight
Definition: brwbox.hxx:275
void SetColumnPos(sal_uInt16 nColumnId, sal_uInt16 nPos)
Definition: brwbox1.cxx:416
void DisposeAccessible()
Definition: brwbox1.cxx:183
sal_uLong nControlAreaWidth
Definition: brwbox.hxx:280
void FreezeColumn(sal_uInt16 nColumnId)
Definition: brwbox1.cxx:371
void DrawCursor()
Definition: brwbox2.cxx:300
bool bHit
Definition: brwbox.hxx:296
bool mbInteractiveRowHeight
Definition: brwbox.hxx:297
BrowserMode m_nCurrentMode
Definition: brwbox.hxx:349
bool bNotToggleSel
Definition: brwbox.hxx:308
BrowseBox(vcl::Window *pParent, WinBits nBits, BrowserMode nMode=BrowserMode::NONE)
Definition: brwbox1.cxx:163
tools::Long CalcReverseZoom(tools::Long nVal) const
Definition: brwbox1.cxx:2321
bool bSelect
Definition: brwbox.hxx:305
sal_uInt16 ColCount() const
Definition: brwbox1.cxx:849
void InsertHandleColumn(sal_uLong nWidth)
Definition: brwbox1.cxx:281
VclPtr< MeasureStatusBar > aStatusBarHeight
Definition: brwbox.hxx:273
SVT_DLLPRIVATE tools::Long GetFrozenWidth() const
Definition: brwbox2.cxx:1261
void SetColumnTitle(sal_uInt16 nColumnId, const OUString &rTitle)
Definition: brwbox1.cxx:530
bool m_bFocusOnlyCursor
Definition: brwbox.hxx:347
void RowModified(sal_Int32 nRow, sal_uInt16 nColId=BROWSER_INVALIDID)
Definition: brwbox1.cxx:1070
void commitTableEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue)
commitTableEvent commit the event at all listeners of the table
Definition: brwbox3.cxx:411
void DoShowCursor()
Definition: brwbox1.cxx:224
void SetFont(const vcl::Font &rNewFont)
Definition: brwbox1.cxx:264
bool PaintCursorIfHiddenOnce() const
Definition: brwbox.hxx:380
bool bBootstrapped
Definition: brwbox.hxx:287
void SetMode(BrowserMode nMode)
Definition: brwbox1.cxx:2145
sal_Int32 ScrollColumns(sal_Int32 nColumns)
Definition: brwbox1.cxx:877
TriState bHideCursor
Definition: brwbox.hxx:311
virtual void ColumnResized(sal_uInt16 nColId)
Definition: brwbox2.cxx:208
void DoHideCursor()
Definition: brwbox1.cxx:242
void SetColumnWidth(sal_uInt16 nColumnId, sal_uLong nWidth)
Definition: brwbox1.cxx:573
sal_uInt16 GetColumnPos(sal_uInt16 nColumnId) const
Definition: brwbox2.cxx:388
void RemoveColumn(sal_uInt16 nColumnId)
Definition: brwbox1.cxx:689
OUString GetColumnTitle(sal_uInt16 nColumnId) const
Definition: brwbox1.cxx:835
static const sal_uInt16 HandleColumnId
Definition: brwbox.hxx:267
sal_Int32 ScrollRows(sal_Int32 nRows)
Definition: brwbox1.cxx:1019
bool GetUpdateMode() const
Definition: brwbox2.cxx:1254
sal_uLong GetDefaultColumnWidth(const OUString &_rText) const
suggests a default width for a column containing a given text
Definition: brwbox1.cxx:275
sal_Int32 nTopRow
Definition: brwbox.hxx:288
bool bKeepHighlight
Definition: brwbox.hxx:283
SVT_DLLPRIVATE tools::Long ImpGetDataRowHeight() const
Definition: brwbox1.cxx:854
tools::Rectangle GetFieldRectPixel(sal_Int32 nRow, sal_uInt16 nColId, bool bRelToBrowser=true) const
Definition: brwbox1.cxx:2004
const vcl::Font & GetFont() const
Definition: brwbox1.cxx:270
bool bSelecting
Definition: brwbox.hxx:294
bool GoToRow(sal_Int32 nRow, bool bRowColMove, bool bDoNotModifySelection=false)
Definition: brwbox1.cxx:1437
virtual void Resize() override
Definition: brwbox2.cxx:469
void SetDataRowHeight(tools::Long nPixel)
Definition: brwbox1.cxx:863
void RowInserted(sal_Int32 nRow, sal_Int32 nNumRows=1, bool bDoPaint=true, bool bKeepSelection=false)
Definition: brwbox1.cxx:1153
bool bHasFocus
Definition: brwbox.hxx:309
virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleRowHeader(sal_Int32 nRow) override
Creates the accessible object of a row header.
Definition: brwbox3.cxx:126
sal_Int32 nRowCount
Definition: brwbox.hxx:290
bool m_bNavigationBar
Definition: brwbox.hxx:390
tools::Long nDragX
Definition: brwbox.hxx:301
bool bRowDividerDrag
Definition: brwbox.hxx:295
SVT_DLLPRIVATE void UpdateScrollbars()
Definition: brwbox2.cxx:1051
virtual sal_Int32 GetRowCount() const override
Definition: brwbox1.cxx:844
sal_Int32 nCurRow
Definition: brwbox.hxx:289
SVT_DLLPRIVATE void ToggleSelection()
Definition: brwbox2.cxx:232
virtual ~BrowseBox() override
Definition: brwbox1.cxx:178
union BrowseBox::@1 uRow
bool isAccessibleAlive() const
return <TRUE> if and only if the accessible object for this instance has been created and is alive
Definition: brwbox3.cxx:428
bool bScrolling
Definition: brwbox.hxx:307
short GetCursorHideCount() const
Definition: brwbox1.cxx:218
bool bResizing
Definition: brwbox.hxx:303
virtual void VisibleRowsChanged(sal_Int32 nNewTopRow, sal_uInt16 nNumRows)
Definition: brwbox1.cxx:2253
virtual void LoseFocus() override
Definition: brwbox1.cxx:2349
void commitHeaderBarEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue, bool _bColumnHeaderBar)
fires an AccessibleEvent relative to a header bar AccessibleContext
Definition: brwbox3.cxx:403
virtual void SetNoSelection() override
Definition: brwbox1.cxx:1614
sal_uInt16 nFirstCol
Definition: brwbox.hxx:291
SVT_DLLPRIVATE tools::Long GetBarHeight() const
Definition: brwbox1.cxx:149
tools::Rectangle GetFieldRect(sal_uInt16 nColumnId) const
Definition: brwbox1.cxx:2098
virtual void EndScroll()
Definition: brwbox2.cxx:224
::std::vector< std::unique_ptr< BrowserColumn > > mvCols
Definition: brwbox.hxx:314
SVT_DLLPRIVATE void ConstructImpl(BrowserMode nMode)
Definition: brwbox1.cxx:62
void SetTitleLines(sal_uInt16 nLines)
Definition: brwbox1.cxx:871
sal_uInt16 ToggleSelectedColumn()
Definition: brwbox1.cxx:345
sal_uInt16 nCurColId
Definition: brwbox.hxx:292
bool IsFrozen(sal_uInt16 nColumnId) const
Definition: brwbox2.cxx:397
::std::unique_ptr< ::svt::BrowseBoxImpl > m_pImpl
Definition: brwbox.hxx:345
sal_uInt16 nTitleLines
Definition: brwbox.hxx:279
VclPtr< ScrollAdaptor > aHScroll
Definition: brwbox.hxx:272
std::unique_ptr< MultiSelection > pColSel
Definition: brwbox.hxx:320
void RemoveColumns()
Definition: brwbox1.cxx:768
Color m_aCursorColor
Definition: brwbox.hxx:348
void commitBrowseBoxEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue)
commitBrowseBoxEvent commit the event at all listeners of the browsebox
Definition: brwbox3.cxx:417
OUString & Title()
Definition: datwin.hxx:69
bool IsFrozen() const
Definition: datwin.hxx:71
sal_uInt16 GetId() const
Definition: datwin.hxx:66
sal_uLong Width() const
Definition: datwin.hxx:68
virtual void dispose() override
virtual void dispose() override
std::unique_ptr< weld::Builder > m_xBuilder
MeasureStatusBar(vcl::Window *pParent)
Definition: brwbox1.cxx:123
std::unique_ptr< weld::Entry > m_xAbsolute
Definition: brwbox1.cxx:119
std::unique_ptr< weld::Label > m_xRecordText
Definition: brwbox1.cxx:118
std::unique_ptr< weld::Label > m_xRecordCount
Definition: brwbox1.cxx:121
virtual void dispose() override
Definition: brwbox1.cxx:139
std::unique_ptr< weld::Label > m_xRecordOf
Definition: brwbox1.cxx:120
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
constexpr tools::Long Width() const
sal_Int32 GetScrollBarSize() const
void disposeAndClear()
static VclPtr< reference_type > Create(Arg &&... arg)
::std::map< sal_Int32, css::uno::Reference< css::accessibility::XAccessible > > THeaderCellMap
Definition: brwimpl.hxx:36
constexpr tools::Long GetWidth() const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr void SetRight(tools::Long v)
constexpr tools::Long Right() const
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr void SetBottom(tools::Long v)
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
const Wallpaper & GetBackground() const
void PaintImmediately()
bool HasChildPathFocus(bool bSystemWindow=false) const
virtual void SetSizePixel(const Size &rNewSize)
Size get_preferred_size() const
const Fraction & GetZoom() const
const AllSettings & GetSettings() const
virtual void Scroll(tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags=ScrollFlags::NONE)
virtual Size GetSizePixel() const
Size GetOutputSizePixel() const
bool IsVisible() const
void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
bool IsScrollable() const
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
void InitSettings_Impl(vcl::Window *pWin)
Definition: datwin.cxx:233
#define MIN_COLUMNWIDTH
Definition: datwin.hxx:28
#define DBG_ASSERT(sCon, aError)
virtual sal_uInt32 GetId() const override
TRISTATE_FALSE
HeaderBarItemBits
#define HEADERBAR_APPEND
sal_uInt16 nPos
const long LONG_MAX
#define SAL_INFO(area, stream)
RttiCompleteObjectLocator col
#define SFX_ENDOFSELECTION
int i
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
long Long
sal_Int16 nId
sal_uIntPtr sal_uLong
#define nPixel
@ TABLE_COLUMN_DESCRIPTION_CHANGED
sal_Int64 WinBits
WinBits const WB_3DLOOK