xref: /AOO41X/main/svtools/source/contnr/svimpbox.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
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 <vcl/svapp.hxx>
27 #include <vcl/salnativewidgets.hxx>
28 #include <vcl/help.hxx>
29 #include <svtools/tabbar.hxx>
30 
31 #include <stack>
32 
33 #define _SVTREEBX_CXX
34 #include <svtools/svtreebx.hxx>
35 #include <svtools/svlbox.hxx>
36 #include <svimpbox.hxx>
37 #include <rtl/instance.hxx>
38 #include <svtools/svtdata.hxx>
39 #include <tools/wintypes.hxx>
40 #include <svtools/svtools.hrc>
41 #include <comphelper/processfactory.hxx>
42 
43 #define NODE_BMP_TABDIST_NOTVALID   -2000000
44 #define FIRST_ENTRY_TAB             1
45 
46 // #i27063# (pl), #i32300# (pb) never access VCL after DeInitVCL - also no destructors
47 Image*  SvImpLBox::s_pDefCollapsed      = NULL;
48 Image*  SvImpLBox::s_pDefExpanded       = NULL;
49 Image*  SvImpLBox::s_pDefCollapsedHC    = NULL;
50 Image*  SvImpLBox::s_pDefExpandedHC     = NULL;
51 sal_Int32 SvImpLBox::s_nImageRefCount   = 0;
52 
SvImpLBox(SvTreeListBox * pLBView,SvLBoxTreeList * pLBTree,WinBits nWinStyle)53 SvImpLBox::SvImpLBox( SvTreeListBox* pLBView, SvLBoxTreeList* pLBTree, WinBits nWinStyle) :
54 
55     pTabBar( NULL ),
56     aVerSBar( pLBView, WB_DRAG | WB_VSCROLL ),
57     aHorSBar( pLBView, WB_DRAG | WB_HSCROLL ),
58     aScrBarBox( pLBView ),
59     aOutputSize( 0, 0 ),
60     aSelEng( pLBView, (FunctionSet*)0 ),
61     aFctSet( this, &aSelEng, pLBView ),
62     nExtendedWinBits( 0 ),
63     bAreChildrenTransient( sal_True ),
64     pIntlWrapper( NULL ) // #102891# -----------------------
65 {
66     osl_incrementInterlockedCount(&s_nImageRefCount);
67     pView = pLBView;
68     pTree = pLBTree;
69     aSelEng.SetFunctionSet( (FunctionSet*)&aFctSet );
70     aSelEng.ExpandSelectionOnMouseMove( sal_False );
71     SetStyle( nWinStyle );
72     SetSelectionMode( SINGLE_SELECTION );
73     SetDragDropMode( 0 );
74 
75     aVerSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollUpDownHdl ) );
76     aHorSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollLeftRightHdl ) );
77     aHorSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
78     aVerSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
79     aVerSBar.SetRange( Range(0,0) );
80     aVerSBar.Hide();
81     aHorSBar.SetRange( Range(0,0) );
82     aHorSBar.SetPageSize( 24 ); // Pixel
83     aHorSBar.SetLineSize( 8 ); // Pixel
84 
85     nHorSBarHeight = (short)aHorSBar.GetSizePixel().Height();
86     nVerSBarWidth = (short)aVerSBar.GetSizePixel().Width();
87 
88     pStartEntry = 0;
89     pCursor             = 0;
90     pAnchor             = 0;
91     nVisibleCount       = 0;    // Anzahl Daten-Zeilen im Control
92     nNodeBmpTabDistance = NODE_BMP_TABDIST_NOTVALID;
93     nYoffsNodeBmp       = 0;
94     nNodeBmpWidth       = 0;
95 
96     bAsyncBeginDrag     = sal_False;
97     aAsyncBeginDragTimer.SetTimeout( 0 );
98     aAsyncBeginDragTimer.SetTimeoutHdl( LINK(this,SvImpLBox,BeginDragHdl));
99     // Button-Animation in Listbox
100     pActiveButton = 0;
101     pActiveEntry = 0;
102     pActiveTab = 0;
103 
104     nFlags = 0;
105     nCurTabPos = FIRST_ENTRY_TAB;
106 
107     aEditTimer.SetTimeout( 800 );
108     aEditTimer.SetTimeoutHdl( LINK(this,SvImpLBox,EditTimerCall) );
109 
110     nMostRight = -1;
111     pMostRightEntry = 0;
112     nCurUserEvent = 0xffffffff;
113 
114     bUpdateMode = sal_True;
115     bInVScrollHdl = sal_False;
116     nFlags |= F_FILLING;
117 
118     bSubLstOpRet = bSubLstOpLR = bContextMenuHandling = bIsCellFocusEnabled = sal_False;
119 }
120 
~SvImpLBox()121 SvImpLBox::~SvImpLBox()
122 {
123     aEditTimer.Stop();
124     StopUserEvent();
125 
126     // #102891# ---------------------
127     if( pIntlWrapper )
128         delete pIntlWrapper;
129     if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
130     {
131         DELETEZ(s_pDefCollapsed);
132         DELETEZ(s_pDefExpanded);
133         DELETEZ(s_pDefCollapsedHC);
134         DELETEZ(s_pDefExpandedHC);
135     }
136 }
137 
138 // #102891# --------------------
UpdateIntlWrapper()139 void SvImpLBox::UpdateIntlWrapper()
140 {
141     const ::com::sun::star::lang::Locale & aNewLocale = Application::GetSettings().GetLocale();
142     if( !pIntlWrapper )
143         pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
144     else
145     {
146         const ::com::sun::star::lang::Locale &aLocale = pIntlWrapper->getLocale();
147         if( aLocale.Language != aNewLocale.Language || // different Locale from the older one
148             aLocale.Country != aNewLocale.Country ||
149             aLocale.Variant != aNewLocale.Variant )
150         {
151             delete pIntlWrapper;
152             pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
153         }
154     }
155 }
156 
157 // #97680# ----------------------
UpdateContextBmpWidthVector(SvLBoxEntry * pEntry,short nWidth)158 short SvImpLBox::UpdateContextBmpWidthVector( SvLBoxEntry* pEntry, short nWidth )
159 {
160     DBG_ASSERT( pView->pModel, "View and Model aren't valid!" );
161 
162     sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
163     // initialize vector if necessary
164     std::vector< short >::size_type nSize = aContextBmpWidthVector.size();
165     while ( nDepth > nSize )
166     {
167         aContextBmpWidthVector.resize( nSize + 1 );
168         aContextBmpWidthVector.at( nSize ) = nWidth;
169         ++nSize;
170     }
171     if( aContextBmpWidthVector.size() == nDepth )
172     {
173         aContextBmpWidthVector.resize( nDepth + 1 );
174         aContextBmpWidthVector.at( nDepth ) = 0;
175     }
176     short nContextBmpWidth = aContextBmpWidthVector[ nDepth ];
177     if( nContextBmpWidth < nWidth )
178     {
179         aContextBmpWidthVector.at( nDepth ) = nWidth;
180         return nWidth;
181     }
182     else
183         return nContextBmpWidth;
184 }
185 
UpdateContextBmpWidthVectorFromMovedEntry(SvLBoxEntry * pEntry)186 void SvImpLBox::UpdateContextBmpWidthVectorFromMovedEntry( SvLBoxEntry* pEntry )
187 {
188     DBG_ASSERT( pEntry, "Moved Entry is invalid!" );
189 
190     SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
191     short nExpWidth = (short)pBmpItem->GetBitmap1().GetSizePixel().Width();
192     short nColWidth = (short)pBmpItem->GetBitmap2().GetSizePixel().Width();
193     short nMax = Max(nExpWidth, nColWidth);
194     UpdateContextBmpWidthVector( pEntry, nMax );
195 
196     if( pEntry->HasChilds() ) // recursive call, whether expanded or not
197     {
198         SvLBoxEntry* pChild = pView->FirstChild( pEntry );
199         DBG_ASSERT( pChild, "The first child is invalid!" );
200         do
201         {
202             UpdateContextBmpWidthVectorFromMovedEntry( pChild );
203             pChild = pView->Next( pChild );
204         } while ( pChild );
205     }
206 }
207 
UpdateContextBmpWidthMax(SvLBoxEntry * pEntry)208 void SvImpLBox::UpdateContextBmpWidthMax( SvLBoxEntry* pEntry )
209 {
210     sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
211     if( aContextBmpWidthVector.size() < 1 )
212         return;
213     short nWidth = aContextBmpWidthVector[ nDepth ];
214     if( nWidth != pView->nContextBmpWidthMax ) {
215         pView->nContextBmpWidthMax = nWidth;
216         nFlags |= F_IGNORE_CHANGED_TABS;
217         pView->SetTabs();
218         nFlags &= ~F_IGNORE_CHANGED_TABS;
219     }
220 }
221 
CalcCellFocusRect(SvLBoxEntry * pEntry,Rectangle & rRect)222 void SvImpLBox::CalcCellFocusRect( SvLBoxEntry* pEntry, Rectangle& rRect )
223 {
224     if ( pEntry && bIsCellFocusEnabled )
225     {
226         if ( nCurTabPos > FIRST_ENTRY_TAB )
227         {
228             SvLBoxItem* pItem = pCursor->GetItem( nCurTabPos );
229             rRect.Left() = pView->GetTab( pCursor, pItem )->GetPos();
230         }
231         if ( pCursor->ItemCount() > ( nCurTabPos + 1 ) )
232         {
233             SvLBoxItem* pNextItem = pCursor->GetItem( nCurTabPos + 1 );
234             long nRight = pView->GetTab( pCursor, pNextItem )->GetPos() - 1;
235             if ( nRight < rRect.Right() )
236                 rRect.Right() = nRight;
237         }
238     }
239 }
240 
SetStyle(WinBits i_nWinStyle)241 void SvImpLBox::SetStyle( WinBits i_nWinStyle )
242 {
243     m_nStyle = i_nWinStyle;
244     if ( ( m_nStyle & WB_SIMPLEMODE) && ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION ) )
245         aSelEng.AddAlways( sal_True );
246 }
247 
SetExtendedWindowBits(ExtendedWinBits _nBits)248 void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits )
249 {
250     nExtendedWinBits = _nBits;
251 }
252 
253 // Das Model darf hier nicht mehr angefasst werden
Clear()254 void SvImpLBox::Clear()
255 {
256     StopUserEvent();
257     pStartEntry = 0;
258     pAnchor = 0;
259 
260     pActiveButton = 0;
261     pActiveEntry = 0;
262     pActiveTab = 0;
263 
264     nMostRight = -1;
265     pMostRightEntry = 0;
266 
267     // Der Cursor darf hier nicht mehr angefasst werden!
268     if( pCursor )
269     {
270         if( pView->HasFocus() )
271             pView->HideFocus();
272         pCursor = 0;
273     }
274     aVerSBar.Hide();
275     aVerSBar.SetThumbPos( 0 );
276     Range aRange( 0, 0 );
277     aVerSBar.SetRange( aRange );
278     aOutputSize = pView->Control::GetOutputSizePixel();
279     nFlags &= ~(F_VER_SBARSIZE_WITH_HBAR | F_HOR_SBARSIZE_WITH_VBAR );
280     if( pTabBar )
281     {
282         aOutputSize.Height() -= nHorSBarHeight;
283         nFlags |= F_VER_SBARSIZE_WITH_HBAR;
284     }
285     if( !pTabBar )
286         aHorSBar.Hide();
287     aHorSBar.SetThumbPos( 0 );
288     MapMode aMapMode( pView->GetMapMode());
289     aMapMode.SetOrigin( Point(0,0) );
290     pView->Control::SetMapMode( aMapMode );
291     aHorSBar.SetRange( aRange );
292     aHorSBar.SetSizePixel(Size(aOutputSize.Width(),nHorSBarHeight));
293     pView->SetClipRegion();
294     if( GetUpdateMode() )
295         pView->Invalidate( GetVisibleArea() );
296     nFlags |= F_FILLING;
297     if( !aHorSBar.IsVisible() && !aVerSBar.IsVisible() )
298         aScrBarBox.Hide();
299 
300     // #97680# ---------
301     aContextBmpWidthVector.clear();
302 
303     CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, NULL );
304 }
305 
306 // *********************************************************************
307 // Painten, Navigieren, Scrollen
308 // *********************************************************************
309 
IMPL_LINK_INLINE_START(SvImpLBox,EndScrollHdl,ScrollBar *,EMPTYARG)310 IMPL_LINK_INLINE_START( SvImpLBox, EndScrollHdl, ScrollBar *, EMPTYARG )
311 {
312     if( nFlags & F_ENDSCROLL_SET_VIS_SIZE )
313     {
314         aVerSBar.SetVisibleSize( nNextVerVisSize );
315         nFlags &= ~F_ENDSCROLL_SET_VIS_SIZE;
316     }
317     EndScroll();
318     return 0;
319 }
IMPL_LINK_INLINE_END(SvImpLBox,EndScrollHdl,ScrollBar *,pScrollBar)320 IMPL_LINK_INLINE_END( SvImpLBox, EndScrollHdl, ScrollBar *, pScrollBar )
321 
322 
323 // Handler vertikale ScrollBar
324 
325 IMPL_LINK( SvImpLBox, ScrollUpDownHdl, ScrollBar *, pScrollBar )
326 {
327     DBG_ASSERT(!bInVScrollHdl,"Scroll-Handler ueberholt sich!");
328     long nDelta = pScrollBar->GetDelta();
329     if( !nDelta )
330         return 0;
331 
332     nFlags &= (~F_FILLING);
333 
334     bInVScrollHdl = sal_True;
335 
336     if( pView->IsEditingActive() )
337     {
338         pView->EndEditing( sal_True ); // Cancel
339         pView->Update();
340     }
341     BeginScroll();
342 
343     if( nDelta > 0 )
344     {
345         if( nDelta == 1 )
346             CursorDown();
347         else
348             PageDown( (sal_uInt16) nDelta );
349     }
350     else
351     {
352         nDelta *= (-1);
353         if( nDelta == 1 )
354             CursorUp();
355         else
356             PageUp( (sal_uInt16) nDelta );
357     }
358     bInVScrollHdl = sal_False;
359     return 0;
360 }
361 
362 
CursorDown()363 void SvImpLBox::CursorDown()
364 {
365     SvLBoxEntry* pNextFirstToDraw = (SvLBoxEntry*)(pView->NextVisible( pStartEntry));
366     if( pNextFirstToDraw )
367     {
368         nFlags &= (~F_FILLING);
369         pView->NotifyScrolling( -1 );
370         ShowCursor( sal_False );
371         pView->Update();
372         pStartEntry = pNextFirstToDraw;
373         Rectangle aArea( GetVisibleArea() );
374         pView->Scroll( 0, -(pView->GetEntryHeight()), aArea, SCROLL_NOCHILDREN );
375         pView->Update();
376         ShowCursor( sal_True );
377         pView->NotifyScrolled();
378     }
379 }
380 
CursorUp()381 void SvImpLBox::CursorUp()
382 {
383     SvLBoxEntry* pPrevFirstToDraw = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry));
384     if( pPrevFirstToDraw )
385     {
386         nFlags &= (~F_FILLING);
387         long nEntryHeight = pView->GetEntryHeight();
388         pView->NotifyScrolling( 1 );
389         ShowCursor( sal_False );
390         pView->Update();
391         pStartEntry = pPrevFirstToDraw;
392         Rectangle aArea( GetVisibleArea() );
393         aArea.Bottom() -= nEntryHeight;
394         pView->Scroll( 0, nEntryHeight, aArea, SCROLL_NOCHILDREN );
395         pView->Update();
396         ShowCursor( sal_True );
397         pView->NotifyScrolled();
398     }
399 }
400 
PageDown(sal_uInt16 nDelta)401 void SvImpLBox::PageDown( sal_uInt16 nDelta )
402 {
403     sal_uInt16 nRealDelta = nDelta;
404 
405     if( !nDelta )
406         return;
407 
408     SvLBoxEntry* pNext;
409     pNext = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nRealDelta ));
410     if( (sal_uLong)pNext == (sal_uLong)pStartEntry )
411         return;
412 
413     ShowCursor( sal_False );
414 
415     nFlags &= (~F_FILLING);
416     pView->Update();
417     pStartEntry = pNext;
418 
419     if( nRealDelta >= nVisibleCount )
420     {
421         pView->Invalidate( GetVisibleArea() );
422         pView->Update();
423     }
424     else
425     {
426         long nScroll = nRealDelta * (-1);
427         pView->NotifyScrolling( nScroll );
428         Rectangle aArea( GetVisibleArea() );
429         nScroll = pView->GetEntryHeight()*nRealDelta;
430         nScroll = -nScroll;
431         pView->Update();
432         pView->Scroll( 0, nScroll, aArea, SCROLL_NOCHILDREN );
433         pView->Update();
434         pView->NotifyScrolled();
435     }
436 
437     ShowCursor( sal_True );
438 }
439 
PageUp(sal_uInt16 nDelta)440 void SvImpLBox::PageUp( sal_uInt16 nDelta )
441 {
442     sal_uInt16 nRealDelta = nDelta;
443     if( !nDelta )
444         return;
445 
446     SvLBoxEntry* pPrev = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry, nRealDelta ));
447     if( (sal_uLong)pPrev == (sal_uLong)pStartEntry )
448         return;
449 
450     nFlags &= (~F_FILLING);
451     ShowCursor( sal_False );
452 
453     pView->Update();
454     pStartEntry = pPrev;
455     if( nRealDelta >= nVisibleCount )
456     {
457         pView->Invalidate( GetVisibleArea() );
458         pView->Update();
459     }
460     else
461     {
462         long nEntryHeight = pView->GetEntryHeight();
463         pView->NotifyScrolling( (long)nRealDelta );
464         Rectangle aArea( GetVisibleArea() );
465         pView->Update();
466         pView->Scroll( 0, nEntryHeight*nRealDelta, aArea, SCROLL_NOCHILDREN );
467         pView->Update();
468         pView->NotifyScrolled();
469     }
470 
471     ShowCursor( sal_True );
472 }
473 
KeyUp(sal_Bool bPageUp,sal_Bool bNotifyScroll)474 void SvImpLBox::KeyUp( sal_Bool bPageUp, sal_Bool bNotifyScroll )
475 {
476     if( !aVerSBar.IsVisible() )
477         return;
478 
479     long nDelta;
480     if( bPageUp )
481         nDelta = aVerSBar.GetPageSize();
482     else
483         nDelta = 1;
484 
485     long nThumbPos = aVerSBar.GetThumbPos();
486 
487     if( nThumbPos < nDelta )
488         nDelta = nThumbPos;
489 
490     if( nDelta <= 0 )
491         return;
492 
493     nFlags &= (~F_FILLING);
494     if( bNotifyScroll )
495         BeginScroll();
496 
497     aVerSBar.SetThumbPos( nThumbPos - nDelta );
498     if( bPageUp )
499         PageUp( (short)nDelta );
500     else
501         CursorUp();
502 
503     if( bNotifyScroll )
504         EndScroll();
505 }
506 
507 
KeyDown(sal_Bool bPageDown,sal_Bool bNotifyScroll)508 void SvImpLBox::KeyDown( sal_Bool bPageDown, sal_Bool bNotifyScroll )
509 {
510     if( !aVerSBar.IsVisible() )
511         return;
512 
513     long nDelta;
514     if( bPageDown )
515         nDelta = aVerSBar.GetPageSize();
516     else
517         nDelta = 1;
518 
519     long nThumbPos = aVerSBar.GetThumbPos();
520     long nVisibleSize = aVerSBar.GetVisibleSize();
521     long nRange = aVerSBar.GetRange().Len();
522 
523     long nTmp = nThumbPos+nVisibleSize;
524     while( (nDelta > 0) && (nTmp+nDelta) >= nRange )
525         nDelta--;
526 
527     if( nDelta <= 0 )
528         return;
529 
530     nFlags &= (~F_FILLING);
531     if( bNotifyScroll )
532         BeginScroll();
533 
534     aVerSBar.SetThumbPos( nThumbPos+nDelta );
535     if( bPageDown )
536         PageDown( (short)nDelta );
537     else
538         CursorDown();
539 
540     if( bNotifyScroll )
541         EndScroll();
542 }
543 
544 
545 
InvalidateEntriesFrom(long nY) const546 void SvImpLBox::InvalidateEntriesFrom( long nY ) const
547 {
548     if( !(nFlags & F_IN_PAINT ))
549     {
550         Rectangle aRect( GetVisibleArea() );
551         aRect.Top() = nY;
552         pView->Invalidate( aRect );
553     }
554 }
555 
InvalidateEntry(long nY) const556 void SvImpLBox::InvalidateEntry( long nY ) const
557 {
558     if( !(nFlags & F_IN_PAINT ))
559     {
560         Rectangle aRect( GetVisibleArea() );
561         long nMaxBottom = aRect.Bottom();
562         aRect.Top() = nY;
563         aRect.Bottom() = nY; aRect.Bottom() += pView->GetEntryHeight();
564         if( aRect.Top() > nMaxBottom )
565             return;
566         if( aRect.Bottom() > nMaxBottom )
567             aRect.Bottom() = nMaxBottom;
568         pView->Invalidate( aRect );
569     }
570 }
571 
InvalidateEntry(SvLBoxEntry * pEntry)572 void SvImpLBox::InvalidateEntry( SvLBoxEntry* pEntry )
573 {
574     if( GetUpdateMode() )
575     {
576         long nPrev = nMostRight;
577         SetMostRight( pEntry );
578         if( nPrev < nMostRight )
579             ShowVerSBar();
580     }
581     if( !(nFlags & F_IN_PAINT ))
582     {
583         sal_Bool bHasFocusRect = sal_False;
584         if( pEntry==pCursor && pView->HasFocus() )
585         {
586             bHasFocusRect = sal_True;
587             ShowCursor( sal_False );
588         }
589         InvalidateEntry( GetEntryLine( pEntry ) );
590         if( bHasFocusRect )
591             ShowCursor( sal_True );
592     }
593 }
594 
595 
RecalcFocusRect()596 void SvImpLBox::RecalcFocusRect()
597 {
598     if( pView->HasFocus() && pCursor )
599     {
600         pView->HideFocus();
601         long nY = GetEntryLine( pCursor );
602         Rectangle aRect = pView->GetFocusRect( pCursor, nY );
603         CalcCellFocusRect( pCursor, aRect );
604         Region aOldClip( pView->GetClipRegion());
605         Region aClipRegion( GetClipRegionRect() );
606         pView->SetClipRegion( aClipRegion );
607         pView->ShowFocus( aRect );
608         pView->SetClipRegion( aOldClip );
609     }
610 }
611 
612 //
613 //  Setzt Cursor. Passt bei SingleSelection die Selektion an
614 //
615 
SetCursor(SvLBoxEntry * pEntry,sal_Bool bForceNoSelect)616 void SvImpLBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect )
617 {
618     SvViewDataEntry* pViewDataNewCur = 0;
619     if( pEntry )
620         pViewDataNewCur= pView->GetViewDataEntry(pEntry);
621     if( pEntry &&
622         pEntry == pCursor &&
623         pViewDataNewCur->HasFocus() &&
624         pViewDataNewCur->IsSelected())
625     {
626         return;
627     }
628 
629     // if this cursor is not selectable, find first visible that is and use it
630     while( pEntry && pViewDataNewCur && !pViewDataNewCur->IsSelectable() )
631     {
632         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
633         pViewDataNewCur = pEntry ? pView->GetViewDataEntry(pEntry) : 0;
634     }
635 
636     SvLBoxEntry* pOldCursor = pCursor;
637     if( pCursor && pEntry != pCursor )
638     {
639         pView->SetEntryFocus( pCursor, sal_False );
640         if( bSimpleTravel )
641             pView->Select( pCursor, sal_False );
642         pView->HideFocus();
643     }
644     pCursor = pEntry;
645     if( pCursor )
646     {
647         pViewDataNewCur->SetFocus( sal_True );
648         if(!bForceNoSelect && bSimpleTravel && !(nFlags & F_DESEL_ALL) && GetUpdateMode())
649         {
650             pView->Select( pCursor, sal_True );
651             CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pCursor );
652         }
653         // Mehrfachselektion: Im Cursor-Move selektieren, wenn
654         // nicht im Add-Mode (Ctrl-F8)
655         else if( GetUpdateMode() &&
656                  pView->GetSelectionMode() == MULTIPLE_SELECTION &&
657                  !(nFlags & F_DESEL_ALL) && !aSelEng.IsAddMode() &&
658                  !bForceNoSelect )
659         {
660             pView->Select( pCursor, sal_True );
661             CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pCursor );
662         }
663         else
664         {
665             ShowCursor( sal_True );
666             if (bForceNoSelect && GetUpdateMode())
667             {
668                 CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pCursor);
669             }
670         }
671 
672         if( pAnchor )
673         {
674             DBG_ASSERT(aSelEng.GetSelectionMode() != SINGLE_SELECTION,"Mode?");
675             SetAnchorSelection( pOldCursor, pCursor );
676         }
677     }
678     nFlags &= (~F_DESEL_ALL);
679 
680     pView->OnCurrentEntryChanged();
681 }
682 
ShowCursor(sal_Bool bShow)683 void SvImpLBox::ShowCursor( sal_Bool bShow )
684 {
685     if( !bShow || !pCursor || !pView->HasFocus() )
686     {
687         Region aOldClip( pView->GetClipRegion());
688         Region aClipRegion( GetClipRegionRect() );
689         pView->SetClipRegion( aClipRegion );
690         pView->HideFocus();
691         pView->SetClipRegion( aOldClip );
692     }
693     else
694     {
695         long nY = GetEntryLine( pCursor );
696         Rectangle aRect = pView->GetFocusRect( pCursor, nY );
697         CalcCellFocusRect( pCursor, aRect );
698         Region aOldClip( pView->GetClipRegion());
699         Region aClipRegion( GetClipRegionRect() );
700         pView->SetClipRegion( aClipRegion );
701         pView->ShowFocus( aRect );
702         pView->SetClipRegion( aOldClip );
703     }
704 }
705 
706 
707 
UpdateAll(sal_Bool bInvalidateCompleteView,sal_Bool bUpdateVerScrollBar)708 void SvImpLBox::UpdateAll( sal_Bool bInvalidateCompleteView,
709     sal_Bool bUpdateVerScrollBar )
710 {
711     if( bUpdateVerScrollBar )
712         FindMostRight(0);
713     aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
714     SyncVerThumb();
715     FillView();
716     ShowVerSBar();
717     if( bSimpleTravel && pCursor && pView->HasFocus() )
718         pView->Select( pCursor, sal_True );
719     ShowCursor( sal_True );
720     if( bInvalidateCompleteView )
721         pView->Invalidate();
722     else
723         pView->Invalidate( GetVisibleArea() );
724 }
725 
IMPL_LINK_INLINE_START(SvImpLBox,ScrollLeftRightHdl,ScrollBar *,pScrollBar)726 IMPL_LINK_INLINE_START( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
727 {
728     long nDelta = pScrollBar->GetDelta();
729     if( nDelta )
730     {
731         if( pView->IsEditingActive() )
732         {
733             pView->EndEditing( sal_True ); // Cancel
734             pView->Update();
735         }
736         pView->nFocusWidth = -1;
737         KeyLeftRight( nDelta );
738     }
739     return 0;
740 }
IMPL_LINK_INLINE_END(SvImpLBox,ScrollLeftRightHdl,ScrollBar *,pScrollBar)741 IMPL_LINK_INLINE_END( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
742 
743 void SvImpLBox::KeyLeftRight( long nDelta )
744 {
745     if( !(nFlags & F_IN_RESIZE) )
746         pView->Update();
747     BeginScroll();
748     nFlags &= (~F_FILLING);
749     pView->NotifyScrolling( 0 ); // 0 == horizontales Scrolling
750     ShowCursor( sal_False );
751 
752     // neuen Origin berechnen
753     long nPos = aHorSBar.GetThumbPos();
754     Point aOrigin( -nPos, 0 );
755 
756     MapMode aMapMode( pView->GetMapMode() );
757     aMapMode.SetOrigin( aOrigin );
758     pView->SetMapMode( aMapMode );
759 
760     if( !(nFlags & F_IN_RESIZE) )
761     {
762         Rectangle aRect( GetVisibleArea() );
763         pView->Scroll( -nDelta, 0, aRect, SCROLL_NOCHILDREN );
764     }
765     else
766         pView->Invalidate();
767     RecalcFocusRect();
768     ShowCursor( sal_True );
769     pView->NotifyScrolled();
770 }
771 
772 
773 // gibt letzten Eintrag zurueck, wenn Position unter
774 // dem letzten Eintrag ist
GetClickedEntry(const Point & rPoint) const775 SvLBoxEntry* SvImpLBox::GetClickedEntry( const Point& rPoint ) const
776 {
777     DBG_ASSERT( pView->GetModel(), "SvImpLBox::GetClickedEntry: how can this ever happen? Please tell me (frank.schoenheit@sun.com) how to reproduce!" );
778     if ( !pView->GetModel() )
779         // this is quite impossible. Nevertheless, stack traces from the crash reporter
780         // suggest it isn't. Okay, make it safe, and wait for somebody to reproduce it
781         // reliably :-\ ....
782         // #122359# / 2005-05-23 / frank.schoenheit@sun.com
783         return NULL;
784     if( pView->GetEntryCount() == 0 || !pStartEntry || !pView->GetEntryHeight())
785         return 0;
786 
787     sal_uInt16 nClickedEntry = (sal_uInt16)(rPoint.Y() / pView->GetEntryHeight() );
788     sal_uInt16 nTemp = nClickedEntry;
789     SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
790     return pEntry;
791 }
792 
793 //
794 //  prueft, ob der Eintrag "richtig" getroffen wurde
795 //  (Focusrect+ ContextBitmap bei TreeListBox)
796 //
EntryReallyHit(SvLBoxEntry * pEntry,const Point & rPosPixel,long nLine)797 sal_Bool SvImpLBox::EntryReallyHit(SvLBoxEntry* pEntry,const Point& rPosPixel,long nLine)
798 {
799     sal_Bool bRet;
800     // bei "besonderen" Entries (mit CheckButtons usw.) sind wir
801     // nicht so pingelig
802     if( pEntry->ItemCount() >= 3 )
803         return sal_True;
804 
805     Rectangle aRect( pView->GetFocusRect( pEntry, nLine ));
806     aRect.Right() = GetOutputSize().Width() - pView->GetMapMode().GetOrigin().X();
807     if( pView->IsA() == SV_LISTBOX_ID_TREEBOX )
808     {
809         SvLBoxContextBmp* pBmp = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
810         aRect.Left() -= pBmp->GetSize(pView,pEntry).Width();
811         aRect.Left() -= 4; // etwas Speilraum lassen
812     }
813     Point aPos( rPosPixel );
814     aPos -= pView->GetMapMode().GetOrigin();
815     if( aRect.IsInside( aPos ) )
816         bRet = sal_True;
817     else
818         bRet = sal_False;
819     return bRet;
820 }
821 
822 
823 // gibt 0 zurueck, wenn Position unter dem letzten Eintrag ist
GetEntry(const Point & rPoint) const824 SvLBoxEntry* SvImpLBox::GetEntry( const Point& rPoint ) const
825 {
826     if( (pView->GetEntryCount() == 0) || !pStartEntry ||
827         (rPoint.Y() > aOutputSize.Height())
828         || !pView->GetEntryHeight())
829         return 0;
830 
831     sal_uInt16 nClickedEntry = (sal_uInt16)(rPoint.Y() / pView->GetEntryHeight() );
832     sal_uInt16 nTemp = nClickedEntry;
833     SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
834     if( nTemp != nClickedEntry )
835         pEntry = 0;
836     return pEntry;
837 }
838 
839 
MakePointVisible(const Point & rPoint,sal_Bool bNotifyScroll)840 SvLBoxEntry* SvImpLBox::MakePointVisible(const Point& rPoint,sal_Bool bNotifyScroll)
841 {
842     if( !pCursor )
843         return 0;
844     long nY = rPoint.Y();
845     SvLBoxEntry* pEntry = 0;
846     long nMax = aOutputSize.Height();
847     if( nY < 0 || nY >= nMax ) // aOutputSize.Height() )
848     {
849         if( nY < 0 )
850             pEntry = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
851         else
852             pEntry = (SvLBoxEntry*)(pView->NextVisible( pCursor ));
853 
854         if( pEntry && pEntry != pCursor )
855             pView->SetEntryFocus( pCursor, sal_False );
856 
857         if( nY < 0 )
858             KeyUp( sal_False, bNotifyScroll );
859         else
860             KeyDown( sal_False, bNotifyScroll );
861     }
862     else
863     {
864         pEntry = GetClickedEntry( rPoint );
865         if( !pEntry )
866         {
867             sal_uInt16 nSteps = 0xFFFF;
868             // LastVisible ist noch nicht implementiert!
869             pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nSteps ));
870         }
871         if( pEntry )
872         {
873             if( pEntry != pCursor &&
874                  aSelEng.GetSelectionMode() == SINGLE_SELECTION
875             )
876                 pView->Select( pCursor, sal_False );
877         }
878     }
879     return pEntry;
880 }
881 
GetClipRegionRect() const882 Rectangle SvImpLBox::GetClipRegionRect() const
883 {
884     Point aOrigin( pView->GetMapMode().GetOrigin() );
885     aOrigin.X() *= -1; // Umrechnung Dokumentkoord.
886     Rectangle aClipRect( aOrigin, aOutputSize );
887     aClipRect.Bottom()++;
888     return aClipRect;
889 }
890 
891 
Paint(const Rectangle & rRect)892 void SvImpLBox::Paint( const Rectangle& rRect )
893 {
894     if( !pView->GetVisibleCount() )
895         return;
896 
897     nFlags |= F_IN_PAINT;
898 
899     if( nFlags & F_FILLING )
900     {
901         SvLBoxEntry* pFirst = pView->First();
902         if( pFirst != pStartEntry )
903         {
904             ShowCursor( sal_False );
905             pStartEntry = pView->First();
906             aVerSBar.SetThumbPos( 0 );
907             StopUserEvent();
908             ShowCursor( sal_True );
909             nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)1);
910             return;
911         }
912     }
913 
914     if( !pStartEntry )
915     {
916         pStartEntry = pView->First();
917     }
918 
919 #ifdef XX_OV
920     sal_uLong nXAbsPos = (sal_uInt16)pTree->GetAbsPos( pStartEntry );
921     sal_uLong nXVisPos = pView->GetVisiblePos( pStartEntry );
922     SvLBoxString* pXStr = (SvLBoxString*)pStartEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING);
923 #endif
924 
925 
926 
927     if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
928         SetNodeBmpTabDistance();
929 
930     long nRectHeight = rRect.GetHeight();
931     long nEntryHeight = pView->GetEntryHeight();
932 
933     // Bereich der zu zeichnenden Entries berechnen
934     sal_uInt16 nStartLine = (sal_uInt16)( rRect.Top() / nEntryHeight );
935     sal_uInt16 nCount = (sal_uInt16)( nRectHeight / nEntryHeight );
936         nCount += 2; // keine Zeile vergessen
937 
938     long nY = nStartLine * nEntryHeight;
939     SvLBoxEntry* pEntry = pStartEntry;
940     while( nStartLine && pEntry )
941     {
942         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
943         nStartLine--;
944     }
945 
946     Region aClipRegion( GetClipRegionRect() );
947 
948     // erst die Linien Zeichnen, dann clippen!
949     pView->SetClipRegion();
950     if( m_nStyle & ( WB_HASLINES | WB_HASLINESATROOT ) )
951         DrawNet();
952 
953     pView->SetClipRegion( aClipRegion );
954 
955     for( sal_uInt16 n=0; n< nCount && pEntry; n++ )
956     {
957         /*long nMaxRight=*/
958         pView->PaintEntry1( pEntry, nY, 0xffff, sal_True );
959         nY += nEntryHeight;
960         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
961     }
962 
963     if ( !pCursor && ( ( nExtendedWinBits & EWB_NO_AUTO_CURENTRY ) == 0 ) )
964     {
965         // do not select if multiselection or explicit set
966         sal_Bool bNotSelect = ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION )
967                 || ( ( m_nStyle & WB_NOINITIALSELECTION ) == WB_NOINITIALSELECTION );
968         SetCursor( pStartEntry, bNotSelect );
969     }
970 
971     nFlags &= (~F_DESEL_ALL);
972     pView->SetClipRegion();
973     Rectangle aRect;
974     if( !(nFlags & F_PAINTED) )
975     {
976         nFlags |= F_PAINTED;
977         RepaintScrollBars();
978     }
979     nFlags &= (~F_IN_PAINT);
980 }
981 
MakeVisible(SvLBoxEntry * pEntry,sal_Bool bMoveToTop)982 void SvImpLBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop )
983 {
984     if( !pEntry )
985         return;
986 
987     sal_Bool bInView = IsEntryInView( pEntry );
988 
989     if( bInView && (!bMoveToTop || pStartEntry == pEntry) )
990         return;  // ist schon sichtbar
991 
992     if( pStartEntry || (m_nStyle & WB_FORCE_MAKEVISIBLE) )
993         nFlags &= (~F_FILLING);
994     if( !bInView )
995     {
996         if( !pView->IsEntryVisible(pEntry) )  // Parent(s) zugeklappt ?
997         {
998             SvLBoxEntry* pParent = pView->GetParent( pEntry );
999             while( pParent )
1000             {
1001                 if( !pView->IsExpanded( pParent ) )
1002                 {
1003                     #ifdef DBG_UTIL
1004                     sal_Bool bRet =
1005                     #endif
1006                         pView->Expand( pParent );
1007                     DBG_ASSERT(bRet,"Not expanded!");
1008                 }
1009                 pParent = pView->GetParent( pParent );
1010             }
1011             // Passen Childs der Parents in View oder muessen wir scrollen ?
1012             if( IsEntryInView( pEntry ) && !bMoveToTop )
1013                 return;  // Scrollen nicht noetig -> tschuess
1014         }
1015     }
1016 
1017     pStartEntry = pEntry;
1018     ShowCursor( sal_False );
1019     FillView();
1020     aVerSBar.SetThumbPos( (long)(pView->GetVisiblePos( pStartEntry )) );
1021     ShowCursor( sal_True );
1022     pView->Invalidate();
1023 }
1024 
1025 
RepaintSelectionItems()1026 void SvImpLBox::RepaintSelectionItems()
1027 {
1028     if( !pView->GetVisibleCount() )
1029         return;
1030 
1031     if( !pStartEntry )
1032         pStartEntry = pView->First();
1033 
1034     if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
1035         SetNodeBmpTabDistance();
1036 
1037     ShowCursor( sal_False );
1038 
1039     long nEntryHeight = pView->GetEntryHeight();
1040 
1041     sal_uLong nCount = nVisibleCount;
1042     long nY = 0;
1043     SvLBoxEntry* pEntry = pStartEntry;
1044     for( sal_uLong n=0; n< nCount && pEntry; n++ )
1045     {
1046         pView->PaintEntry1( pEntry, nY, 0xffff ); //wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1047         nY += nEntryHeight;
1048         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
1049     }
1050 
1051     ShowCursor( sal_True );
1052 }
1053 
1054 
DrawNet()1055 void SvImpLBox::DrawNet()
1056 {
1057     if( pView->GetVisibleCount() < 2 && !pStartEntry->HasChildsOnDemand() &&
1058         !pStartEntry->HasChilds() )
1059         return;
1060 
1061     //for platforms who don't have nets, DrawNativeControl does nothing and return true
1062     //so that SvImpLBox::DrawNet() doesn't draw anything too
1063     if(pView->IsNativeControlSupported( CTRL_LISTNET, PART_ENTIRE_CONTROL)) {
1064         ImplControlValue    aControlValue;
1065         Point  aTemp(0,0);   // temporary needed for g++ 3.3.5
1066         Rectangle aCtrlRegion( aTemp, Size( 0, 0 ) );
1067         ControlState        nState = CTRL_STATE_ENABLED;
1068         if( pView->DrawNativeControl( CTRL_LISTNET, PART_ENTIRE_CONTROL,
1069                                       aCtrlRegion, nState, aControlValue, rtl::OUString() ) )
1070         {
1071             return;
1072         }
1073 
1074     }
1075 
1076     long nEntryHeight = pView->GetEntryHeight();
1077     long nEntryHeightDIV2 = nEntryHeight / 2;
1078     if( nEntryHeightDIV2 && !(nEntryHeight & 0x0001))
1079         nEntryHeightDIV2--;
1080 
1081     SvLBoxEntry* pChild;
1082     SvLBoxEntry* pEntry = pStartEntry;
1083 
1084     SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
1085     while( pTree->GetDepth( pEntry ) > 0 )
1086         pEntry = pView->GetParent( pEntry );
1087     sal_uInt16 nOffs = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ) -
1088                             pView->GetVisiblePos( pEntry ));
1089     long nY = 0;
1090     nY -= ( nOffs * nEntryHeight );
1091 
1092     DBG_ASSERT(pFirstDynamicTab,"No Tree!");
1093 
1094     Color aOldLineColor = pView->GetLineColor();
1095     const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1096     Color aCol= rStyleSettings.GetFaceColor();
1097 
1098     if( aCol.IsRGBEqual( pView->GetBackground().GetColor()) )
1099         aCol = rStyleSettings.GetShadowColor();
1100     pView->SetLineColor( aCol );
1101     Point aPos1, aPos2;
1102     sal_uInt16 nDistance;
1103     sal_uLong nMax = nVisibleCount + nOffs + 1;
1104 
1105     const Image& rExpandedNodeBitmap = GetExpandedNodeBmp();
1106 
1107     for( sal_uLong n=0; n< nMax && pEntry; n++ )
1108     {
1109         if( pView->IsExpanded(pEntry) )
1110         {
1111             aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1112             // wenn keine ContextBitmap, dann etwas nach rechts
1113             // unter den ersten Text (Node.Bmp ebenfalls
1114             if( !pView->nContextBmpWidthMax )
1115                 aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1116 
1117             aPos1.Y() = nY;
1118             aPos1.Y() += nEntryHeightDIV2;
1119 
1120             pChild = pView->FirstChild( pEntry );
1121             DBG_ASSERT(pChild,"Child?");
1122             pChild = pTree->LastSibling( pChild );
1123             nDistance = (sal_uInt16)(pView->GetVisiblePos(pChild) -
1124                                  pView->GetVisiblePos(pEntry));
1125             aPos2 = aPos1;
1126             aPos2.Y() += nDistance * nEntryHeight;
1127             pView->DrawLine( aPos1, aPos2 );
1128         }
1129         // Sichtbar im Control ?
1130         if( n>= nOffs && ((m_nStyle & WB_HASLINESATROOT) || !pTree->IsAtRootDepth(pEntry)))
1131         {
1132             // kann aPos1 recyclet werden ?
1133             if( !pView->IsExpanded(pEntry) )
1134             {
1135                 // njet
1136                 aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1137                 // wenn keine ContextBitmap, dann etwas nach rechts
1138                 // unter den ersten Text (Node.Bmp ebenfalls
1139                 if( !pView->nContextBmpWidthMax )
1140                     aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1141                 aPos1.Y() = nY;
1142                 aPos1.Y() += nEntryHeightDIV2;
1143                 aPos2.X() = aPos1.X();
1144             }
1145             aPos2.Y() = aPos1.Y();
1146             aPos2.X() -= pView->GetIndent();
1147             pView->DrawLine( aPos1, aPos2 );
1148         }
1149         nY += nEntryHeight;
1150         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
1151     }
1152     if( m_nStyle & WB_HASLINESATROOT )
1153     {
1154         pEntry = pView->First();
1155         aPos1.X() = pView->GetTabPos( pEntry, pFirstDynamicTab);
1156         // wenn keine ContextBitmap, dann etwas nach rechts
1157         // unter den ersten Text (Node.Bmp ebenfalls
1158         if( !pView->nContextBmpWidthMax )
1159             aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1160         aPos1.X() -=  pView->GetIndent();
1161         aPos1.Y() = GetEntryLine( pEntry );
1162         aPos1.Y() += nEntryHeightDIV2;
1163         pChild = pTree->LastSibling( pEntry );
1164         aPos2.X() = aPos1.X();
1165         aPos2.Y() = GetEntryLine( pChild );
1166         aPos2.Y() += nEntryHeightDIV2;
1167         pView->DrawLine( aPos1, aPos2 );
1168     }
1169     pView->SetLineColor( aOldLineColor );
1170 }
1171 
1172 
GetOptSize(TabBar * pTabBar)1173 static long GetOptSize( TabBar* pTabBar )
1174 {
1175     return pTabBar->CalcWindowSizePixel().Width();
1176 }
1177 
PositionScrollBars(Size & rSize,sal_uInt16 nMask)1178 void SvImpLBox::PositionScrollBars( Size& rSize, sal_uInt16 nMask )
1179 {
1180     long nOverlap = 0;
1181 
1182     Size aVerSize( nVerSBarWidth, rSize.Height() );
1183     Size aHorSize( rSize.Width(), nHorSBarHeight );
1184     long nTabBarWidth = 0;
1185     if( pTabBar )
1186     {
1187         nTabBarWidth = GetOptSize( pTabBar );
1188         long nMaxWidth = (rSize.Width() * 700) / 1000;
1189         if( nTabBarWidth > nMaxWidth )
1190         {
1191             nTabBarWidth = nMaxWidth;
1192             pTabBar->SetStyle( pTabBar->GetStyle() | WB_MINSCROLL );
1193         }
1194         else
1195         {
1196             WinBits nStyle = pTabBar->GetStyle();
1197             nStyle &= ~(WB_MINSCROLL);
1198             pTabBar->SetStyle( nStyle );
1199         }
1200         aHorSize.Width() -= nTabBarWidth;
1201         Size aTabSize( pTabBar->GetSizePixel() );
1202         aTabSize.Width() = nTabBarWidth;
1203         pTabBar->SetSizePixel( aTabSize );
1204     }
1205     if( nMask & 0x0001 )
1206         aHorSize.Width() -= nVerSBarWidth;
1207     if( nMask & 0x0002 )
1208         aVerSize.Height() -= nHorSBarHeight;
1209 
1210     aVerSize.Height() += 2 * nOverlap;
1211     Point aVerPos( rSize.Width() - aVerSize.Width() + nOverlap, -nOverlap );
1212     aVerSBar.SetPosSizePixel( aVerPos, aVerSize );
1213 
1214     aHorSize.Width() += 2 * nOverlap;
1215     Point aHorPos( -nOverlap, rSize.Height() - aHorSize.Height() + nOverlap );
1216     if( pTabBar )
1217         pTabBar->SetPosPixel( aHorPos );
1218     aHorPos.X() += nTabBarWidth;
1219     aHorSBar.SetPosSizePixel( aHorPos, aHorSize );
1220 
1221     if( nMask & 0x0001 )
1222         rSize.Width() = aVerPos.X();
1223     if( nMask & 0x0002 )
1224         rSize.Height() = aHorPos.Y();
1225     if( pTabBar )
1226         pTabBar->Show();
1227 
1228     if( (nMask & (0x0001|0x0002)) == (0x0001|0x0002) )
1229         aScrBarBox.Show();
1230     else
1231         aScrBarBox.Hide();
1232 
1233 }
1234 
1235 // nResult: Bit0 == VerSBar Bit1 == HorSBar
AdjustScrollBars(Size & rSize)1236 sal_uInt16 SvImpLBox::AdjustScrollBars( Size& rSize )
1237 {
1238     long nEntryHeight = pView->GetEntryHeight();
1239     if( !nEntryHeight )
1240         return 0;
1241 
1242     sal_uInt16 nResult = 0;
1243 
1244     Size aOSize( pView->Control::GetOutputSizePixel() );
1245 
1246     const WinBits nWindowStyle = pView->GetStyle();
1247     sal_Bool bVerSBar = ( nWindowStyle & WB_VSCROLL ) != 0;
1248     sal_Bool bHorBar = sal_False;
1249     long nMaxRight = aOSize.Width(); //GetOutputSize().Width();
1250     Point aOrigin( pView->GetMapMode().GetOrigin() );
1251     aOrigin.X() *= -1;
1252     nMaxRight += aOrigin.X() - 1;
1253     long nVis = nMostRight - aOrigin.X();
1254     if( pTabBar || (
1255         (nWindowStyle & WB_HSCROLL) &&
1256         (nVis < nMostRight || nMaxRight < nMostRight) ))
1257         bHorBar = sal_True;
1258 
1259     // Anzahl aller nicht eingeklappten Eintraege
1260     sal_uLong nTotalCount = pView->GetVisibleCount();
1261 
1262     // Anzahl in der View sichtbarer Eintraege
1263     nVisibleCount = aOSize.Height() / nEntryHeight;
1264 
1265     // muessen wir eine vertikale Scrollbar einblenden?
1266     if( bVerSBar || nTotalCount > nVisibleCount )
1267     {
1268         nResult = 1;
1269         nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1270         nMaxRight -= nVerSBarWidth;
1271         if( !bHorBar )
1272         {
1273             if( (nWindowStyle & WB_HSCROLL) &&
1274                 (nVis < nMostRight || nMaxRight < nMostRight) )
1275                 bHorBar = sal_True;
1276         }
1277     }
1278 
1279     // muessen wir eine horizontale Scrollbar einblenden?
1280     if( bHorBar )
1281     {
1282         nResult |= 0x0002;
1283         // die Anzahl der in der View sichtbaren Eintraege
1284         // muss neu berechnet werden, da die horizontale
1285         // ScrollBar eingeblendet wird
1286         nVisibleCount =  (aOSize.Height() - nHorSBarHeight) / nEntryHeight;
1287         // eventuell brauchen wir jetzt doch eine vertikale ScrollBar
1288         if( !(nResult & 0x0001) &&
1289             ((nTotalCount > nVisibleCount) || bVerSBar) )
1290         {
1291             nResult = 3;
1292             nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1293         }
1294     }
1295 
1296     PositionScrollBars( aOSize, nResult );
1297 
1298     // Range, VisibleRange usw. anpassen
1299 
1300     // Output-Size aktualisieren, falls wir scrollen muessen
1301     Rectangle aRect;
1302     aRect.SetSize( aOSize );
1303     aSelEng.SetVisibleArea( aRect );
1304 
1305     // Vertikale ScrollBar
1306     long nTemp = (long)nVisibleCount;
1307     nTemp--;
1308     if( nTemp != aVerSBar.GetVisibleSize() )
1309     {
1310         if( !bInVScrollHdl )
1311         {
1312             aVerSBar.SetPageSize( nTemp - 1 );
1313             aVerSBar.SetVisibleSize( nTemp );
1314         }
1315         else
1316         {
1317             nFlags |= F_ENDSCROLL_SET_VIS_SIZE;
1318             nNextVerVisSize = nTemp;
1319         }
1320     }
1321 
1322     // Horizontale ScrollBar
1323     nTemp = aHorSBar.GetThumbPos();
1324     aHorSBar.SetVisibleSize( aOSize.Width() );
1325     long nNewThumbPos = aHorSBar.GetThumbPos();
1326     Range aRange( aHorSBar.GetRange() );
1327     if( aRange.Max() < nMostRight+25 )
1328     {
1329         aRange.Max() = nMostRight+25;
1330         aHorSBar.SetRange( aRange );
1331     }
1332 
1333     if( nTemp != nNewThumbPos )
1334     {
1335         nTemp = nNewThumbPos - nTemp;
1336         if( pView->IsEditingActive() )
1337         {
1338             pView->EndEditing( sal_True ); // Cancel
1339             pView->Update();
1340         }
1341         pView->nFocusWidth = -1;
1342         KeyLeftRight( nTemp );
1343     }
1344 
1345     if( nResult & 0x0001 )
1346         aVerSBar.Show();
1347     else
1348         aVerSBar.Hide();
1349 
1350     if( nResult & 0x0002 )
1351         aHorSBar.Show();
1352     else
1353     {
1354         if( !pTabBar )
1355             aHorSBar.Hide();
1356     }
1357     rSize = aOSize;
1358     return nResult;
1359 }
1360 
InitScrollBarBox()1361 void SvImpLBox::InitScrollBarBox()
1362 {
1363     aScrBarBox.SetSizePixel( Size(nVerSBarWidth, nHorSBarHeight) );
1364     Size aSize( pView->Control::GetOutputSizePixel() );
1365     aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth, aSize.Height()-nHorSBarHeight));
1366 }
1367 
Resize()1368 void SvImpLBox::Resize()
1369 {
1370     Size aSize( pView->Control::GetOutputSizePixel());
1371     if( aSize.Width() <= 0 || aSize.Height() <= 0 )
1372         return;
1373     nFlags |= F_IN_RESIZE;
1374     InitScrollBarBox();
1375 
1376     if( pView->GetEntryHeight())
1377     {
1378         AdjustScrollBars( aOutputSize );
1379         FillView();
1380     }
1381     // !!!HACK, da in Floating- & Docking-Windows nach Resizes
1382     // die Scrollbars nicht richtig, bzw. ueberhaupt nicht gezeichnet werden
1383     if( aHorSBar.IsVisible())
1384         aHorSBar.Invalidate();
1385     if( aVerSBar.IsVisible())
1386         aVerSBar.Invalidate();
1387     nFlags &= (~(F_IN_RESIZE | F_PAINTED));
1388 }
1389 
FillView()1390 void SvImpLBox::FillView()
1391 {
1392     if( !pStartEntry )
1393     {
1394         sal_uInt16 nVisibleViewCount = (sal_uInt16)(pView->GetVisibleCount());
1395         sal_uInt16 nTempThumb = (sal_uInt16)aVerSBar.GetThumbPos();
1396         if( nTempThumb >= nVisibleViewCount )
1397             nTempThumb = nVisibleViewCount - 1;
1398         pStartEntry = (SvLBoxEntry*)(pView->GetEntryAtVisPos(nTempThumb));
1399     }
1400     if( pStartEntry )
1401     {
1402         sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
1403         sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1404         sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1405         if( nCurDispEntries <  nVisibleCount )
1406         {
1407             ShowCursor( sal_False );
1408             // Fenster fuellen, indem der Thumb schrittweise
1409             // nach oben bewegt wird
1410             sal_Bool bFound = sal_False;
1411             SvLBoxEntry* pTemp = pStartEntry;
1412             while( nCurDispEntries < nVisibleCount && pTemp )
1413             {
1414                 pTemp = (SvLBoxEntry*)(pView->PrevVisible(pStartEntry));
1415                 if( pTemp )
1416                 {
1417                     nThumb--;
1418                     pStartEntry = pTemp;
1419                     nCurDispEntries++;
1420                     bFound = sal_True;
1421                 }
1422             }
1423             if( bFound )
1424             {
1425                 aVerSBar.SetThumbPos( nThumb );
1426                 ShowCursor( sal_True ); // Focusrect neu berechnen
1427                 pView->Invalidate();
1428             }
1429         }
1430     }
1431 }
1432 
1433 
1434 
1435 
ShowVerSBar()1436 void SvImpLBox::ShowVerSBar()
1437 {
1438     sal_Bool bVerBar = ( pView->GetStyle() & WB_VSCROLL ) != 0;
1439     sal_uLong nVis = 0;
1440     if( !bVerBar )
1441         nVis = pView->GetVisibleCount();
1442     if( bVerBar || (nVisibleCount && nVis > (sal_uLong)(nVisibleCount-1)) )
1443     {
1444         if( !aVerSBar.IsVisible() )
1445         {
1446             pView->nFocusWidth = -1;
1447             AdjustScrollBars( aOutputSize );
1448             if( GetUpdateMode() )
1449                 aVerSBar.Update();
1450         }
1451     }
1452     else
1453     {
1454         if( aVerSBar.IsVisible() )
1455         {
1456             pView->nFocusWidth = -1;
1457             AdjustScrollBars( aOutputSize );
1458         }
1459     }
1460 
1461     long nMaxRight = GetOutputSize().Width();
1462     Point aPos( pView->GetMapMode().GetOrigin() );
1463     aPos.X() *= -1; // Umrechnung Dokumentkoord.
1464     nMaxRight = nMaxRight + aPos.X() - 1;
1465     if( nMaxRight < nMostRight  )
1466     {
1467         if( !aHorSBar.IsVisible() )
1468         {
1469             pView->nFocusWidth = -1;
1470             AdjustScrollBars( aOutputSize );
1471             if( GetUpdateMode() )
1472                 aHorSBar.Update();
1473         }
1474         else
1475         {
1476             Range aRange( aHorSBar.GetRange() );
1477             if( aRange.Max() < nMostRight+25 )
1478             {
1479                 aRange.Max() = nMostRight+25;
1480                 aHorSBar.SetRange( aRange );
1481             }
1482             else
1483             {
1484                 pView->nFocusWidth = -1;
1485                 AdjustScrollBars( aOutputSize );
1486             }
1487         }
1488     }
1489     else
1490     {
1491         if( aHorSBar.IsVisible() )
1492         {
1493             pView->nFocusWidth = -1;
1494             AdjustScrollBars( aOutputSize );
1495         }
1496     }
1497 }
1498 
1499 
SyncVerThumb()1500 void SvImpLBox::SyncVerThumb()
1501 {
1502     if( pStartEntry )
1503     {
1504         long nEntryPos = pView->GetVisiblePos( pStartEntry );
1505         aVerSBar.SetThumbPos( nEntryPos );
1506     }
1507     else
1508         aVerSBar.SetThumbPos( 0 );
1509 }
1510 
IsEntryInView(SvLBoxEntry * pEntry) const1511 sal_Bool SvImpLBox::IsEntryInView( SvLBoxEntry* pEntry ) const
1512 {
1513     // Parent eingeklappt
1514     if( !pView->IsEntryVisible(pEntry) )
1515         return sal_False;
1516     long nY = GetEntryLine( pEntry );
1517     if( nY < 0 )
1518         return sal_False;
1519     long nMax = nVisibleCount * pView->GetEntryHeight();
1520     if( nY >= nMax )
1521         return sal_False;
1522     return sal_True;
1523 }
1524 
1525 
GetEntryLine(SvLBoxEntry * pEntry) const1526 long SvImpLBox::GetEntryLine( SvLBoxEntry* pEntry ) const
1527 {
1528     if(!pStartEntry )
1529         return -1; // unsichtbare Position
1530 
1531     long nFirstVisPos = pView->GetVisiblePos( pStartEntry );
1532     long nEntryVisPos = pView->GetVisiblePos( pEntry );
1533     nFirstVisPos = nEntryVisPos - nFirstVisPos;
1534     nFirstVisPos *= pView->GetEntryHeight();
1535     return nFirstVisPos;
1536 }
1537 
SetEntryHeight(short)1538 void SvImpLBox::SetEntryHeight( short /* nHeight */ )
1539 {
1540     SetNodeBmpYOffset( GetExpandedNodeBmp() );
1541     SetNodeBmpYOffset( GetCollapsedNodeBmp() );
1542     if(!pView->HasViewData()) // stehen wir im Clear?
1543     {
1544         Size aSize = pView->Control::GetOutputSizePixel();
1545         AdjustScrollBars( aSize );
1546     }
1547     else
1548     {
1549         Resize();
1550         if( GetUpdateMode() )
1551             pView->Invalidate();
1552     }
1553 }
1554 
1555 
1556 
1557 // ***********************************************************************
1558 // Callback-Functions
1559 // ***********************************************************************
1560 
IndentChanged(short)1561 void SvImpLBox::IndentChanged( short /* nIndentPixel */ ) {}
1562 
EntryExpanded(SvLBoxEntry * pEntry)1563 void SvImpLBox::EntryExpanded( SvLBoxEntry* pEntry )
1564 {
1565     // SelAllDestrAnch( sal_False, sal_True ); //DeselectAll();
1566     if( GetUpdateMode() )
1567     {
1568         ShowCursor( sal_False );
1569         long nY = GetEntryLine( pEntry );
1570         if( IsLineVisible(nY) )
1571         {
1572             InvalidateEntriesFrom( nY );
1573             FindMostRight( pEntry, 0  );
1574         }
1575         aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1576         // falls vor dem Thumb expandiert wurde, muss
1577         // die Thumb-Position korrigiert werden.
1578         SyncVerThumb();
1579         ShowVerSBar();
1580         ShowCursor( sal_True );
1581     }
1582 }
1583 
EntryCollapsed(SvLBoxEntry * pEntry)1584 void SvImpLBox::EntryCollapsed( SvLBoxEntry* pEntry )
1585 {
1586     if( !pView->IsEntryVisible( pEntry ) )
1587         return;
1588 
1589     ShowCursor( sal_False );
1590 
1591     if( !pMostRightEntry || pTree->IsChild( pEntry,pMostRightEntry ) )
1592     {
1593         FindMostRight(0);
1594     }
1595 
1596     if( pStartEntry )
1597     {
1598         long nOldThumbPos   = aVerSBar.GetThumbPos();
1599         sal_uLong nVisList      = pView->GetVisibleCount();
1600         aVerSBar.SetRange( Range(0, nVisList-1) );
1601         long nNewThumbPos   = aVerSBar.GetThumbPos();
1602         if( nNewThumbPos != nOldThumbPos  )
1603         {
1604             pStartEntry = pView->First();
1605             sal_uInt16 nDistance = (sal_uInt16)nNewThumbPos;
1606             if( nDistance )
1607                 pStartEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry,
1608                                                         nDistance));
1609             if( GetUpdateMode() )
1610                 pView->Invalidate();
1611         }
1612         else
1613             SyncVerThumb();
1614         ShowVerSBar();
1615     }
1616     // wurde Cursor eingeklappt ?
1617     if( pTree->IsChild( pEntry, pCursor ) )
1618         SetCursor( pEntry );
1619     if( GetUpdateMode() )
1620         ShowVerSBar();
1621     ShowCursor( sal_True );
1622     if( GetUpdateMode() && pCursor )
1623         pView->Select( pCursor, sal_True );
1624 }
1625 
CollapsingEntry(SvLBoxEntry * pEntry)1626 void SvImpLBox::CollapsingEntry( SvLBoxEntry* pEntry )
1627 {
1628     if( !pView->IsEntryVisible( pEntry ) || !pStartEntry )
1629         return;
1630 
1631     SelAllDestrAnch( sal_False, sal_True ); // deselectall
1632 
1633     // ist der eingeklappte Parent sichtbar ?
1634     long nY = GetEntryLine( pEntry );
1635     if( IsLineVisible(nY) )
1636     {
1637         if( GetUpdateMode() )
1638             InvalidateEntriesFrom( nY );
1639     }
1640     else
1641     {
1642         if( pTree->IsChild(pEntry, pStartEntry) )
1643         {
1644             pStartEntry = pEntry;
1645             if( GetUpdateMode() )
1646                 pView->Invalidate();
1647         }
1648     }
1649 }
1650 
1651 
SetNodeBmpYOffset(const Image & rBmp)1652 void SvImpLBox::SetNodeBmpYOffset( const Image& rBmp )
1653 {
1654     Size aSize;
1655     nYoffsNodeBmp = pView->GetHeightOffset( rBmp, aSize );
1656     nNodeBmpWidth = aSize.Width();
1657 }
1658 
SetNodeBmpTabDistance()1659 void SvImpLBox::SetNodeBmpTabDistance()
1660 {
1661     nNodeBmpTabDistance = -pView->GetIndent();
1662     if( pView->nContextBmpWidthMax )
1663     {
1664         // nur, wenn der erste dynamische Tab zentriert ist
1665         // (setze ich momentan voraus)
1666         Size aSize = GetExpandedNodeBmp().GetSizePixel();
1667         nNodeBmpTabDistance -= aSize.Width() / 2;
1668     }
1669 }
1670 
1671 //
1672 // korrigiert bei SingleSelection den Cursor
1673 //
EntrySelected(SvLBoxEntry * pEntry,sal_Bool bSelect)1674 void SvImpLBox::EntrySelected( SvLBoxEntry* pEntry, sal_Bool bSelect )
1675 {
1676     if( nFlags & F_IGNORE_SELECT )
1677         return;
1678 
1679     /*
1680     if( (m_nStyle & WB_HIDESELECTION) && pEntry && !pView->HasFocus() )
1681     {
1682         SvViewData* pViewData = pView->GetViewData( pEntry );
1683         pViewData->SetCursored( bSelect );
1684     }
1685     */
1686 
1687     nFlags &= (~F_DESEL_ALL);
1688     if( bSelect &&
1689         aSelEng.GetSelectionMode() == SINGLE_SELECTION &&
1690         pEntry != pCursor )
1691     {
1692         SetCursor( pEntry );
1693         DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1694     }
1695 
1696     if( GetUpdateMode() && pView->IsEntryVisible(pEntry) )
1697     {
1698         long nY = GetEntryLine( pEntry );
1699         if( IsLineVisible( nY ) )
1700         {
1701             ShowCursor( sal_False );
1702             pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1703             ShowCursor( sal_True );
1704         }
1705     }
1706 }
1707 
1708 
RemovingEntry(SvLBoxEntry * pEntry)1709 void SvImpLBox::RemovingEntry( SvLBoxEntry* pEntry )
1710 {
1711     CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED , pEntry );
1712 
1713     DestroyAnchor();
1714 
1715     if( !pView->IsEntryVisible( pEntry ) )
1716     {
1717         // wenn Parent eingeklappt, dann tschuess
1718         nFlags |= F_REMOVED_ENTRY_INVISIBLE;
1719         return;
1720     }
1721 
1722     if( pEntry == pMostRightEntry || (
1723         pEntry->HasChilds() && pView->IsExpanded(pEntry) &&
1724         pTree->IsChild(pEntry, pMostRightEntry)))
1725     {
1726         nFlags |= F_REMOVED_RECALC_MOST_RIGHT;
1727     }
1728 
1729     SvLBoxEntry* pOldStartEntry = pStartEntry;
1730 
1731     SvLBoxEntry* pParent = (SvLBoxEntry*)(pView->GetModel()->GetParent(pEntry));
1732 
1733     if( pParent && pView->GetModel()->GetChildList(pParent)->Count() == 1 )
1734     {
1735         DBG_ASSERT( pView->IsExpanded( pParent ), "Parent not expanded");
1736         pParent->SetFlags( pParent->GetFlags() | SV_ENTRYFLAG_NO_NODEBMP);
1737         InvalidateEntry( pParent );
1738     }
1739 
1740     if( pCursor && pTree->IsChild( pEntry, pCursor) )
1741         pCursor = pEntry;
1742     if( pStartEntry && pTree->IsChild(pEntry,pStartEntry) )
1743         pStartEntry = pEntry;
1744 
1745     SvLBoxEntry* pTemp;
1746     if( pCursor && pCursor == pEntry )
1747     {
1748         if( bSimpleTravel )
1749             pView->Select( pCursor, sal_False );
1750         ShowCursor( sal_False );    // Focus-Rect weg
1751         // NextSibling, weil auch Childs des Cursors geloescht werden
1752         pTemp = pView->NextSibling( pCursor );
1753         if( !pTemp )
1754             pTemp = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
1755 
1756         SetCursor( pTemp, sal_True );
1757     }
1758     if( pStartEntry && pStartEntry == pEntry )
1759     {
1760         pTemp = pView->NextSibling( pStartEntry );
1761         if( !pTemp )
1762             pTemp = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
1763         pStartEntry = pTemp;
1764     }
1765     if( GetUpdateMode())
1766     {
1767         // wenns der letzte ist, muss invalidiert werden, damit die Linien
1768         // richtig gezeichnet (in diesem Fall geloescht) werden.
1769         if( pStartEntry && (pStartEntry != pOldStartEntry || pEntry == (SvLBoxEntry*)pView->GetModel()->Last()) )
1770         {
1771             aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry ));
1772             pView->Invalidate( GetVisibleArea() );
1773         }
1774         else
1775             InvalidateEntriesFrom( GetEntryLine( pEntry ) );
1776     }
1777 }
1778 
EntryRemoved()1779 void SvImpLBox::EntryRemoved()
1780 {
1781     if( nFlags & F_REMOVED_ENTRY_INVISIBLE )
1782     {
1783         nFlags &= (~F_REMOVED_ENTRY_INVISIBLE);
1784         return;
1785     }
1786     if( !pStartEntry )
1787         pStartEntry = pTree->First();
1788     if( !pCursor )
1789         SetCursor( pStartEntry, sal_True );
1790 
1791     if( pCursor && (bSimpleTravel || !pView->GetSelectionCount() ))
1792         pView->Select( pCursor, sal_True );
1793 
1794     if( GetUpdateMode())
1795     {
1796         if( nFlags & F_REMOVED_RECALC_MOST_RIGHT )
1797             FindMostRight(0);
1798         aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1799         FillView();
1800         if( pStartEntry )
1801             // falls ueber dem Thumb geloescht wurde
1802             aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry) );
1803 
1804         ShowVerSBar();
1805         if( pCursor && pView->HasFocus() && !pView->IsSelected(pCursor) )
1806         {
1807             if( pView->GetSelectionCount() )
1808             {
1809                 // ist ein benachbarter Eintrag selektiert?
1810                 SvLBoxEntry* pNextCursor = (SvLBoxEntry*)pView->PrevVisible( pCursor );
1811                 if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1812                     pNextCursor = (SvLBoxEntry*)pView->NextVisible( pCursor );
1813                 if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1814                     // kein Nachbar selektiert: Ersten selektierten nehmen
1815                     pNextCursor = pView->FirstSelected();
1816                 SetCursor( pNextCursor );
1817                 MakeVisible( pCursor );
1818             }
1819             else
1820                 pView->Select( pCursor, sal_True );
1821         }
1822         ShowCursor( sal_True );
1823     }
1824     nFlags &= (~F_REMOVED_RECALC_MOST_RIGHT);
1825 }
1826 
1827 
MovingEntry(SvLBoxEntry * pEntry)1828 void SvImpLBox::MovingEntry( SvLBoxEntry* pEntry )
1829 {
1830     int bDeselAll = nFlags & F_DESEL_ALL;
1831     SelAllDestrAnch( sal_False, sal_True );  // DeselectAll();
1832     if( !bDeselAll )
1833         nFlags &= (~F_DESEL_ALL);
1834 
1835     if( pEntry == pCursor )
1836         ShowCursor( sal_False );
1837     if( IsEntryInView( pEntry ) )
1838         pView->Invalidate();
1839     if( pEntry == pStartEntry )
1840     {
1841         SvLBoxEntry* pNew = 0;
1842         if( !pEntry->HasChilds() )
1843         {
1844             pNew = (SvLBoxEntry*)(pView->NextVisible( pStartEntry ));
1845             if( !pNew )
1846                 pNew = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
1847         }
1848         else
1849         {
1850             pNew = pTree->NextSibling( pEntry );
1851             if( !pNew )
1852                 pNew = pTree->PrevSibling( pEntry );
1853         }
1854         pStartEntry = pNew;
1855     }
1856 }
1857 
EntryMoved(SvLBoxEntry * pEntry)1858 void SvImpLBox::EntryMoved( SvLBoxEntry* pEntry )
1859 {
1860     // #97680# --------------
1861     UpdateContextBmpWidthVectorFromMovedEntry( pEntry );
1862 
1863     if ( !pStartEntry )
1864         // this might happen if the only entry in the view is moved to its very same position
1865         // #i97346#
1866         pStartEntry = pView->First();
1867 
1868     aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1869     sal_uInt16 nFirstPos = (sal_uInt16)pTree->GetAbsPos( pStartEntry );
1870     sal_uInt16 nNewPos = (sal_uInt16)pTree->GetAbsPos( pEntry );
1871     FindMostRight(0);
1872     if( nNewPos < nFirstPos ) //!!!Notloesung
1873         pStartEntry = pEntry;
1874     // #97702# ---------------
1875     SyncVerThumb();
1876     if( pEntry == pCursor )
1877     {
1878         if( pView->IsEntryVisible( pCursor ) )
1879             ShowCursor( sal_True );
1880         else
1881         {
1882             SvLBoxEntry* pParent = pEntry;
1883             do {
1884                 pParent = pTree->GetParent( pParent );
1885             }
1886             while( !pView->IsEntryVisible( pParent ) );
1887             SetCursor( pParent );
1888         }
1889     }
1890     if( IsEntryInView( pEntry ) )
1891         pView->Invalidate();
1892 }
1893 
1894 
1895 
EntryInserted(SvLBoxEntry * pEntry)1896 void SvImpLBox::EntryInserted( SvLBoxEntry* pEntry )
1897 {
1898     if( GetUpdateMode() )
1899     {
1900         SvLBoxEntry* pParent = (SvLBoxEntry*)pTree->GetParent(pEntry);
1901         if( pParent && pTree->GetChildList(pParent)->Count() == 1 )
1902             // Pluszeichen zeichnen
1903             pTree->InvalidateEntry( pParent );
1904 
1905         if( !pView->IsEntryVisible( pEntry ) )
1906             return;
1907         int bDeselAll = nFlags & F_DESEL_ALL;
1908         if( bDeselAll )
1909             SelAllDestrAnch( sal_False, sal_True );
1910         else
1911             DestroyAnchor();
1912         //  nFlags &= (~F_DESEL_ALL);
1913 //      ShowCursor( sal_False ); // falls sich Cursor nach unten verschiebt
1914         long nY = GetEntryLine( pEntry );
1915         sal_Bool bEntryVisible = IsLineVisible( nY );
1916         if( bEntryVisible )
1917         {
1918             ShowCursor( sal_False ); // falls sich Cursor nach unten verschiebt
1919             nY -= pView->GetEntryHeight(); // wg. Linien
1920             InvalidateEntriesFrom( nY );
1921         }
1922         else if( pStartEntry && nY < GetEntryLine(pStartEntry) )
1923         {
1924             // pruefen, ob die View komplett gefuellt ist. Wenn
1925             // nicht, dann pStartEntry und den Cursor anpassen
1926             // (automatisches scrollen)
1927             sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
1928             sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1929             sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1930             if( nCurDispEntries < nVisibleCount )
1931             {
1932                 // beim naechsten Paint-Event setzen
1933                 pStartEntry = 0;
1934                 SetCursor( 0 );
1935                 pView->Invalidate();
1936             }
1937         }
1938         else if( !pStartEntry )
1939             pView->Invalidate();
1940 
1941         // die Linien invalidieren
1942         /*
1943         if( (bEntryVisible || bPrevEntryVisible) &&
1944             (m_nStyle & ( WB_HASLINES | WB_HASLINESATROOT )) )
1945         {
1946             SvLBoxTab* pTab = pView->GetFirstDynamicTab();
1947             if( pTab )
1948             {
1949                 long nDX = pView->GetTabPos( pEntry, pTab );
1950                 Point aTmpPoint;
1951                 Size aSize( nDX, nY );
1952                 Rectangle aRect( aTmpPoint, aSize );
1953                 pView->Invalidate( aRect );
1954             }
1955         }
1956         */
1957 
1958         SetMostRight( pEntry );
1959         aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1960         SyncVerThumb(); // falls vor Thumb eingefuegt wurde
1961         ShowVerSBar();
1962         ShowCursor( sal_True );
1963         if( pStartEntry != pView->First() && (nFlags & F_FILLING) )
1964             pView->Update();
1965     }
1966 }
1967 
1968 
1969 
1970 // ********************************************************************
1971 // Eventhandler
1972 // ********************************************************************
1973 
1974 
1975 // ****** Steuerung der Controlanimation
1976 
ButtonDownCheckCtrl(const MouseEvent & rMEvt,SvLBoxEntry * pEntry,long nY)1977 sal_Bool SvImpLBox::ButtonDownCheckCtrl(const MouseEvent& rMEvt, SvLBoxEntry* pEntry,
1978                                    long nY  )
1979 {
1980     SvLBoxItem* pItem = pView->GetItem(pEntry,rMEvt.GetPosPixel().X(),&pActiveTab);
1981     if( pItem && (pItem->IsA()==SV_ITEM_ID_LBOXBUTTON))
1982     {
1983         pActiveButton = (SvLBoxButton*)pItem;
1984         pActiveEntry = pEntry;
1985         if( pCursor == pActiveEntry )
1986             pView->HideFocus();
1987         pView->CaptureMouse();
1988         pActiveButton->SetStateHilighted( sal_True );
1989         pView->PaintEntry1( pActiveEntry, nY,
1990                     SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
1991                     SV_LBOXTAB_ADJUST_RIGHT );
1992         return sal_True;
1993     }
1994     else
1995         pActiveButton = 0;
1996     return sal_False;
1997 }
1998 
MouseMoveCheckCtrl(const MouseEvent & rMEvt,SvLBoxEntry * pEntry)1999 sal_Bool SvImpLBox::MouseMoveCheckCtrl( const MouseEvent& rMEvt, SvLBoxEntry* pEntry)
2000 {
2001     if( pActiveButton )
2002     {
2003         long nY;
2004         long nMouseX = rMEvt.GetPosPixel().X();
2005         if( pEntry == pActiveEntry &&
2006              pView->GetItem(pActiveEntry, nMouseX) == pActiveButton )
2007         {
2008             if( !pActiveButton->IsStateHilighted() )
2009             {
2010                 pActiveButton->SetStateHilighted(sal_True );
2011                 nY = GetEntryLine( pActiveEntry );
2012                 pView->PaintEntry1( pActiveEntry, nY,
2013                     SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2014                     SV_LBOXTAB_ADJUST_RIGHT );
2015             }
2016         }
2017         else
2018         {
2019             if( pActiveButton->IsStateHilighted() )
2020             {
2021                 pActiveButton->SetStateHilighted(sal_False );
2022                 nY = GetEntryLine( pActiveEntry );
2023                 pView->PaintEntry1( pActiveEntry, nY, SV_LBOXTAB_PUSHABLE );
2024             }
2025         }
2026         return sal_True;
2027     }
2028     return sal_False;
2029 }
2030 
ButtonUpCheckCtrl(const MouseEvent & rMEvt)2031 sal_Bool SvImpLBox::ButtonUpCheckCtrl( const MouseEvent& rMEvt )
2032 {
2033     if( pActiveButton )
2034     {
2035         pView->ReleaseMouse();
2036         SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2037         long nY = GetEntryLine( pActiveEntry );
2038         pActiveButton->SetStateHilighted( sal_False );
2039         long nMouseX = rMEvt.GetPosPixel().X();
2040         if( pEntry == pActiveEntry &&
2041              pView->GetItem( pActiveEntry, nMouseX ) == pActiveButton )
2042             pActiveButton->ClickHdl( pView, pActiveEntry );
2043         pView->PaintEntry1( pActiveEntry, nY,
2044                     SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2045                     SV_LBOXTAB_ADJUST_RIGHT );
2046         if( pCursor == pActiveEntry )
2047             ShowCursor( sal_True );
2048         pActiveButton = 0;
2049         pActiveEntry = 0;
2050         pActiveTab = 0;
2051         return sal_True;
2052     }
2053     return sal_False;
2054 }
2055 
2056 // ******* Steuerung Plus/Minus-Button zum Expandieren/Kollabieren
2057 
2058 // sal_False == kein Expand/Collapse-Button getroffen
IsNodeButton(const Point & rPosPixel,SvLBoxEntry * pEntry) const2059 sal_Bool SvImpLBox::IsNodeButton( const Point& rPosPixel, SvLBoxEntry* pEntry ) const
2060 {
2061     if( !pEntry->HasChilds() && !pEntry->HasChildsOnDemand() )
2062         return sal_False;
2063 
2064     SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
2065     if( !pFirstDynamicTab )
2066         return sal_False;
2067 
2068     long nMouseX = rPosPixel.X();
2069     // in Doc-Koords umrechnen
2070     Point aOrigin( pView->GetMapMode().GetOrigin() );
2071     nMouseX -= aOrigin.X();
2072 
2073     long nX = pView->GetTabPos( pEntry, pFirstDynamicTab);
2074     nX += nNodeBmpTabDistance;
2075     if( nMouseX < nX )
2076         return sal_False;
2077     nX += nNodeBmpWidth;
2078     if( nMouseX > nX )
2079         return sal_False;
2080     return sal_True;
2081 }
2082 
2083 // sal_False == hit no node button
ButtonDownCheckExpand(const MouseEvent & rMEvt,SvLBoxEntry * pEntry,long)2084 sal_Bool SvImpLBox::ButtonDownCheckExpand( const MouseEvent& rMEvt, SvLBoxEntry* pEntry, long /* nY */ )
2085 {
2086     sal_Bool bRet = sal_False;
2087 
2088     if ( pView->IsEditingActive() && pEntry == pView->pEdEntry )
2089         // inplace editing -> nothing to do
2090         bRet = sal_True;
2091     else if ( IsNodeButton( rMEvt.GetPosPixel(), pEntry ) )
2092     {
2093         if ( pView->IsExpanded( pEntry ) )
2094         {
2095             pView->EndEditing( sal_True );
2096             pView->Collapse( pEntry );
2097         }
2098         else
2099         {
2100             // you can expand an entry, which is in editing
2101             pView->Expand( pEntry );
2102         }
2103         bRet = sal_True;
2104     }
2105 
2106     return bRet;
2107 }
2108 
MouseButtonDown(const MouseEvent & rMEvt)2109 void SvImpLBox::MouseButtonDown( const MouseEvent& rMEvt )
2110 {
2111     if ( !rMEvt.IsLeft() && !rMEvt.IsRight())
2112         return;
2113 
2114 #ifdef OS2
2115     // unter OS/2 kommt zwischen MouseButtonDown und
2116     // MouseButtonUp ein MouseMove
2117     nFlags |= F_IGNORE_NEXT_MOUSEMOVE;
2118 #endif
2119     aEditTimer.Stop();
2120     Point aPos( rMEvt.GetPosPixel());
2121 
2122     if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
2123         return;
2124 
2125     SvLBoxEntry* pEntry = GetEntry( aPos );
2126     if ( pEntry != pCursor )
2127         // new entry selected -> reset current tab position to first tab
2128         nCurTabPos = FIRST_ENTRY_TAB;
2129     nFlags &= (~F_FILLING);
2130     pView->GrabFocus();
2131     // #120417# the entry can still be invalid!
2132     if( !pEntry || !pView->GetViewData( pEntry ))
2133         return;
2134 
2135     long nY = GetEntryLine( pEntry );
2136     // Node-Button?
2137     if( ButtonDownCheckExpand( rMEvt, pEntry, nY ) )
2138         return;
2139 
2140     if( !EntryReallyHit(pEntry,aPos,nY))
2141         return;
2142 
2143     SvLBoxItem* pXItem = pView->GetItem( pEntry, aPos.X() );
2144     if( pXItem )
2145     {
2146         SvLBoxTab* pXTab = pView->GetTab( pEntry, pXItem );
2147         if ( !rMEvt.IsMod1() && !rMEvt.IsMod2() && rMEvt.IsLeft() && pXTab->IsEditable()
2148             && pEntry == pView->FirstSelected() && NULL == pView->NextSelected( pEntry ) )
2149                 // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
2150             nFlags |= F_START_EDITTIMER;
2151         if ( !pView->IsSelected( pEntry ) )
2152             nFlags &= ~F_START_EDITTIMER;
2153     }
2154 
2155 
2156     if( (rMEvt.GetClicks() % 2) == 0 )
2157     {
2158         nFlags &= (~F_START_EDITTIMER);
2159         pView->pHdlEntry = pEntry;
2160         if( pView->DoubleClickHdl() )
2161         {
2162             // falls im Handler der Eintrag geloescht wurde
2163             pEntry = GetClickedEntry( aPos );
2164             if( !pEntry )
2165                 return;
2166             if( pEntry != pView->pHdlEntry )
2167             {
2168                 // neu selektieren & tschuess
2169                 if( !bSimpleTravel && !aSelEng.IsAlwaysAdding())
2170                     SelAllDestrAnch( sal_False, sal_True ); // DeselectAll();
2171                 SetCursor( pEntry );
2172 
2173                 return;
2174             }
2175             if( pEntry->HasChilds() || pEntry->HasChildsOnDemand() )
2176             {
2177                 if( pView->IsExpanded(pEntry) )
2178                     pView->Collapse( pEntry );
2179                 else
2180                     pView->Expand( pEntry );
2181                 if( pEntry == pCursor )  // nur wenn Entryitem angeklickt wurde
2182                                           // (Nodebutton ist kein Entryitem!)
2183                     pView->Select( pCursor, sal_True );
2184                 return;
2185             }
2186         }
2187     }
2188     else
2189     {
2190         // CheckButton? (TreeListBox: Check + Info)
2191         if( ButtonDownCheckCtrl(rMEvt, pEntry, nY) == sal_True)
2192             return;
2193         // Inplace-Editing?
2194 #if 0
2195         if( rMEvt.IsMod2() && pView->IsInplaceEditingEnabled() )
2196         {
2197             SvLBoxItem* pItem = pView->GetItem( pEntry, aPos.X() );
2198             if( pItem )
2199                 pView->EditingRequest( pEntry, pItem, aPos );
2200             return;
2201         }
2202 #endif
2203     }
2204     if ( aSelEng.GetSelectionMode() != NO_SELECTION )
2205         aSelEng.SelMouseButtonDown( rMEvt );
2206 }
2207 
MouseButtonUp(const MouseEvent & rMEvt)2208 void SvImpLBox::MouseButtonUp( const MouseEvent& rMEvt)
2209 {
2210 #ifdef OS2
2211     nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
2212 #endif
2213     if ( !ButtonUpCheckCtrl( rMEvt ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2214         aSelEng.SelMouseButtonUp( rMEvt );
2215     EndScroll();
2216     if( nFlags & F_START_EDITTIMER )
2217     {
2218         nFlags &= (~F_START_EDITTIMER);
2219         aEditClickPos = rMEvt.GetPosPixel();
2220         aEditTimer.Start();
2221     }
2222 
2223     return;
2224 }
2225 
MouseMove(const MouseEvent & rMEvt)2226 void SvImpLBox::MouseMove( const MouseEvent& rMEvt)
2227 {
2228 #ifdef OS2
2229     if( nFlags & F_IGNORE_NEXT_MOUSEMOVE )
2230     {
2231         nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
2232         return;
2233     }
2234 #endif
2235     SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2236     if ( !MouseMoveCheckCtrl( rMEvt, pEntry ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2237         aSelEng.SelMouseMove( rMEvt );
2238     return;
2239 }
2240 
KeyInput(const KeyEvent & rKEvt)2241 sal_Bool SvImpLBox::KeyInput( const KeyEvent& rKEvt)
2242 {
2243     aEditTimer.Stop();
2244     const KeyCode&  rKeyCode = rKEvt.GetKeyCode();
2245 
2246     if( rKeyCode.IsMod2() )
2247         return sal_False; // Alt-Taste nicht auswerten
2248 
2249     nFlags &= (~F_FILLING);
2250 
2251     if( !pCursor )
2252         pCursor = pStartEntry;
2253     if( !pCursor )
2254         return sal_False;
2255 
2256     sal_Bool bKeyUsed = sal_True;
2257 
2258     sal_uInt16  nDelta = (sal_uInt16)aVerSBar.GetPageSize();
2259     sal_uInt16  aCode = rKeyCode.GetCode();
2260 
2261     sal_Bool    bShift = rKeyCode.IsShift();
2262     sal_Bool    bMod1 = rKeyCode.IsMod1();
2263 
2264     SvLBoxEntry* pNewCursor;
2265 
2266     const WinBits nWindowStyle = pView->GetStyle();
2267     switch( aCode )
2268     {
2269         case KEY_UP:
2270             if( !IsEntryInView( pCursor ) )
2271                 MakeVisible( pCursor );
2272 
2273             pNewCursor = pCursor;
2274             do
2275             {
2276                 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2277             } while( pNewCursor && !IsSelectable(pNewCursor) );
2278 
2279             if ( pNewCursor )
2280                 // new entry selected -> reset current tab position to first tab
2281                 nCurTabPos = FIRST_ENTRY_TAB;
2282             // if there is no next entry, take the current one
2283             // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2284             // the cursor key
2285             // 06.09.20001 - 83416 - fs@openoffice.org
2286             if ( !pNewCursor && pCursor )
2287                 pNewCursor = pCursor;
2288 
2289             if( pNewCursor )
2290             {
2291                 aSelEng.CursorPosChanging( bShift, bMod1 );
2292                 SetCursor( pNewCursor, bMod1 );     // no selection, when Ctrl is on
2293                 if( !IsEntryInView( pNewCursor ) )
2294                     KeyUp( sal_False );
2295             }
2296             break;
2297 
2298         case KEY_DOWN:
2299             if( !IsEntryInView( pCursor ) )
2300                 MakeVisible( pCursor );
2301 
2302             pNewCursor = pCursor;
2303             do
2304             {
2305                 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2306             } while( pNewCursor && !IsSelectable(pNewCursor) );
2307 
2308             if ( pNewCursor )
2309                 // new entry selected -> reset current tab position to first tab
2310                 nCurTabPos = FIRST_ENTRY_TAB;
2311 
2312             // if there is no next entry, take the current one
2313             // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2314             // the cursor key
2315             // 06.09.20001 - 83416 - frank.schoenheit@sun.com
2316             if ( !pNewCursor && pCursor )
2317                 pNewCursor = pCursor;
2318 
2319             if( pNewCursor )
2320             {
2321                 aSelEng.CursorPosChanging( bShift, bMod1 );
2322                 if( IsEntryInView( pNewCursor ) )
2323                     SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2324                 else
2325                 {
2326                     if( pCursor )
2327                         pView->Select( pCursor, sal_False );
2328                     KeyDown( sal_False );
2329                     SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2330                 }
2331             }
2332             else
2333                 KeyDown( sal_False ); // weil ScrollBar-Range evtl. noch
2334                                   // scrollen erlaubt
2335             break;
2336 
2337         case KEY_RIGHT:
2338         {
2339             if( bSubLstOpLR && IsNowExpandable() )
2340                 pView->Expand( pCursor );
2341             else if ( bIsCellFocusEnabled && pCursor )
2342             {
2343                 if ( nCurTabPos < ( pView->TabCount() - 1 /*!2*/ ) )
2344                 {
2345                     ++nCurTabPos;
2346                     ShowCursor( sal_True );
2347                     CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2348                 }
2349             }
2350             else if( nWindowStyle & WB_HSCROLL )
2351             {
2352                 long    nThumb = aHorSBar.GetThumbPos();
2353                 nThumb += aHorSBar.GetLineSize();
2354                 long    nOldThumb = aHorSBar.GetThumbPos();
2355                 aHorSBar.SetThumbPos( nThumb );
2356                 nThumb = nOldThumb;
2357                 nThumb -= aHorSBar.GetThumbPos();
2358                 nThumb *= -1;
2359                 if( nThumb )
2360                 {
2361                     KeyLeftRight( nThumb );
2362                     EndScroll();
2363                 }
2364             }
2365             else
2366                 bKeyUsed = sal_False;
2367             break;
2368         }
2369 
2370         case KEY_LEFT:
2371         {
2372             // if ( bIsCellFocusEnabled )
2373             if ( bIsCellFocusEnabled && pCursor )
2374             {
2375                 if ( nCurTabPos > FIRST_ENTRY_TAB )
2376                 {
2377                     --nCurTabPos;
2378                     ShowCursor( sal_True );
2379                     CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2380                 }
2381             }
2382             else if ( nWindowStyle & WB_HSCROLL )
2383             {
2384                 long    nThumb = aHorSBar.GetThumbPos();
2385                 nThumb -= aHorSBar.GetLineSize();
2386                 long    nOldThumb = aHorSBar.GetThumbPos();
2387                 aHorSBar.SetThumbPos( nThumb );
2388                 nThumb = nOldThumb;
2389                 nThumb -= aHorSBar.GetThumbPos();
2390                 if( nThumb )
2391                 {
2392                     KeyLeftRight( -nThumb );
2393                     EndScroll();
2394                 }
2395                 else if( bSubLstOpLR )
2396                 {
2397                     if( IsExpandable() && pView->IsExpanded( pCursor ) )
2398                         pView->Collapse( pCursor );
2399                     else
2400                     {
2401                         pNewCursor = pView->GetParent( pCursor );
2402                         if( pNewCursor )
2403                             SetCursor( pNewCursor );
2404                     }
2405                 }
2406             }
2407             else if( bSubLstOpLR && IsExpandable() )
2408                 pView->Collapse( pCursor );
2409             else
2410                 bKeyUsed = sal_False;
2411             break;
2412         }
2413 
2414         case KEY_PAGEUP:
2415             if( !bMod1 )
2416             {
2417                 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pCursor, nDelta ));
2418 
2419                 while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2420                 {
2421                     pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2422                     nDelta--;
2423                 }
2424 
2425                 if( nDelta )
2426                 {
2427                     DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2428                     aSelEng.CursorPosChanging( bShift, bMod1 );
2429                     if( IsEntryInView( pNewCursor ) )
2430                         SetCursor( pNewCursor );
2431                     else
2432                     {
2433                         SetCursor( pNewCursor );
2434                         KeyUp( sal_True );
2435                     }
2436                 }
2437             }
2438             else
2439                 bKeyUsed = sal_False;
2440             break;
2441 
2442         case KEY_PAGEDOWN:
2443             if( !bMod1 )
2444             {
2445                 pNewCursor= (SvLBoxEntry*)(pView->NextVisible( pCursor, nDelta ));
2446 
2447                 while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2448                 {
2449                     pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2450                     nDelta--;
2451                 }
2452 
2453                 if( nDelta )
2454                 {
2455                     DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2456                     aSelEng.CursorPosChanging( bShift, bMod1 );
2457                     if( IsEntryInView( pNewCursor ) )
2458                         SetCursor( pNewCursor );
2459                     else
2460                     {
2461                         SetCursor( pNewCursor );
2462                         KeyDown( sal_True );
2463                     }
2464                 }
2465                 else
2466                     KeyDown( sal_False ); // siehe KEY_DOWN
2467             }
2468             else
2469                 bKeyUsed = sal_False;
2470             break;
2471 
2472         case KEY_SPACE:
2473             if ( pView->GetSelectionMode() != NO_SELECTION )
2474             {
2475                 if ( bMod1 )
2476                 {
2477                     if ( pView->GetSelectionMode() == MULTIPLE_SELECTION && !bShift )
2478                         // toggle selection
2479                         pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2480                 }
2481                 else if ( !bShift /*&& !bMod1*/ )
2482                 {
2483                     if ( aSelEng.IsAddMode() )
2484                     {
2485                         // toggle selection
2486                         pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2487                     }
2488                     else if ( !pView->IsSelected( pCursor ) )
2489                     {
2490                         SelAllDestrAnch( sal_False );
2491                         pView->Select( pCursor, sal_True );
2492                     }
2493                     else
2494                         bKeyUsed = sal_False;
2495                 }
2496                 else
2497                     bKeyUsed = sal_False;
2498             }
2499             else
2500                 bKeyUsed = sal_False;
2501             break;
2502 
2503         case KEY_RETURN:
2504             if( bSubLstOpRet && IsExpandable() )
2505             {
2506                 if( pView->IsExpanded( pCursor ) )
2507                     pView->Collapse( pCursor );
2508                 else
2509                     pView->Expand( pCursor );
2510             }
2511             else
2512                 bKeyUsed = sal_False;
2513             break;
2514 
2515         case KEY_F2:
2516             if( !bShift && !bMod1 )
2517             {
2518                 aEditClickPos = Point( -1, -1 );
2519                 EditTimerCall( 0 );
2520             }
2521             else
2522                 bKeyUsed = sal_False;
2523             break;
2524 
2525         case KEY_F8:
2526             if( bShift && pView->GetSelectionMode()==MULTIPLE_SELECTION &&
2527                 !(m_nStyle & WB_SIMPLEMODE))
2528             {
2529                 if( aSelEng.IsAlwaysAdding() )
2530                     aSelEng.AddAlways( sal_False );
2531                 else
2532                     aSelEng.AddAlways( sal_True );
2533             }
2534             else
2535                 bKeyUsed = sal_False;
2536             break;
2537 
2538 
2539 #ifdef OV_DEBUG
2540         case KEY_F9:
2541             MakeVisible( pCursor );
2542             break;
2543         case KEY_F10:
2544             pView->RemoveSelection();
2545             break;
2546         case KEY_DELETE:
2547             pView->RemoveEntry( pCursor );
2548             break;
2549 #endif
2550 
2551         case KEY_ADD:
2552             if( pCursor )
2553             {
2554                 if( !pView->IsExpanded(pCursor))
2555                     pView->Expand( pCursor );
2556                 if( bMod1 )
2557                 {
2558                     sal_uInt16 nRefDepth = pTree->GetDepth( pCursor );
2559                     SvLBoxEntry* pCur = pTree->Next( pCursor );
2560                     while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2561                     {
2562                         if( pCur->HasChilds() && !pView->IsExpanded(pCur))
2563                             pView->Expand( pCur );
2564                         pCur = pTree->Next( pCur );
2565                     }
2566                 }
2567             }
2568             else
2569                 bKeyUsed = sal_False;
2570             break;
2571 
2572         case KEY_A:
2573             if( bMod1 )
2574                 SelAllDestrAnch( sal_True );
2575             else
2576                 bKeyUsed = sal_False;
2577             break;
2578 
2579         case KEY_SUBTRACT:
2580             if( pCursor )
2581             {
2582                 if( pView->IsExpanded(pCursor))
2583                     pView->Collapse( pCursor );
2584                 if( bMod1 )
2585                 {
2586                     // bis zur Root alle Parents einklappen
2587                     SvLBoxEntry* pParentToCollapse = (SvLBoxEntry*)pTree->GetRootLevelParent(pCursor);
2588                     if( pParentToCollapse )
2589                     {
2590                         sal_uInt16 nRefDepth;
2591                         // Sonderbehandlung Explorer: Befindet sich auf der
2592                         // Root nur ein Eintrag,dann den Root-Entry nicht
2593                         // einklappen
2594                         if( pTree->GetChildList(0)->Count() < 2 )
2595                         {
2596                             nRefDepth = 1;
2597                             pParentToCollapse = pCursor;
2598                             while( pTree->GetParent(pParentToCollapse) &&
2599                                    pTree->GetDepth( pTree->GetParent(pParentToCollapse)) > 0)
2600                             {
2601                                 pParentToCollapse = pTree->GetParent(pParentToCollapse);
2602                             }
2603                         }
2604                         else
2605                             nRefDepth = 0;
2606 
2607                         if( pView->IsExpanded(pParentToCollapse) )
2608                             pView->Collapse( pParentToCollapse );
2609                         SvLBoxEntry* pCur = pTree->Next( pParentToCollapse );
2610                         while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2611                         {
2612                             if( pCur->HasChilds() && pView->IsExpanded(pCur) )
2613                                 pView->Collapse( pCur );
2614                             pCur = pTree->Next( pCur );
2615                         }
2616                     }
2617                 }
2618             }
2619             else
2620                 bKeyUsed = sal_False;
2621             break;
2622 
2623         case KEY_DIVIDE :
2624             if( bMod1 )
2625                 SelAllDestrAnch( sal_True );
2626             else
2627                 bKeyUsed = sal_False;
2628             break;
2629 
2630         case KEY_COMMA :
2631             if( bMod1 )
2632                 SelAllDestrAnch( sal_False );
2633             else
2634                 bKeyUsed = sal_False;
2635             break;
2636 
2637         case KEY_HOME :
2638             pNewCursor = pView->GetModel()->First();
2639 
2640             while( pNewCursor && !IsSelectable(pNewCursor) )
2641             {
2642                 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2643             }
2644 
2645             if( pNewCursor && pNewCursor != pCursor )
2646             {
2647 //              SelAllDestrAnch( sal_False );
2648                 aSelEng.CursorPosChanging( bShift, bMod1 );
2649                 SetCursor( pNewCursor );
2650                 if( !IsEntryInView( pNewCursor ) )
2651                     MakeVisible( pNewCursor );
2652             }
2653             else
2654                 bKeyUsed = sal_False;
2655             break;
2656 
2657         case KEY_END :
2658             pNewCursor = pView->GetModel()->Last();
2659 
2660             while( pNewCursor && !IsSelectable(pNewCursor) )
2661             {
2662                 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2663             }
2664 
2665             if( pNewCursor && pNewCursor != pCursor)
2666             {
2667 //              SelAllDestrAnch( sal_False );
2668                 aSelEng.CursorPosChanging( bShift, bMod1 );
2669                 SetCursor( pNewCursor );
2670                 if( !IsEntryInView( pNewCursor ) )
2671                     MakeVisible( pNewCursor );
2672             }
2673             else
2674                 bKeyUsed = sal_False;
2675             break;
2676 
2677         case KEY_ESCAPE:
2678         case KEY_TAB:
2679         case KEY_DELETE:
2680         case KEY_BACKSPACE:
2681             // #105907# must not be handled because this quits dialogs and does other magic things...
2682             // if there are other single keys which should not be handled, they can be added here
2683             bKeyUsed = sal_False;
2684             break;
2685 
2686         default:
2687             // is there any reason why we should eat the events here? The only place where this is called
2688             // is from SvTreeListBox::KeyInput. If we set bKeyUsed to sal_True here, then the key input
2689             // is just silenced. However, we want SvLBox::KeyInput to get a chance, to do the QuickSelection
2690             // handling.
2691             // (The old code here which intentionally set bKeyUsed to sal_True said this was because of "quick search"
2692             // handling, but actually there was no quick search handling anymore. We just re-implemented it.)
2693             // #i31275# / 2009-06-16 / frank.schoenheit@sun.com
2694             bKeyUsed = sal_False;
2695             break;
2696     }
2697     return bKeyUsed;
2698 }
2699 
GetFocus()2700 void __EXPORT SvImpLBox::GetFocus()
2701 {
2702     if( pCursor )
2703     {
2704         pView->SetEntryFocus( pCursor, sal_True );
2705         ShowCursor( sal_True );
2706 // auskommentiert wg. deselectall
2707 //      if( bSimpleTravel && !pView->IsSelected(pCursor) )
2708 //          pView->Select( pCursor, sal_True );
2709     }
2710     if( m_nStyle & WB_HIDESELECTION )
2711     {
2712         SvLBoxEntry* pEntry = pView->FirstSelected();
2713         while( pEntry )
2714         {
2715             InvalidateEntry( pEntry );
2716             pEntry = pView->NextSelected( pEntry );
2717         }
2718         /*
2719         SvLBoxEntry* pEntry = pView->GetModel()->First();
2720         while( pEntry )
2721         {
2722             SvViewData* pViewData = pView->GetViewData( pEntry );
2723             if( pViewData->IsCursored() )
2724             {
2725                 pViewData->SetCursored( sal_False );
2726                 InvalidateEntry( pEntry );
2727             }
2728             pEntry = pView->GetModel()->Next( pEntry );
2729         }
2730         */
2731 
2732 
2733     }
2734 }
2735 
LoseFocus()2736 void __EXPORT SvImpLBox::LoseFocus()
2737 {
2738     aEditTimer.Stop();
2739     if( pCursor )
2740         pView->SetEntryFocus( pCursor,sal_False );
2741     ShowCursor( sal_False );
2742 
2743     if( m_nStyle & WB_HIDESELECTION )
2744     {
2745         SvLBoxEntry* pEntry = pView->FirstSelected();
2746         while( pEntry )
2747         {
2748             //SvViewData* pViewData = pView->GetViewData( pEntry );
2749             //pViewData->SetCursored( sal_True );
2750             InvalidateEntry( pEntry );
2751             pEntry = pView->NextSelected( pEntry );
2752         }
2753     }
2754 }
2755 
2756 
2757 // ********************************************************************
2758 // SelectionEngine
2759 // ********************************************************************
2760 
SelectEntry(SvLBoxEntry * pEntry,sal_Bool bSelect)2761 inline void SvImpLBox::SelectEntry( SvLBoxEntry* pEntry, sal_Bool bSelect )
2762 {
2763     pView->Select( pEntry, bSelect );
2764 }
2765 
ImpLBSelEng(SvImpLBox * pImpl,SelectionEngine * pSEng,SvTreeListBox * pV)2766 __EXPORT ImpLBSelEng::ImpLBSelEng( SvImpLBox* pImpl, SelectionEngine* pSEng,
2767     SvTreeListBox* pV )
2768 {
2769     pImp = pImpl;
2770     pSelEng = pSEng;
2771     pView = pV;
2772 }
2773 
~ImpLBSelEng()2774 __EXPORT ImpLBSelEng::~ImpLBSelEng()
2775 {
2776 }
2777 
BeginDrag()2778 void __EXPORT ImpLBSelEng::BeginDrag()
2779 {
2780     pImp->BeginDrag();
2781 }
2782 
2783 /*
2784 void __EXPORT ImpLBSelEng::EndDrag( const Point& )
2785 {
2786 }
2787 */
2788 
CreateAnchor()2789 void __EXPORT ImpLBSelEng::CreateAnchor()
2790 {
2791     pImp->pAnchor = pImp->pCursor;
2792 }
2793 
DestroyAnchor()2794 void __EXPORT ImpLBSelEng::DestroyAnchor()
2795 {
2796     pImp->pAnchor = 0;
2797 }
2798 
2799 /*
2800 void __EXPORT ImpLBSelEng::CreateCursor()
2801 {
2802     pImp->pAnchor = 0;
2803 }
2804 */
2805 
2806 
SetCursorAtPoint(const Point & rPoint,sal_Bool bDontSelectAtCursor)2807 sal_Bool __EXPORT ImpLBSelEng::SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor)
2808 {
2809     SvLBoxEntry* pNewCursor = pImp->MakePointVisible( rPoint );
2810     if( pNewCursor != pImp->pCursor  )
2811         pImp->BeginScroll();
2812 
2813     if( pNewCursor )
2814     {
2815         // bei SimpleTravel wird in SetCursor selektiert und
2816         // der Select-Handler gerufen
2817         //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
2818         //  pImp->SelectEntry( pNewCursor, sal_True );
2819         pImp->SetCursor( pNewCursor, bDontSelectAtCursor );
2820         return sal_True;
2821     }
2822     return sal_False;
2823 }
2824 
IsSelectionAtPoint(const Point & rPoint)2825 sal_Bool __EXPORT ImpLBSelEng::IsSelectionAtPoint( const Point& rPoint )
2826 {
2827     SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2828     if( pEntry )
2829         return pView->IsSelected(pEntry);
2830     return sal_False;
2831 }
2832 
DeselectAtPoint(const Point & rPoint)2833 void __EXPORT ImpLBSelEng::DeselectAtPoint( const Point& rPoint )
2834 {
2835     SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2836     if( !pEntry )
2837         return;
2838     pImp->SelectEntry( pEntry, sal_False );
2839 }
2840 
2841 /*
2842 void __EXPORT ImpLBSelEng::SelectAtPoint( const Point& rPoint )
2843 {
2844     SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2845     if( !pEntry )
2846         return;
2847     pImp->SelectEntry( pEntry, sal_True );
2848 }
2849 */
2850 
DeselectAll()2851 void __EXPORT ImpLBSelEng::DeselectAll()
2852 {
2853     pImp->SelAllDestrAnch( sal_False, sal_False ); // SelectionEngine nicht resetten!
2854     pImp->nFlags &= (~F_DESEL_ALL);
2855 }
2856 
2857 // ***********************************************************************
2858 // Selektion
2859 // ***********************************************************************
2860 
SetAnchorSelection(SvLBoxEntry * pOldCursor,SvLBoxEntry * pNewCursor)2861 void SvImpLBox::SetAnchorSelection(SvLBoxEntry* pOldCursor,SvLBoxEntry* pNewCursor)
2862 {
2863     SvLBoxEntry* pEntry;
2864     sal_uLong nAnchorVisPos = pView->GetVisiblePos( pAnchor );
2865     sal_uLong nOldVisPos = pView->GetVisiblePos( pOldCursor );
2866     sal_uLong nNewVisPos = pView->GetVisiblePos( pNewCursor );
2867 
2868     if( nOldVisPos > nAnchorVisPos ||
2869         ( nAnchorVisPos==nOldVisPos && nNewVisPos > nAnchorVisPos) )
2870     {
2871         if( nNewVisPos > nOldVisPos )
2872         {
2873             pEntry = pOldCursor;
2874             while( pEntry && pEntry != pNewCursor )
2875             {
2876                 pView->Select( pEntry, sal_True );
2877                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2878             }
2879             if( pEntry )
2880                 pView->Select( pEntry, sal_True );
2881             return;
2882         }
2883 
2884         if( nNewVisPos < nAnchorVisPos )
2885         {
2886             pEntry = pAnchor;
2887             while( pEntry && pEntry != pOldCursor )
2888             {
2889                 pView->Select( pEntry, sal_False );
2890                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2891             }
2892             if( pEntry )
2893                 pView->Select( pEntry, sal_False );
2894 
2895             pEntry = pNewCursor;
2896             while( pEntry && pEntry != pAnchor )
2897             {
2898                 pView->Select( pEntry, sal_True );
2899                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2900             }
2901             if( pEntry )
2902                 pView->Select( pEntry, sal_True );
2903             return;
2904         }
2905 
2906         if( nNewVisPos < nOldVisPos )
2907         {
2908             pEntry = pNewCursor;
2909             pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2910             while( pEntry && pEntry != pOldCursor )
2911             {
2912                 pView->Select( pEntry, sal_False );
2913                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2914             }
2915             if( pEntry )
2916                 pView->Select( pEntry, sal_False );
2917             return;
2918         }
2919     }
2920     else
2921     {
2922         if( nNewVisPos < nOldVisPos )  // Vergroessern der Selektion
2923         {
2924             pEntry = pNewCursor;
2925             while( pEntry && pEntry != pOldCursor )
2926             {
2927                 pView->Select( pEntry, sal_True );
2928                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2929             }
2930             if( pEntry )
2931                 pView->Select( pEntry, sal_True );
2932             return;
2933         }
2934 
2935         if( nNewVisPos > nAnchorVisPos )
2936         {
2937             pEntry = pOldCursor;
2938             while( pEntry && pEntry != pAnchor )
2939             {
2940                 pView->Select( pEntry, sal_False );
2941                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2942             }
2943             if( pEntry )
2944                 pView->Select( pEntry, sal_False );
2945             pEntry = pAnchor;
2946             while( pEntry && pEntry != pNewCursor )
2947             {
2948                 pView->Select( pEntry, sal_True );
2949                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2950             }
2951             if( pEntry )
2952                 pView->Select( pEntry, sal_True );
2953             return;
2954         }
2955 
2956         if( nNewVisPos > nOldVisPos )
2957         {
2958             pEntry = pOldCursor;
2959             while( pEntry && pEntry != pNewCursor )
2960             {
2961                 pView->Select( pEntry, sal_False );
2962                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2963             }
2964             return;
2965         }
2966     }
2967 }
2968 
SelAllDestrAnch(sal_Bool bSelect,sal_Bool bDestroyAnchor,sal_Bool bSingleSelToo)2969 void SvImpLBox::SelAllDestrAnch( sal_Bool bSelect, sal_Bool bDestroyAnchor,
2970     sal_Bool bSingleSelToo )
2971 {
2972     SvLBoxEntry* pEntry;
2973     nFlags &= (~F_DESEL_ALL);
2974     if( bSelect && bSimpleTravel )
2975     {
2976         if( pCursor && !pView->IsSelected( pCursor ))
2977         {
2978             pView->Select( pCursor, sal_True );
2979         }
2980         return;
2981     }
2982     if( !bSelect && pView->GetSelectionCount() == 0 )
2983     {
2984         if( bSimpleTravel && ( !GetUpdateMode() || !pCursor) )
2985             nFlags |= F_DESEL_ALL;
2986         return;
2987     }
2988     if( bSelect && pView->GetSelectionCount() == pView->GetEntryCount())
2989         return;
2990     if( !bSingleSelToo && bSimpleTravel )
2991         return;
2992 
2993     if( !bSelect && pView->GetSelectionCount()==1 && pCursor &&
2994         pView->IsSelected( pCursor ))
2995     {
2996         pView->Select( pCursor, sal_False );
2997         if( bDestroyAnchor )
2998             DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
2999         else
3000             pAnchor = 0; // internen Anker immer loeschen
3001         return;
3002     }
3003 
3004     if( bSimpleTravel && !pCursor && !GetUpdateMode() )
3005         nFlags |= F_DESEL_ALL;
3006 
3007     ShowCursor( sal_False );
3008     sal_Bool bUpdate = GetUpdateMode();
3009 
3010     nFlags |= F_IGNORE_SELECT; // EntryInserted soll nix tun
3011     pEntry = pTree->First();
3012     while( pEntry )
3013     {
3014         if( pView->Select( pEntry, bSelect ) )
3015         {
3016             if( bUpdate && pView->IsEntryVisible(pEntry) )
3017             {
3018                 long nY = GetEntryLine( pEntry );
3019                 if( IsLineVisible( nY ) )
3020                     pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
3021             }
3022         }
3023         pEntry = pTree->Next( pEntry );
3024     }
3025     nFlags &= ~F_IGNORE_SELECT;
3026 
3027     if( bDestroyAnchor )
3028         DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
3029     else
3030         pAnchor = 0; // internen Anker immer loeschen
3031     ShowCursor( sal_True );
3032 }
3033 
SetSelectionMode(SelectionMode eSelMode)3034 void SvImpLBox::SetSelectionMode( SelectionMode eSelMode  )
3035 {
3036     aSelEng.SetSelectionMode( eSelMode);
3037     if( eSelMode == SINGLE_SELECTION )
3038         bSimpleTravel = sal_True;
3039     else
3040         bSimpleTravel = sal_False;
3041     if( (m_nStyle & WB_SIMPLEMODE) && (eSelMode == MULTIPLE_SELECTION) )
3042         aSelEng.AddAlways( sal_True );
3043 }
3044 
3045 // ***********************************************************************
3046 // Drag & Drop
3047 // ***********************************************************************
3048 
SetDragDropMode(DragDropMode eDDMode)3049 void SvImpLBox::SetDragDropMode( DragDropMode eDDMode )
3050 {
3051     if( eDDMode && eDDMode != SV_DRAGDROP_APP_DROP )
3052     {
3053         aSelEng.ExpandSelectionOnMouseMove( sal_False );
3054         aSelEng.EnableDrag( sal_True );
3055     }
3056     else
3057     {
3058         aSelEng.ExpandSelectionOnMouseMove( sal_True );
3059         aSelEng.EnableDrag( sal_False );
3060     }
3061 }
3062 
BeginDrag()3063 void SvImpLBox::BeginDrag()
3064 {
3065     nFlags &= (~F_FILLING);
3066     if( !bAsyncBeginDrag )
3067     {
3068         BeginScroll();
3069         pView->StartDrag( 0, aSelEng.GetMousePosPixel() );
3070         EndScroll();
3071     }
3072     else
3073     {
3074         aAsyncBeginDragPos = aSelEng.GetMousePosPixel();
3075         aAsyncBeginDragTimer.Start();
3076     }
3077 }
3078 
IMPL_LINK(SvImpLBox,BeginDragHdl,void *,EMPTYARG)3079 IMPL_LINK( SvImpLBox, BeginDragHdl, void*, EMPTYARG )
3080 {
3081     pView->StartDrag( 0, aAsyncBeginDragPos );
3082     return 0;
3083 }
3084 
PaintDDCursor(SvLBoxEntry * pInsertionPos)3085 void SvImpLBox::PaintDDCursor( SvLBoxEntry* pInsertionPos )
3086 {
3087     long nY;
3088     if( pInsertionPos )
3089     {
3090         nY = GetEntryLine( pInsertionPos );
3091         nY += pView->GetEntryHeight();
3092     }
3093     else
3094         nY = 1;
3095     RasterOp eOldOp = pView->GetRasterOp();
3096     pView->SetRasterOp( ROP_INVERT );
3097     Color aOldLineColor = pView->GetLineColor();
3098     pView->SetLineColor( Color( COL_BLACK ) );
3099     pView->DrawLine( Point( 0, nY ), Point( aOutputSize.Width(), nY ) );
3100     pView->SetLineColor( aOldLineColor );
3101     pView->SetRasterOp( eOldOp );
3102 }
3103 /* -----------------26.08.2003 12:52-----------------
3104     Delete all sub menues of a PopupMenu, recursively
3105  --------------------------------------------------*/
lcl_DeleteSubPopups(PopupMenu * pPopup)3106 void lcl_DeleteSubPopups(PopupMenu* pPopup)
3107 {
3108     for(sal_uInt16 i = 0; i < pPopup->GetItemCount(); i++)
3109     {
3110         PopupMenu* pSubPopup = pPopup->GetPopupMenu( pPopup->GetItemId( i ));
3111         if(pSubPopup)
3112         {
3113             lcl_DeleteSubPopups(pSubPopup);
3114             delete pSubPopup;
3115         }
3116     }
3117 }
3118 
Command(const CommandEvent & rCEvt)3119 void SvImpLBox::Command( const CommandEvent& rCEvt )
3120 {
3121     sal_uInt16              nCommand = rCEvt.GetCommand();
3122 
3123     if( nCommand == COMMAND_CONTEXTMENU )
3124         aEditTimer.Stop();
3125 
3126     // Rollmaus-Event?
3127     if( ( ( nCommand == COMMAND_WHEEL ) || ( nCommand == COMMAND_STARTAUTOSCROLL ) || ( nCommand == COMMAND_AUTOSCROLL ) )
3128         && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) )
3129             return;
3130 
3131     if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU )
3132     {
3133         Point   aPopupPos;
3134         sal_Bool    bClickedIsFreePlace = sal_False;
3135         std::stack<SvLBoxEntry*> aSelRestore;
3136 
3137         if( rCEvt.IsMouseEvent() )
3138         {   // change selection, if mouse pos doesn't fit to selection
3139 
3140             aPopupPos = rCEvt.GetMousePosPixel();
3141 
3142             SvLBoxEntry*    pClickedEntry = GetEntry( aPopupPos );
3143             if( pClickedEntry )
3144             {   // mouse in non empty area
3145                 sal_Bool                bClickedIsSelected = sal_False;
3146 
3147                 // collect the currently selected entries
3148                 SvLBoxEntry*        pSelected = pView->FirstSelected();
3149                 while( pSelected )
3150                 {
3151                     bClickedIsSelected |= ( pClickedEntry == pSelected );
3152                     pSelected = pView->NextSelected( pSelected );
3153                 }
3154 
3155                 // if the entry which the user clicked at is not selected
3156                 if( !bClickedIsSelected )
3157                 {   // deselect all other and select the clicked one
3158                     pView->SelectAll( sal_False );
3159                     pView->SetCursor( pClickedEntry );
3160                 }
3161             }
3162             else if( aSelEng.GetSelectionMode() == SINGLE_SELECTION )
3163             {//modified by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
3164                 bClickedIsFreePlace = sal_True;
3165                 sal_Int32               nSelectedEntries = pView->GetSelectionCount();
3166                 SvLBoxEntry*        pSelected = pView->FirstSelected();
3167                 for(sal_uInt16 nSel = 0; nSel < nSelectedEntries; nSel++ )
3168                 {
3169                     aSelRestore.push(pSelected);
3170                     pSelected = pView->NextSelected( pSelected );
3171                 }
3172                 pView->SelectAll( sal_False );
3173             }
3174             else
3175             {   // deselect all
3176                 pView->SelectAll( sal_False );
3177             }
3178 
3179 
3180         }
3181         else
3182         {   // key event (or at least no mouse event)
3183             sal_Int32   nSelectionCount = pView->GetSelectionCount();
3184 
3185             if( nSelectionCount )
3186             {   // now allways take first visible as base for positioning the menu
3187                 SvLBoxEntry*    pSelected = pView->FirstSelected();
3188                 while( pSelected )
3189                 {
3190                     if( IsEntryInView( pSelected ) )
3191                         break;
3192 
3193                     pSelected = pView->NextSelected( pSelected );
3194                 }
3195 
3196                 if( !pSelected )
3197                 {
3198                     // no one was visible
3199                     pSelected = pView->FirstSelected();
3200                     pView->MakeVisible( pSelected );
3201                 }
3202 
3203                 aPopupPos = pView->GetFocusRect( pSelected, pView->GetEntryPosition( pSelected ).Y() ).Center();
3204             }
3205             else
3206                 aPopupPos = Point( 0, 0 );
3207         }
3208 
3209         PopupMenu*  pPopup = pView->CreateContextMenu();
3210 
3211         if( pPopup )
3212         {
3213             // do action for selected entry in popup menu
3214             sal_uInt16 nMenuAction = pPopup->Execute( pView, aPopupPos );
3215             if ( nMenuAction )
3216                 pView->ExcecuteContextMenuAction( nMenuAction );
3217             lcl_DeleteSubPopups(pPopup);
3218             delete pPopup;
3219         }
3220         //added by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
3221         if( bClickedIsFreePlace )
3222         {
3223             while(!aSelRestore.empty())
3224             {
3225                 SvLBoxEntry* pEntry = aSelRestore.top();
3226                 //#i19717# the entry is maybe already deleted
3227                 bool bFound = false;
3228                 for(sal_uLong nEntry = 0; nEntry < pView->GetEntryCount(); nEntry++)
3229                     if(pEntry == pView->GetEntry(nEntry))
3230                     {
3231                         bFound = true;
3232                         break;
3233                     }
3234                 if(bFound)
3235                     SetCurEntry( pEntry );
3236                 aSelRestore.pop();
3237             }
3238         }
3239     }
3240 #ifndef NOCOMMAND
3241     else
3242     {
3243         const Point& rPos = rCEvt.GetMousePosPixel();
3244         if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() )
3245             aSelEng.Command( rCEvt );
3246     }
3247 #endif
3248 }
3249 
BeginScroll()3250 void SvImpLBox::BeginScroll()
3251 {
3252     if( !(nFlags & F_IN_SCROLLING))
3253     {
3254         pView->NotifyBeginScroll();
3255         nFlags |= F_IN_SCROLLING;
3256     }
3257 }
3258 
EndScroll()3259 void SvImpLBox::EndScroll()
3260 {
3261     if( nFlags & F_IN_SCROLLING)
3262     {
3263         pView->NotifyEndScroll();
3264         nFlags &= (~F_IN_SCROLLING);
3265     }
3266 }
3267 
3268 
GetVisibleArea() const3269 Rectangle SvImpLBox::GetVisibleArea() const
3270 {
3271     Point aPos( pView->GetMapMode().GetOrigin() );
3272     aPos.X() *= -1;
3273     Rectangle aRect( aPos, aOutputSize );
3274     return aRect;
3275 }
3276 
Invalidate()3277 void SvImpLBox::Invalidate()
3278 {
3279     pView->SetClipRegion();
3280 }
3281 
SetCurEntry(SvLBoxEntry * pEntry)3282 void SvImpLBox::SetCurEntry( SvLBoxEntry* pEntry )
3283 {
3284     if  (  ( aSelEng.GetSelectionMode() != SINGLE_SELECTION )
3285         && ( aSelEng.GetSelectionMode() != NO_SELECTION )
3286         )
3287         SelAllDestrAnch( sal_False, sal_True, sal_False );
3288     if ( pEntry )
3289         MakeVisible( pEntry );
3290     SetCursor( pEntry );
3291     if ( pEntry && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
3292         pView->Select( pEntry, sal_True );
3293 }
3294 
IMPL_LINK(SvImpLBox,EditTimerCall,Timer *,EMPTYARG)3295 IMPL_LINK( SvImpLBox, EditTimerCall, Timer *, EMPTYARG )
3296 {
3297     if( pView->IsInplaceEditingEnabled() )
3298     {
3299         sal_Bool bIsMouseTriggered = aEditClickPos.X() >= 0;
3300         if ( bIsMouseTriggered )
3301         {
3302             Point aCurrentMousePos = pView->GetPointerPosPixel();
3303             if  (   ( abs( aCurrentMousePos.X() - aEditClickPos.X() ) > 5 )
3304                 ||  ( abs( aCurrentMousePos.Y() - aEditClickPos.Y() ) > 5 )
3305                 )
3306             {
3307                 return 0L;
3308             }
3309         }
3310 
3311         SvLBoxEntry* pEntry = GetCurEntry();
3312         if( pEntry )
3313         {
3314             ShowCursor( sal_False );
3315             pView->ImplEditEntry( pEntry );
3316             ShowCursor( sal_True );
3317         }
3318     }
3319     return 0;
3320 }
3321 
RequestHelp(const HelpEvent & rHEvt)3322 sal_Bool SvImpLBox::RequestHelp( const HelpEvent& rHEvt )
3323 {
3324     if( rHEvt.GetMode() & HELPMODE_QUICK )
3325     {
3326         Point aPos( pView->ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
3327         if( !GetVisibleArea().IsInside( aPos ))
3328             return sal_False;
3329 
3330         SvLBoxEntry* pEntry = GetEntry( aPos );
3331         if( pEntry )
3332         {
3333             // Rechteck des Textes berechnen
3334             SvLBoxTab* pTab;
3335             SvLBoxString* pItem = (SvLBoxString*)(pView->GetItem( pEntry, aPos.X(), &pTab ));
3336             if( !pItem || pItem->IsA() != SV_ITEM_ID_LBOXSTRING )
3337                 return sal_False;
3338 
3339             aPos = GetEntryPosition( pEntry );
3340             aPos.X() = pView->GetTabPos( pEntry, pTab ); //pTab->GetPos();
3341             Size aSize( pItem->GetSize( pView, pEntry ) );
3342             SvLBoxTab* pNextTab = NextTab( pTab );
3343             sal_Bool bItemClipped = sal_False;
3344             // wurde das Item von seinem rechten Nachbarn abgeschnitten?
3345             if( pNextTab && pView->GetTabPos(pEntry,pNextTab) < aPos.X()+aSize.Width() )
3346             {
3347                 aSize.Width() = pNextTab->GetPos() - pTab->GetPos();
3348                 bItemClipped = sal_True;
3349             }
3350             Rectangle aItemRect( aPos, aSize );
3351 
3352             Rectangle aViewRect( GetVisibleArea() );
3353 
3354             if( bItemClipped || !aViewRect.IsInside( aItemRect ) )
3355             {
3356                 // rechten Item-Rand am View-Rand clippen
3357                 //if( aItemRect.Right() > aViewRect.Right() )
3358                 //  aItemRect.Right() = aViewRect.Right();
3359 
3360                 Point aPt = pView->OutputToScreenPixel( aItemRect.TopLeft() );
3361                 aItemRect.Left()   = aPt.X();
3362                 aItemRect.Top()    = aPt.Y();
3363                 aPt = pView->OutputToScreenPixel( aItemRect.BottomRight() );
3364                 aItemRect.Right()  = aPt.X();
3365                 aItemRect.Bottom() = aPt.Y();
3366 
3367                 Help::ShowQuickHelp( pView, aItemRect,
3368                                      pItem->GetText(), QUICKHELP_LEFT | QUICKHELP_VCENTER );
3369                 return sal_True;
3370             }
3371         }
3372     }
3373     return sal_False;
3374 }
3375 
NextTab(SvLBoxTab * pTab)3376 SvLBoxTab* SvImpLBox::NextTab( SvLBoxTab* pTab )
3377 {
3378     sal_uInt16 nTabCount = pView->TabCount();
3379     if( nTabCount <= 1 )
3380         return 0;
3381     for( sal_uInt16 nTab=0; nTab < (nTabCount-1); nTab++)
3382     {
3383         if( pView->aTabs[nTab]==pTab )
3384             return (SvLBoxTab*)(pView->aTabs[nTab+1]);
3385     }
3386     return 0;
3387 }
3388 
EndSelection()3389 void SvImpLBox::EndSelection()
3390 {
3391     DestroyAnchor();
3392     nFlags &=  ~F_START_EDITTIMER;
3393 }
3394 
RepaintScrollBars()3395 void SvImpLBox::RepaintScrollBars()
3396 {
3397 }
3398 
SetUpdateMode(sal_Bool bMode)3399 void SvImpLBox::SetUpdateMode( sal_Bool bMode )
3400 {
3401     if( bUpdateMode != bMode )
3402     {
3403         bUpdateMode = bMode;
3404         if( bUpdateMode )
3405             UpdateAll( sal_False );
3406     }
3407 }
3408 
SetUpdateModeFast(sal_Bool bMode)3409 void SvImpLBox::SetUpdateModeFast( sal_Bool bMode )
3410 {
3411     if( bUpdateMode != bMode )
3412     {
3413         bUpdateMode = bMode;
3414         if( bUpdateMode )
3415             UpdateAll( sal_False, sal_False );
3416     }
3417 }
3418 
3419 
SetMostRight(SvLBoxEntry * pEntry)3420 sal_Bool SvImpLBox::SetMostRight( SvLBoxEntry* pEntry )
3421 {
3422     if( pView->nTreeFlags & TREEFLAG_RECALCTABS )
3423     {
3424         nFlags |= F_IGNORE_CHANGED_TABS;
3425         pView->SetTabs();
3426         nFlags &= ~F_IGNORE_CHANGED_TABS;
3427     }
3428 
3429     sal_uInt16 nLastTab = pView->aTabs.Count() - 1;
3430     sal_uInt16 nLastItem = pEntry->ItemCount() - 1;
3431     if( nLastTab != USHRT_MAX && nLastItem != USHRT_MAX )
3432     {
3433         if( nLastItem < nLastTab )
3434             nLastTab = nLastItem;
3435 
3436         SvLBoxTab* pTab = (SvLBoxTab*)pView->aTabs[ nLastTab ];
3437         SvLBoxItem* pItem = pEntry->GetItem( nLastTab );
3438 
3439         long nTabPos = pView->GetTabPos( pEntry, pTab );
3440 
3441         long nMaxRight = GetOutputSize().Width();
3442         Point aPos( pView->GetMapMode().GetOrigin() );
3443         aPos.X() *= -1; // Umrechnung Dokumentkoord.
3444         nMaxRight = nMaxRight + aPos.X() - 1;
3445 
3446         long nNextTab = nTabPos < nMaxRight ? nMaxRight : nMaxRight + 50;
3447         long nTabWidth = nNextTab - nTabPos + 1;
3448         long nItemSize = pItem->GetSize(pView,pEntry).Width();
3449         long nOffset = pTab->CalcOffset( nItemSize, nTabWidth );
3450 
3451         long nRight = nTabPos + nOffset + nItemSize;
3452         if( nRight > nMostRight )
3453         {
3454             nMostRight = nRight;
3455             pMostRightEntry = pEntry;
3456             return sal_True;
3457         }
3458     }
3459     return sal_False;
3460 }
3461 
FindMostRight(SvLBoxEntry * pEntryToIgnore)3462 void SvImpLBox::FindMostRight( SvLBoxEntry* pEntryToIgnore )
3463 {
3464     nMostRight = -1;
3465     pMostRightEntry = 0;
3466     if( !pView->GetModel() )
3467         return;
3468 
3469     SvLBoxEntry* pEntry = (SvLBoxEntry*)pView->FirstVisible();
3470     while( pEntry )
3471     {
3472         if( pEntry != pEntryToIgnore )
3473             SetMostRight( pEntry );
3474         pEntry = (SvLBoxEntry*)pView->NextVisible( pEntry );
3475     }
3476 }
3477 
FindMostRight(SvLBoxEntry * pParent,SvLBoxEntry * pEntryToIgnore)3478 void SvImpLBox::FindMostRight( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
3479 {
3480     if( !pParent )
3481         FindMostRight( pEntryToIgnore );
3482     else
3483         FindMostRight_Impl( pParent, pEntryToIgnore  );
3484 }
3485 
FindMostRight_Impl(SvLBoxEntry * pParent,SvLBoxEntry * pEntryToIgnore)3486 void SvImpLBox::FindMostRight_Impl( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
3487 {
3488     SvTreeEntryList* pList = pTree->GetChildList( pParent );
3489 
3490     if( !pList )
3491         return;
3492 
3493     sal_uLong nCount = pList->Count();
3494     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
3495     {
3496         SvLBoxEntry* pChild = (SvLBoxEntry*)pList->GetObject( nCur );
3497         if( pChild != pEntryToIgnore )
3498         {
3499             SetMostRight( pChild );
3500             if( pChild->HasChilds() && pView->IsExpanded( pChild ))
3501                 FindMostRight_Impl( pChild, pEntryToIgnore );
3502         }
3503     }
3504 }
3505 
NotifyTabsChanged()3506 void SvImpLBox::NotifyTabsChanged()
3507 {
3508     if( GetUpdateMode() && !(nFlags & F_IGNORE_CHANGED_TABS ) &&
3509         nCurUserEvent == 0xffffffff )
3510     {
3511         nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)0);
3512     }
3513 }
3514 
IMPL_LINK(SvImpLBox,MyUserEvent,void *,pArg)3515 IMPL_LINK(SvImpLBox,MyUserEvent,void*, pArg )
3516 {
3517     nCurUserEvent = 0xffffffff;
3518     if( !pArg )
3519     {
3520         pView->Invalidate();
3521         pView->Update();
3522     }
3523     else
3524     {
3525         FindMostRight( 0 );
3526         ShowVerSBar();
3527         pView->Invalidate( GetVisibleArea() );
3528     }
3529     return 0;
3530 }
3531 
3532 
StopUserEvent()3533 void SvImpLBox::StopUserEvent()
3534 {
3535     if( nCurUserEvent != 0xffffffff )
3536     {
3537         Application::RemoveUserEvent( nCurUserEvent );
3538         nCurUserEvent = 0xffffffff;
3539     }
3540 }
3541 
ShowFocusRect(const SvLBoxEntry * pEntry)3542 void SvImpLBox::ShowFocusRect( const SvLBoxEntry* pEntry )
3543 {
3544     if( pEntry )
3545     {
3546         long nY = GetEntryLine( (SvLBoxEntry*)pEntry );
3547         Rectangle aRect = pView->GetFocusRect( (SvLBoxEntry*)pEntry, nY );
3548         Region aOldClip( pView->GetClipRegion());
3549         Region aClipRegion( GetClipRegionRect() );
3550         pView->SetClipRegion( aClipRegion );
3551         pView->ShowFocus( aRect );
3552         pView->SetClipRegion( aOldClip );
3553 
3554     }
3555     else
3556     {
3557         pView->HideFocus();
3558     }
3559 }
3560 
SetTabBar(TabBar * _pTabBar)3561 void SvImpLBox::SetTabBar( TabBar* _pTabBar )
3562 {
3563     pTabBar = _pTabBar;
3564 }
3565 
CancelPendingEdit()3566 void SvImpLBox::CancelPendingEdit()
3567 {
3568     if( aEditTimer.IsActive() )
3569         aEditTimer.Stop();
3570     nFlags &= ~F_START_EDITTIMER;
3571 }
3572 
3573 // -----------------------------------------------------------------------
implInitDefaultNodeImages()3574 void SvImpLBox::implInitDefaultNodeImages()
3575 {
3576     if ( s_pDefCollapsed )
3577         // assume that all or nothing is initialized
3578         return;
3579 
3580     s_pDefCollapsed = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED ) );
3581     s_pDefCollapsedHC = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED_HC ) );
3582     s_pDefExpanded = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED ) );
3583     s_pDefExpandedHC = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED_HC ) );
3584 }
3585 
3586 // -----------------------------------------------------------------------
GetDefaultExpandedNodeImage(BmpColorMode _eMode)3587 const Image& SvImpLBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode )
3588 {
3589     implInitDefaultNodeImages();
3590     return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefExpanded : *s_pDefExpandedHC;
3591 }
3592 
3593 // -----------------------------------------------------------------------
GetDefaultCollapsedNodeImage(BmpColorMode _eMode)3594 const Image& SvImpLBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode )
3595 {
3596     implInitDefaultNodeImages();
3597     return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefCollapsed : *s_pDefCollapsedHC;
3598 }
3599 
3600 // -----------------------------------------------------------------------
CallEventListeners(sal_uLong nEvent,void * pData)3601 void SvImpLBox::CallEventListeners( sal_uLong nEvent, void* pData )
3602 {
3603     if ( pView )
3604         pView->CallImplEventListeners( nEvent, pData);
3605 }
3606 
3607 // -----------------------------------------------------------------------
3608 
SetCurrentTabPos(sal_uInt16 _nNewPos)3609 bool SvImpLBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
3610 {
3611     bool bRet = false;
3612 
3613     if ( pView && _nNewPos < ( pView->TabCount() - 2 ) )
3614     {
3615         nCurTabPos = _nNewPos;
3616         ShowCursor( sal_True );
3617         bRet = true;
3618     }
3619 
3620     return bRet;
3621 }
3622 
3623 // -----------------------------------------------------------------------
3624 
IsSelectable(const SvLBoxEntry * pEntry)3625 bool SvImpLBox::IsSelectable( const SvLBoxEntry* pEntry )
3626 {
3627     if( pEntry )
3628     {
3629         SvViewDataEntry* pViewDataNewCur = pView->GetViewDataEntry(const_cast<SvLBoxEntry*>(pEntry));
3630         return (pViewDataNewCur == 0) || pViewDataNewCur->IsSelectable();
3631     }
3632     else
3633     {
3634         return false;
3635     }
3636 }
3637 
3638