fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svtools / source / brwbox / brwbox1.cxx
blob91e29cfd9efe9e5ee09a22367cac41f74d2bf825
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svtools/brwbox.hxx>
21 #include <svtools/brwhead.hxx>
22 #include "datwin.hxx"
23 #include <tools/debug.hxx>
24 #include <tools/stream.hxx>
26 #include <functional>
27 #include <algorithm>
28 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
29 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/XAccessible.hpp>
32 #include <tools/multisel.hxx>
33 #include "brwimpl.hxx"
35 DBG_NAME(BrowseBox)
37 extern const char* BrowseBoxCheckInvariants( const void* pVoid );
39 #define SCROLL_FLAGS (SCROLL_CLIP | SCROLL_NOCHILDREN)
40 #define getDataWindow() ((BrowserDataWin*)pDataWin)
42 using namespace com::sun::star::accessibility::AccessibleEventId;
43 using namespace com::sun::star::accessibility::AccessibleTableModelChangeType;
44 using com::sun::star::accessibility::AccessibleTableModelChange;
45 using com::sun::star::lang::XComponent;
46 using namespace ::com::sun::star::uno;
47 using namespace svt;
49 //-------------------------------------------------------------------
51 namespace
53 void disposeAndClearHeaderCell(::svt::BrowseBoxImpl::THeaderCellMap& _rHeaderCell)
55 ::std::for_each(
56 _rHeaderCell.begin(),
57 _rHeaderCell.end(),
58 ::svt::BrowseBoxImpl::THeaderCellMapFunctorDispose()
60 _rHeaderCell.clear();
64 //===================================================================
66 void BrowseBox::ConstructImpl( BrowserMode nMode )
68 OSL_TRACE( "BrowseBox: %p->ConstructImpl", this );
69 bMultiSelection = sal_False;
70 pColSel = 0;
71 pDataWin = 0;
72 pVScroll = 0;
74 pDataWin = new BrowserDataWin( this );
75 pCols = new BrowserColumns;
76 m_pImpl.reset( new ::svt::BrowseBoxImpl() );
78 aGridLineColor = Color( COL_LIGHTGRAY );
79 InitSettings_Impl( this );
80 InitSettings_Impl( pDataWin );
82 bBootstrapped = sal_False;
83 nDataRowHeight = 0;
84 nTitleLines = 1;
85 nFirstCol = 0;
86 nTopRow = 0;
87 nCurRow = BROWSER_ENDOFSELECTION;
88 nCurColId = 0;
89 bResizing = sal_False;
90 bSelect = sal_False;
91 bSelecting = sal_False;
92 bScrolling = sal_False;
93 bSelectionIsVisible = sal_False;
94 bNotToggleSel = sal_False;
95 bRowDividerDrag = sal_False;
96 bHit = sal_False;
97 mbInteractiveRowHeight = sal_False;
98 bHideSelect = sal_False;
99 bHideCursor = NO_CURSOR_HIDE;
100 nRowCount = 0;
101 m_bFocusOnlyCursor = sal_True;
102 m_aCursorColor = COL_TRANSPARENT;
103 m_nCurrentMode = 0;
104 nControlAreaWidth = USHRT_MAX;
105 uRow.nSel = BROWSER_ENDOFSELECTION;
107 aHScroll.SetLineSize(1);
108 aHScroll.SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) );
109 aHScroll.SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) );
110 pDataWin->Show();
112 SetMode( nMode );
113 bSelectionIsVisible = bKeepHighlight;
114 bHasFocus = HasChildPathFocus();
115 getDataWindow()->nCursorHidden =
116 ( bHasFocus ? 0 : 1 ) + ( GetUpdateMode() ? 0 : 1 );
119 //-------------------------------------------------------------------
121 BrowseBox::BrowseBox( Window* pParent, WinBits nBits, BrowserMode nMode )
122 :Control( pParent, nBits | WB_3DLOOK )
123 ,DragSourceHelper( this )
124 ,DropTargetHelper( this )
125 ,aHScroll( this, WinBits( WB_HSCROLL ) )
127 DBG_CTOR( BrowseBox, NULL );
128 ConstructImpl( nMode );
131 //-------------------------------------------------------------------
133 BrowseBox::BrowseBox( Window* pParent, const ResId& rId, BrowserMode nMode )
134 :Control( pParent, rId )
135 ,DragSourceHelper( this )
136 ,DropTargetHelper( this )
137 ,aHScroll( this, WinBits(WB_HSCROLL) )
139 DBG_CTOR( BrowseBox, NULL );
140 ConstructImpl(nMode);
142 //-------------------------------------------------------------------
144 BrowseBox::~BrowseBox()
146 DBG_DTOR(BrowseBox,BrowseBoxCheckInvariants);
147 OSL_TRACE( "BrowseBox: %p~", this );
149 if ( m_pImpl->m_pAccessible )
151 disposeAndClearHeaderCell(m_pImpl->m_aColHeaderCellMap);
152 disposeAndClearHeaderCell(m_pImpl->m_aRowHeaderCellMap);
153 m_pImpl->m_pAccessible->dispose();
156 Hide();
157 delete getDataWindow()->pHeaderBar;
158 delete getDataWindow()->pCornerWin;
159 delete pDataWin;
160 delete pVScroll;
162 // free columns-space
163 for ( size_t i = 0, n = pCols->size(); i < n; ++i )
164 delete (*pCols)[ i ];
165 pCols->clear();
166 delete pCols;
167 delete pColSel;
168 if ( bMultiSelection )
169 delete uRow.pSel;
172 //-------------------------------------------------------------------
174 short BrowseBox::GetCursorHideCount() const
176 return getDataWindow()->nCursorHidden;
179 //-------------------------------------------------------------------
181 void BrowseBox::DoShowCursor( const char * )
183 short nHiddenCount = --getDataWindow()->nCursorHidden;
184 if (PaintCursorIfHiddenOnce())
186 if (1 == nHiddenCount)
187 DrawCursor();
189 else
191 if (0 == nHiddenCount)
192 DrawCursor();
196 //-------------------------------------------------------------------
198 void BrowseBox::DoHideCursor( const char * )
200 short nHiddenCount = ++getDataWindow()->nCursorHidden;
201 if (PaintCursorIfHiddenOnce())
203 if (2 == nHiddenCount)
204 DrawCursor();
206 else
208 if (1 == nHiddenCount)
209 DrawCursor();
213 //-------------------------------------------------------------------
215 void BrowseBox::SetRealRowCount( const String &rRealRowCount )
217 getDataWindow()->aRealRowCount = rRealRowCount;
220 //-------------------------------------------------------------------
222 void BrowseBox::SetFont( const Font& rNewFont )
224 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
225 pDataWin->SetFont( rNewFont );
226 ImpGetDataRowHeight();
229 //-------------------------------------------------------------------
231 sal_uLong BrowseBox::GetDefaultColumnWidth( const String& _rText ) const
233 return GetDataWindow().GetTextWidth( _rText ) + GetDataWindow().GetTextWidth(OUString('0')) * 4;
236 //-------------------------------------------------------------------
238 void BrowseBox::InsertHandleColumn( sal_uLong nWidth )
240 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
242 #if OSL_DEBUG_LEVEL > 0
243 OSL_ENSURE( ColCount() == 0 || (*pCols)[0]->GetId() != HandleColumnId , "BrowseBox::InsertHandleColumn: there is already a handle column" );
245 BrowserColumns::iterator iCol = pCols->begin();
246 const BrowserColumns::iterator colsEnd = pCols->end();
247 if ( iCol < colsEnd )
248 for (++iCol; iCol < colsEnd; ++iCol)
249 OSL_ENSURE( (*iCol)->GetId() != HandleColumnId, "BrowseBox::InsertHandleColumn: there is a non-Handle column with handle ID" );
251 #endif
253 pCols->insert( pCols->begin(), new BrowserColumn( 0, Image(), String(), nWidth, GetZoom() ) );
254 FreezeColumn( 0 );
256 // adjust headerbar
257 if ( getDataWindow()->pHeaderBar )
259 getDataWindow()->pHeaderBar->SetPosSizePixel(
260 Point(nWidth, 0),
261 Size( GetOutputSizePixel().Width() - nWidth, GetTitleHeight() )
265 ColumnInserted( 0 );
268 //-------------------------------------------------------------------
270 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId, const XubString& rText,
271 long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos )
273 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
275 OSL_ENSURE( nItemId != HandleColumnId, "BrowseBox::InsertDataColumn: nItemId is HandleColumnId" );
276 OSL_ENSURE( nItemId != BROWSER_INVALIDID, "BrowseBox::InsertDataColumn: nItemId is reserved value BROWSER_INVALIDID" );
278 #if OSL_DEBUG_LEVEL > 0
280 const BrowserColumns::iterator colsEnd = pCols->end();
281 for (BrowserColumns::iterator iCol = pCols->begin(); iCol < colsEnd; ++iCol)
282 OSL_ENSURE( (*iCol)->GetId() != nItemId, "BrowseBox::InsertDataColumn: duplicate column Id" );
284 #endif
286 if ( nPos < pCols->size() )
288 BrowserColumns::iterator it = pCols->begin();
289 ::std::advance( it, nPos );
290 pCols->insert( it, new BrowserColumn( nItemId, Image(), rText, nWidth, GetZoom() ) );
292 else
294 pCols->push_back( new BrowserColumn( nItemId, Image(), rText, nWidth, GetZoom() ) );
296 if ( nCurColId == 0 )
297 nCurColId = nItemId;
299 if ( getDataWindow()->pHeaderBar )
301 // Handle column not in the header bar
302 sal_uInt16 nHeaderPos = nPos;
303 if (nHeaderPos != HEADERBAR_APPEND && GetColumnId(0) == HandleColumnId )
304 nHeaderPos--;
305 getDataWindow()->pHeaderBar->InsertItem(
306 nItemId, rText, nWidth, nBits, nHeaderPos );
308 ColumnInserted( nPos );
311 //-------------------------------------------------------------------
312 sal_uInt16 BrowseBox::ToggleSelectedColumn()
314 sal_uInt16 nSelectedColId = BROWSER_INVALIDID;
315 if ( pColSel && pColSel->GetSelectCount() )
317 DoHideCursor( "ToggleSelectedColumn" );
318 ToggleSelection();
319 nSelectedColId = (*pCols)[ pColSel->FirstSelected() ]->GetId();
320 pColSel->SelectAll(sal_False);
322 return nSelectedColId;
324 // -----------------------------------------------------------------------------
325 void BrowseBox::SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)
327 if ( pColSel && _nSelectedColumnId != BROWSER_INVALIDID )
329 pColSel->Select( GetColumnPos( _nSelectedColumnId ) );
330 ToggleSelection();
331 OSL_TRACE( "BrowseBox: %p->SetToggledSelectedColumn", this );
332 DoShowCursor( "SetToggledSelectedColumn" );
335 // -----------------------------------------------------------------------------
336 void BrowseBox::FreezeColumn( sal_uInt16 nItemId, sal_Bool bFreeze )
338 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
340 // never unfreeze the handle-column
341 if ( nItemId == HandleColumnId && !bFreeze )
342 return;
344 // get the position in the current array
345 size_t nItemPos = GetColumnPos( nItemId );
346 if ( nItemPos >= pCols->size() )
347 // not available!
348 return;
350 // doesn't the state change?
351 if ( (*pCols)[ nItemPos ]->IsFrozen() == bFreeze )
352 return;
354 // remark the column selection
355 sal_uInt16 nSelectedColId = ToggleSelectedColumn();
357 // freeze or unfreeze?
358 if ( bFreeze )
360 // to be moved?
361 if ( nItemPos != 0 && !(*pCols)[ nItemPos-1 ]->IsFrozen() )
363 // move to the right of the last frozen column
364 sal_uInt16 nFirstScrollable = FrozenColCount();
365 BrowserColumn *pColumn = (*pCols)[ nItemPos ];
366 BrowserColumns::iterator it = pCols->begin();
367 ::std::advance( it, nItemPos );
368 pCols->erase( it );
369 nItemPos = nFirstScrollable;
370 it = pCols->begin();
371 ::std::advance( it, nItemPos );
372 pCols->insert( it, pColumn );
375 // adjust the number of the first scrollable and visible column
376 if ( nFirstCol <= nItemPos )
377 nFirstCol = nItemPos + 1;
379 else
381 // to be moved?
382 if ( (sal_Int32)nItemPos != FrozenColCount()-1 )
384 // move to the leftmost scrollable colum
385 sal_uInt16 nFirstScrollable = FrozenColCount();
386 BrowserColumn *pColumn = (*pCols)[ nItemPos ];
387 BrowserColumns::iterator it = pCols->begin();
388 ::std::advance( it, nItemPos );
389 pCols->erase( it );
390 nItemPos = nFirstScrollable;
391 it = pCols->begin();
392 ::std::advance( it, nItemPos );
393 pCols->insert( it, pColumn );
396 // adjust the number of the first scrollable and visible column
397 nFirstCol = nItemPos;
400 // toggle the freeze-state of the column
401 (*pCols)[ nItemPos ]->Freeze( bFreeze );
403 // align the scrollbar-range
404 UpdateScrollbars();
406 // repaint
407 Control::Invalidate();
408 getDataWindow()->Invalidate();
410 // remember the column selection
411 SetToggledSelectedColumn(nSelectedColId);
414 //-------------------------------------------------------------------
416 void BrowseBox::SetColumnPos( sal_uInt16 nColumnId, sal_uInt16 nPos )
418 // never set pos of the handle column
419 if ( nColumnId == HandleColumnId )
420 return;
422 // get the position in the current array
423 sal_uInt16 nOldPos = GetColumnPos( nColumnId );
424 if ( nOldPos >= pCols->size() )
425 // not available!
426 return;
428 // does the state change?
429 if (nOldPos != nPos)
431 // remark the column selection
432 sal_uInt16 nSelectedColId = ToggleSelectedColumn();
434 // determine old column area
435 Size aDataWinSize( pDataWin->GetSizePixel() );
436 if ( getDataWindow()->pHeaderBar )
437 aDataWinSize.Height() += getDataWindow()->pHeaderBar->GetSizePixel().Height();
439 Rectangle aFromRect( GetFieldRect( nColumnId) );
440 aFromRect.Right() += 2*MIN_COLUMNWIDTH;
442 sal_uInt16 nNextPos = nOldPos + 1;
443 if ( nOldPos > nPos )
444 nNextPos = nOldPos - 1;
446 BrowserColumn *pNextCol = (*pCols)[ nNextPos ];
447 Rectangle aNextRect(GetFieldRect( pNextCol->GetId() ));
449 // move column internally
451 BrowserColumns::iterator it = pCols->begin();
452 ::std::advance( it, nOldPos );
453 BrowserColumn* pTemp = *it;
454 pCols->erase( it );
455 it = pCols->begin();
456 ::std::advance( it, nPos );
457 pCols->insert( it, pTemp );
460 // determine new column area
461 Rectangle aToRect( GetFieldRect( nColumnId ) );
462 aToRect.Right() += 2*MIN_COLUMNWIDTH;
464 // do scroll, let redraw
465 if( pDataWin->GetBackground().IsScrollable() )
467 long nScroll = -aFromRect.GetWidth();
468 Rectangle aScrollArea;
469 if ( nOldPos > nPos )
471 long nFrozenWidth = GetFrozenWidth();
472 if ( aToRect.Left() < nFrozenWidth )
473 aToRect.Left() = nFrozenWidth;
474 aScrollArea = Rectangle(Point(aToRect.Left(),0),
475 Point(aNextRect.Right(),aDataWinSize.Height()));
476 nScroll *= -1; // reverse direction
478 else
479 aScrollArea = Rectangle(Point(aNextRect.Left(),0),
480 Point(aToRect.Right(),aDataWinSize.Height()));
482 pDataWin->Scroll( nScroll, 0, aScrollArea );
483 aToRect.Top() = 0;
484 aToRect.Bottom() = aScrollArea.Bottom();
485 Invalidate( aToRect );
487 else
488 pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
490 // adjust header bar positions
491 if ( getDataWindow()->pHeaderBar )
493 sal_uInt16 nNewPos = nPos;
494 if ( GetColumnId(0) == HandleColumnId )
495 --nNewPos;
496 getDataWindow()->pHeaderBar->MoveItem(nColumnId,nNewPos);
498 // remember the column selection
499 SetToggledSelectedColumn(nSelectedColId);
501 if ( isAccessibleAlive() )
503 commitTableEvent(
504 TABLE_MODEL_CHANGED,
505 makeAny( AccessibleTableModelChange(
506 DELETE,
508 GetRowCount(),
509 nOldPos,
510 nOldPos
513 Any()
516 commitTableEvent(
517 TABLE_MODEL_CHANGED,
518 makeAny( AccessibleTableModelChange(
519 INSERT,
521 GetRowCount(),
522 nPos,
523 nPos
526 Any()
533 //-------------------------------------------------------------------
535 void BrowseBox::SetColumnTitle( sal_uInt16 nItemId, const String& rTitle )
537 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
539 // never set title of the handle-column
540 if ( nItemId == HandleColumnId )
541 return;
543 // get the position in the current array
544 sal_uInt16 nItemPos = GetColumnPos( nItemId );
545 if ( nItemPos >= pCols->size() )
546 // not available!
547 return;
549 // does the state change?
550 BrowserColumn *pCol = (*pCols)[ nItemPos ];
551 if ( pCol->Title() != rTitle )
553 OUString sNew(rTitle);
554 OUString sOld(pCol->Title());
556 pCol->Title() = rTitle;
558 // adjust headerbar column
559 if ( getDataWindow()->pHeaderBar )
560 getDataWindow()->pHeaderBar->SetItemText( nItemId, rTitle );
561 else
563 // redraw visible columns
564 if ( GetUpdateMode() && ( pCol->IsFrozen() || nItemPos > nFirstCol ) )
565 Invalidate( Rectangle( Point(0,0),
566 Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
569 if ( isAccessibleAlive() )
571 commitTableEvent( TABLE_COLUMN_DESCRIPTION_CHANGED,
572 makeAny( sNew ),
573 makeAny( sOld )
579 //-------------------------------------------------------------------
581 void BrowseBox::SetColumnWidth( sal_uInt16 nItemId, sal_uLong nWidth )
583 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
585 // get the position in the current array
586 size_t nItemPos = GetColumnPos( nItemId );
587 if ( nItemPos >= pCols->size() )
588 return;
590 // does the state change?
591 nWidth = QueryColumnResize( nItemId, nWidth );
592 if ( nWidth >= LONG_MAX || (*pCols)[ nItemPos ]->Width() != nWidth )
594 long nOldWidth = (*pCols)[ nItemPos ]->Width();
596 // adjust last column, if necessary
597 if ( IsVisible() && nItemPos == pCols->size() - 1 )
599 long nMaxWidth = pDataWin->GetSizePixel().Width();
600 nMaxWidth -= getDataWindow()->bAutoSizeLastCol
601 ? GetFieldRect(nItemId).Left()
602 : GetFrozenWidth();
603 if ( ( (BrowserDataWin*)pDataWin )->bAutoSizeLastCol || nWidth > (sal_uLong)nMaxWidth )
605 nWidth = nMaxWidth > 16 ? nMaxWidth : nOldWidth;
606 nWidth = QueryColumnResize( nItemId, nWidth );
610 // OV
611 // In AutoSizeLastColumn(), we call SetColumnWidth with nWidth==0xffff.
612 // Thus, check here, if the width has actually changed.
613 if( (sal_uLong)nOldWidth == nWidth )
614 return;
616 // do we want to display the change immediately?
617 sal_Bool bUpdate = GetUpdateMode() &&
618 ( (*pCols)[ nItemPos ]->IsFrozen() || nItemPos >= nFirstCol );
620 if ( bUpdate )
622 // Selection hidden
623 DoHideCursor( "SetColumnWidth" );
624 ToggleSelection();
625 //!getDataWindow()->Update();
626 //!Control::Update();
629 // set width
630 (*pCols)[ nItemPos ]->SetWidth(nWidth, GetZoom());
632 // scroll and invalidate
633 if ( bUpdate )
635 // get X-Pos of the column changed
636 long nX = 0;
637 for ( sal_uInt16 nCol = 0; nCol < nItemPos; ++nCol )
639 BrowserColumn *pCol = (*pCols)[ nCol ];
640 if ( pCol->IsFrozen() || nCol >= nFirstCol )
641 nX += pCol->Width();
644 // actually scroll+invalidate
645 pDataWin->SetClipRegion();
646 sal_Bool bSelVis = bSelectionIsVisible;
647 bSelectionIsVisible = sal_False;
648 if( GetBackground().IsScrollable() )
651 Rectangle aScrRect( nX + std::min( (sal_uLong)nOldWidth, nWidth ), 0,
652 GetSizePixel().Width() , // the header is longer than the datawin
653 pDataWin->GetPosPixel().Y() - 1 );
654 Control::Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
655 aScrRect.Bottom() = pDataWin->GetSizePixel().Height();
656 getDataWindow()->Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
657 Rectangle aInvRect( nX, 0, nX + std::max( nWidth, (sal_uLong)nOldWidth ), USHRT_MAX );
658 Control::Invalidate( aInvRect, INVALIDATE_NOCHILDREN );
659 ( (BrowserDataWin*)pDataWin )->Invalidate( aInvRect );
661 else
663 Control::Invalidate( INVALIDATE_NOCHILDREN );
664 getDataWindow()->Window::Invalidate( INVALIDATE_NOCHILDREN );
668 //!getDataWindow()->Update();
669 //!Control::Update();
670 bSelectionIsVisible = bSelVis;
671 ToggleSelection();
672 DoShowCursor( "SetColumnWidth" );
674 UpdateScrollbars();
676 // adjust headerbar column
677 if ( getDataWindow()->pHeaderBar )
678 getDataWindow()->pHeaderBar->SetItemSize(
679 nItemId ? nItemId : USHRT_MAX - 1, nWidth );
681 // adjust last column
682 if ( nItemPos != pCols->size() - 1 )
683 AutoSizeLastColumn();
688 //-------------------------------------------------------------------
690 void BrowseBox::AutoSizeLastColumn()
692 if ( getDataWindow()->bAutoSizeLastCol &&
693 getDataWindow()->GetUpdateMode() )
695 sal_uInt16 nId = GetColumnId( (sal_uInt16)pCols->size() - 1 );
696 SetColumnWidth( nId, LONG_MAX );
697 ColumnResized( nId );
701 //-------------------------------------------------------------------
703 void BrowseBox::RemoveColumn( sal_uInt16 nItemId )
705 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
707 // get column position
708 sal_uInt16 nPos = GetColumnPos(nItemId);
709 if ( nPos >= ColCount() )
710 // not available
711 return;
713 // correct column selection
714 if ( pColSel )
715 pColSel->Remove( nPos );
717 // correct column cursor
718 if ( nCurColId == nItemId )
719 nCurColId = 0;
721 // delete column
722 BrowserColumns::iterator it = pCols->begin();
723 ::std::advance( it, nPos );
724 delete *it;
725 pCols->erase( it );
726 if ( nFirstCol >= nPos && nFirstCol > FrozenColCount() )
728 OSL_ENSURE(nFirstCol > 0,"FirstCol must be greater zero!");
729 --nFirstCol;
732 // handlecolumn not in headerbar
733 if (nItemId)
735 if ( getDataWindow()->pHeaderBar )
736 getDataWindow()->pHeaderBar->RemoveItem( nItemId );
738 else
740 // adjust headerbar
741 if ( getDataWindow()->pHeaderBar )
743 getDataWindow()->pHeaderBar->SetPosSizePixel(
744 Point(0, 0),
745 Size( GetOutputSizePixel().Width(), GetTitleHeight() )
750 // correct vertical scrollbar
751 UpdateScrollbars();
753 // trigger repaint, if necessary
754 if ( GetUpdateMode() )
756 getDataWindow()->Invalidate();
757 Control::Invalidate();
758 if ( getDataWindow()->bAutoSizeLastCol && nPos ==ColCount() )
759 SetColumnWidth( GetColumnId( nPos - 1 ), LONG_MAX );
762 if ( isAccessibleAlive() )
764 commitTableEvent(
765 TABLE_MODEL_CHANGED,
766 makeAny( AccessibleTableModelChange( DELETE,
768 GetRowCount(),
769 nPos,
770 nPos
773 Any()
776 commitHeaderBarEvent(
777 CHILD,
778 Any(),
779 makeAny( CreateAccessibleColumnHeader( nPos ) ),
780 sal_True
785 //-------------------------------------------------------------------
787 void BrowseBox::RemoveColumns()
789 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
791 size_t nOldCount = pCols->size();
793 // remove all columns
794 for ( size_t i = 0; i < nOldCount; ++i )
795 delete (*pCols)[ i ];
796 pCols->clear();
798 // correct column selection
799 if ( pColSel )
801 pColSel->SelectAll(sal_False);
802 pColSel->SetTotalRange( Range( 0, 0 ) );
805 // correct column cursor
806 nCurColId = 0;
807 nFirstCol = 0;
809 if ( getDataWindow()->pHeaderBar )
810 getDataWindow()->pHeaderBar->Clear( );
812 // correct vertical scrollbar
813 UpdateScrollbars();
815 // trigger repaint if necessary
816 if ( GetUpdateMode() )
818 getDataWindow()->Invalidate();
819 Control::Invalidate();
822 if ( isAccessibleAlive() )
824 if ( pCols->size() != nOldCount )
826 // all columns should be removed, so we remove the column header bar and append it again
827 // to avoid to notify every column remove
828 commitBrowseBoxEvent(
829 CHILD,
830 Any(),
831 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_COLUMNHEADERBAR))
834 // and now append it again
835 commitBrowseBoxEvent(
836 CHILD,
837 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_COLUMNHEADERBAR)),
838 Any()
841 // notify a table model change
842 commitTableEvent(
843 TABLE_MODEL_CHANGED,
844 makeAny ( AccessibleTableModelChange( DELETE,
846 GetRowCount(),
848 nOldCount
851 Any()
857 //-------------------------------------------------------------------
859 String BrowseBox::GetColumnTitle( sal_uInt16 nId ) const
861 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
863 sal_uInt16 nItemPos = GetColumnPos( nId );
864 if ( nItemPos >= pCols->size() )
865 return String();
866 return (*pCols)[ nItemPos ]->Title();
869 //-------------------------------------------------------------------
871 long BrowseBox::GetRowCount() const
873 return nRowCount;
876 //-------------------------------------------------------------------
878 sal_uInt16 BrowseBox::ColCount() const
880 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
882 return (sal_uInt16) pCols->size();
885 //-------------------------------------------------------------------
887 long BrowseBox::ImpGetDataRowHeight() const
889 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
891 BrowseBox *pThis = (BrowseBox*)this;
892 pThis->nDataRowHeight = pThis->CalcReverseZoom(pDataWin->GetTextHeight() + 2);
893 pThis->Resize();
894 getDataWindow()->Invalidate();
895 return nDataRowHeight;
898 //-------------------------------------------------------------------
900 void BrowseBox::SetDataRowHeight( long nPixel )
902 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
904 nDataRowHeight = CalcReverseZoom(nPixel);
905 Resize();
906 getDataWindow()->Invalidate();
909 //-------------------------------------------------------------------
911 void BrowseBox::SetTitleLines( sal_uInt16 nLines )
913 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
915 nTitleLines = nLines;
918 //-------------------------------------------------------------------
920 long BrowseBox::ScrollColumns( long nCols )
922 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
924 if ( nFirstCol + nCols < 0 ||
925 nFirstCol + nCols >= (long)pCols->size() )
926 return 0;
928 // implicitly hides cursor while scrolling
929 StartScroll();
930 bScrolling = sal_True;
931 sal_Bool bScrollable = pDataWin->GetBackground().IsScrollable();
932 sal_Bool bInvalidateView = sal_False;
934 // scrolling one column to the right?
935 if ( nCols == 1 )
937 // update internal value and scrollbar
938 ++nFirstCol;
939 aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
941 if ( !bScrollable )
943 bInvalidateView = sal_True;
945 else
947 long nDelta = (*pCols)[ nFirstCol-1 ]->Width();
948 long nFrozenWidth = GetFrozenWidth();
950 Rectangle aScrollRect( Point( nFrozenWidth + nDelta, 0 ),
951 Size ( GetOutputSizePixel().Width() - nFrozenWidth - nDelta,
952 GetTitleHeight() - 1
953 ) );
955 // scroll the header bar area (if there is no dedicated HeaderBar control)
956 if ( !getDataWindow()->pHeaderBar && nTitleLines )
958 // actually scroll
959 Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
961 // invalidate the area of the column which was scrolled out to the left hand side
962 Rectangle aInvalidateRect( aScrollRect );
963 aInvalidateRect.Left() = nFrozenWidth;
964 aInvalidateRect.Right() = nFrozenWidth + nDelta - 1;
965 Invalidate( aInvalidateRect );
968 // scroll the data-area
969 aScrollRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
971 // actually scroll
972 pDataWin->Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
974 // invalidate the area of the column which was scrolled out to the left hand side
975 aScrollRect.Left() = nFrozenWidth;
976 aScrollRect.Right() = nFrozenWidth + nDelta - 1;
977 getDataWindow()->Invalidate( aScrollRect );
981 // scrolling one column to the left?
982 else if ( nCols == -1 )
984 --nFirstCol;
985 aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
987 if ( !bScrollable )
989 bInvalidateView = sal_True;
991 else
993 long nDelta = (*pCols)[ nFirstCol ]->Width();
994 long nFrozenWidth = GetFrozenWidth();
996 Rectangle aScrollRect( Point( nFrozenWidth, 0 ),
997 Size ( GetOutputSizePixel().Width() - nFrozenWidth,
998 GetTitleHeight() - 1
999 ) );
1001 // scroll the header bar area (if there is no dedicated HeaderBar control)
1002 if ( !getDataWindow()->pHeaderBar && nTitleLines )
1004 Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
1007 // scroll the data-area
1008 aScrollRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
1009 pDataWin->Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
1012 else
1014 if ( GetUpdateMode() )
1016 Invalidate( Rectangle(
1017 Point( GetFrozenWidth(), 0 ),
1018 Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
1019 getDataWindow()->Invalidate( Rectangle(
1020 Point( GetFrozenWidth(), 0 ),
1021 pDataWin->GetSizePixel() ) );
1024 nFirstCol = nFirstCol + (sal_uInt16)nCols;
1025 aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1028 // adjust external headerbar, if necessary
1029 if ( getDataWindow()->pHeaderBar )
1031 long nWidth = 0;
1032 for ( size_t nCol = 0;
1033 nCol < pCols->size() && nCol < nFirstCol;
1034 ++nCol )
1036 // not the handle column
1037 if ( (*pCols)[ nCol ]->GetId() )
1038 nWidth += (*pCols)[ nCol ]->Width();
1041 getDataWindow()->pHeaderBar->SetOffset( nWidth );
1044 if( bInvalidateView )
1046 Control::Invalidate( INVALIDATE_NOCHILDREN );
1047 pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1050 // implicitly show cursor after scrolling
1051 if ( nCols )
1053 getDataWindow()->Update();
1054 Update();
1056 bScrolling = sal_False;
1057 EndScroll();
1059 return nCols;
1062 //-------------------------------------------------------------------
1064 long BrowseBox::ScrollRows( long nRows )
1066 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1068 // out of range?
1069 if ( getDataWindow()->bNoScrollBack && nRows < 0 )
1070 return 0;
1072 // compute new top row
1073 long nTmpMin = std::min( (long)(nTopRow + nRows), (long)(nRowCount - 1) );
1075 long nNewTopRow = std::max( (long)nTmpMin, (long)0 );
1077 if ( nNewTopRow == nTopRow )
1078 return 0;
1080 sal_uInt16 nVisibleRows =
1081 (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1083 VisibleRowsChanged(nNewTopRow, nVisibleRows);
1085 // compute new top row again (nTopRow might have changed!)
1086 nTmpMin = std::min( (long)(nTopRow + nRows), (long)(nRowCount - 1) );
1088 nNewTopRow = std::max( (long)nTmpMin, (long)0 );
1090 StartScroll();
1092 // scroll area on screen and/or repaint
1093 long nDeltaY = GetDataRowHeight() * ( nNewTopRow - nTopRow );
1094 long nOldTopRow = nTopRow;
1095 nTopRow = nNewTopRow;
1097 if ( GetUpdateMode() )
1099 pVScroll->SetRange( Range( 0L, nRowCount ) );
1100 pVScroll->SetThumbPos( nTopRow );
1102 if( pDataWin->GetBackground().IsScrollable() &&
1103 std::abs( nDeltaY ) > 0 &&
1104 std::abs( nDeltaY ) < pDataWin->GetSizePixel().Height() )
1106 pDataWin->Scroll( 0, (short)-nDeltaY, SCROLL_FLAGS );
1108 else
1109 getDataWindow()->Invalidate();
1111 if ( nTopRow - nOldTopRow )
1112 getDataWindow()->Update();
1115 EndScroll();
1117 return nTopRow - nOldTopRow;
1120 //-------------------------------------------------------------------
1122 void BrowseBox::RowModified( long nRow, sal_uInt16 nColId )
1124 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1126 if ( !GetUpdateMode() )
1127 return;
1129 Rectangle aRect;
1130 if ( nColId == BROWSER_INVALIDID )
1131 // invalidate the whole row
1132 aRect = Rectangle( Point( 0, (nRow-nTopRow) * GetDataRowHeight() ),
1133 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1134 else
1136 // invalidate the specific field
1137 aRect = GetFieldRectPixel( nRow, nColId, sal_False );
1139 getDataWindow()->Invalidate( aRect );
1142 //-------------------------------------------------------------------
1144 void BrowseBox::Clear()
1146 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1148 // adjust the total number of rows
1149 DoHideCursor( "Clear" );
1150 long nOldRowCount = nRowCount;
1151 nRowCount = 0;
1152 if(bMultiSelection)
1154 assert(uRow.pSel);
1155 *uRow.pSel = MultiSelection();
1157 else
1158 uRow.nSel = BROWSER_ENDOFSELECTION;
1159 nCurRow = BROWSER_ENDOFSELECTION;
1160 nTopRow = 0;
1161 nCurColId = 0;
1163 // nFirstCol may not be reset, else the scrolling code will become confused.
1164 // nFirstCol may only be changed when adding or deleting columns
1165 // nFirstCol = 0; -> wrong!
1166 aHScroll.SetThumbPos( 0 );
1167 pVScroll->SetThumbPos( 0 );
1169 Invalidate();
1170 UpdateScrollbars();
1171 SetNoSelection();
1172 DoShowCursor( "Clear" );
1173 CursorMoved();
1175 if ( isAccessibleAlive() )
1177 // all rows should be removed, so we remove the row header bar and append it again
1178 // to avoid to notify every row remove
1179 if ( nOldRowCount != nRowCount )
1181 commitBrowseBoxEvent(
1182 CHILD,
1183 Any(),
1184 makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) )
1187 // and now append it again
1188 commitBrowseBoxEvent(
1189 CHILD,
1190 makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) ),
1191 Any()
1194 // notify a table model change
1195 commitTableEvent(
1196 TABLE_MODEL_CHANGED,
1197 makeAny( AccessibleTableModelChange( DELETE,
1199 nOldRowCount,
1201 GetColumnCount())
1203 Any()
1208 // -----------------------------------------------------------------------------
1209 void BrowseBox::RowInserted( long nRow, long nNumRows, sal_Bool bDoPaint, sal_Bool bKeepSelection )
1211 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1213 if (nRow < 0)
1214 nRow = 0;
1215 else if (nRow > nRowCount) // maximal = nRowCount
1216 nRow = nRowCount;
1218 if ( nNumRows <= 0 )
1219 return;
1221 // adjust total row count
1222 sal_Bool bLastRow = nRow >= nRowCount;
1223 nRowCount += nNumRows;
1225 DoHideCursor( "RowInserted" );
1227 // must we paint the new rows?
1228 long nOldCurRow = nCurRow;
1229 Size aSz = pDataWin->GetOutputSizePixel();
1230 if ( bDoPaint && nRow >= nTopRow &&
1231 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1233 long nY = (nRow-nTopRow) * GetDataRowHeight();
1234 if ( !bLastRow )
1236 // scroll down the rows behind the new row
1237 pDataWin->SetClipRegion();
1238 if( pDataWin->GetBackground().IsScrollable() )
1240 pDataWin->Scroll( 0, GetDataRowHeight() * nNumRows,
1241 Rectangle( Point( 0, nY ),
1242 Size( aSz.Width(), aSz.Height() - nY ) ),
1243 SCROLL_FLAGS );
1245 else
1246 pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1248 else
1249 // scroll would cause a repaint, so we must explicitly invalidate
1250 pDataWin->Invalidate( Rectangle( Point( 0, nY ),
1251 Size( aSz.Width(), nNumRows * GetDataRowHeight() ) ) );
1254 // correct top row if necessary
1255 if ( nRow < nTopRow )
1256 nTopRow += nNumRows;
1258 // adjust the selection
1259 if ( bMultiSelection )
1260 uRow.pSel->Insert( nRow, nNumRows );
1261 else if ( uRow.nSel != BROWSER_ENDOFSELECTION && nRow <= uRow.nSel )
1262 uRow.nSel += nNumRows;
1264 // adjust the cursor
1265 if ( nCurRow == BROWSER_ENDOFSELECTION )
1266 GoToRow( 0, sal_False, bKeepSelection );
1267 else if ( nRow <= nCurRow )
1268 GoToRow( nCurRow += nNumRows, sal_False, bKeepSelection );
1270 // adjust the vertical scrollbar
1271 if ( bDoPaint )
1273 UpdateScrollbars();
1274 AutoSizeLastColumn();
1277 DoShowCursor( "RowInserted" );
1278 // notify accessible that rows were inserted
1279 if ( isAccessibleAlive() )
1281 commitTableEvent(
1282 TABLE_MODEL_CHANGED,
1283 makeAny( AccessibleTableModelChange(
1284 INSERT,
1285 nRow,
1286 nRow + nNumRows,
1288 GetColumnCount()
1291 Any()
1294 for (sal_Int32 i = nRow+1 ; i <= nRowCount ; ++i)
1296 commitHeaderBarEvent(
1297 CHILD,
1298 makeAny( CreateAccessibleRowHeader( i ) ),
1299 Any(),
1300 sal_False
1305 if ( nCurRow != nOldCurRow )
1306 CursorMoved();
1308 DBG_ASSERT(nRowCount > 0,"BrowseBox: nRowCount <= 0");
1309 DBG_ASSERT(nCurRow >= 0,"BrowseBox: nCurRow < 0");
1310 DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1313 //-------------------------------------------------------------------
1315 void BrowseBox::RowRemoved( long nRow, long nNumRows, sal_Bool bDoPaint )
1317 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1319 if ( nRow < 0 )
1320 nRow = 0;
1321 else if ( nRow >= nRowCount )
1322 nRow = nRowCount - 1;
1324 if ( nNumRows <= 0 )
1325 return;
1327 if ( nRowCount <= 0 )
1328 return;
1330 if ( bDoPaint )
1332 // hide cursor and selection
1333 OSL_TRACE( "BrowseBox: %p->HideCursor", this );
1334 ToggleSelection();
1335 DoHideCursor( "RowRemoved" );
1338 // adjust total row count
1339 nRowCount -= nNumRows;
1340 if (nRowCount < 0) nRowCount = 0;
1341 long nOldCurRow = nCurRow;
1343 // adjust the selection
1344 if ( bMultiSelection )
1345 // uRow.pSel->Remove( nRow, nNumRows );
1346 for ( long i = 0; i < nNumRows; i++ )
1347 uRow.pSel->Remove( nRow );
1348 else if ( nRow < uRow.nSel && uRow.nSel >= nNumRows )
1349 uRow.nSel -= nNumRows;
1350 else if ( nRow <= uRow.nSel )
1351 uRow.nSel = BROWSER_ENDOFSELECTION;
1353 // adjust the cursor
1354 if ( nRowCount == 0 ) // don't compare nRowCount with nNumRows as nNumRows already was subtracted from nRowCount
1355 nCurRow = BROWSER_ENDOFSELECTION;
1356 else if ( nRow < nCurRow )
1358 nCurRow -= std::min( nCurRow - nRow, nNumRows );
1359 // with the above nCurRow points a) to the first row after the removed block or b) to the same line
1360 // as before, but moved up nNumRows
1361 // case a) needs an additional correction if the last n lines were deleted, as 'the first row after the
1362 // removed block' is an invalid position then
1363 // FS - 09/28/99 - 68429
1364 if (nCurRow == nRowCount)
1365 --nCurRow;
1367 else if( nRow == nCurRow && nCurRow == nRowCount )
1368 nCurRow = nRowCount-1;
1370 // is the deleted row visible?
1371 Size aSz = pDataWin->GetOutputSizePixel();
1372 if ( nRow >= nTopRow &&
1373 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1375 if ( bDoPaint )
1377 // scroll up the rows behind the deleted row
1378 // if there are Rows behind
1379 if (nRow < nRowCount)
1381 long nY = (nRow-nTopRow) * GetDataRowHeight();
1382 pDataWin->SetClipRegion();
1383 if( pDataWin->GetBackground().IsScrollable() )
1385 pDataWin->Scroll( 0, - (short) GetDataRowHeight() * nNumRows,
1386 Rectangle( Point( 0, nY ), Size( aSz.Width(),
1387 aSz.Height() - nY + nNumRows*GetDataRowHeight() ) ),
1388 SCROLL_FLAGS );
1390 else
1391 pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1393 else
1395 // Repaint the Rect of the deleted row
1396 Rectangle aRect(
1397 Point( 0, (nRow-nTopRow)*GetDataRowHeight() ),
1398 Size( pDataWin->GetSizePixel().Width(),
1399 nNumRows * GetDataRowHeight() ) );
1400 pDataWin->Invalidate( aRect );
1404 // is the deleted row above of the visible area?
1405 else if ( nRow < nTopRow )
1406 nTopRow = nTopRow >= nNumRows ? nTopRow-nNumRows : 0;
1408 if ( bDoPaint )
1410 // reshow cursor and selection
1411 ToggleSelection();
1412 OSL_TRACE( "BrowseBox: %p->ShowCursor", this );
1413 DoShowCursor( "RowRemoved" );
1415 // adjust the vertical scrollbar
1416 UpdateScrollbars();
1417 AutoSizeLastColumn();
1420 if ( isAccessibleAlive() )
1422 if ( nRowCount == 0 )
1424 // all columns should be removed, so we remove the column header bar and append it again
1425 // to avoid to notify every column remove
1426 commitBrowseBoxEvent(
1427 CHILD,
1428 Any(),
1429 makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) )
1432 // and now append it again
1433 commitBrowseBoxEvent(
1434 CHILD,
1435 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_ROWHEADERBAR)),
1436 Any()
1438 commitBrowseBoxEvent(
1439 CHILD,
1440 Any(),
1441 makeAny( m_pImpl->getAccessibleTable() )
1444 // and now append it again
1445 commitBrowseBoxEvent(
1446 CHILD,
1447 makeAny( m_pImpl->getAccessibleTable() ),
1448 Any()
1451 else
1453 commitTableEvent(
1454 TABLE_MODEL_CHANGED,
1455 makeAny( AccessibleTableModelChange(
1456 DELETE,
1457 nRow,
1458 nRow + nNumRows,
1460 GetColumnCount()
1463 Any()
1466 for (sal_Int32 i = nRow+1 ; i <= (nRow+nNumRows) ; ++i)
1468 commitHeaderBarEvent(
1469 CHILD,
1470 Any(),
1471 makeAny( CreateAccessibleRowHeader( i ) ),
1472 sal_False
1478 if ( nOldCurRow != nCurRow )
1479 CursorMoved();
1481 DBG_ASSERT(nRowCount >= 0,"BrowseBox: nRowCount < 0");
1482 DBG_ASSERT(nCurRow >= 0 || nRowCount == 0,"BrowseBox: nCurRow < 0 && nRowCount != 0");
1483 DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1486 //-------------------------------------------------------------------
1488 sal_Bool BrowseBox::GoToRow( long nRow)
1490 return GoToRow(nRow, sal_False, sal_False);
1493 //-------------------------------------------------------------------
1495 sal_Bool BrowseBox::GoToRow( long nRow, sal_Bool bRowColMove, sal_Bool bKeepSelection )
1497 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1499 long nOldCurRow = nCurRow;
1501 // nothing to do?
1502 if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) )
1503 return sal_True;
1505 // out of range?
1506 if ( nRow < 0 || nRow >= nRowCount )
1507 return sal_False;
1509 // not allowed?
1510 if ( ( !bRowColMove && !IsCursorMoveAllowed( nRow, nCurColId ) ) )
1511 return sal_False;
1513 if ( getDataWindow()->bNoScrollBack && nRow < nTopRow )
1514 nRow = nTopRow;
1516 // compute the last visible row
1517 Size aSz( pDataWin->GetSizePixel() );
1518 sal_uInt16 nVisibleRows = sal_uInt16( aSz.Height() / GetDataRowHeight() - 1 );
1519 long nLastRow = nTopRow + nVisibleRows;
1521 // suspend Updates
1522 getDataWindow()->EnterUpdateLock();
1524 // remove old highlight, if necessary
1525 if ( !bMultiSelection && !bKeepSelection )
1526 ToggleSelection();
1527 DoHideCursor( "GoToRow" );
1529 // must we scroll?
1530 sal_Bool bWasVisible = bSelectionIsVisible;
1531 if (! bMultiSelection)
1533 if( !bKeepSelection )
1534 bSelectionIsVisible = sal_False;
1536 if ( nRow < nTopRow )
1537 ScrollRows( nRow - nTopRow );
1538 else if ( nRow > nLastRow )
1539 ScrollRows( nRow - nLastRow );
1540 bSelectionIsVisible = bWasVisible;
1542 // adjust cursor (selection) and thumb
1543 if ( GetUpdateMode() )
1544 pVScroll->SetThumbPos( nTopRow );
1546 // relative positioning (because nCurRow might have changed in the meantime)!
1547 if (nCurRow != BROWSER_ENDOFSELECTION )
1548 nCurRow = nCurRow + (nRow - nOldCurRow);
1550 // make sure that the current position is valid
1551 if (nCurRow == BROWSER_ENDOFSELECTION && nRowCount > 0)
1552 nCurRow = 0;
1553 else if ( nCurRow >= nRowCount )
1554 nCurRow = nRowCount - 1;
1555 aSelRange = Range( nCurRow, nCurRow );
1557 // display new highlight if necessary
1558 if ( !bMultiSelection && !bKeepSelection )
1559 uRow.nSel = nRow;
1561 // resume Updates
1562 getDataWindow()->LeaveUpdateLock();
1564 // Cursor+Highlight
1565 if ( !bMultiSelection && !bKeepSelection)
1566 ToggleSelection();
1567 DoShowCursor( "GoToRow" );
1568 if ( !bRowColMove && nOldCurRow != nCurRow )
1569 CursorMoved();
1571 if ( !bMultiSelection && !bKeepSelection )
1573 if ( !bSelecting )
1574 Select();
1575 else
1576 bSelect = sal_True;
1578 return sal_True;
1581 //-------------------------------------------------------------------
1583 sal_Bool BrowseBox::GoToColumnId( sal_uInt16 nColId)
1585 return GoToColumnId(nColId,sal_True,sal_False);
1589 sal_Bool BrowseBox::GoToColumnId( sal_uInt16 nColId, sal_Bool bMakeVisible, sal_Bool bRowColMove)
1591 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1593 if (!bColumnCursor)
1594 return sal_False;
1596 // allowed?
1597 if (!bRowColMove && !IsCursorMoveAllowed( nCurRow, nColId ) )
1598 return sal_False;
1600 if ( nColId != nCurColId || (bMakeVisible && !IsFieldVisible(nCurRow, nColId, sal_True)))
1602 sal_uInt16 nNewPos = GetColumnPos(nColId);
1603 BrowserColumn* pColumn = (nNewPos < pCols->size()) ? (*pCols)[ nNewPos ] : NULL;
1604 DBG_ASSERT( pColumn, "no column object - invalid id?" );
1605 if ( !pColumn )
1606 return sal_False;
1608 DoHideCursor( "GoToColumnId" );
1609 nCurColId = nColId;
1611 sal_uInt16 nFirstPos = nFirstCol;
1612 sal_uInt16 nWidth = (sal_uInt16)pColumn->Width();
1613 sal_uInt16 nLastPos = GetColumnAtXPosPixel(
1614 pDataWin->GetSizePixel().Width()-nWidth, sal_False );
1615 sal_uInt16 nFrozen = FrozenColCount();
1616 if ( bMakeVisible && nLastPos &&
1617 nNewPos >= nFrozen && ( nNewPos < nFirstPos || nNewPos > nLastPos ) )
1619 if ( nNewPos < nFirstPos )
1620 ScrollColumns( nNewPos-nFirstPos );
1621 else if ( nNewPos > nLastPos )
1622 ScrollColumns( nNewPos-nLastPos );
1625 DoShowCursor( "GoToColumnId" );
1626 if (!bRowColMove)
1627 CursorMoved();
1628 return sal_True;
1630 return sal_True;
1633 //-------------------------------------------------------------------
1635 sal_Bool BrowseBox::GoToRowColumnId( long nRow, sal_uInt16 nColId )
1637 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1639 // out of range?
1640 if ( nRow < 0 || nRow >= nRowCount )
1641 return sal_False;
1643 if (!bColumnCursor)
1644 return sal_False;
1646 // nothing to do ?
1647 if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) &&
1648 nColId == nCurColId && IsFieldVisible(nCurRow, nColId, sal_True))
1649 return sal_True;
1651 // allowed?
1652 if (!IsCursorMoveAllowed(nRow, nColId))
1653 return sal_False;
1655 DoHideCursor( "GoToRowColumnId" );
1656 sal_Bool bMoved = GoToRow(nRow, sal_True) && GoToColumnId(nColId, sal_True, sal_True);
1657 DoShowCursor( "GoToRowColumnId" );
1659 if (bMoved)
1660 CursorMoved();
1662 return bMoved;
1665 //-------------------------------------------------------------------
1667 void BrowseBox::SetNoSelection()
1669 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1671 // is there no selection
1672 if ( ( !pColSel || !pColSel->GetSelectCount() ) &&
1673 ( ( !bMultiSelection && uRow.nSel == BROWSER_ENDOFSELECTION ) ||
1674 ( bMultiSelection && !uRow.pSel->GetSelectCount() ) ) )
1675 // nothing to do
1676 return;
1678 OSL_TRACE( "BrowseBox: %p->HideCursor", this );
1679 ToggleSelection();
1681 // unselect all
1682 if ( bMultiSelection )
1683 uRow.pSel->SelectAll(sal_False);
1684 else
1685 uRow.nSel = BROWSER_ENDOFSELECTION;
1686 if ( pColSel )
1687 pColSel->SelectAll(sal_False);
1688 if ( !bSelecting )
1689 Select();
1690 else
1691 bSelect = sal_True;
1693 // restore screen
1694 OSL_TRACE( "BrowseBox: %p->ShowCursor", this );
1696 if ( isAccessibleAlive() )
1698 commitTableEvent(
1699 SELECTION_CHANGED,
1700 Any(),
1701 Any()
1706 //-------------------------------------------------------------------
1708 void BrowseBox::SelectAll()
1710 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1712 if ( !bMultiSelection )
1713 return;
1715 OSL_TRACE( "BrowseBox: %p->HideCursor", this );
1716 ToggleSelection();
1718 // select all rows
1719 if ( pColSel )
1720 pColSel->SelectAll(sal_False);
1721 uRow.pSel->SelectAll(sal_True);
1723 // don't highlight handle column
1724 BrowserColumn *pFirstCol = (*pCols)[ 0 ];
1725 long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1727 // highlight the row selection
1728 if ( !bHideSelect )
1730 Rectangle aHighlightRect;
1731 sal_uInt16 nVisibleRows =
1732 (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1733 for ( long nRow = std::max( nTopRow, uRow.pSel->FirstSelected() );
1734 nRow != BROWSER_ENDOFSELECTION && nRow < nTopRow + nVisibleRows;
1735 nRow = uRow.pSel->NextSelected() )
1736 aHighlightRect.Union( Rectangle(
1737 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1738 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) ) );
1739 pDataWin->Invalidate( aHighlightRect );
1742 if ( !bSelecting )
1743 Select();
1744 else
1745 bSelect = sal_True;
1747 // restore screen
1748 OSL_TRACE( "BrowseBox: %p->ShowCursor", this );
1750 if ( isAccessibleAlive() )
1752 commitTableEvent(
1753 SELECTION_CHANGED,
1754 Any(),
1755 Any()
1757 commitHeaderBarEvent(
1758 SELECTION_CHANGED,
1759 Any(),
1760 Any(),
1761 sal_True
1762 ); // column header event
1764 commitHeaderBarEvent(
1765 SELECTION_CHANGED,
1766 Any(),
1767 Any(),
1768 sal_False
1769 ); // row header event
1773 //-------------------------------------------------------------------
1775 void BrowseBox::SelectRow( long nRow, sal_Bool _bSelect, sal_Bool bExpand )
1777 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1779 if ( !bMultiSelection )
1781 // deselecting is impossible, selecting via cursor
1782 if ( _bSelect )
1783 GoToRow(nRow, sal_False);
1784 return;
1787 OSL_TRACE( "BrowseBox: %p->HideCursor", this );
1789 // remove old selection?
1790 if ( !bExpand || !bMultiSelection )
1792 ToggleSelection();
1793 if ( bMultiSelection )
1794 uRow.pSel->SelectAll(sal_False);
1795 else
1796 uRow.nSel = BROWSER_ENDOFSELECTION;
1797 if ( pColSel )
1798 pColSel->SelectAll(sal_False);
1801 // set new selection
1802 if ( !bHideSelect
1803 && ( ( bMultiSelection
1804 && uRow.pSel->GetTotalRange().Max() >= nRow
1805 && uRow.pSel->Select( nRow, _bSelect )
1807 || ( !bMultiSelection
1808 && ( uRow.nSel = nRow ) != BROWSER_ENDOFSELECTION )
1812 // don't highlight handle column
1813 BrowserColumn *pFirstCol = (*pCols)[ 0 ];
1814 long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1816 // highlight only newly selected part
1817 Rectangle aRect(
1818 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1819 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1820 pDataWin->Invalidate( aRect );
1823 if ( !bSelecting )
1824 Select();
1825 else
1826 bSelect = sal_True;
1828 // restore screen
1829 OSL_TRACE( "BrowseBox: %p->ShowCursor", this );
1831 if ( isAccessibleAlive() )
1833 commitTableEvent(
1834 SELECTION_CHANGED,
1835 Any(),
1836 Any()
1838 commitHeaderBarEvent(
1839 SELECTION_CHANGED,
1840 Any(),
1841 Any(),
1842 sal_False
1843 ); // row header event
1847 //-------------------------------------------------------------------
1849 long BrowseBox::GetSelectRowCount() const
1851 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1853 return bMultiSelection ? uRow.pSel->GetSelectCount() :
1854 uRow.nSel == BROWSER_ENDOFSELECTION ? 0 : 1;
1857 //-------------------------------------------------------------------
1859 void BrowseBox::SelectColumnPos( sal_uInt16 nNewColPos, sal_Bool _bSelect, sal_Bool bMakeVisible )
1861 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1863 if ( !bColumnCursor || nNewColPos == BROWSER_INVALIDID )
1864 return;
1866 if ( !bMultiSelection )
1868 if ( _bSelect )
1869 GoToColumnId( (*pCols)[ nNewColPos ]->GetId(), bMakeVisible );
1870 return;
1872 else
1874 if ( !GoToColumnId( (*pCols)[ nNewColPos ]->GetId(), bMakeVisible ) )
1875 return;
1878 OSL_TRACE( "BrowseBox: %p->HideCursor", this );
1879 ToggleSelection();
1880 if ( bMultiSelection )
1881 uRow.pSel->SelectAll(sal_False);
1882 else
1883 uRow.nSel = BROWSER_ENDOFSELECTION;
1884 pColSel->SelectAll(sal_False);
1886 if ( pColSel->Select( nNewColPos, _bSelect ) )
1888 // GoToColumnId( pCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
1890 // only highlight painted areas
1891 pDataWin->Update();
1892 Rectangle aFieldRectPix( GetFieldRectPixel( nCurRow, nCurColId, sal_False ) );
1893 Rectangle aRect(
1894 Point( aFieldRectPix.Left() - MIN_COLUMNWIDTH, 0 ),
1895 Size( (*pCols)[ nNewColPos ]->Width(),
1896 pDataWin->GetOutputSizePixel().Height() ) );
1897 pDataWin->Invalidate( aRect );
1898 if ( !bSelecting )
1899 Select();
1900 else
1901 bSelect = sal_True;
1903 if ( isAccessibleAlive() )
1905 commitTableEvent(
1906 SELECTION_CHANGED,
1907 Any(),
1908 Any()
1910 commitHeaderBarEvent(
1911 SELECTION_CHANGED,
1912 Any(),
1913 Any(),
1914 sal_True
1915 ); // column header event
1919 // restore screen
1920 OSL_TRACE( "BrowseBox: %p->ShowCursor", this );
1923 //-------------------------------------------------------------------
1925 sal_uInt16 BrowseBox::GetSelectColumnCount() const
1927 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1929 // while bAutoSelect (==!pColSel), 1 if any rows (yes rows!) else none
1930 return pColSel ? (sal_uInt16) pColSel->GetSelectCount() :
1931 nCurRow >= 0 ? 1 : 0;
1934 //-------------------------------------------------------------------
1935 long BrowseBox::FirstSelectedColumn( ) const
1937 return pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
1940 //-------------------------------------------------------------------
1942 long BrowseBox::FirstSelectedRow( sal_Bool bInverse )
1944 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1946 return bMultiSelection ? uRow.pSel->FirstSelected(bInverse) : uRow.nSel;
1949 //-------------------------------------------------------------------
1951 long BrowseBox::NextSelectedRow()
1953 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1955 return bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION;
1958 //-------------------------------------------------------------------
1960 long BrowseBox::LastSelectedRow()
1962 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1964 return bMultiSelection ? uRow.pSel->LastSelected() : uRow.nSel;
1967 //-------------------------------------------------------------------
1969 bool BrowseBox::IsRowSelected( long nRow ) const
1971 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1973 return bMultiSelection ? uRow.pSel->IsSelected(nRow) : nRow == uRow.nSel;
1976 //-------------------------------------------------------------------
1978 bool BrowseBox::IsColumnSelected( sal_uInt16 nColumnId ) const
1980 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1982 return pColSel ? pColSel->IsSelected( GetColumnPos(nColumnId) ) :
1983 nCurColId == nColumnId;
1986 //-------------------------------------------------------------------
1988 sal_Bool BrowseBox::MakeFieldVisible
1990 long nRow, // line number of the field (starting with 0)
1991 sal_uInt16 nColId, // column ID of the field
1992 sal_Bool bComplete // (== sal_False), sal_True => make visible in its entirety
1995 /* [Description]
1997 Makes visible the field described in 'nRow' and 'nColId' by scrolling
1998 accordingly. If 'bComplete' is set, the field should become visible in its
1999 entirety.
2001 [Returned Value]
2003 sal_Bool sal_True
2004 The given field is already visible or was already visible.
2006 sal_False
2007 The given field could not be made visible or in the case of
2008 'bComplete' could not be made visible in its entirety.
2012 Size aTestSize = pDataWin->GetSizePixel();
2014 if ( !bBootstrapped ||
2015 ( aTestSize.Width() == 0 && aTestSize.Height() == 0 ) )
2016 return sal_False;
2018 // is it visible already?
2019 sal_Bool bVisible = IsFieldVisible( nRow, nColId, bComplete );
2020 if ( bVisible )
2021 return sal_True;
2023 // calculate column position, field rectangle and painting area
2024 sal_uInt16 nColPos = GetColumnPos( nColId );
2025 Rectangle aFieldRect = GetFieldRectPixel( nRow, nColId, sal_False );
2026 Rectangle aDataRect = Rectangle( Point(0, 0), pDataWin->GetSizePixel() );
2028 // positioned outside on the left?
2029 if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
2030 // => scroll to the right
2031 ScrollColumns( nColPos - nFirstCol );
2033 // while outside on the right
2034 while ( aDataRect.Right() < ( bComplete
2035 ? aFieldRect.Right()
2036 : aFieldRect.Left()+aFieldRect.GetWidth()/2 ) )
2038 // => scroll to the left
2039 if ( ScrollColumns( 1 ) != 1 )
2040 // no more need to scroll
2041 break;
2042 aFieldRect = GetFieldRectPixel( nRow, nColId, sal_False );
2045 // positioned outside above?
2046 if ( nRow < nTopRow )
2047 // scroll further to the bottom
2048 ScrollRows( nRow - nTopRow );
2050 // positioned outside below?
2051 long nBottomRow = nTopRow + GetVisibleRows();
2052 // decrement nBottomRow to make it the number of the last visible line
2053 // (count starts with 0!).
2054 // Example: BrowseBox contains exactly one entry. nBottomRow := 0 + 1 - 1
2055 if( nBottomRow )
2056 nBottomRow--;
2058 if ( nRow > nBottomRow )
2059 // scroll further to the top
2060 ScrollRows( nRow - nBottomRow );
2062 // it might still not actually fit, e.g. if the window is too small
2063 return IsFieldVisible( nRow, nColId, bComplete );
2066 //-------------------------------------------------------------------
2068 sal_Bool BrowseBox::IsFieldVisible( long nRow, sal_uInt16 nColumnId,
2069 sal_Bool bCompletely ) const
2071 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2073 // hidden by frozen column?
2074 sal_uInt16 nColPos = GetColumnPos( nColumnId );
2075 if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
2076 return sal_False;
2078 Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2079 if ( aRect.IsEmpty() )
2080 return sal_False;
2082 // get the visible area
2083 Rectangle aOutRect( Point(0, 0), pDataWin->GetOutputSizePixel() );
2085 if ( bCompletely )
2086 // test if the field is completely visible
2087 return aOutRect.IsInside( aRect );
2088 else
2089 // test if the field is partly of completely visible
2090 return !aOutRect.Intersection( aRect ).IsEmpty();
2093 //-------------------------------------------------------------------
2095 Rectangle BrowseBox::GetFieldRectPixel( long nRow, sal_uInt16 nColumnId,
2096 sal_Bool bRelToBrowser) const
2098 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2100 // get the rectangle relative to DataWin
2101 Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2102 if ( aRect.IsEmpty() )
2103 return aRect;
2105 // adjust relative to BrowseBox's output area
2106 Point aTopLeft( aRect.TopLeft() );
2107 if ( bRelToBrowser )
2109 aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2110 aTopLeft = ScreenToOutputPixel( aTopLeft );
2113 return Rectangle( aTopLeft, aRect.GetSize() );
2116 //-------------------------------------------------------------------
2118 Rectangle BrowseBox::GetRowRectPixel( long nRow, sal_Bool bRelToBrowser ) const
2120 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2122 // get the rectangle relative to DataWin
2123 Rectangle aRect;
2124 if ( nTopRow > nRow )
2125 // row is above visible area
2126 return aRect;
2127 aRect = Rectangle(
2128 Point( 0, GetDataRowHeight() * (nRow-nTopRow) ),
2129 Size( pDataWin->GetOutputSizePixel().Width(), GetDataRowHeight() ) );
2130 if ( aRect.TopLeft().Y() > pDataWin->GetOutputSizePixel().Height() )
2131 // row is below visible area
2132 return aRect;
2134 // adjust relative to BrowseBox's output area
2135 Point aTopLeft( aRect.TopLeft() );
2136 if ( bRelToBrowser )
2138 aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2139 aTopLeft = ScreenToOutputPixel( aTopLeft );
2142 return Rectangle( aTopLeft, aRect.GetSize() );
2145 //-------------------------------------------------------------------
2147 Rectangle BrowseBox::ImplFieldRectPixel( long nRow, sal_uInt16 nColumnId ) const
2149 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2151 // compute the X-coordinate relative to DataWin by accumulation
2152 long nColX = 0;
2153 sal_uInt16 nFrozenCols = FrozenColCount();
2154 size_t nCol;
2155 for ( nCol = 0;
2156 nCol < pCols->size() && (*pCols)[ nCol ]->GetId() != nColumnId;
2157 ++nCol )
2158 if ( (*pCols)[ nCol ]->IsFrozen() || nCol >= nFirstCol )
2159 nColX += (*pCols)[ nCol ]->Width();
2161 if ( nCol >= pCols->size() || ( nCol >= nFrozenCols && nCol < nFirstCol ) )
2162 return Rectangle();
2164 // compute the Y-coordinate relative to DataWin
2165 long nRowY = GetDataRowHeight();
2166 if ( nRow != BROWSER_ENDOFSELECTION ) // #105497# OJ
2167 nRowY = ( nRow - nTopRow ) * GetDataRowHeight();
2169 // assemble the Rectangle relative to DataWin
2170 return Rectangle(
2171 Point( nColX + MIN_COLUMNWIDTH, nRowY ),
2172 Size( (*pCols)[ nCol ]->Width() - 2*MIN_COLUMNWIDTH,
2173 GetDataRowHeight() - 1 ) );
2176 //-------------------------------------------------------------------
2178 long BrowseBox::GetRowAtYPosPixel( long nY, sal_Bool bRelToBrowser ) const
2180 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2182 // compute the Y-coordinate
2183 if ( bRelToBrowser )
2185 Point aDataTopLeft = pDataWin->OutputToScreenPixel( Point(0, 0) );
2186 Point aTopLeft = OutputToScreenPixel( Point(0, 0) );
2187 nY -= aDataTopLeft.Y() - aTopLeft.Y();
2190 // no row there (e.g. in the header)
2191 if ( nY < 0 || nY >= pDataWin->GetOutputSizePixel().Height() )
2192 return -1;
2194 return nY / GetDataRowHeight() + nTopRow;
2197 //-------------------------------------------------------------------
2199 Rectangle BrowseBox::GetFieldRect( sal_uInt16 nColumnId ) const
2201 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2203 return GetFieldRectPixel( nCurRow, nColumnId );
2206 //-------------------------------------------------------------------
2208 sal_uInt16 BrowseBox::GetColumnAtXPosPixel( long nX, sal_Bool ) const
2210 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2212 // accumulate the widths of the visible columns
2213 long nColX = 0;
2214 for ( size_t nCol = 0; nCol < pCols->size(); ++nCol )
2216 BrowserColumn *pCol = (*pCols)[ nCol ];
2217 if ( pCol->IsFrozen() || nCol >= nFirstCol )
2218 nColX += pCol->Width();
2220 if ( nColX > nX )
2221 return nCol;
2224 return BROWSER_INVALIDID;
2227 //-------------------------------------------------------------------
2229 void BrowseBox::ReserveControlArea( sal_uInt16 nWidth )
2231 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2233 if ( nWidth != nControlAreaWidth )
2235 OSL_ENSURE(nWidth,"Control area of 0 is not allowed, Use USHRT_MAX instead!");
2236 nControlAreaWidth = nWidth;
2237 UpdateScrollbars();
2241 //-------------------------------------------------------------------
2243 Rectangle BrowseBox::GetControlArea() const
2245 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2247 return Rectangle(
2248 Point( 0, GetOutputSizePixel().Height() - aHScroll.GetSizePixel().Height() ),
2249 Size( GetOutputSizePixel().Width() - aHScroll.GetSizePixel().Width(),
2250 aHScroll.GetSizePixel().Height() ) );
2253 //-------------------------------------------------------------------
2255 void BrowseBox::SetMode( BrowserMode nMode )
2257 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2259 getDataWindow()->bAutoHScroll = BROWSER_AUTO_HSCROLL == ( nMode & BROWSER_AUTO_HSCROLL );
2260 getDataWindow()->bAutoVScroll = BROWSER_AUTO_VSCROLL == ( nMode & BROWSER_AUTO_VSCROLL );
2261 getDataWindow()->bNoHScroll = BROWSER_NO_HSCROLL == ( nMode & BROWSER_NO_HSCROLL );
2262 getDataWindow()->bNoVScroll = BROWSER_NO_VSCROLL == ( nMode & BROWSER_NO_VSCROLL );
2264 DBG_ASSERT( !( getDataWindow()->bAutoHScroll && getDataWindow()->bNoHScroll ),
2265 "BrowseBox::SetMode: AutoHScroll *and* NoHScroll?" );
2266 DBG_ASSERT( !( getDataWindow()->bAutoVScroll && getDataWindow()->bNoVScroll ),
2267 "BrowseBox::SetMode: AutoVScroll *and* NoVScroll?" );
2268 if ( getDataWindow()->bAutoHScroll )
2269 getDataWindow()->bNoHScroll = sal_False;
2270 if ( getDataWindow()->bAutoVScroll )
2271 getDataWindow()->bNoVScroll = sal_False;
2273 if ( getDataWindow()->bNoHScroll )
2274 aHScroll.Hide();
2276 nControlAreaWidth = USHRT_MAX;
2278 getDataWindow()->bNoScrollBack =
2279 BROWSER_NO_SCROLLBACK == ( nMode & BROWSER_NO_SCROLLBACK);
2281 long nOldRowSel = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
2282 MultiSelection *pOldRowSel = bMultiSelection ? uRow.pSel : 0;
2283 MultiSelection *pOldColSel = pColSel;
2285 delete pVScroll;
2287 bThumbDragging = ( nMode & BROWSER_THUMBDRAGGING ) == BROWSER_THUMBDRAGGING;
2288 bMultiSelection = ( nMode & BROWSER_MULTISELECTION ) == BROWSER_MULTISELECTION;
2289 bColumnCursor = ( nMode & BROWSER_COLUMNSELECTION ) == BROWSER_COLUMNSELECTION;
2290 bKeepHighlight = ( nMode & BROWSER_KEEPSELECTION ) == BROWSER_KEEPSELECTION;
2292 bHideSelect = ((nMode & BROWSER_HIDESELECT) == BROWSER_HIDESELECT);
2293 // default: do not hide the cursor at all (untaken scrolling and such)
2294 bHideCursor = NO_CURSOR_HIDE;
2296 if ( BROWSER_SMART_HIDECURSOR == ( nMode & BROWSER_SMART_HIDECURSOR ) )
2297 { // smart cursor hide overrules hard cursor hide
2298 bHideCursor = SMART_CURSOR_HIDE;
2300 else if ( BROWSER_HIDECURSOR == ( nMode & BROWSER_HIDECURSOR ) )
2302 bHideCursor = HARD_CURSOR_HIDE;
2305 m_bFocusOnlyCursor = ((nMode & BROWSER_CURSOR_WO_FOCUS) == 0);
2307 bHLines = ( nMode & BROWSER_HLINESFULL ) == BROWSER_HLINESFULL;
2308 bVLines = ( nMode & BROWSER_VLINESFULL ) == BROWSER_VLINESFULL;
2309 bHDots = ( nMode & BROWSER_HLINESDOTS ) == BROWSER_HLINESDOTS;
2310 bVDots = ( nMode & BROWSER_VLINESDOTS ) == BROWSER_VLINESDOTS;
2312 WinBits nVScrollWinBits =
2313 WB_VSCROLL | ( ( nMode & BROWSER_THUMBDRAGGING ) ? WB_DRAG : 0 );
2314 pVScroll = ( nMode & BROWSER_TRACKING_TIPS ) == BROWSER_TRACKING_TIPS
2315 ? new BrowserScrollBar( this, nVScrollWinBits,
2316 (BrowserDataWin*) pDataWin )
2317 : new ScrollBar( this, nVScrollWinBits );
2318 pVScroll->SetLineSize( 1 );
2319 pVScroll->SetPageSize(1);
2320 pVScroll->SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) );
2321 pVScroll->SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) );
2323 getDataWindow()->bAutoSizeLastCol =
2324 BROWSER_AUTOSIZE_LASTCOL == ( nMode & BROWSER_AUTOSIZE_LASTCOL );
2325 getDataWindow()->bOwnDataChangedHdl =
2326 BROWSER_OWN_DATACHANGED == ( nMode & BROWSER_OWN_DATACHANGED );
2328 // create a headerbar. what happens, if a headerbar has to be created and
2329 // there already are columns?
2330 if ( BROWSER_HEADERBAR_NEW == ( nMode & BROWSER_HEADERBAR_NEW ) )
2332 if (!getDataWindow()->pHeaderBar)
2333 getDataWindow()->pHeaderBar = CreateHeaderBar( this );
2335 else
2337 DELETEZ(getDataWindow()->pHeaderBar);
2342 if ( bColumnCursor )
2344 pColSel = pOldColSel ? pOldColSel : new MultiSelection;
2345 pColSel->SetTotalRange( Range( 0, pCols->size()-1 ) );
2347 else
2349 pColSel = 0;
2350 delete pColSel;
2353 if ( bMultiSelection )
2355 if ( pOldRowSel )
2356 uRow.pSel = pOldRowSel;
2357 else
2358 uRow.pSel = new MultiSelection;
2360 else
2362 uRow.nSel = nOldRowSel;
2363 delete pOldRowSel;
2366 if ( bBootstrapped )
2368 StateChanged( STATE_CHANGE_INITSHOW );
2369 if ( bMultiSelection && !pOldRowSel &&
2370 nOldRowSel != BROWSER_ENDOFSELECTION )
2371 uRow.pSel->Select( nOldRowSel );
2374 if ( pDataWin )
2375 pDataWin->Invalidate();
2377 // no cursor on handle column
2378 if ( nCurColId == HandleColumnId )
2379 nCurColId = GetColumnId( 1 );
2381 m_nCurrentMode = nMode;
2384 //-------------------------------------------------------------------
2386 void BrowseBox::VisibleRowsChanged( long, sal_uInt16 )
2388 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2390 // old behavior: automatically correct NumRows:
2391 if ( nRowCount < GetRowCount() )
2393 RowInserted(nRowCount,GetRowCount() - nRowCount,sal_False);
2395 else if ( nRowCount > GetRowCount() )
2397 RowRemoved(nRowCount-(nRowCount - GetRowCount()),nRowCount - GetRowCount(),sal_False);
2401 //-------------------------------------------------------------------
2403 sal_Bool BrowseBox::IsCursorMoveAllowed( long, sal_uInt16 ) const
2405 /* [Description]
2407 This virtual method is always called before the cursor is moved directly.
2408 By means of 'return sal_False', we avoid doing this if e.g. a record
2409 contradicts any rules.
2411 This method is not called, if the cursor movement results from removing or
2412 deleting a row/column (thus, in cases where only a "cursor correction" happens).
2414 The base implementation currently always returns sal_True.
2418 return sal_True;
2421 //-------------------------------------------------------------------
2423 long BrowseBox::GetDataRowHeight() const
2425 return CalcZoom(nDataRowHeight ? nDataRowHeight : ImpGetDataRowHeight());
2428 //-------------------------------------------------------------------
2430 BrowserHeader* BrowseBox::CreateHeaderBar( BrowseBox* pParent )
2432 BrowserHeader* pNewBar = new BrowserHeader( pParent );
2433 pNewBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2434 return pNewBar;
2437 void BrowseBox::SetHeaderBar( BrowserHeader* pHeaderBar )
2439 delete ( (BrowserDataWin*)pDataWin )->pHeaderBar;
2440 ( (BrowserDataWin*)pDataWin )->pHeaderBar = pHeaderBar;
2441 ( (BrowserDataWin*)pDataWin )->pHeaderBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2443 //-------------------------------------------------------------------
2445 #ifdef DBG_UTIL
2446 const char* BrowseBoxCheckInvariants( const void * pVoid )
2448 const BrowseBox * p = (const BrowseBox *)pVoid;
2450 if (p->nRowCount < 0) return "BrowseBox: nRowCount < 0";
2451 if (p->nTopRow < 0) return "BrowseBox: nTopRow < 0";
2452 if (p->nTopRow >= p->nRowCount && p->nRowCount != 0) return "BrowseBox: nTopRow >= nRowCount && nRowCount != 0";
2453 if (p->nCurRow < -1) return "BrowseBox: nCurRow < -1";
2454 if (p->nCurRow > p->nRowCount) return "BrowseBox: nCurRow > nRowCount";
2456 // Sadly not always the case when editing:
2457 //if (p->nCurRow < 0 && p->nRowCount != 0) return "nCurRow < 0 && nRowCount != 0";
2458 //if (p->nCurRow >= p->nRowCount && p->nRowCount != 0) return "nCurRow >= nRowCount && nRowCount != 0";
2460 return NULL;
2462 #endif
2464 //-------------------------------------------------------------------
2465 long BrowseBox::GetTitleHeight() const
2467 long nHeight;
2468 // ask the header bar for the text height (if possible), as the header bar's font is adjusted with
2469 // our (and the header's) zoom factor
2470 HeaderBar* pHeaderBar = ( (BrowserDataWin*)pDataWin )->pHeaderBar;
2471 if ( pHeaderBar )
2472 nHeight = pHeaderBar->GetTextHeight();
2473 else
2474 nHeight = GetTextHeight();
2476 return nTitleLines ? nTitleLines * nHeight + 4 : 0;
2479 //-------------------------------------------------------------------
2480 long BrowseBox::CalcReverseZoom(long nVal)
2482 if (IsZoom())
2484 const Fraction& rZoom = GetZoom();
2485 double n = (double)nVal;
2486 n *= (double)rZoom.GetDenominator();
2487 n /= (double)rZoom.GetNumerator();
2488 nVal = n>0 ? (long)(n + 0.5) : -(long)(-n + 0.5);
2491 return nVal;
2494 void BrowseBox::CursorMoved()
2496 // before implementing more here, please adjust the EditBrowseBox
2497 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2499 if ( isAccessibleAlive() && HasFocus() )
2500 commitTableEvent(
2501 ACTIVE_DESCENDANT_CHANGED,
2502 makeAny( CreateAccessibleCell( GetCurRow(),GetColumnPos( GetCurColumnId() ) ) ),
2503 Any()
2507 //-------------------------------------------------------------------
2509 void BrowseBox::LoseFocus()
2511 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2512 OSL_TRACE( "BrowseBox: %p->LoseFocus", this );
2514 if ( bHasFocus )
2516 OSL_TRACE( "BrowseBox: %p->HideCursor", this );
2517 DoHideCursor( "LoseFocus" );
2519 if ( !bKeepHighlight )
2521 ToggleSelection();
2522 bSelectionIsVisible = sal_False;
2525 bHasFocus = sal_False;
2527 Control::LoseFocus();
2530 //-------------------------------------------------------------------
2532 void BrowseBox::GetFocus()
2534 DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2535 OSL_TRACE( "BrowseBox: %p->GetFocus", this );
2537 if ( !bHasFocus )
2539 if ( !bSelectionIsVisible )
2541 bSelectionIsVisible = sal_True;
2542 if ( bBootstrapped )
2543 ToggleSelection();
2546 bHasFocus = sal_True;
2547 DoShowCursor( "GetFocus" );
2549 Control::GetFocus();
2553 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */