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