xref: /AOO41X/main/svtools/source/brwbox/brwbox1.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <svtools/brwbox.hxx>
27 #include <svtools/brwhead.hxx>
28 #include "datwin.hxx"
29 #include <tools/debug.hxx>
30 #include <tools/stream.hxx>
31 
32 #include <functional>
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 <com/sun/star/accessibility/XAccessible.hpp>
38 #include <tools/multisel.hxx>
39 #include "brwimpl.hxx"
40 
41 DBG_NAME(BrowseBox)
42 
43 extern const char* BrowseBoxCheckInvariants( const void* pVoid );
44 
45 DECLARE_LIST( BrowserColumns, BrowserColumn* )
46 
47 #define SCROLL_FLAGS (SCROLL_CLIP | SCROLL_NOCHILDREN)
48 #define getDataWindow() ((BrowserDataWin*)pDataWin)
49 
50 using namespace com::sun::star::accessibility::AccessibleEventId;
51 using namespace com::sun::star::accessibility::AccessibleTableModelChangeType;
52 using com::sun::star::accessibility::AccessibleTableModelChange;
53 using com::sun::star::lang::XComponent;
54 using namespace ::com::sun::star::uno;
55 using namespace svt;
56 
57 //-------------------------------------------------------------------
58 
59 #ifdef DBG_MI
DoLog_Impl(const BrowseBox * pThis,const char * pWhat,const char * pWho)60 void DoLog_Impl( const BrowseBox *pThis, const char *pWhat, const char *pWho )
61 {
62     SvFileStream aLog( "d:\\cursor.log", STREAM_WRITE|STREAM_NOCREATE );
63     if ( aLog.IsOpen() )
64     {
65         aLog.Seek( STREAM_SEEK_TO_END );
66         String aEntry( (long) pThis );
67         aEntry += "(row=";
68         aEntry += pThis->GetCurRow();
69         aEntry += "): ";
70         aEntry += pWhat;
71         aEntry += " from ";
72         aEntry += pWho;
73         aEntry += " => ";
74         aEntry += pThis->GetCursorHideCount();
75         aLog.WriteLine( aEntry );
76     }
77 }
78 #endif
79 
80 namespace
81 {
disposeAndClearHeaderCell(::svt::BrowseBoxImpl::THeaderCellMap & _rHeaderCell)82     void disposeAndClearHeaderCell(::svt::BrowseBoxImpl::THeaderCellMap& _rHeaderCell)
83     {
84         ::std::for_each(
85                         _rHeaderCell.begin(),
86                         _rHeaderCell.end(),
87                         ::svt::BrowseBoxImpl::THeaderCellMapFunctorDispose()
88                             );
89         _rHeaderCell.clear();
90     }
91 }
92 
93 //===================================================================
94 
ConstructImpl(BrowserMode nMode)95 void BrowseBox::ConstructImpl( BrowserMode nMode )
96 {
97     DBG_TRACE1( "BrowseBox: %p->ConstructImpl", this );
98     bMultiSelection = sal_False;
99     pColSel = 0;
100     pDataWin = 0;
101     pVScroll = 0;
102 
103     pDataWin = new BrowserDataWin( this );
104     pCols = new BrowserColumns;
105     m_pImpl.reset( new ::svt::BrowseBoxImpl() );
106 
107     aGridLineColor = Color( COL_LIGHTGRAY );
108     InitSettings_Impl( this );
109     InitSettings_Impl( pDataWin );
110 
111     bBootstrapped = sal_False;
112     nDataRowHeight = 0;
113     nTitleLines = 1;
114     nFirstCol = 0;
115     nTopRow = 0;
116     nCurRow = BROWSER_ENDOFSELECTION;
117     nCurColId = 0;
118     bResizing = sal_False;
119     bSelect = sal_False;
120     bSelecting = sal_False;
121     bScrolling = sal_False;
122     bSelectionIsVisible = sal_False;
123     bNotToggleSel = sal_False;
124     bRowDividerDrag = sal_False;
125     bHit = sal_False;
126     mbInteractiveRowHeight = sal_False;
127     bHideSelect = sal_False;
128     bHideCursor = NO_CURSOR_HIDE;
129     nRowCount = 0;
130     m_bFocusOnlyCursor = sal_True;
131     m_aCursorColor = COL_TRANSPARENT;
132     m_nCurrentMode = 0;
133     nControlAreaWidth = USHRT_MAX;
134     uRow.nSel = BROWSER_ENDOFSELECTION;
135 
136     aHScroll.SetLineSize(1);
137     aHScroll.SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) );
138     aHScroll.SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) );
139     pDataWin->Show();
140 
141     SetMode( nMode );
142     bSelectionIsVisible = bKeepHighlight;
143     bHasFocus = HasChildPathFocus();
144     getDataWindow()->nCursorHidden =
145                 ( bHasFocus ? 0 : 1 ) + ( GetUpdateMode() ? 0 : 1 );
146     LOG( this, "ConstructImpl", "*" );
147 }
148 
149 //-------------------------------------------------------------------
150 
BrowseBox(Window * pParent,WinBits nBits,BrowserMode nMode)151 BrowseBox::BrowseBox( Window* pParent, WinBits nBits, BrowserMode nMode )
152     :Control( pParent, nBits | WB_3DLOOK )
153     ,DragSourceHelper( this )
154     ,DropTargetHelper( this )
155     ,aHScroll( this, WinBits( WB_HSCROLL ) )
156 {
157     DBG_CTOR( BrowseBox, NULL );
158     ConstructImpl( nMode );
159 }
160 
161 //-------------------------------------------------------------------
162 
BrowseBox(Window * pParent,const ResId & rId,BrowserMode nMode)163 BrowseBox::BrowseBox( Window* pParent, const ResId& rId, BrowserMode nMode )
164     :Control( pParent, rId )
165     ,DragSourceHelper( this )
166     ,DropTargetHelper( this )
167     ,aHScroll( this, WinBits(WB_HSCROLL) )
168 {
169     DBG_CTOR( BrowseBox, NULL );
170     ConstructImpl(nMode);
171 }
172 //-------------------------------------------------------------------
173 
~BrowseBox()174 BrowseBox::~BrowseBox()
175 {
176     DBG_DTOR(BrowseBox,BrowseBoxCheckInvariants);
177     DBG_TRACE1( "BrowseBox: %p~", this );
178 
179     if ( m_pImpl->m_pAccessible )
180     {
181         disposeAndClearHeaderCell(m_pImpl->m_aColHeaderCellMap);
182         disposeAndClearHeaderCell(m_pImpl->m_aRowHeaderCellMap);
183         m_pImpl->m_pAccessible->dispose();
184     }
185 
186     Hide();
187     delete getDataWindow()->pHeaderBar;
188     delete getDataWindow()->pCornerWin;
189     delete pDataWin;
190     delete pVScroll;
191 
192     // free columns-space
193     for ( sal_uInt16 n = 0; n < pCols->Count(); ++n )
194         delete pCols->GetObject(n);
195     delete pCols;
196     delete pColSel;
197     if ( bMultiSelection )
198         delete uRow.pSel;
199 }
200 
201 //-------------------------------------------------------------------
202 
GetCursorHideCount() const203 short BrowseBox::GetCursorHideCount() const
204 {
205     return getDataWindow()->nCursorHidden;
206 }
207 
208 //-------------------------------------------------------------------
209 
DoShowCursor(const char * pWhoLogs)210 void BrowseBox::DoShowCursor( const char *
211 #ifdef DBG_MI
212 pWhoLogs
213 #endif
214 )
215 {
216     short nHiddenCount = --getDataWindow()->nCursorHidden;
217     if (PaintCursorIfHiddenOnce())
218     {
219         if (1 == nHiddenCount)
220             DrawCursor();
221     }
222     else
223     {
224         if (0 == nHiddenCount)
225             DrawCursor();
226     }
227     LOG( this, "DoShowCursor", pWhoLogs );
228 }
229 
230 //-------------------------------------------------------------------
231 
DoHideCursor(const char * pWhoLogs)232 void BrowseBox::DoHideCursor( const char *
233 #ifdef DBG_MI
234 pWhoLogs
235 #endif
236 )
237 {
238     short nHiddenCount = ++getDataWindow()->nCursorHidden;
239     if (PaintCursorIfHiddenOnce())
240     {
241         if (2 == nHiddenCount)
242             DrawCursor();
243     }
244     else
245     {
246         if (1 == nHiddenCount)
247             DrawCursor();
248     }
249     LOG( this, "DoHideCursor", pWhoLogs );
250 }
251 
252 //-------------------------------------------------------------------
253 
SetRealRowCount(const String & rRealRowCount)254 void BrowseBox::SetRealRowCount( const String &rRealRowCount )
255 {
256     getDataWindow()->aRealRowCount = rRealRowCount;
257 }
258 
259 //-------------------------------------------------------------------
260 
SetFont(const Font & rNewFont)261 void BrowseBox::SetFont( const Font& rNewFont )
262 {
263     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
264     pDataWin->SetFont( rNewFont );
265     ImpGetDataRowHeight();
266 }
267 
268 //-------------------------------------------------------------------
269 
GetDefaultColumnWidth(const String & _rText) const270 sal_uLong BrowseBox::GetDefaultColumnWidth( const String& _rText ) const
271 {
272     return GetDataWindow().GetTextWidth( _rText ) + GetDataWindow().GetTextWidth( '0' ) * 4;
273 }
274 
275 //-------------------------------------------------------------------
276 
InsertHandleColumn(sal_uLong nWidth)277 void BrowseBox::InsertHandleColumn( sal_uLong nWidth )
278 {
279     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
280 
281     pCols->Insert( new BrowserColumn( 0, Image(), String(), nWidth, GetZoom(), 0 ), (sal_uLong) 0 );
282     FreezeColumn( 0 );
283 
284     // Headerbar anpassen
285     if ( getDataWindow()->pHeaderBar )
286     {
287         getDataWindow()->pHeaderBar->SetPosSizePixel(
288                     Point(nWidth, 0),
289                     Size( GetOutputSizePixel().Width() - nWidth, GetTitleHeight() )
290                     );
291     }
292 
293     /*if ( getDataWindow()->pHeaderBar )
294         getDataWindow()->pHeaderBar->InsertItem( USHRT_MAX - 1,
295                 "", nWidth, HIB_FIXEDPOS|HIB_FIXED, 0 );*/
296     ColumnInserted( 0 );
297 }
298 
299 //-------------------------------------------------------------------
InsertDataColumn(sal_uInt16 nItemId,const Image & rImage,long nWidth,HeaderBarItemBits nBits,sal_uInt16 nPos)300 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId, const Image& rImage,
301         long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos )
302 {
303     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
304 
305     pCols->Insert( new BrowserColumn( nItemId, rImage, String(), nWidth, GetZoom(), nBits ),
306                            Min( nPos, (sal_uInt16)(pCols->Count()) ) );
307     if ( nCurColId == 0 )
308         nCurColId = nItemId;
309     if ( getDataWindow()->pHeaderBar )
310     {
311         // Handlecolumn nicht in der Headerbar
312         sal_uInt16 nHeaderPos = nPos;
313         if (nHeaderPos != HEADERBAR_APPEND && !GetColumnId(0))
314             nHeaderPos--;
315         getDataWindow()->pHeaderBar->InsertItem(
316                 nItemId, rImage, nWidth, nBits, nHeaderPos );
317     }
318     ColumnInserted( nPos );
319 }
320 
321 //-------------------------------------------------------------------
322 
InsertDataColumn(sal_uInt16 nItemId,const XubString & rText,long nWidth,HeaderBarItemBits nBits,sal_uInt16 nPos)323 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId, const XubString& rText,
324         long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos )
325 {
326     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
327 
328     pCols->Insert( new BrowserColumn( nItemId, Image(), rText, nWidth, GetZoom(), nBits ),
329                            Min( nPos, (sal_uInt16)(pCols->Count()) ) );
330     if ( nCurColId == 0 )
331         nCurColId = nItemId;
332 
333     if ( getDataWindow()->pHeaderBar )
334     {
335         // Handlecolumn nicht in der Headerbar
336         sal_uInt16 nHeaderPos = nPos;
337         if (nHeaderPos != HEADERBAR_APPEND && !GetColumnId(0))
338             nHeaderPos--;
339         getDataWindow()->pHeaderBar->InsertItem(
340                 nItemId, rText, nWidth, nBits, nHeaderPos );
341     }
342     ColumnInserted( nPos );
343 }
344 
345 //-------------------------------------------------------------------
346 
InsertDataColumn(sal_uInt16 nItemId,const Image & rImage,const XubString & rText,long nWidth,HeaderBarItemBits nBits,sal_uInt16 nPos,const String * pHelpText)347 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId,
348         const Image& rImage, const XubString& rText,
349         long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos,
350         const String* pHelpText )
351 {
352     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
353 
354     pCols->Insert( new BrowserColumn( nItemId, rImage, rText, nWidth, GetZoom(), nBits ),
355                            Min( nPos, (sal_uInt16)(pCols->Count()) ) );
356     if ( nCurColId == 0 )
357         nCurColId = nItemId;
358     if ( getDataWindow()->pHeaderBar )
359     {
360         // Handlecolumn nicht in der Headerbar
361         sal_uInt16 nHeaderPos = nPos;
362         if (nHeaderPos != HEADERBAR_APPEND && !GetColumnId(0))
363             nHeaderPos--;
364 
365         getDataWindow()->pHeaderBar->InsertItem(
366                 nItemId, rImage, rText, nWidth, nBits, nHeaderPos );
367         if( pHelpText && !rText.Len() )
368         {
369             getDataWindow()->pHeaderBar->SetHelpText(
370                 nItemId, *pHelpText );
371         }
372     }
373     ColumnInserted( nPos );
374 }
375 //-------------------------------------------------------------------
ToggleSelectedColumn()376 sal_uInt16 BrowseBox::ToggleSelectedColumn()
377 {
378     sal_uInt16 nSelectedColId = USHRT_MAX;
379     if ( pColSel && pColSel->GetSelectCount() )
380     {
381         DoHideCursor( "ToggleSelectedColumn" );
382         ToggleSelection();
383         nSelectedColId = pCols->GetObject(pColSel->FirstSelected())->GetId();
384         pColSel->SelectAll(sal_False);
385     }
386     return nSelectedColId;
387 }
388 // -----------------------------------------------------------------------------
SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)389 void BrowseBox::SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)
390 {
391     if ( pColSel && _nSelectedColumnId != USHRT_MAX )
392     {
393         pColSel->Select( GetColumnPos( _nSelectedColumnId ) );
394         ToggleSelection();
395         DBG_TRACE1( "BrowseBox: %p->SetToggledSelectedColumn", this );
396         DoShowCursor( "SetToggledSelectedColumn" );
397     }
398 }
399 // -----------------------------------------------------------------------------
FreezeColumn(sal_uInt16 nItemId,sal_Bool bFreeze)400 void BrowseBox::FreezeColumn( sal_uInt16 nItemId, sal_Bool bFreeze )
401 {
402     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
403 
404     // never unfreeze the handle-column
405     if ( nItemId == 0 && !bFreeze )
406         return;
407 
408     // get the position in the current array
409     sal_uInt16 nItemPos = GetColumnPos( nItemId );
410     if ( nItemPos >= pCols->Count() )
411         // not available!
412         return;
413 
414     // doesn't the state change?
415     if ( pCols->GetObject(nItemPos)->IsFrozen() == bFreeze )
416         return;
417 
418     // remark the column selection
419     sal_uInt16 nSelectedColId = ToggleSelectedColumn();
420 
421     // freeze or unfreeze?
422     if ( bFreeze )
423     {
424         // to be moved?
425         if ( nItemPos != 0 && !pCols->GetObject(nItemPos-1)->IsFrozen() )
426         {
427             // move to the right of the last frozen column
428             sal_uInt16 nFirstScrollable = FrozenColCount();
429             BrowserColumn *pColumn = pCols->GetObject(nItemPos);
430             pCols->Remove( (sal_uLong) nItemPos );
431             nItemPos = nFirstScrollable;
432             pCols->Insert( pColumn, (sal_uLong) nItemPos );
433         }
434 
435         // adjust the number of the first scrollable and visible column
436         if ( nFirstCol <= nItemPos )
437             nFirstCol = nItemPos + 1;
438     }
439     else
440     {
441         // to be moved?
442         if ( nItemPos != FrozenColCount()-1 )
443         {
444             // move to the leftmost scrollable colum
445             sal_uInt16 nFirstScrollable = FrozenColCount();
446             BrowserColumn *pColumn = pCols->GetObject(nItemPos);
447             pCols->Remove( (sal_uLong) nItemPos );
448             nItemPos = nFirstScrollable;
449             pCols->Insert( pColumn, (sal_uLong) nItemPos );
450         }
451 
452         // adjust the number of the first scrollable and visible column
453         nFirstCol = nItemPos;
454     }
455 
456     // toggle the freeze-state of the column
457     pCols->GetObject(nItemPos)->Freeze( bFreeze );
458 
459     // align the scrollbar-range
460     UpdateScrollbars();
461 
462     // repaint
463     Control::Invalidate();
464     getDataWindow()->Invalidate();
465 
466     // remember the column selection
467     SetToggledSelectedColumn(nSelectedColId);
468 }
469 
470 //-------------------------------------------------------------------
471 
SetColumnPos(sal_uInt16 nColumnId,sal_uInt16 nPos)472 void BrowseBox::SetColumnPos( sal_uInt16 nColumnId, sal_uInt16 nPos )
473 {
474     // never set pos of the handle-column
475     if ( nColumnId == 0 )
476         return;
477 
478     // do not move handle column
479     if (nPos == 0 && !pCols->GetObject(0)->GetId())
480         return;
481 
482     // get the position in the current array
483     sal_uInt16 nOldPos = GetColumnPos( nColumnId );
484     if ( nOldPos >= pCols->Count() )
485         // not available!
486         return;
487 
488     // does the state change?
489     if (nOldPos != nPos)
490     {
491         // remark the column selection
492         sal_uInt16 nSelectedColId = ToggleSelectedColumn();
493 
494         // determine old column area
495         Size aDataWinSize( pDataWin->GetSizePixel() );
496         if ( getDataWindow()->pHeaderBar )
497             aDataWinSize.Height() += getDataWindow()->pHeaderBar->GetSizePixel().Height();
498 
499         Rectangle aFromRect( GetFieldRect( nColumnId) );
500         aFromRect.Right() += 2*MIN_COLUMNWIDTH;
501 
502         sal_uInt16 nNextPos = nOldPos + 1;
503         if ( nOldPos > nPos )
504             nNextPos = nOldPos - 1;
505 
506         BrowserColumn *pNextCol = pCols->GetObject(nNextPos);
507         Rectangle aNextRect(GetFieldRect( pNextCol->GetId() ));
508 
509         // move column internally
510         pCols->Insert( pCols->Remove( nOldPos ), nPos );
511 
512         // determine new column area
513         Rectangle aToRect( GetFieldRect( nColumnId ) );
514         aToRect.Right() += 2*MIN_COLUMNWIDTH;
515 
516         // do scroll, let redraw
517         if( pDataWin->GetBackground().IsScrollable() )
518         {
519             long nScroll = -aFromRect.GetWidth();
520             Rectangle aScrollArea;
521             if ( nOldPos > nPos )
522             {
523                 long nFrozenWidth = GetFrozenWidth();
524                 if ( aToRect.Left() < nFrozenWidth )
525                     aToRect.Left() = nFrozenWidth;
526                 aScrollArea = Rectangle(Point(aToRect.Left(),0),
527                                         Point(aNextRect.Right(),aDataWinSize.Height()));
528                 nScroll *= -1; // reverse direction
529             }
530             else
531                 aScrollArea = Rectangle(Point(aNextRect.Left(),0),
532                                         Point(aToRect.Right(),aDataWinSize.Height()));
533 
534             pDataWin->Scroll( nScroll, 0, aScrollArea );
535             aToRect.Top() = 0;
536             aToRect.Bottom() = aScrollArea.Bottom();
537             Invalidate( aToRect );
538         }
539         else
540             pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
541 
542         // adjust header bar positions
543         if ( getDataWindow()->pHeaderBar )
544         {
545             sal_uInt16 nNewPos = nPos;
546             if ( !GetColumnId(0) )
547                 --nNewPos;
548             getDataWindow()->pHeaderBar->MoveItem(nColumnId,nNewPos);
549         }
550         // remember the column selection
551         SetToggledSelectedColumn(nSelectedColId);
552 
553         if ( isAccessibleAlive() )
554         {
555             commitTableEvent(
556                 TABLE_MODEL_CHANGED,
557                 makeAny( AccessibleTableModelChange(
558                             DELETE,
559                             0,
560                             GetRowCount(),
561                             nOldPos,
562                             nOldPos
563                         )
564                 ),
565                 Any()
566             );
567 
568             commitTableEvent(
569                 TABLE_MODEL_CHANGED,
570                 makeAny( AccessibleTableModelChange(
571                             INSERT,
572                             0,
573                             GetRowCount(),
574                             nPos,
575                             nPos
576                         )
577                 ),
578                 Any()
579             );
580         }
581     }
582 
583 }
584 
585 //-------------------------------------------------------------------
586 
SetColumnMode(sal_uInt16 nColumnId,BrowserColumnMode nFlags)587 void BrowseBox::SetColumnMode( sal_uInt16 nColumnId, BrowserColumnMode nFlags )
588 {
589     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
590 
591     // never set mode of the handle-column
592     if ( nColumnId == 0 )
593         return;
594 
595     // get the position in the current array
596     sal_uInt16 nColumnPos = GetColumnPos( nColumnId );
597     if ( nColumnPos >= pCols->Count() )
598         // not available!
599         return;
600 
601     // does the state change?
602     BrowserColumn *pCol = pCols->GetObject(nColumnPos);
603     if ( pCol->Flags() != nFlags )
604     {
605         pCol->Flags() = sal::static_int_cast< HeaderBarItemBits >(nFlags);
606 
607         // redraw visible colums
608         if ( GetUpdateMode() && ( pCol->IsFrozen() || nColumnPos > nFirstCol ) )
609             Invalidate( Rectangle( Point(0,0),
610                 Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
611     }
612 }
613 
614 //-------------------------------------------------------------------
615 
SetColumnTitle(sal_uInt16 nItemId,const String & rTitle)616 void BrowseBox::SetColumnTitle( sal_uInt16 nItemId, const String& rTitle )
617 {
618     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
619 
620     // never set title of the handle-column
621     if ( nItemId == 0 )
622         return;
623 
624     // get the position in the current array
625     sal_uInt16 nItemPos = GetColumnPos( nItemId );
626     if ( nItemPos >= pCols->Count() )
627         // not available!
628         return;
629 
630     // does the state change?
631     BrowserColumn *pCol = pCols->GetObject(nItemPos);
632     if ( pCol->Title() != rTitle )
633     {
634         ::rtl::OUString sNew(rTitle);
635         ::rtl::OUString sOld(pCol->Title());
636 
637         pCol->Title() = rTitle;
638 
639         // Headerbar-Column anpassen
640         if ( getDataWindow()->pHeaderBar )
641             getDataWindow()->pHeaderBar->SetItemText(
642                     nItemId ? nItemId : USHRT_MAX - 1, rTitle );
643         else
644         {
645             // redraw visible colums
646             if ( GetUpdateMode() && ( pCol->IsFrozen() || nItemPos > nFirstCol ) )
647                 Invalidate( Rectangle( Point(0,0),
648                     Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
649         }
650 
651         if ( isAccessibleAlive() )
652         {
653             commitTableEvent(   TABLE_COLUMN_DESCRIPTION_CHANGED,
654                 makeAny( sNew ),
655                 makeAny( sOld )
656             );
657         }
658     }
659 }
660 
661 //-------------------------------------------------------------------
662 
SetColumnWidth(sal_uInt16 nItemId,sal_uLong nWidth)663 void BrowseBox::SetColumnWidth( sal_uInt16 nItemId, sal_uLong nWidth )
664 {
665     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
666 
667     // get the position in the current array
668     sal_uInt16 nItemPos = GetColumnPos( nItemId );
669     if ( nItemPos >= pCols->Count() )
670         return;
671 
672     // does the state change?
673     nWidth = QueryColumnResize( nItemId, nWidth );
674     if ( nWidth >= LONG_MAX || pCols->GetObject(nItemPos)->Width() != nWidth )
675     {
676         long nOldWidth = pCols->GetObject(nItemPos)->Width();
677 
678         // ggf. letzte Spalte anpassen
679         if ( IsVisible() && nItemPos == pCols->Count() - 1 )
680         {
681             long nMaxWidth = pDataWin->GetSizePixel().Width();
682             nMaxWidth -= getDataWindow()->bAutoSizeLastCol
683                     ? GetFieldRect(nItemId).Left()
684                     : GetFrozenWidth();
685             if ( ( (BrowserDataWin*)pDataWin )->bAutoSizeLastCol || nWidth > (sal_uLong)nMaxWidth )
686             {
687                 nWidth = nMaxWidth > 16 ? nMaxWidth : nOldWidth;
688                 nWidth = QueryColumnResize( nItemId, nWidth );
689             }
690         }
691 
692         // OV
693         // In AutoSizeLastColumn() wird SetColumnWidth mit nWidth==0xffff
694         // gerufen. Deshalb muss hier nochmal geprueft werden, ob sich die
695         // Breite tatsaechlich geaendert hat.
696         if( (sal_uLong)nOldWidth == nWidth )
697             return;
698 
699         // soll die Aenderung sofort dargestellt werden?
700         sal_Bool bUpdate = GetUpdateMode() &&
701                        ( pCols->GetObject(nItemPos)->IsFrozen() || nItemPos >= nFirstCol );
702 
703         if ( bUpdate )
704         {
705             // Selection hiden
706             DoHideCursor( "SetColumnWidth" );
707             ToggleSelection();
708             //!getDataWindow()->Update();
709             //!Control::Update();
710         }
711 
712         // Breite setzen
713         pCols->GetObject(nItemPos)->SetWidth(nWidth, GetZoom());
714 #if 0
715         if ( nItemPos != pCols->Count() - 1 )
716         {
717             long nLastColMaxWidth = pDataWin->GetSizePixel().Width() -
718                         GetFieldRect(GetColumnId(pCols->Count()-1)).Left();
719             pCols->GetObject(pCols->Count()-1)->Width() = nLastColMaxWidth;
720         }
721 #endif
722 
723         // scroll and invalidate
724         if ( bUpdate )
725         {
726             // X-Pos der veraenderten Spalte ermitteln
727             long nX = 0;
728             for ( sal_uInt16 nCol = 0; nCol < nItemPos; ++nCol )
729             {
730                 BrowserColumn *pCol = pCols->GetObject(nCol);
731                 if ( pCol->IsFrozen() || nCol >= nFirstCol )
732                     nX += pCol->Width();
733             }
734 
735             // eigentliches scroll+invalidate
736             pDataWin->SetClipRegion();
737             sal_Bool bSelVis = bSelectionIsVisible;
738             bSelectionIsVisible = sal_False;
739             if( GetBackground().IsScrollable() )
740             {
741 
742                 Rectangle aScrRect( nX + std::min( (sal_uLong)nOldWidth, nWidth ), 0,
743                                     GetSizePixel().Width() , // the header is longer than the datawin
744                                     pDataWin->GetPosPixel().Y() - 1 );
745                 Control::Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
746                 aScrRect.Bottom() = pDataWin->GetSizePixel().Height();
747                 getDataWindow()->Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
748                 Rectangle aInvRect( nX, 0, nX + std::max( nWidth, (sal_uLong)nOldWidth ), USHRT_MAX );
749                 Control::Invalidate( aInvRect, INVALIDATE_NOCHILDREN );
750                 ( (BrowserDataWin*)pDataWin )->Invalidate( aInvRect );
751             }
752             else
753             {
754                 Control::Invalidate( INVALIDATE_NOCHILDREN );
755                 getDataWindow()->Window::Invalidate( INVALIDATE_NOCHILDREN );
756             }
757 
758 
759             //!getDataWindow()->Update();
760             //!Control::Update();
761             bSelectionIsVisible = bSelVis;
762             ToggleSelection();
763             DoShowCursor( "SetColumnWidth" );
764         }
765         UpdateScrollbars();
766 
767         // Headerbar-Column anpassen
768         if ( getDataWindow()->pHeaderBar )
769             getDataWindow()->pHeaderBar->SetItemSize(
770                     nItemId ? nItemId : USHRT_MAX - 1, nWidth );
771 
772         // adjust last column
773         if ( nItemPos != pCols->Count() - 1 )
774             AutoSizeLastColumn();
775 
776     }
777 }
778 
779 //-------------------------------------------------------------------
780 
AutoSizeLastColumn()781 void BrowseBox::AutoSizeLastColumn()
782 {
783     if ( getDataWindow()->bAutoSizeLastCol &&
784          getDataWindow()->GetUpdateMode() )
785     {
786         sal_uInt16 nId = GetColumnId( (sal_uInt16)pCols->Count() - 1 );
787         SetColumnWidth( nId, LONG_MAX );
788         ColumnResized( nId );
789     }
790 }
791 
792 //-------------------------------------------------------------------
793 
RemoveColumn(sal_uInt16 nItemId)794 void BrowseBox::RemoveColumn( sal_uInt16 nItemId )
795 {
796     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
797 
798     // Spaltenposition ermitteln
799     sal_uInt16 nPos = GetColumnPos(nItemId);
800     if ( nPos >= ColCount() )
801         // nicht vorhanden
802         return;
803 
804     // Spaltenselektion korrigieren
805     if ( pColSel )
806         pColSel->Remove( nPos );
807 
808     // Spaltencursor korrigieren
809     if ( nCurColId == nItemId )
810         nCurColId = 0;
811 
812     // Spalte entfernen
813     delete( pCols->Remove( (sal_uLong) nPos ));
814     // OJ #93534#
815     if ( nFirstCol >= nPos && nFirstCol > FrozenColCount() )
816     {
817         OSL_ENSURE(nFirstCol > 0,"FirstCol must be greater zero!");
818         --nFirstCol;
819     }
820 
821     // Handlecolumn nicht in der Headerbar
822     if (nItemId)
823     {
824         if ( getDataWindow()->pHeaderBar )
825             getDataWindow()->pHeaderBar->RemoveItem( nItemId );
826     }
827     else
828     {
829         // Headerbar anpassen
830         if ( getDataWindow()->pHeaderBar )
831         {
832             getDataWindow()->pHeaderBar->SetPosSizePixel(
833                         Point(0, 0),
834                         Size( GetOutputSizePixel().Width(), GetTitleHeight() )
835                         );
836         }
837     }
838 
839     // vertikalen Scrollbar korrigieren
840     UpdateScrollbars();
841 
842     // ggf. Repaint ausl"osen
843     if ( GetUpdateMode() )
844     {
845         getDataWindow()->Invalidate();
846         Control::Invalidate();
847         if ( getDataWindow()->bAutoSizeLastCol && nPos ==ColCount() )
848             SetColumnWidth( GetColumnId( nPos - 1 ), LONG_MAX );
849     }
850 
851     if ( isAccessibleAlive() )
852     {
853         commitTableEvent(
854             TABLE_MODEL_CHANGED,
855             makeAny( AccessibleTableModelChange(    DELETE,
856                                                     0,
857                                                     GetRowCount(),
858                                                     nPos,
859                                                     nPos
860                                                )
861             ),
862             Any()
863         );
864 
865         commitHeaderBarEvent(
866             CHILD,
867             Any(),
868             makeAny( CreateAccessibleColumnHeader( nPos ) ),
869             sal_True
870         );
871     }
872 }
873 
874 //-------------------------------------------------------------------
875 
RemoveColumns()876 void BrowseBox::RemoveColumns()
877 {
878     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
879 
880     unsigned int nOldCount = pCols->Count();
881     // alle Spalten entfernen
882     while ( pCols->Count() )
883         delete ( pCols->Remove( (sal_uLong) 0 ));
884 
885     // Spaltenselektion korrigieren
886     if ( pColSel )
887     {
888         pColSel->SelectAll(sal_False);
889         pColSel->SetTotalRange( Range( 0, 0 ) );
890     }
891 
892     // Spaltencursor korrigieren
893     nCurColId = 0;
894     nFirstCol = 0;
895 
896     if ( getDataWindow()->pHeaderBar )
897         getDataWindow()->pHeaderBar->Clear( );
898 
899     // vertikalen Scrollbar korrigieren
900     UpdateScrollbars();
901 
902     // ggf. Repaint ausl"osen
903     if ( GetUpdateMode() )
904     {
905         getDataWindow()->Invalidate();
906         Control::Invalidate();
907     }
908 
909     if ( isAccessibleAlive() )
910     {
911         if ( pCols->Count() != nOldCount )
912         {
913             // all columns should be removed, so we remove the column header bar and append it again
914             // to avoid to notify every column remove
915             commitBrowseBoxEvent(
916                 CHILD,
917                 Any(),
918                 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_COLUMNHEADERBAR))
919             );
920 
921             // and now append it again
922             commitBrowseBoxEvent(
923                 CHILD,
924                 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_COLUMNHEADERBAR)),
925                 Any()
926             );
927 
928             // notify a table model change
929             commitTableEvent(
930                 TABLE_MODEL_CHANGED,
931                 makeAny ( AccessibleTableModelChange( DELETE,
932                                 0,
933                                 GetRowCount(),
934                                 0,
935                                 nOldCount
936                             )
937                         ),
938                 Any()
939             );
940         }
941     }
942 }
943 
944 //-------------------------------------------------------------------
945 
GetColumnTitle(sal_uInt16 nId) const946 String BrowseBox::GetColumnTitle( sal_uInt16 nId ) const
947 {
948     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
949 
950     sal_uInt16 nItemPos = GetColumnPos( nId );
951     if ( nItemPos >= pCols->Count() )
952         return String();
953     return pCols->GetObject(nItemPos)->Title();
954 }
955 
956 //-------------------------------------------------------------------
957 
GetRowCount() const958 long BrowseBox::GetRowCount() const
959 {
960     return nRowCount;
961 }
962 
963 //-------------------------------------------------------------------
964 
ColCount() const965 sal_uInt16 BrowseBox::ColCount() const
966 {
967     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
968 
969     return (sal_uInt16) pCols->Count();
970 }
971 
972 //-------------------------------------------------------------------
973 
ImpGetDataRowHeight() const974 long BrowseBox::ImpGetDataRowHeight() const
975 {
976     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
977 
978     BrowseBox *pThis = (BrowseBox*)this;
979     pThis->nDataRowHeight = pThis->CalcReverseZoom(pDataWin->GetTextHeight() + 2);
980     pThis->Resize();
981     getDataWindow()->Invalidate();
982     return nDataRowHeight;
983 }
984 
985 //-------------------------------------------------------------------
986 
SetDataRowHeight(long nPixel)987 void BrowseBox::SetDataRowHeight( long nPixel )
988 {
989     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
990 
991     nDataRowHeight = CalcReverseZoom(nPixel);
992     Resize();
993     getDataWindow()->Invalidate();
994 }
995 
996 //-------------------------------------------------------------------
997 
SetTitleLines(sal_uInt16 nLines)998 void BrowseBox::SetTitleLines( sal_uInt16 nLines )
999 {
1000     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1001 
1002     nTitleLines = nLines;
1003 }
1004 
1005 //-------------------------------------------------------------------
1006 
ScrollColumns(long nCols)1007 long BrowseBox::ScrollColumns( long nCols )
1008 {
1009     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1010 
1011     if ( nFirstCol + nCols < 0 ||
1012          nFirstCol + nCols >= (long)pCols->Count() )
1013          //?MI: pCols->GetObject( nFirstCol + nCols )->IsFrozen() )
1014         return 0;
1015 
1016     // implicitly hides cursor while scrolling
1017     StartScroll();
1018     bScrolling = sal_True;
1019     sal_Bool bScrollable = pDataWin->GetBackground().IsScrollable();
1020     sal_Bool bInvalidateView = sal_False;
1021 
1022     // scrolling one column to the right?
1023     if ( nCols == 1 )
1024     {
1025         // update internal value and scrollbar
1026         ++nFirstCol;
1027         aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1028 
1029         if ( !bScrollable )
1030         {
1031             bInvalidateView = sal_True;
1032         }
1033         else
1034         {
1035             long nDelta = pCols->GetObject(nFirstCol-1)->Width();
1036             long nFrozenWidth = GetFrozenWidth();
1037 
1038             Rectangle aScrollRect(  Point( nFrozenWidth + nDelta, 0 ),
1039                                     Size ( GetOutputSizePixel().Width() - nFrozenWidth - nDelta,
1040                                            GetTitleHeight() - 1
1041                                          ) );
1042 
1043             // scroll the header bar area (if there is no dedicated HeaderBar control)
1044             if ( !getDataWindow()->pHeaderBar && nTitleLines )
1045             {
1046                 // actually scroll
1047                 Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
1048 
1049                 // invalidate the area of the column which was scrolled out to the left hand side
1050                 Rectangle aInvalidateRect( aScrollRect );
1051                 aInvalidateRect.Left() = nFrozenWidth;
1052                 aInvalidateRect.Right() = nFrozenWidth + nDelta - 1;
1053                 Invalidate( aInvalidateRect );
1054             }
1055 
1056             // scroll the data-area
1057             aScrollRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
1058 
1059             // actually scroll
1060             pDataWin->Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
1061 
1062             // invalidate the area of the column which was scrolled out to the left hand side
1063             aScrollRect.Left() = nFrozenWidth;
1064             aScrollRect.Right() = nFrozenWidth + nDelta - 1;
1065             getDataWindow()->Invalidate( aScrollRect );
1066         }
1067     }
1068 
1069     // scrolling one column to the left?
1070     else if ( nCols == -1 )
1071     {
1072         --nFirstCol;
1073         aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1074 
1075         if ( !bScrollable )
1076         {
1077             bInvalidateView = sal_True;
1078         }
1079         else
1080         {
1081             long nDelta = pCols->GetObject(nFirstCol)->Width();
1082             long nFrozenWidth = GetFrozenWidth();
1083 
1084             Rectangle aScrollRect(  Point(  nFrozenWidth, 0 ),
1085                                     Size (  GetOutputSizePixel().Width() - nFrozenWidth,
1086                                             GetTitleHeight() - 1
1087                                          ) );
1088 
1089             // scroll the header bar area (if there is no dedicated HeaderBar control)
1090             if ( !getDataWindow()->pHeaderBar && nTitleLines )
1091             {
1092                 Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
1093             }
1094 
1095             // scroll the data-area
1096             aScrollRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
1097             pDataWin->Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
1098         }
1099     }
1100     else
1101     {
1102         if ( GetUpdateMode() )
1103         {
1104             Invalidate( Rectangle(
1105                 Point( GetFrozenWidth(), 0 ),
1106                 Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
1107             getDataWindow()->Invalidate( Rectangle(
1108                 Point( GetFrozenWidth(), 0 ),
1109                 pDataWin->GetSizePixel() ) );
1110         }
1111 
1112         nFirstCol = nFirstCol + (sal_uInt16)nCols;
1113         aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1114     }
1115 
1116     // ggf. externe Headerbar anpassen
1117     if ( getDataWindow()->pHeaderBar )
1118     {
1119         long nWidth = 0;
1120         for ( sal_uInt16 nCol = 0;
1121               nCol < pCols->Count() && nCol < nFirstCol;
1122               ++nCol )
1123         {
1124             // HandleColumn nicht
1125             if ( pCols->GetObject(nCol)->GetId() )
1126                 nWidth += pCols->GetObject(nCol)->Width();
1127         }
1128 
1129         getDataWindow()->pHeaderBar->SetOffset( nWidth );
1130     }
1131 
1132     if( bInvalidateView )
1133     {
1134         Control::Invalidate( INVALIDATE_NOCHILDREN );
1135         pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1136     }
1137 
1138     // implicitly show cursor after scrolling
1139     if ( nCols )
1140     {
1141         getDataWindow()->Update();
1142         Update();
1143     }
1144     bScrolling = sal_False;
1145     EndScroll();
1146 
1147     return nCols;
1148 }
1149 
1150 //-------------------------------------------------------------------
1151 
ScrollRows(long nRows)1152 long BrowseBox::ScrollRows( long nRows )
1153 {
1154     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1155 
1156     // out of range?
1157     if ( getDataWindow()->bNoScrollBack && nRows < 0 )
1158         return 0;
1159 
1160     // compute new top row
1161     long nTmpMin = Min( (long)(nTopRow + nRows), (long)(nRowCount - 1) );
1162 
1163     long nNewTopRow = Max( (long)nTmpMin, (long)0 );
1164 
1165     if ( nNewTopRow == nTopRow )
1166         return 0;
1167 
1168     sal_uInt16 nVisibleRows =
1169         (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1170 
1171     VisibleRowsChanged(nNewTopRow, nVisibleRows);
1172 
1173     // compute new top row again (nTopRow might have changed!)
1174     nTmpMin = Min( (long)(nTopRow + nRows), (long)(nRowCount - 1) );
1175 
1176     nNewTopRow = Max( (long)nTmpMin, (long)0 );
1177 
1178     StartScroll();
1179 
1180     // scroll area on screen and/or repaint
1181     long nDeltaY = GetDataRowHeight() * ( nNewTopRow - nTopRow );
1182     long nOldTopRow = nTopRow;
1183     nTopRow = nNewTopRow;
1184 
1185     if ( GetUpdateMode() )
1186     {
1187         pVScroll->SetRange( Range( 0L, nRowCount ) );
1188         pVScroll->SetThumbPos( nTopRow );
1189 
1190         if( pDataWin->GetBackground().IsScrollable() &&
1191             Abs( nDeltaY ) > 0 &&
1192             Abs( nDeltaY ) < pDataWin->GetSizePixel().Height() )
1193         {
1194             pDataWin->Scroll( 0, (short)-nDeltaY, SCROLL_FLAGS );
1195         }
1196         else
1197             getDataWindow()->Invalidate();
1198 
1199         if ( nTopRow - nOldTopRow )
1200             getDataWindow()->Update();
1201     }
1202 
1203     EndScroll();
1204 
1205     return nTopRow - nOldTopRow;
1206 }
1207 
1208 //-------------------------------------------------------------------
1209 
ScrollPages(long)1210 long BrowseBox::ScrollPages( long )
1211 {
1212     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1213 
1214     return ScrollRows( pDataWin->GetSizePixel().Height() / GetDataRowHeight() );
1215 }
1216 
1217 //-------------------------------------------------------------------
1218 
RowModified(long nRow,sal_uInt16 nColId)1219 void BrowseBox::RowModified( long nRow, sal_uInt16 nColId )
1220 {
1221     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1222 
1223     if ( !GetUpdateMode() )
1224         return;
1225 
1226     Rectangle aRect;
1227     if ( nColId == USHRT_MAX )
1228         // invalidate the whole row
1229         aRect = Rectangle( Point( 0, (nRow-nTopRow) * GetDataRowHeight() ),
1230                     Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1231     else
1232     {
1233         // invalidate the specific field
1234         aRect = GetFieldRectPixel( nRow, nColId, sal_False );
1235     }
1236     getDataWindow()->Invalidate( aRect );
1237 }
1238 
1239 //-------------------------------------------------------------------
1240 
Clear()1241 void BrowseBox::Clear()
1242 {
1243     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1244 
1245     // adjust the total number of rows
1246     DoHideCursor( "Clear" );
1247     long nOldRowCount = nRowCount;
1248     nRowCount = 0;
1249     nCurRow = BROWSER_ENDOFSELECTION;
1250     nTopRow = 0;
1251     nCurColId = 0;
1252 
1253     // nFirstCol darf nicht zurueckgesetzt werden, da ansonsten das Scrollen
1254     // total durcheinander kommt
1255     // nFirstCol darf nur beim Hinzufuegen oder Loeschen von Spalten geaendert werden
1256     // nFirstCol = 0; ->Falsch!!!!
1257     aHScroll.SetThumbPos( 0 );
1258     pVScroll->SetThumbPos( 0 );
1259 
1260     Invalidate();
1261     UpdateScrollbars();
1262     SetNoSelection();
1263     DoShowCursor( "Clear" );
1264     CursorMoved();
1265 
1266     if ( isAccessibleAlive() )
1267     {
1268         // all rows should be removed, so we remove the row header bar and append it again
1269         // to avoid to notify every row remove
1270         if ( nOldRowCount != nRowCount )
1271         {
1272             commitBrowseBoxEvent(
1273                 CHILD,
1274                 Any(),
1275                 makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) )
1276             );
1277 
1278             // and now append it again
1279             commitBrowseBoxEvent(
1280                 CHILD,
1281                 makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) ),
1282                 Any()
1283             );
1284 
1285             // notify a table model change
1286             commitTableEvent(
1287                 TABLE_MODEL_CHANGED,
1288                 makeAny( AccessibleTableModelChange( DELETE,
1289                     0,
1290                     nOldRowCount,
1291                     0,
1292                     GetColumnCount())
1293                 ),
1294                 Any()
1295             );
1296         }
1297     }
1298 }
1299 // -----------------------------------------------------------------------------
RowInserted(long nRow,long nNumRows,sal_Bool bDoPaint,sal_Bool bKeepSelection)1300 void BrowseBox::RowInserted( long nRow, long nNumRows, sal_Bool bDoPaint, sal_Bool bKeepSelection )
1301 {
1302     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1303 
1304     if (nRow < 0)
1305         nRow = 0;
1306     else if (nRow > nRowCount) // maximal = nRowCount
1307         nRow = nRowCount;
1308 
1309     if ( nNumRows <= 0 )
1310         return;
1311 
1312 #if 0
1313     // Zerlegung in einzelne RowInserted-Aufrufe:
1314     if (nNumRows > 1)
1315     {
1316         for (long i = 0; i < nNumRows; i++)
1317             RowInserted(nRow + i,1,bDoPaint);
1318         return;
1319     }
1320 #endif
1321 
1322     // adjust total row count
1323     sal_Bool bLastRow = nRow >= nRowCount;
1324     nRowCount += nNumRows;
1325 
1326     DoHideCursor( "RowInserted" );
1327 
1328     // must we paint the new rows?
1329     long nOldCurRow = nCurRow;
1330     Size aSz = pDataWin->GetOutputSizePixel();
1331     if ( bDoPaint && nRow >= nTopRow &&
1332          nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1333     {
1334         long nY = (nRow-nTopRow) * GetDataRowHeight();
1335         if ( !bLastRow )
1336         {
1337             // scroll down the rows behind the new row
1338             pDataWin->SetClipRegion();
1339             if( pDataWin->GetBackground().IsScrollable() )
1340             {
1341                 pDataWin->Scroll( 0, GetDataRowHeight() * nNumRows,
1342                                 Rectangle( Point( 0, nY ),
1343                                         Size( aSz.Width(), aSz.Height() - nY ) ),
1344                                 SCROLL_FLAGS );
1345             }
1346             else
1347                 pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1348         }
1349         else
1350             // scroll would cause a repaint, so we must explicitly invalidate
1351             pDataWin->Invalidate( Rectangle( Point( 0, nY ),
1352                          Size( aSz.Width(), nNumRows * GetDataRowHeight() ) ) );
1353     }
1354 
1355     // ggf. Top-Row korrigieren
1356     if ( nRow < nTopRow )
1357         nTopRow += nNumRows;
1358 
1359     // adjust the selection
1360     if ( bMultiSelection )
1361         uRow.pSel->Insert( nRow, nNumRows );
1362     else if ( uRow.nSel != BROWSER_ENDOFSELECTION && nRow <= uRow.nSel )
1363         uRow.nSel += nNumRows;
1364 
1365     // adjust the cursor
1366     if ( nCurRow == BROWSER_ENDOFSELECTION )
1367         GoToRow( 0, sal_False, bKeepSelection );
1368     else if ( nRow <= nCurRow )
1369         GoToRow( nCurRow += nNumRows, sal_False, bKeepSelection );
1370 
1371     // adjust the vertical scrollbar
1372     if ( bDoPaint )
1373     {
1374         UpdateScrollbars();
1375         AutoSizeLastColumn();
1376     }
1377 
1378     DoShowCursor( "RowInserted" );
1379     // notify accessible that rows were inserted
1380     if ( isAccessibleAlive() )
1381     {
1382         commitTableEvent(
1383             TABLE_MODEL_CHANGED,
1384             makeAny( AccessibleTableModelChange(
1385                         INSERT,
1386                         nRow,
1387                         nRow + nNumRows,
1388                         0,
1389                         GetColumnCount()
1390                     )
1391             ),
1392             Any()
1393         );
1394 
1395         for (sal_Int32 i = nRow+1 ; i <= nRowCount ; ++i)
1396         {
1397             commitHeaderBarEvent(
1398                 CHILD,
1399                 makeAny( CreateAccessibleRowHeader( i ) ),
1400                 Any(),
1401                 sal_False
1402             );
1403         }
1404     }
1405 
1406     if ( nCurRow != nOldCurRow )
1407         CursorMoved();
1408 
1409     DBG_ASSERT(nRowCount > 0,"BrowseBox: nRowCount <= 0");
1410     DBG_ASSERT(nCurRow >= 0,"BrowseBox: nCurRow < 0");
1411     DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1412 }
1413 
1414 //-------------------------------------------------------------------
1415 
RowRemoved(long nRow,long nNumRows,sal_Bool bDoPaint)1416 void BrowseBox::RowRemoved( long nRow, long nNumRows, sal_Bool bDoPaint )
1417 {
1418     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1419 
1420     if ( nRow < 0 )
1421         nRow = 0;
1422     else if ( nRow >= nRowCount )
1423         nRow = nRowCount - 1;
1424 
1425     if ( nNumRows <= 0 )
1426         return;
1427 
1428     if ( nRowCount <= 0 )
1429         return;
1430 
1431     if ( bDoPaint )
1432     {
1433         // hide cursor and selection
1434         DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1435         ToggleSelection();
1436         DoHideCursor( "RowRemoved" );
1437     }
1438 
1439     // adjust total row count
1440     nRowCount -= nNumRows;
1441     if (nRowCount < 0) nRowCount = 0;
1442     long nOldCurRow = nCurRow;
1443 
1444     // adjust the selection
1445     if ( bMultiSelection )
1446         // uRow.pSel->Remove( nRow, nNumRows );
1447         for ( long i = 0; i < nNumRows; i++ )
1448             uRow.pSel->Remove( nRow );
1449     else if ( nRow < uRow.nSel && uRow.nSel >= nNumRows )
1450         uRow.nSel -= nNumRows;
1451     else if ( nRow <= uRow.nSel )
1452         uRow.nSel = BROWSER_ENDOFSELECTION;
1453 
1454     // adjust the cursor
1455     if ( nRowCount == 0 )   // don't compare nRowCount with nNumRows as nNumRows already was subtracted from nRowCount
1456         nCurRow = BROWSER_ENDOFSELECTION;
1457     else if ( nRow < nCurRow )
1458     {
1459         nCurRow -= Min( nCurRow - nRow, nNumRows );
1460         // with the above nCurRow points a) to the first row after the removed block or b) to the same line
1461         // as before, but moved up nNumRows
1462         // case a) needs an additional correction if the last n lines were deleted, as 'the first row after the
1463         // removed block' is an invalid position then
1464         // FS - 09/28/99 - 68429
1465         if (nCurRow == nRowCount)
1466             --nCurRow;
1467     }
1468     else if( nRow == nCurRow && nCurRow == nRowCount )
1469         nCurRow = nRowCount-1;
1470 
1471     // is the deleted row visible?
1472     Size aSz = pDataWin->GetOutputSizePixel();
1473     if ( nRow >= nTopRow &&
1474          nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1475     {
1476         if ( bDoPaint )
1477         {
1478             // scroll up the rows behind the deleted row
1479             // if there are Rows behind
1480             if (nRow < nRowCount)
1481             {
1482                 long nY = (nRow-nTopRow) * GetDataRowHeight();
1483                 pDataWin->SetClipRegion();
1484                 if( pDataWin->GetBackground().IsScrollable() )
1485                 {
1486                     pDataWin->Scroll( 0, - (short) GetDataRowHeight() * nNumRows,
1487                         Rectangle( Point( 0, nY ), Size( aSz.Width(),
1488                             aSz.Height() - nY + nNumRows*GetDataRowHeight() ) ),
1489                             SCROLL_FLAGS );
1490                 }
1491                 else
1492                     pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1493             }
1494             else
1495             {
1496                 // Repaint the Rect of the deleted row
1497                 Rectangle aRect(
1498                         Point( 0, (nRow-nTopRow)*GetDataRowHeight() ),
1499                         Size( pDataWin->GetSizePixel().Width(),
1500                               nNumRows * GetDataRowHeight() ) );
1501                 pDataWin->Invalidate( aRect );
1502             }
1503         }
1504     }
1505     // is the deleted row above of the visible area?
1506     else if ( nRow < nTopRow )
1507         nTopRow = nTopRow >= nNumRows ? nTopRow-nNumRows : 0;
1508 
1509     if ( bDoPaint )
1510     {
1511         // reshow cursor and selection
1512         ToggleSelection();
1513         DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1514         DoShowCursor( "RowRemoved" );
1515 
1516         // adjust the vertical scrollbar
1517         UpdateScrollbars();
1518         AutoSizeLastColumn();
1519     }
1520 
1521     if ( isAccessibleAlive() )
1522     {
1523         if ( nRowCount == 0 )
1524         {
1525             // all columns should be removed, so we remove the column header bar and append it again
1526             // to avoid to notify every column remove
1527             commitBrowseBoxEvent(
1528                 CHILD,
1529                 Any(),
1530                 makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) )
1531             );
1532 
1533             // and now append it again
1534             commitBrowseBoxEvent(
1535                 CHILD,
1536                 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_ROWHEADERBAR)),
1537                 Any()
1538             );
1539             commitBrowseBoxEvent(
1540                 CHILD,
1541                 Any(),
1542                 makeAny( m_pImpl->getAccessibleTable() )
1543             );
1544 
1545             // and now append it again
1546             commitBrowseBoxEvent(
1547                 CHILD,
1548                 makeAny( m_pImpl->getAccessibleTable() ),
1549                 Any()
1550             );
1551         }
1552         else
1553         {
1554             commitTableEvent(
1555                 TABLE_MODEL_CHANGED,
1556                 makeAny( AccessibleTableModelChange(
1557                             DELETE,
1558                             nRow,
1559                             nRow + nNumRows,
1560                             0,
1561                             GetColumnCount()
1562                             )
1563                 ),
1564                 Any()
1565             );
1566 
1567             for (sal_Int32 i = nRow+1 ; i <= (nRow+nNumRows) ; ++i)
1568             {
1569                 commitHeaderBarEvent(
1570                     CHILD,
1571                     Any(),
1572                     makeAny( CreateAccessibleRowHeader( i ) ),
1573                     sal_False
1574                 );
1575             }
1576         }
1577     }
1578 
1579     if ( nOldCurRow != nCurRow )
1580         CursorMoved();
1581 
1582     DBG_ASSERT(nRowCount >= 0,"BrowseBox: nRowCount < 0");
1583     DBG_ASSERT(nCurRow >= 0 || nRowCount == 0,"BrowseBox: nCurRow < 0 && nRowCount != 0");
1584     DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1585 }
1586 
1587 //-------------------------------------------------------------------
1588 
GoToRow(long nRow)1589 sal_Bool BrowseBox::GoToRow( long nRow)
1590 {
1591     return GoToRow(nRow, sal_False, sal_False);
1592 }
1593 
1594 //-------------------------------------------------------------------
1595 
GoToRowAndDoNotModifySelection(long nRow)1596 sal_Bool BrowseBox::GoToRowAndDoNotModifySelection( long nRow )
1597 {
1598     return GoToRow( nRow, sal_False, sal_True );
1599 }
1600 
1601 //-------------------------------------------------------------------
GoToRow(long nRow,sal_Bool bRowColMove,sal_Bool bKeepSelection)1602 sal_Bool BrowseBox::GoToRow( long nRow, sal_Bool bRowColMove, sal_Bool bKeepSelection )
1603 {
1604     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1605 
1606     long nOldCurRow = nCurRow;
1607 
1608     // nothing to do?
1609     if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) )
1610         return sal_True;
1611 
1612     // out of range?
1613     if ( nRow < 0 || nRow >= nRowCount )
1614         return sal_False;
1615 
1616     // nicht erlaubt?
1617     if ( ( !bRowColMove && !IsCursorMoveAllowed( nRow, nCurColId ) ) )
1618         return sal_False;
1619 
1620     if ( getDataWindow()->bNoScrollBack && nRow < nTopRow )
1621         nRow = nTopRow;
1622 
1623     // compute the last visible row
1624     Size aSz( pDataWin->GetSizePixel() );
1625     sal_uInt16 nVisibleRows = sal_uInt16( aSz.Height() / GetDataRowHeight() - 1 );
1626     long nLastRow = nTopRow + nVisibleRows;
1627 
1628     // suspend Updates
1629     getDataWindow()->EnterUpdateLock();
1630 
1631     // ggf. altes Highlight weg
1632     if ( !bMultiSelection && !bKeepSelection )
1633         ToggleSelection();
1634     DoHideCursor( "GoToRow" );
1635 
1636     // must we scroll?
1637     sal_Bool bWasVisible = bSelectionIsVisible;
1638     if (! bMultiSelection)
1639     {
1640         if( !bKeepSelection )
1641             bSelectionIsVisible = sal_False;
1642     }
1643     if ( nRow < nTopRow )
1644         ScrollRows( nRow - nTopRow );
1645     else if ( nRow > nLastRow )
1646         ScrollRows( nRow - nLastRow );
1647     bSelectionIsVisible = bWasVisible;
1648 
1649     // adjust cursor (selection) and thumb
1650     if ( GetUpdateMode() )
1651         pVScroll->SetThumbPos( nTopRow );
1652 
1653     // relative positioning (because nCurRow might have changed in the meantime)!
1654     if (nCurRow != BROWSER_ENDOFSELECTION )
1655         nCurRow = nCurRow + (nRow - nOldCurRow);
1656 
1657     // make sure that the current position is valid
1658     if (nCurRow == BROWSER_ENDOFSELECTION && nRowCount > 0)
1659         nCurRow = 0;
1660     else if ( nCurRow >= nRowCount )
1661         nCurRow = nRowCount - 1;
1662     aSelRange = Range( nCurRow, nCurRow );
1663 
1664     // ggf. neues Highlight anzeigen
1665     if ( !bMultiSelection && !bKeepSelection )
1666         uRow.nSel = nRow;
1667 
1668     // resume Updates
1669     getDataWindow()->LeaveUpdateLock();
1670 
1671     // Cursor+Highlight
1672     if ( !bMultiSelection && !bKeepSelection)
1673         ToggleSelection();
1674     DoShowCursor( "GoToRow" );
1675     if ( !bRowColMove  && nOldCurRow != nCurRow )
1676         CursorMoved();
1677 
1678     if ( !bMultiSelection && !bKeepSelection )
1679     {
1680         if ( !bSelecting )
1681             Select();
1682         else
1683             bSelect = sal_True;
1684     }
1685     return sal_True;
1686 }
1687 
1688 //-------------------------------------------------------------------
1689 
GoToColumnId(sal_uInt16 nColId)1690 sal_Bool BrowseBox::GoToColumnId( sal_uInt16 nColId)
1691 {
1692     return GoToColumnId(nColId,sal_True,sal_False);
1693 }
1694 
1695 
GoToColumnId(sal_uInt16 nColId,sal_Bool bMakeVisible,sal_Bool bRowColMove)1696 sal_Bool BrowseBox::GoToColumnId( sal_uInt16 nColId, sal_Bool bMakeVisible, sal_Bool bRowColMove)
1697 {
1698     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1699 
1700     if (!bColumnCursor)
1701         return sal_False;
1702 
1703     // erlaubt?
1704     if (!bRowColMove && !IsCursorMoveAllowed( nCurRow, nColId ) )
1705         return sal_False;
1706 
1707     if ( nColId != nCurColId || (bMakeVisible && !IsFieldVisible(nCurRow, nColId, sal_True)))
1708     {
1709         sal_uInt16 nNewPos = GetColumnPos(nColId);
1710         BrowserColumn* pColumn = pCols->GetObject( nNewPos );
1711         DBG_ASSERT( pColumn, "no column object - invalid id?" );
1712         if ( !pColumn )
1713             return sal_False;
1714 
1715         DoHideCursor( "GoToColumnId" );
1716         nCurColId = nColId;
1717 
1718         sal_uInt16 nFirstPos = nFirstCol;
1719         sal_uInt16 nWidth = (sal_uInt16)pColumn->Width();
1720         sal_uInt16 nLastPos = GetColumnAtXPosPixel(
1721                             pDataWin->GetSizePixel().Width()-nWidth, sal_False );
1722         sal_uInt16 nFrozen = FrozenColCount();
1723         if ( bMakeVisible && nLastPos &&
1724              nNewPos >= nFrozen && ( nNewPos < nFirstPos || nNewPos > nLastPos ) )
1725         {
1726             if ( nNewPos < nFirstPos )
1727                 ScrollColumns( nNewPos-nFirstPos );
1728             else if ( nNewPos > nLastPos )
1729                 ScrollColumns( nNewPos-nLastPos );
1730         }
1731 
1732         DoShowCursor( "GoToColumnId" );
1733         if (!bRowColMove)
1734             CursorMoved();
1735         return sal_True;
1736     }
1737     return sal_True;
1738 }
1739 
1740 //-------------------------------------------------------------------
1741 
GoToRowColumnId(long nRow,sal_uInt16 nColId)1742 sal_Bool BrowseBox::GoToRowColumnId( long nRow, sal_uInt16 nColId )
1743 {
1744     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1745 
1746     // out of range?
1747     if ( nRow < 0 || nRow >= nRowCount )
1748         return sal_False;
1749 
1750     if (!bColumnCursor)
1751         return sal_False;
1752 
1753     // nothing to do ?
1754     if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) &&
1755          nColId == nCurColId && IsFieldVisible(nCurRow, nColId, sal_True))
1756         return sal_True;
1757 
1758     // erlaubt?
1759     if (!IsCursorMoveAllowed(nRow, nColId))
1760         return sal_False;
1761 
1762     DoHideCursor( "GoToRowColumnId" );
1763     sal_Bool bMoved = GoToRow(nRow, sal_True) && GoToColumnId(nColId, sal_True, sal_True);
1764     DoShowCursor( "GoToRowColumnId" );
1765 
1766     if (bMoved)
1767         CursorMoved();
1768 
1769     return bMoved;
1770 }
1771 
1772 //-------------------------------------------------------------------
1773 
SetNoSelection()1774 void BrowseBox::SetNoSelection()
1775 {
1776     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1777 
1778     // is there no selection
1779     if ( ( !pColSel || !pColSel->GetSelectCount() ) &&
1780          ( ( !bMultiSelection && uRow.nSel == BROWSER_ENDOFSELECTION ) ||
1781            ( bMultiSelection && !uRow.pSel->GetSelectCount() ) ) )
1782         // nothing to do
1783         return;
1784 
1785     DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1786     ToggleSelection();
1787 
1788     // unselect all
1789     if ( bMultiSelection )
1790         uRow.pSel->SelectAll(sal_False);
1791     else
1792         uRow.nSel = BROWSER_ENDOFSELECTION;
1793     if ( pColSel )
1794         pColSel->SelectAll(sal_False);
1795     if ( !bSelecting )
1796         Select();
1797     else
1798         bSelect = sal_True;
1799 
1800     // restore screen
1801     DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1802 
1803     if ( isAccessibleAlive() )
1804     {
1805         commitTableEvent(
1806             SELECTION_CHANGED,
1807             Any(),
1808             Any()
1809         );
1810     }
1811 }
1812 
1813 //-------------------------------------------------------------------
1814 
SetSelection(const MultiSelection & rSel)1815 void BrowseBox::SetSelection( const MultiSelection &rSel )
1816 {
1817     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1818     DBG_ASSERT( bMultiSelection, "SetSelection only allowed with Multi-Selection-Mode" );
1819 
1820     // prepare inverted areas
1821     DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1822     ToggleSelection();
1823 
1824     // assign Selection
1825     *uRow.pSel = rSel;
1826 
1827     // only highlight painted areas
1828     pDataWin->Update();
1829 
1830     // notify derived class
1831     if ( !bSelecting )
1832         Select();
1833     else
1834         bSelect = sal_True;
1835 
1836     // restore screen
1837     ToggleSelection();
1838     DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1839 
1840     if ( isAccessibleAlive() )
1841     {
1842         commitTableEvent(
1843             SELECTION_CHANGED,
1844             Any(),
1845             Any()
1846         );
1847     }
1848 }
1849 
1850 //-------------------------------------------------------------------
1851 
SelectAll()1852 void BrowseBox::SelectAll()
1853 {
1854     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1855 
1856     if ( !bMultiSelection )
1857         return;
1858 
1859     DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1860     ToggleSelection();
1861 
1862     // select all rows
1863     if ( pColSel )
1864         pColSel->SelectAll(sal_False);
1865     uRow.pSel->SelectAll(sal_True);
1866 
1867     // Handle-Column nicht highlighten
1868     BrowserColumn *pFirstCol = pCols->GetObject(0);
1869     long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1870 
1871     // highlight the row selection
1872     if ( !bHideSelect )
1873     {
1874         Rectangle aHighlightRect;
1875         sal_uInt16 nVisibleRows =
1876             (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1877         for ( long nRow = Max( nTopRow, uRow.pSel->FirstSelected() );
1878               nRow != BROWSER_ENDOFSELECTION && nRow < nTopRow + nVisibleRows;
1879               nRow = uRow.pSel->NextSelected() )
1880             aHighlightRect.Union( Rectangle(
1881                 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1882                 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) ) );
1883         pDataWin->Invalidate( aHighlightRect );
1884     }
1885 
1886     if ( !bSelecting )
1887         Select();
1888     else
1889         bSelect = sal_True;
1890 
1891     // restore screen
1892     DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1893 
1894     if ( isAccessibleAlive() )
1895     {
1896         commitTableEvent(
1897             SELECTION_CHANGED,
1898             Any(),
1899             Any()
1900         );
1901         commitHeaderBarEvent(
1902             SELECTION_CHANGED,
1903             Any(),
1904             Any(),
1905             sal_True
1906         ); // column header event
1907 
1908         commitHeaderBarEvent(
1909             SELECTION_CHANGED,
1910             Any(),
1911             Any(),
1912             sal_False
1913         ); // row header event
1914     }
1915 }
1916 
1917 //-------------------------------------------------------------------
1918 
SelectRow(long nRow,sal_Bool _bSelect,sal_Bool bExpand)1919 void BrowseBox::SelectRow( long nRow, sal_Bool _bSelect, sal_Bool bExpand )
1920 {
1921     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1922 
1923     if ( !bMultiSelection )
1924     {
1925         // deselecting is impossible, selecting via cursor
1926         if ( _bSelect )
1927             GoToRow(nRow, sal_False);
1928         return;
1929     }
1930 
1931     DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1932 
1933     // remove old selection?
1934     if ( !bExpand || !bMultiSelection )
1935     {
1936         ToggleSelection();
1937         if ( bMultiSelection )
1938             uRow.pSel->SelectAll(sal_False);
1939         else
1940             uRow.nSel = BROWSER_ENDOFSELECTION;
1941         if ( pColSel )
1942             pColSel->SelectAll(sal_False);
1943     }
1944 
1945     // set new selection
1946     if  (   !bHideSelect
1947         &&  (   (   bMultiSelection
1948                 &&  uRow.pSel->GetTotalRange().Max() >= nRow
1949                 &&  uRow.pSel->Select( nRow, _bSelect )
1950                 )
1951             ||  (   !bMultiSelection
1952                 &&  ( uRow.nSel = nRow ) != BROWSER_ENDOFSELECTION )
1953                 )
1954             )
1955     {
1956         // Handle-Column nicht highlighten
1957         BrowserColumn *pFirstCol = pCols->GetObject(0);
1958         long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1959 
1960         // highlight only newly selected part
1961         Rectangle aRect(
1962             Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1963             Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1964         pDataWin->Invalidate( aRect );
1965     }
1966 
1967     if ( !bSelecting )
1968         Select();
1969     else
1970         bSelect = sal_True;
1971 
1972     // restore screen
1973     DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1974 
1975     if ( isAccessibleAlive() )
1976     {
1977         commitTableEvent(
1978             SELECTION_CHANGED,
1979             Any(),
1980             Any()
1981         );
1982         commitHeaderBarEvent(
1983             SELECTION_CHANGED,
1984             Any(),
1985             Any(),
1986             sal_False
1987         ); // row header event
1988     }
1989 }
1990 
1991 //-------------------------------------------------------------------
1992 
GetSelectRowCount() const1993 long BrowseBox::GetSelectRowCount() const
1994 {
1995     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1996 
1997     return bMultiSelection ? uRow.pSel->GetSelectCount() :
1998            uRow.nSel == BROWSER_ENDOFSELECTION ? 0 : 1;
1999 }
2000 
2001 //-------------------------------------------------------------------
2002 
SelectColumnPos(sal_uInt16 nNewColPos,sal_Bool _bSelect,sal_Bool bMakeVisible)2003 void BrowseBox::SelectColumnPos( sal_uInt16 nNewColPos, sal_Bool _bSelect, sal_Bool bMakeVisible )
2004 {
2005     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2006 
2007     if ( !bColumnCursor || nNewColPos == BROWSER_INVALIDID )
2008         return;
2009 
2010     if ( !bMultiSelection )
2011     {
2012         if ( _bSelect )
2013             GoToColumnId( pCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
2014         return;
2015     }
2016     else
2017     {
2018         if ( !GoToColumnId( pCols->GetObject( nNewColPos )->GetId(), bMakeVisible ) )
2019             return;
2020     }
2021 
2022     DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
2023     ToggleSelection();
2024     if ( bMultiSelection )
2025         uRow.pSel->SelectAll(sal_False);
2026     else
2027         uRow.nSel = BROWSER_ENDOFSELECTION;
2028     pColSel->SelectAll(sal_False);
2029 
2030     if ( pColSel->Select( nNewColPos, _bSelect ) )
2031     {
2032         // GoToColumnId( pCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
2033 
2034         // only highlight painted areas
2035         pDataWin->Update();
2036         Rectangle aFieldRectPix( GetFieldRectPixel( nCurRow, nCurColId, sal_False ) );
2037         Rectangle aRect(
2038             Point( aFieldRectPix.Left() - MIN_COLUMNWIDTH, 0 ),
2039             Size( pCols->GetObject(nNewColPos)->Width(),
2040                   pDataWin->GetOutputSizePixel().Height() ) );
2041         pDataWin->Invalidate( aRect );
2042         if ( !bSelecting )
2043             Select();
2044         else
2045             bSelect = sal_True;
2046 
2047         if ( isAccessibleAlive() )
2048         {
2049             commitTableEvent(
2050                 SELECTION_CHANGED,
2051                 Any(),
2052                 Any()
2053             );
2054             commitHeaderBarEvent(
2055                 SELECTION_CHANGED,
2056                 Any(),
2057                 Any(),
2058                 sal_True
2059             ); // column header event
2060         }
2061     }
2062 
2063     // restore screen
2064     DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
2065 }
2066 
2067 //-------------------------------------------------------------------
2068 
GetSelectColumnCount() const2069 sal_uInt16 BrowseBox::GetSelectColumnCount() const
2070 {
2071     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2072 
2073     // while bAutoSelect (==!pColSel), 1 if any rows (yes rows!) else none
2074     return pColSel ? (sal_uInt16) pColSel->GetSelectCount() :
2075            nCurRow >= 0 ? 1 : 0;
2076 }
2077 
2078 //-------------------------------------------------------------------
FirstSelectedColumn() const2079 long BrowseBox::FirstSelectedColumn( ) const
2080 {
2081     return pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
2082 }
2083 
2084 //-------------------------------------------------------------------
NextSelectedColumn() const2085 long BrowseBox::NextSelectedColumn( ) const
2086 {
2087     return pColSel ? pColSel->NextSelected() : BROWSER_ENDOFSELECTION;
2088 }
2089 
2090 //-------------------------------------------------------------------
2091 
FirstSelectedRow(sal_Bool bInverse)2092 long BrowseBox::FirstSelectedRow( sal_Bool bInverse )
2093 {
2094     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2095 
2096     return bMultiSelection ? uRow.pSel->FirstSelected(bInverse) : uRow.nSel;
2097 }
2098 
2099 //-------------------------------------------------------------------
2100 
NextSelectedRow()2101 long BrowseBox::NextSelectedRow()
2102 {
2103     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2104 
2105     return bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION;
2106 }
2107 
2108 //-------------------------------------------------------------------
2109 
PrevSelectedRow()2110 long BrowseBox::PrevSelectedRow()
2111 {
2112     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2113 
2114     return bMultiSelection ? uRow.pSel->PrevSelected() : BROWSER_ENDOFSELECTION;
2115 }
2116 
2117 //-------------------------------------------------------------------
2118 
LastSelectedRow()2119 long BrowseBox::LastSelectedRow()
2120 {
2121     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2122 
2123     return bMultiSelection ? uRow.pSel->LastSelected() : uRow.nSel;
2124 }
2125 
2126 //-------------------------------------------------------------------
2127 
IsRowSelected(long nRow) const2128 bool BrowseBox::IsRowSelected( long nRow ) const
2129 {
2130     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2131 
2132     return bMultiSelection ? uRow.pSel->IsSelected(nRow) : nRow == uRow.nSel;
2133 }
2134 
2135 //-------------------------------------------------------------------
2136 
IsColumnSelected(sal_uInt16 nColumnId) const2137 bool BrowseBox::IsColumnSelected( sal_uInt16 nColumnId ) const
2138 {
2139     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2140 
2141     return pColSel ? pColSel->IsSelected( GetColumnPos(nColumnId) ) :
2142                      nCurColId == nColumnId;
2143 }
2144 
2145 //-------------------------------------------------------------------
2146 
IsAllSelected() const2147 sal_Bool BrowseBox::IsAllSelected() const
2148 {
2149     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2150 
2151     return bMultiSelection && uRow.pSel->IsAllSelected();
2152 }
2153 
2154 //-------------------------------------------------------------------
2155 
MakeFieldVisible(long nRow,sal_uInt16 nColId,sal_Bool bComplete)2156 sal_Bool BrowseBox::MakeFieldVisible
2157 (
2158     long    nRow,       // Zeilen-Nr des Feldes (beginnend mit 0)
2159     sal_uInt16  nColId,     // Spalten-Id des Feldes
2160     sal_Bool    bComplete   // (== sal_False), sal_True => vollst"andig sichtbar machen
2161 )
2162 
2163 /*  [Beschreibung]
2164 
2165     Macht das durch 'nRow' und 'nColId' beschriebene Feld durch
2166     entsprechendes scrollen sichtbar. Ist 'bComplete' gesetzt, dann wird
2167     gefordert, da\s das Feld ganz sichtbar wird.
2168 
2169     [R"uckgabewert]
2170 
2171     sal_Bool            sal_True
2172                     Das angegebene Feld wurde sichtbar gemacht, bzw. war
2173                     bereits sichtbar.
2174 
2175                     sal_False
2176                     Das angegebene Feld konnte nicht sichtbar bzw. bei
2177                     'bComplete' nicht vollst"andig sichtbar gemacht werden.
2178 */
2179 
2180 {
2181     Size aTestSize = pDataWin->GetSizePixel();
2182 
2183     if ( !bBootstrapped ||
2184          ( aTestSize.Width() == 0 && aTestSize.Height() == 0 ) )
2185         return sal_False;
2186 
2187     // ist es schon sichtbar?
2188     sal_Bool bVisible = IsFieldVisible( nRow, nColId, bComplete );
2189     if ( bVisible )
2190         return sal_True;
2191 
2192     // Spaltenposition und Feld-Rechteck und Ausgabebereich berechnen
2193     sal_uInt16 nColPos = GetColumnPos( nColId );
2194     Rectangle aFieldRect = GetFieldRectPixel( nRow, nColId, sal_False );
2195     Rectangle aDataRect = Rectangle( Point(0, 0), pDataWin->GetSizePixel() );
2196 
2197     // links au\serhalb?
2198     if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
2199         // => nach rechts scrollen
2200         ScrollColumns( nColPos - nFirstCol );
2201 
2202     // solange rechts au\serhalb
2203     while ( aDataRect.Right() < ( bComplete
2204                 ? aFieldRect.Right()
2205                 : aFieldRect.Left()+aFieldRect.GetWidth()/2 ) )
2206     {
2207         // => nach links scrollen
2208         if ( ScrollColumns( 1 ) != 1 )
2209             // nichts mehr zu scrollen
2210             break;
2211         aFieldRect = GetFieldRectPixel( nRow, nColId, sal_False );
2212     }
2213 
2214     // oben au\serhalb?
2215     if ( nRow < nTopRow )
2216         // nach unten scrollen
2217         ScrollRows( nRow - nTopRow );
2218 
2219     // unten au\serhalb?
2220     long nBottomRow = nTopRow + GetVisibleRows();
2221     // OV: damit nBottomRow die Nummer der letzten sichtbaren Zeile ist
2222     // (Zaehlung ab Null!), muss sie dekrementiert werden.
2223     // Beispiel: BrowseBox enthaelt genau einen Eintrag. nBottomRow := 0 + 1 - 1
2224     if( nBottomRow )
2225         nBottomRow--;
2226 
2227     if ( nRow > nBottomRow )
2228         // nach oben scrollen
2229         ScrollRows( nRow - nBottomRow );
2230 
2231     // jetzt kann es immer noch nicht passen, z.B. weil Window zu klein
2232     return IsFieldVisible( nRow, nColId, bComplete );
2233 }
2234 
2235 //-------------------------------------------------------------------
2236 
IsFieldVisible(long nRow,sal_uInt16 nColumnId,sal_Bool bCompletely) const2237 sal_Bool BrowseBox::IsFieldVisible( long nRow, sal_uInt16 nColumnId,
2238                                 sal_Bool bCompletely ) const
2239 {
2240     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2241 
2242     // durch frozen-Column verdeckt?
2243     sal_uInt16 nColPos = GetColumnPos( nColumnId );
2244     if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
2245         return sal_False;
2246 
2247     Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2248     if ( aRect.IsEmpty() )
2249         return sal_False;
2250 
2251     // get the visible area
2252     Rectangle aOutRect( Point(0, 0), pDataWin->GetOutputSizePixel() );
2253 
2254     if ( bCompletely )
2255         // test if the field is completely visible
2256         return aOutRect.IsInside( aRect );
2257     else
2258         // test if the field is partly of completely visible
2259         return !aOutRect.Intersection( aRect ).IsEmpty();
2260 }
2261 
2262 //-------------------------------------------------------------------
2263 
GetFieldRectPixel(long nRow,sal_uInt16 nColumnId,sal_Bool bRelToBrowser) const2264 Rectangle BrowseBox::GetFieldRectPixel( long nRow, sal_uInt16 nColumnId,
2265                                         sal_Bool bRelToBrowser) const
2266 {
2267     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2268 
2269     // get the rectangle relative to DataWin
2270     Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2271     if ( aRect.IsEmpty() )
2272         return aRect;
2273 
2274     // adjust relative to BrowseBox's output area
2275     Point aTopLeft( aRect.TopLeft() );
2276     if ( bRelToBrowser )
2277     {
2278         aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2279         aTopLeft = ScreenToOutputPixel( aTopLeft );
2280     }
2281 
2282     return Rectangle( aTopLeft, aRect.GetSize() );
2283 }
2284 
2285 //-------------------------------------------------------------------
2286 
GetRowRectPixel(long nRow,sal_Bool bRelToBrowser) const2287 Rectangle BrowseBox::GetRowRectPixel( long nRow, sal_Bool bRelToBrowser  ) const
2288 {
2289     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2290 
2291     // get the rectangle relative to DataWin
2292     Rectangle aRect;
2293     if ( nTopRow > nRow )
2294         // row is above visible area
2295         return aRect;
2296     aRect = Rectangle(
2297         Point( 0, GetDataRowHeight() * (nRow-nTopRow) ),
2298         Size( pDataWin->GetOutputSizePixel().Width(), GetDataRowHeight() ) );
2299     if ( aRect.TopLeft().Y() > pDataWin->GetOutputSizePixel().Height() )
2300         // row is below visible area
2301         return aRect;
2302 
2303     // adjust relative to BrowseBox's output area
2304     Point aTopLeft( aRect.TopLeft() );
2305     if ( bRelToBrowser )
2306     {
2307         aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2308         aTopLeft = ScreenToOutputPixel( aTopLeft );
2309     }
2310 
2311     return Rectangle( aTopLeft, aRect.GetSize() );
2312 }
2313 
2314 //-------------------------------------------------------------------
2315 
ImplFieldRectPixel(long nRow,sal_uInt16 nColumnId) const2316 Rectangle BrowseBox::ImplFieldRectPixel( long nRow, sal_uInt16 nColumnId ) const
2317 {
2318     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2319 
2320     // compute the X-coordinte realtiv to DataWin by accumulation
2321     long nColX = 0;
2322     sal_uInt16 nFrozenCols = FrozenColCount();
2323     sal_uInt16 nCol;
2324     for ( nCol = 0;
2325           nCol < pCols->Count() && pCols->GetObject(nCol)->GetId() != nColumnId;
2326           ++nCol )
2327         if ( pCols->GetObject(nCol)->IsFrozen() || nCol >= nFirstCol )
2328             nColX += pCols->GetObject(nCol)->Width();
2329 
2330     if ( nCol >= pCols->Count() || ( nCol >= nFrozenCols && nCol < nFirstCol ) )
2331         return Rectangle();
2332 
2333     // compute the Y-coordinate relative to DataWin
2334     long nRowY = GetDataRowHeight();
2335     if ( nRow != BROWSER_ENDOFSELECTION ) // #105497# OJ
2336         nRowY = ( nRow - nTopRow ) * GetDataRowHeight();
2337 
2338     // assemble the Rectangle relative to DataWin
2339     return Rectangle(
2340         Point( nColX + MIN_COLUMNWIDTH, nRowY ),
2341         Size( pCols->GetObject(nCol)->Width() - 2*MIN_COLUMNWIDTH,
2342               GetDataRowHeight() - 1 ) );
2343 }
2344 
2345 //-------------------------------------------------------------------
2346 
GetRowAtYPosPixel(long nY,sal_Bool bRelToBrowser) const2347 long BrowseBox::GetRowAtYPosPixel( long nY, sal_Bool bRelToBrowser ) const
2348 {
2349     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2350 
2351     // compute the Y-coord
2352     if ( bRelToBrowser )
2353     {
2354         Point aDataTopLeft = pDataWin->OutputToScreenPixel( Point(0, 0) );
2355         Point aTopLeft = OutputToScreenPixel( Point(0, 0) );
2356         nY -= aDataTopLeft.Y() - aTopLeft.Y();
2357     }
2358 
2359     // no row there (e.g. in the header)
2360     if ( nY < 0 || nY >= pDataWin->GetOutputSizePixel().Height() )
2361         return -1;
2362 
2363     return nY / GetDataRowHeight() + nTopRow;
2364 }
2365 
2366 //-------------------------------------------------------------------
2367 
GetFieldRect(sal_uInt16 nColumnId) const2368 Rectangle BrowseBox::GetFieldRect( sal_uInt16 nColumnId ) const
2369 {
2370     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2371 
2372     return GetFieldRectPixel( nCurRow, nColumnId );
2373 }
2374 
2375 //-------------------------------------------------------------------
2376 
GetColumnAtXPosPixel(long nX,sal_Bool) const2377 sal_uInt16 BrowseBox::GetColumnAtXPosPixel( long nX, sal_Bool ) const
2378 {
2379     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2380 
2381     // accumulate the withds of the visible columns
2382     long nColX = 0;
2383     sal_uInt16 nCol;
2384     for ( nCol = 0; nCol < sal_uInt16(pCols->Count()); ++nCol )
2385     {
2386         BrowserColumn *pCol = pCols->GetObject(nCol);
2387         if ( pCol->IsFrozen() || nCol >= nFirstCol )
2388             nColX += pCol->Width();
2389 
2390         if ( nColX > nX )
2391             return nCol;
2392     }
2393 
2394     return BROWSER_INVALIDID;
2395 }
2396 
2397 //-------------------------------------------------------------------
2398 
ReserveControlArea(sal_uInt16 nWidth)2399 void BrowseBox::ReserveControlArea( sal_uInt16 nWidth )
2400 {
2401     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2402 
2403     if ( nWidth != nControlAreaWidth )
2404     {
2405         OSL_ENSURE(nWidth,"Control aera of 0 is not allowed, Use USHRT_MAX instead!");
2406         nControlAreaWidth = nWidth;
2407         UpdateScrollbars();
2408     }
2409 }
2410 
2411 //-------------------------------------------------------------------
2412 
GetControlArea() const2413 Rectangle BrowseBox::GetControlArea() const
2414 {
2415     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2416 
2417     return Rectangle(
2418         Point( 0, GetOutputSizePixel().Height() - aHScroll.GetSizePixel().Height() ),
2419         Size( GetOutputSizePixel().Width() - aHScroll.GetSizePixel().Width(),
2420              aHScroll.GetSizePixel().Height() ) );
2421 }
2422 
2423 //-------------------------------------------------------------------
2424 
SetMode(BrowserMode nMode)2425 void BrowseBox::SetMode( BrowserMode nMode )
2426 {
2427     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2428 
2429 #ifdef DBG_MIx
2430     Sound::Beep();
2431     nMode =
2432 //          BROWSER_COLUMNSELECTION |
2433 //          BROWSER_MULTISELECTION |
2434             BROWSER_THUMBDRAGGING |
2435             BROWSER_KEEPHIGHLIGHT |
2436             BROWSER_HLINES |
2437             BROWSER_VLINES |
2438 //          BROWSER_HIDECURSOR |
2439 //          BROWSER_NO_HSCROLL |
2440 //          BROWSER_NO_SCROLLBACK |
2441             BROWSER_AUTO_VSCROLL |
2442             BROWSER_AUTO_HSCROLL |
2443             BROWSER_TRACKING_TIPS |
2444 //          BROWSER_HIGHLIGHT_NONE |
2445             BROWSER_HEADERBAR_NEW |
2446 //          BROWSER_AUTOSIZE_LASTCOL |
2447             0;
2448 #endif
2449 
2450     getDataWindow()->bAutoHScroll = BROWSER_AUTO_HSCROLL == ( nMode & BROWSER_AUTO_HSCROLL );
2451     getDataWindow()->bAutoVScroll = BROWSER_AUTO_VSCROLL == ( nMode & BROWSER_AUTO_VSCROLL );
2452     getDataWindow()->bNoHScroll   = BROWSER_NO_HSCROLL   == ( nMode & BROWSER_NO_HSCROLL );
2453     getDataWindow()->bNoVScroll   = BROWSER_NO_VSCROLL   == ( nMode & BROWSER_NO_VSCROLL );
2454 
2455     DBG_ASSERT( !( getDataWindow()->bAutoHScroll && getDataWindow()->bNoHScroll ),
2456         "BrowseBox::SetMode: AutoHScroll *and* NoHScroll?" );
2457     DBG_ASSERT( !( getDataWindow()->bAutoVScroll && getDataWindow()->bNoVScroll ),
2458         "BrowseBox::SetMode: AutoVScroll *and* NoVScroll?" );
2459     if ( getDataWindow()->bAutoHScroll )
2460         getDataWindow()->bNoHScroll = sal_False;
2461     if ( getDataWindow()->bAutoVScroll )
2462         getDataWindow()->bNoVScroll = sal_False;
2463 
2464     if ( getDataWindow()->bNoHScroll )
2465         aHScroll.Hide();
2466 
2467     nControlAreaWidth = USHRT_MAX;
2468 
2469     getDataWindow()->bNoScrollBack =
2470             BROWSER_NO_SCROLLBACK == ( nMode & BROWSER_NO_SCROLLBACK);
2471 
2472     long nOldRowSel = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
2473     MultiSelection *pOldRowSel = bMultiSelection ? uRow.pSel : 0;
2474     MultiSelection *pOldColSel = pColSel;
2475 
2476     delete pVScroll;
2477 
2478     bThumbDragging = ( nMode & BROWSER_THUMBDRAGGING ) == BROWSER_THUMBDRAGGING;
2479     bMultiSelection = ( nMode & BROWSER_MULTISELECTION ) == BROWSER_MULTISELECTION;
2480     bColumnCursor = ( nMode & BROWSER_COLUMNSELECTION ) == BROWSER_COLUMNSELECTION;
2481     bKeepHighlight = ( nMode & BROWSER_KEEPSELECTION ) == BROWSER_KEEPSELECTION;
2482 
2483     bHideSelect = ((nMode & BROWSER_HIDESELECT) == BROWSER_HIDESELECT);
2484     // default: do not hide the cursor at all (untaken scrolling and such)
2485     bHideCursor = NO_CURSOR_HIDE;
2486 
2487     if ( BROWSER_SMART_HIDECURSOR == ( nMode & BROWSER_SMART_HIDECURSOR ) )
2488     {   // smart cursor hide overrules hard cursor hide
2489         bHideCursor = SMART_CURSOR_HIDE;
2490     }
2491     else if ( BROWSER_HIDECURSOR == ( nMode & BROWSER_HIDECURSOR ) )
2492     {
2493         bHideCursor = HARD_CURSOR_HIDE;
2494     }
2495 
2496     m_bFocusOnlyCursor = ((nMode & BROWSER_CURSOR_WO_FOCUS) == 0);
2497 
2498     bHLines = ( nMode & BROWSER_HLINESFULL ) == BROWSER_HLINESFULL;
2499     bVLines = ( nMode & BROWSER_VLINESFULL ) == BROWSER_VLINESFULL;
2500     bHDots  = ( nMode & BROWSER_HLINESDOTS ) == BROWSER_HLINESDOTS;
2501     bVDots  = ( nMode & BROWSER_VLINESDOTS ) == BROWSER_VLINESDOTS;
2502 
2503     WinBits nVScrollWinBits =
2504         WB_VSCROLL | ( ( nMode & BROWSER_THUMBDRAGGING ) ? WB_DRAG : 0 );
2505     pVScroll = ( nMode & BROWSER_TRACKING_TIPS ) == BROWSER_TRACKING_TIPS
2506                 ? new BrowserScrollBar( this, nVScrollWinBits,
2507                                         (BrowserDataWin*) pDataWin )
2508                 : new ScrollBar( this, nVScrollWinBits );
2509     pVScroll->SetLineSize( 1 );
2510     pVScroll->SetPageSize(1);
2511     pVScroll->SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) );
2512     pVScroll->SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) );
2513 
2514     getDataWindow()->bAutoSizeLastCol =
2515             BROWSER_AUTOSIZE_LASTCOL == ( nMode & BROWSER_AUTOSIZE_LASTCOL );
2516     getDataWindow()->bOwnDataChangedHdl =
2517             BROWSER_OWN_DATACHANGED == ( nMode & BROWSER_OWN_DATACHANGED );
2518 
2519     // Headerbar erzeugen, was passiert, wenn eine erzeugt werden mu� und schon Spalten bestehen ?
2520     if ( BROWSER_HEADERBAR_NEW == ( nMode & BROWSER_HEADERBAR_NEW ) )
2521     {
2522         if (!getDataWindow()->pHeaderBar)
2523             getDataWindow()->pHeaderBar = CreateHeaderBar( this );
2524     }
2525     else
2526     {
2527         DELETEZ(getDataWindow()->pHeaderBar);
2528     }
2529 
2530 
2531 
2532     if ( bColumnCursor )
2533     {
2534         pColSel = pOldColSel ? pOldColSel : new MultiSelection;
2535         pColSel->SetTotalRange( Range( 0, pCols->Count()-1 ) );
2536     }
2537     else
2538     {
2539         pColSel = 0;
2540         delete pColSel;
2541     }
2542 
2543     if ( bMultiSelection )
2544     {
2545         if ( pOldRowSel )
2546             uRow.pSel = pOldRowSel;
2547         else
2548             uRow.pSel = new MultiSelection;
2549     }
2550     else
2551     {
2552         uRow.nSel = nOldRowSel;
2553         delete pOldRowSel;
2554     }
2555 
2556     if ( bBootstrapped )
2557     {
2558         StateChanged( STATE_CHANGE_INITSHOW );
2559         if ( bMultiSelection && !pOldRowSel &&
2560              nOldRowSel != BROWSER_ENDOFSELECTION )
2561             uRow.pSel->Select( nOldRowSel );
2562     }
2563 
2564     if ( pDataWin )
2565         pDataWin->Invalidate();
2566 
2567     // kein Cursor auf Handle-Column
2568     if ( nCurColId == 0 )
2569         nCurColId = GetColumnId( 1 );
2570 
2571     m_nCurrentMode = nMode;
2572 }
2573 
2574 //-------------------------------------------------------------------
2575 
VisibleRowsChanged(long,sal_uInt16)2576 void BrowseBox::VisibleRowsChanged( long, sal_uInt16 )
2577 {
2578     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2579 
2580     // Das alte Verhalten: NumRows automatisch korrigieren:
2581     if ( nRowCount < GetRowCount() )
2582     {
2583         RowInserted(nRowCount,GetRowCount() - nRowCount,sal_False);
2584     }
2585     else if ( nRowCount > GetRowCount() )
2586     {
2587         RowRemoved(nRowCount-(nRowCount - GetRowCount()),nRowCount - GetRowCount(),sal_False);
2588     }
2589 }
2590 
2591 //-------------------------------------------------------------------
2592 
IsCursorMoveAllowed(long,sal_uInt16) const2593 sal_Bool BrowseBox::IsCursorMoveAllowed( long, sal_uInt16 ) const
2594 
2595 /*  [Beschreibung]
2596 
2597     Diese virtuelle Methode wird immer gerufen bevor der Cursor direkt
2598     bewegt werden soll. Durch 'return sal_False' kann verhindert werden, da\s
2599     dies geschieht, wenn z.B. ein Datensatz irgendwelchen Rules widerspricht.
2600 
2601     Diese Methode wird nicht gerufen, wenn die Cursorbewegung durch
2602     ein L"oschen oder Einf"ugen (einer Zeile/Spalte) ausgel"ost wird, also
2603     genaugenommen nur eine Cursor-Korrektur vorliegt.
2604 
2605     Die Basisimplementierung liefert derzeit immer sal_True.
2606 */
2607 
2608 {
2609     return sal_True;
2610 }
2611 
2612 //-------------------------------------------------------------------
2613 
GetDataRowHeight() const2614 long BrowseBox::GetDataRowHeight() const
2615 {
2616     return CalcZoom(nDataRowHeight ? nDataRowHeight : ImpGetDataRowHeight());
2617 }
2618 
2619 //-------------------------------------------------------------------
2620 
GetEventWindow() const2621 Window& BrowseBox::GetEventWindow() const
2622 {
2623     return *getDataWindow()->pEventWin;
2624 }
2625 
2626 //-------------------------------------------------------------------
2627 
CreateHeaderBar(BrowseBox * pParent)2628 BrowserHeader* BrowseBox::CreateHeaderBar( BrowseBox* pParent )
2629 {
2630     BrowserHeader* pNewBar = new BrowserHeader( pParent );
2631     pNewBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2632     return pNewBar;
2633 }
2634 
SetHeaderBar(BrowserHeader * pHeaderBar)2635 void BrowseBox::SetHeaderBar( BrowserHeader* pHeaderBar )
2636 {
2637     delete ( (BrowserDataWin*)pDataWin )->pHeaderBar;
2638     ( (BrowserDataWin*)pDataWin )->pHeaderBar = pHeaderBar;
2639     ( (BrowserDataWin*)pDataWin )->pHeaderBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2640 }
2641 //-------------------------------------------------------------------
2642 
2643 #ifdef DBG_UTIL
BrowseBoxCheckInvariants(const void * pVoid)2644 const char* BrowseBoxCheckInvariants( const void * pVoid )
2645 {
2646     const BrowseBox * p = (const BrowseBox *)pVoid;
2647 
2648     if (p->nRowCount < 0) return "BrowseBox: nRowCount < 0";
2649     if (p->nTopRow < 0) return "BrowseBox: nTopRow < 0";
2650     if (p->nTopRow >= p->nRowCount && p->nRowCount != 0) return "BrowseBox: nTopRow >= nRowCount && nRowCount != 0";
2651     if (p->nCurRow < -1) return "BrowseBox: nCurRow < -1";
2652     if (p->nCurRow > p->nRowCount) return "BrowseBox: nCurRow > nRowCount";
2653 
2654     // Leider waehrend der Bearbeitung nicht immer der Fall:
2655     //if (p->nCurRow < 0 && p->nRowCount != 0) return "nCurRow < 0 && nRowCount != 0";
2656     //if (p->nCurRow >= p->nRowCount && p->nRowCount != 0) return "nCurRow >= nRowCount && nRowCount != 0";
2657 
2658     return NULL;
2659 }
2660 #endif
2661 
2662 //-------------------------------------------------------------------
GetTitleHeight() const2663 long BrowseBox::GetTitleHeight() const
2664 {
2665     long nHeight;
2666     // ask the header bar for the text height (if possible), as the header bar's font is adjusted with
2667     // our (and the header's) zoom factor
2668     HeaderBar* pHeaderBar = ( (BrowserDataWin*)pDataWin )->pHeaderBar;
2669     if ( pHeaderBar )
2670         nHeight = pHeaderBar->GetTextHeight();
2671     else
2672         nHeight = GetTextHeight();
2673 
2674     return nTitleLines ? nTitleLines * nHeight + 4 : 0;
2675 }
2676 
2677 //-------------------------------------------------------------------
CalcReverseZoom(long nVal)2678 long BrowseBox::CalcReverseZoom(long nVal)
2679 {
2680     if (IsZoom())
2681     {
2682         const Fraction& rZoom = GetZoom();
2683         double n = (double)nVal;
2684         n *= (double)rZoom.GetDenominator();
2685         n /= (double)rZoom.GetNumerator();
2686         nVal = n>0 ? (long)(n + 0.5) : -(long)(-n + 0.5);
2687     }
2688 
2689     return nVal;
2690 }
2691 
2692 //-------------------------------------------------------------------
GetHeaderBar() const2693 HeaderBar* BrowseBox::GetHeaderBar() const
2694 {
2695     return getDataWindow()->pHeaderBar;
2696 }
2697 //-------------------------------------------------------------------
2698 
CursorMoved()2699 void BrowseBox::CursorMoved()
2700 {
2701     // before implementing more here, please adjust the EditBrowseBox
2702     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2703 
2704     if ( isAccessibleAlive() && HasFocus() )
2705         commitTableEvent(
2706             ACTIVE_DESCENDANT_CHANGED,
2707             makeAny( CreateAccessibleCell( GetCurRow(),GetColumnPos( GetCurColumnId() ) ) ),
2708             Any()
2709         );
2710 }
2711 
2712 //-------------------------------------------------------------------
2713 
LoseFocus()2714 void BrowseBox::LoseFocus()
2715 {
2716     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2717     DBG_TRACE1( "BrowseBox: %p->LoseFocus", this );
2718 
2719     if ( bHasFocus )
2720     {
2721         DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
2722         DoHideCursor( "LoseFocus" );
2723 
2724         if ( !bKeepHighlight )
2725         {
2726             ToggleSelection();
2727             bSelectionIsVisible = sal_False;
2728         }
2729 
2730         bHasFocus = sal_False;
2731     }
2732     Control::LoseFocus();
2733 }
2734 
2735 //-------------------------------------------------------------------
2736 
GetFocus()2737 void BrowseBox::GetFocus()
2738 {
2739     DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2740     DBG_TRACE1( "BrowseBox: %p->GetFocus", this );
2741 
2742     if ( !bHasFocus )
2743     {
2744         if ( !bSelectionIsVisible )
2745         {
2746             bSelectionIsVisible = sal_True;
2747             if ( bBootstrapped )
2748                 ToggleSelection();
2749         }
2750 
2751         bHasFocus = sal_True;
2752         DoShowCursor( "GetFocus" );
2753     }
2754     Control::GetFocus();
2755 }
2756 
2757 
2758