xref: /trunk/main/svtools/source/contnr/svtreebx.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 
31 #define _SVTREEBX_CXX
32 #include <vcl/svapp.hxx>
33 #ifndef GCC
34 #endif
35 
36 class TabBar;
37 
38 // #102891# -----------------------
39 
40 #include <svtools/svlbox.hxx>
41 #include <svtools/svlbitm.hxx>
42 #include <svtools/svtreebx.hxx>
43 #include <tools/diagnose_ex.h>
44 #include <svimpbox.hxx>
45 #include <unotools/accessiblestatesethelper.hxx>
46 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
47 #include <com/sun/star/awt/XWindowPeer.hpp>
48 
49 
50 using namespace ::com::sun::star::accessibility;
51 
52 /*
53     Bugs/ToDo
54 
55     - Berechnung Rectangle beim Inplace-Editing (Bug bei manchen Fonts)
56     - SetSpaceBetweenEntries: Offset wird in SetEntryHeight nicht
57       beruecksichtigt
58 */
59 
60 #define TREEFLAG_FIXEDHEIGHT        0x0010
61 
62 
63 DBG_NAME(SvTreeListBox)
64 
65 #define SV_LBOX_DEFAULT_INDENT_PIXEL 20
66 
67 SvTreeListBox::SvTreeListBox( Window* pParent, WinBits nWinStyle )
68     : SvLBox( pParent, nWinStyle )
69 {
70     DBG_CTOR(SvTreeListBox,0);
71     InitTreeView();
72 
73     SetSublistOpenWithLeftRight();
74 }
75 
76 SvTreeListBox::SvTreeListBox( Window* pParent , const ResId& rResId )
77     : SvLBox( pParent,rResId )
78 {
79     DBG_CTOR(SvTreeListBox,0);
80 
81     InitTreeView();
82     Resize();
83 
84     SetSublistOpenWithLeftRight();
85 }
86 
87 void SvTreeListBox::InitTreeView()
88 {
89     DBG_CHKTHIS(SvTreeListBox,0);
90     pCheckButtonData = NULL;
91     pEdEntry = NULL;
92     pEdItem = NULL;
93     nEntryHeight = 0;
94     pEdCtrl = NULL;
95     nFirstSelTab = 0;
96     nLastSelTab = 0;
97     nFocusWidth = -1;
98 
99     Link* pLink = new Link( LINK(this,SvTreeListBox, DefaultCompare) );
100     pLBoxImpl->m_pLink = pLink;
101 
102     nTreeFlags = TREEFLAG_RECALCTABS;
103     nIndent = SV_LBOX_DEFAULT_INDENT_PIXEL;
104     nEntryHeightOffs = SV_ENTRYHEIGHTOFFS_PIXEL;
105     pImp = new SvImpLBox( this, GetModel(), GetStyle() );
106 
107     aContextBmpMode = SVLISTENTRYFLAG_EXPANDED;
108     nContextBmpWidthMax = 0;
109     SetFont( GetFont() );
110     SetSpaceBetweenEntries( 0 );
111     SetLineColor();
112     InitSettings( sal_True, sal_True, sal_True );
113     ImplInitStyle();
114     SetTabs();
115 }
116 
117 
118 SvTreeListBox::~SvTreeListBox()
119 {
120     DBG_DTOR(SvTreeListBox,0);
121     pImp->CallEventListeners( VCLEVENT_OBJECT_DYING );
122     delete pImp;
123     delete pLBoxImpl->m_pLink;
124     ClearTabList();
125 }
126 
127 void SvTreeListBox::SetExtendedWinBits( ExtendedWinBits _nBits )
128 {
129     pImp->SetExtendedWindowBits( _nBits );
130 }
131 
132 ExtendedWinBits SvTreeListBox::GetExtendedWinBits() const
133 {
134     return pImp->GetExtendedWindowBits();
135 }
136 
137 void SvTreeListBox::SetModel( SvLBoxTreeList* pNewModel )
138 {
139     DBG_CHKTHIS(SvTreeListBox,0);
140     pImp->SetModel( pNewModel );
141     SvLBox::SetModel( pNewModel );
142 }
143 
144 void SvTreeListBox::DisconnectFromModel()
145 {
146     DBG_CHKTHIS(SvTreeListBox,0);
147     SvLBox::DisconnectFromModel();
148     pImp->SetModel( GetModel() );
149 }
150 
151 
152 sal_uInt16 SvTreeListBox::IsA()
153 {
154     DBG_CHKTHIS(SvTreeListBox,0);
155     return SV_LISTBOX_ID_TREEBOX;
156 }
157 
158 void SvTreeListBox::SetSublistOpenWithReturn( sal_Bool b )
159 {
160     pImp->bSubLstOpRet = b;
161 }
162 
163 sal_Bool SvTreeListBox::IsSublistOpenWithReturn() const
164 {
165     return pImp->bSubLstOpRet;
166 }
167 
168 void SvTreeListBox::SetSublistOpenWithLeftRight( sal_Bool b )
169 {
170     pImp->bSubLstOpLR = b;
171 }
172 
173 sal_Bool SvTreeListBox::IsSublistOpenWithLeftRight() const
174 {
175     return pImp->bSubLstOpLR;
176 }
177 
178 void SvTreeListBox::Resize()
179 {
180     DBG_CHKTHIS(SvTreeListBox,0);
181     if( IsEditingActive() )
182         EndEditing( sal_True );
183     SvLBox::Resize();
184     pImp->Resize();
185     nFocusWidth = -1;
186     pImp->ShowCursor( sal_False );
187     pImp->ShowCursor( sal_True );
188 }
189 
190 /* Faelle:
191 
192    A) Entries haben Bitmaps
193        0. Keine Buttons
194        1. Node-Buttons (optional auch an Root-Items)
195        2. Node-Buttons (optional auch an Root-Items) + CheckButton
196        3. CheckButton
197    B) Entries haben keine Bitmaps  (->ueber WindowBits wg. D&D !!!!!!)
198        0. Keine Buttons
199        1. Node-Buttons (optional auch an Root-Items)
200        2. Node-Buttons (optional auch an Root-Items) + CheckButton
201        3. CheckButton
202 */
203 
204 #define NO_BUTTONS              0
205 #define NODE_BUTTONS            1
206 #define NODE_AND_CHECK_BUTTONS  2
207 #define CHECK_BUTTONS           3
208 
209 #define TABFLAGS_TEXT (SV_LBOXTAB_DYNAMIC |        \
210                        SV_LBOXTAB_ADJUST_LEFT |    \
211                        SV_LBOXTAB_EDITABLE |       \
212                        SV_LBOXTAB_SHOW_SELECTION)
213 
214 #define TABFLAGS_CONTEXTBMP (SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER)
215 
216 #define TABFLAGS_CHECKBTN (SV_LBOXTAB_DYNAMIC |        \
217                            SV_LBOXTAB_ADJUST_CENTER |  \
218                            SV_LBOXTAB_PUSHABLE)
219 
220 #define TAB_STARTPOS    2
221 
222 // bei Aenderungen GetTextOffset beruecksichtigen
223 void SvTreeListBox::SetTabs()
224 {
225     DBG_CHKTHIS(SvTreeListBox,0);
226     if( IsEditingActive() )
227         EndEditing( sal_True );
228     nTreeFlags &= (~TREEFLAG_RECALCTABS);
229     nFocusWidth = -1;
230     const WinBits nStyle( GetStyle() );
231     sal_Bool bHasButtons = (nStyle & WB_HASBUTTONS)!=0;
232     sal_Bool bHasButtonsAtRoot = (nStyle & (WB_HASLINESATROOT |
233                                               WB_HASBUTTONSATROOT))!=0;
234     long nStartPos = TAB_STARTPOS;
235     long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
236 
237     long nCheckWidth = 0;
238     if( nTreeFlags & TREEFLAG_CHKBTN )
239         nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width();
240     long nCheckWidthDIV2 = nCheckWidth / 2;
241 
242     long nContextWidth = nContextBmpWidthMax;
243     long nContextWidthDIV2 = nContextWidth / 2;
244 
245     ClearTabList();
246 
247     int nCase = NO_BUTTONS;
248     if( !(nTreeFlags & TREEFLAG_CHKBTN) )
249     {
250         if( bHasButtons )
251             nCase = NODE_BUTTONS;
252     }
253     else
254     {
255         if( bHasButtons )
256             nCase = NODE_AND_CHECK_BUTTONS;
257          else
258             nCase = CHECK_BUTTONS;
259     }
260 
261     switch( nCase )
262     {
263         case NO_BUTTONS :
264             nStartPos += nContextWidthDIV2;  // wg. Zentrierung
265             AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
266             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
267             // Abstand setzen nur wenn Bitmaps da
268             if( nContextBmpWidthMax )
269                 nStartPos += 5; // Abstand Context-Bmp - Text
270             AddTab( nStartPos, TABFLAGS_TEXT );
271             break;
272 
273         case NODE_BUTTONS :
274             if( bHasButtonsAtRoot )
275                 nStartPos += ( nIndent + (nNodeWidthPixel/2) );
276             else
277                 nStartPos += nContextWidthDIV2;
278             AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
279             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
280             // Abstand setzen nur wenn Bitmaps da
281             if( nContextBmpWidthMax )
282                 nStartPos += 5; // Abstand Context-Bmp - Text
283             AddTab( nStartPos, TABFLAGS_TEXT );
284             break;
285 
286         case NODE_AND_CHECK_BUTTONS :
287             if( bHasButtonsAtRoot )
288                 nStartPos += ( nIndent + nNodeWidthPixel );
289             else
290                 nStartPos += nCheckWidthDIV2;
291             AddTab( nStartPos, TABFLAGS_CHECKBTN );
292             nStartPos += nCheckWidthDIV2;  // rechter Rand des CheckButtons
293             nStartPos += 3;  // Abstand CheckButton Context-Bmp
294             nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
295             AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
296             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
297             // Abstand setzen nur wenn Bitmaps da
298             if( nContextBmpWidthMax )
299                 nStartPos += 5; // Abstand Context-Bmp - Text
300             AddTab( nStartPos, TABFLAGS_TEXT );
301             break;
302 
303         case CHECK_BUTTONS :
304             nStartPos += nCheckWidthDIV2;
305             AddTab( nStartPos, TABFLAGS_CHECKBTN );
306             nStartPos += nCheckWidthDIV2;  // rechter Rand CheckButton
307             nStartPos += 3;  // Abstand CheckButton Context-Bmp
308             nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
309             AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
310             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
311             // Abstand setzen nur wenn Bitmaps da
312             if( nContextBmpWidthMax )
313                 nStartPos += 5; // Abstand Context-Bmp - Text
314             AddTab( nStartPos, TABFLAGS_TEXT );
315             break;
316     }
317     pImp->NotifyTabsChanged();
318 }
319 
320 void SvTreeListBox::InitEntry( SvLBoxEntry* pEntry,
321   const XubString& aStr, const Image& aCollEntryBmp, const Image& aExpEntryBmp,
322   SvLBoxButtonKind eButtonKind)
323 {
324     DBG_CHKTHIS(SvTreeListBox,0);
325     SvLBoxButton* pButton;
326     SvLBoxString* pString;
327     SvLBoxContextBmp* pContextBmp;
328 
329     if( nTreeFlags & TREEFLAG_CHKBTN )
330     {
331         pButton= new SvLBoxButton( pEntry,eButtonKind,0,pCheckButtonData );
332         pEntry->AddItem( pButton );
333     }
334 
335     pContextBmp= new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp,
336                                      aContextBmpMode );
337     pEntry->AddItem( pContextBmp );
338 
339     pString = new SvLBoxString( pEntry, 0, aStr );
340     pEntry->AddItem( pString );
341 }
342 
343 String SvTreeListBox::GetEntryText(SvLBoxEntry* pEntry) const
344 {
345     DBG_CHKTHIS(SvTreeListBox,0);
346     DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): no entry" );
347     SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
348     DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): item not found" );
349     return pItem->GetText();
350 }
351 
352 String SvTreeListBox::SearchEntryText( SvLBoxEntry* pEntry ) const
353 {
354     DBG_CHKTHIS(SvTreeListBox,0);
355     DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" );
356     String sRet;
357     sal_uInt16 nCount = pEntry->ItemCount();
358     sal_uInt16 nCur = 0;
359     SvLBoxItem* pItem;
360     while( nCur < nCount )
361     {
362         pItem = pEntry->GetItem( nCur );
363         if ( pItem->IsA() == SV_ITEM_ID_LBOXSTRING &&
364              static_cast<SvLBoxString*>( pItem )->GetText().Len() > 0 )
365         {
366             sRet = static_cast<SvLBoxString*>( pItem )->GetText();
367             break;
368         }
369         nCur++;
370     }
371     return sRet;
372 }
373 
374 const Image& SvTreeListBox::GetExpandedEntryBmp(SvLBoxEntry* pEntry, BmpColorMode _eMode) const
375 {
376     DBG_CHKTHIS(SvTreeListBox,0);
377     DBG_ASSERT(pEntry,"Entry?");
378     SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
379     DBG_ASSERT(pItem,"GetContextBmp:Item not found");
380     return pItem->GetBitmap2( _eMode );
381 }
382 
383 const Image& SvTreeListBox::GetCollapsedEntryBmp( SvLBoxEntry* pEntry, BmpColorMode _eMode ) const
384 {
385     DBG_CHKTHIS(SvTreeListBox,0);
386     DBG_ASSERT(pEntry,"Entry?");
387     SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
388     DBG_ASSERT(pItem,"GetContextBmp:Item not found");
389     return pItem->GetBitmap1( _eMode );
390 }
391 
392 IMPL_LINK_INLINE_START( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData )
393 {
394     DBG_CHKTHIS(SvTreeListBox,0);
395     pHdlEntry = pData->GetActEntry();
396     CheckButtonHdl();
397     return 0;
398 }
399 IMPL_LINK_INLINE_END( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData )
400 
401 SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,SvLBoxEntry* pParent,
402                                      sal_Bool bChildsOnDemand, sal_uLong nPos, void* pUser,
403                                      SvLBoxButtonKind eButtonKind )
404 {
405     DBG_CHKTHIS(SvTreeListBox,0);
406     nTreeFlags |= TREEFLAG_MANINS;
407 
408     const Image& rDefExpBmp = pImp->GetDefaultEntryExpBmp( );
409     const Image& rDefColBmp = pImp->GetDefaultEntryColBmp( );
410 
411     aCurInsertedExpBmp = rDefExpBmp;
412     aCurInsertedColBmp = rDefColBmp;
413 
414     SvLBoxEntry* pEntry = CreateEntry();
415     pEntry->SetUserData( pUser );
416     InitEntry( pEntry, aText, rDefColBmp, rDefExpBmp, eButtonKind );
417     pEntry->EnableChildsOnDemand( bChildsOnDemand );
418 
419     // Add the HC versions of the default images
420     SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
421     if( pBmpItem )
422     {
423         pBmpItem->SetBitmap1( pImp->GetDefaultEntryColBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
424         pBmpItem->SetBitmap2( pImp->GetDefaultEntryExpBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
425     }
426 
427     if( !pParent )
428         SvLBox::Insert( pEntry, nPos );
429     else
430         SvLBox::Insert( pEntry, pParent, nPos );
431 
432     aPrevInsertedExpBmp = rDefExpBmp;
433     aPrevInsertedColBmp = rDefColBmp;
434 
435     nTreeFlags &= (~TREEFLAG_MANINS);
436 
437     return pEntry;
438 }
439 
440 SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,
441     const Image& aExpEntryBmp, const Image& aCollEntryBmp,
442     SvLBoxEntry* pParent, sal_Bool bChildsOnDemand, sal_uLong nPos, void* pUser,
443     SvLBoxButtonKind eButtonKind )
444 {
445     DBG_CHKTHIS(SvTreeListBox,0);
446     nTreeFlags |= TREEFLAG_MANINS;
447 
448     aCurInsertedExpBmp = aExpEntryBmp;
449     aCurInsertedColBmp = aCollEntryBmp;
450 
451     SvLBoxEntry* pEntry = CreateEntry();
452     pEntry->SetUserData( pUser );
453     InitEntry( pEntry, aText, aCollEntryBmp, aExpEntryBmp, eButtonKind );
454 
455     pEntry->EnableChildsOnDemand( bChildsOnDemand );
456 
457     if( !pParent )
458         SvLBox::Insert( pEntry, nPos );
459     else
460         SvLBox::Insert( pEntry, pParent, nPos );
461 
462     aPrevInsertedExpBmp = aExpEntryBmp;
463     aPrevInsertedColBmp = aCollEntryBmp;
464 
465     nTreeFlags &= (~TREEFLAG_MANINS);
466 
467     return pEntry;
468 }
469 
470 void SvTreeListBox::SetEntryText( SvLBoxEntry* pEntry, const XubString& aStr)
471 {
472     DBG_CHKTHIS(SvTreeListBox,0);
473     SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
474     DBG_ASSERT(pItem,"SetText:Item not found");
475     pItem->SetText( pEntry, aStr );
476     pItem->InitViewData( this, pEntry, 0 );
477     GetModel()->InvalidateEntry( pEntry );
478 }
479 
480 void SvTreeListBox::SetExpandedEntryBmp( SvLBoxEntry* pEntry, const Image& aBmp, BmpColorMode _eMode )
481 {
482     DBG_CHKTHIS(SvTreeListBox,0);
483     SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
484 
485     DBG_ASSERT(pItem,"SetExpBmp:Item not found");
486     pItem->SetBitmap2( aBmp, _eMode );
487 
488     GetModel()->InvalidateEntry( pEntry );
489     SetEntryHeight( pEntry );
490     Size aSize = aBmp.GetSizePixel();
491     // #97680# ---------------
492     short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
493     if( nWidth > nContextBmpWidthMax )
494     {
495         nContextBmpWidthMax = nWidth;
496         SetTabs();
497     }
498 }
499 
500 void SvTreeListBox::SetCollapsedEntryBmp(SvLBoxEntry* pEntry,const Image& aBmp, BmpColorMode _eMode )
501 {
502     DBG_CHKTHIS(SvTreeListBox,0);
503     SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
504 
505     DBG_ASSERT(pItem,"SetExpBmp:Item not found");
506     pItem->SetBitmap1( aBmp, _eMode );
507 
508     GetModel()->InvalidateEntry( pEntry );
509     SetEntryHeight( pEntry );
510     Size aSize = aBmp.GetSizePixel();
511     // #97680# -----------
512     short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
513     if( nWidth > nContextBmpWidthMax )
514     {
515         nContextBmpWidthMax = nWidth;
516         SetTabs();
517     }
518 }
519 
520 void SvTreeListBox::ImpEntryInserted( SvLBoxEntry* pEntry )
521 {
522     DBG_CHKTHIS(SvTreeListBox,0);
523 
524     SvLBoxEntry* pParent = (SvLBoxEntry*)pModel->GetParent( pEntry );
525     if( pParent )
526     {
527         sal_uInt16 nFlags = pParent->GetFlags();
528         nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
529         pParent->SetFlags( nFlags );
530     }
531 
532     if(!((nTreeFlags & TREEFLAG_MANINS) &&
533          (aPrevInsertedExpBmp == aCurInsertedExpBmp)  &&
534          (aPrevInsertedColBmp == aCurInsertedColBmp) ))
535     {
536         Size aSize = GetCollapsedEntryBmp( pEntry ).GetSizePixel();
537         if( aSize.Width() > nContextBmpWidthMax )
538         {
539             nContextBmpWidthMax = (short)aSize.Width();
540             nTreeFlags |= TREEFLAG_RECALCTABS;
541         }
542         aSize = GetExpandedEntryBmp( pEntry ).GetSizePixel();
543         if( aSize.Width() > nContextBmpWidthMax )
544         {
545             nContextBmpWidthMax = (short)aSize.Width();
546             nTreeFlags |= TREEFLAG_RECALCTABS;
547         }
548     }
549     SetEntryHeight( (SvLBoxEntry*)pEntry );
550 }
551 
552 
553 
554 void SvTreeListBox::SetCheckButtonState( SvLBoxEntry* pEntry, SvButtonState eState)
555 {
556     DBG_CHKTHIS(SvTreeListBox,0);
557     if( nTreeFlags & TREEFLAG_CHKBTN )
558     {
559         SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
560         if(!(pItem && pItem->CheckModification()))
561             return ;
562         switch( eState )
563         {
564             case SV_BUTTON_CHECKED:
565                 pItem->SetStateChecked();
566                 break;
567 
568             case SV_BUTTON_UNCHECKED:
569                 pItem->SetStateUnchecked();
570                 break;
571 
572             case SV_BUTTON_TRISTATE:
573                 pItem->SetStateTristate();
574                 break;
575         }
576         InvalidateEntry( pEntry );
577     }
578 }
579 
580 SvButtonState SvTreeListBox::GetCheckButtonState( SvLBoxEntry* pEntry ) const
581 {
582     DBG_CHKTHIS(SvTreeListBox,0);
583     SvButtonState eState = SV_BUTTON_UNCHECKED;
584     if( nTreeFlags & TREEFLAG_CHKBTN )
585     {
586         SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
587         if(!pItem)
588             return SV_BUTTON_TRISTATE;
589         sal_uInt16 nButtonFlags = pItem->GetButtonFlags();
590         eState = pCheckButtonData->ConvertToButtonState( nButtonFlags );
591     }
592     return eState;
593 }
594 
595 void SvTreeListBox::CheckButtonHdl()
596 {
597     DBG_CHKTHIS(SvTreeListBox,0);
598     aCheckButtonHdl.Call( this );
599     if ( pCheckButtonData )
600         pImp->CallEventListeners( VCLEVENT_CHECKBOX_TOGGLE, (void*)pCheckButtonData->GetActEntry() );
601 }
602 
603 // *********************************************************************
604 // *********************************************************************
605 
606 //
607 //  TODO: Momentan werden die Daten so geklont, dass sie dem
608 //  Standard-TreeView-Format entsprechen. Hier sollte eigentlich
609 //  das Model als Referenz dienen. Dies fuehrt dazu, dass
610 //  SvLBoxEntry::Clone _nicht_ gerufen wird, sondern nur dessen
611 //  Basisklasse SvListEntry
612 //
613 
614 SvLBoxEntry* SvTreeListBox::CloneEntry( SvLBoxEntry* pSource )
615 {
616     DBG_CHKTHIS(SvTreeListBox,0);
617     XubString aStr;
618     Image aCollEntryBmp;
619     Image aExpEntryBmp;
620     SvLBoxButtonKind eButtonKind = SvLBoxButtonKind_enabledCheckbox;
621 
622     SvLBoxString* pStringItem = (SvLBoxString*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
623     if( pStringItem )
624         aStr = pStringItem->GetText();
625     SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
626     if( pBmpItem )
627     {
628         aCollEntryBmp = pBmpItem->GetBitmap1( BMP_COLOR_NORMAL );
629         aExpEntryBmp  = pBmpItem->GetBitmap2( BMP_COLOR_NORMAL );
630     }
631     SvLBoxButton* pButtonItem = (SvLBoxButton*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
632     if( pButtonItem )
633         eButtonKind = pButtonItem->GetKind();
634     SvLBoxEntry* pClone = CreateEntry();
635     InitEntry( pClone, aStr, aCollEntryBmp, aExpEntryBmp, eButtonKind );
636     pClone->SvListEntry::Clone( pSource );
637     pClone->EnableChildsOnDemand( pSource->HasChildsOnDemand() );
638     pClone->SetUserData( pSource->GetUserData() );
639 
640     if ( pBmpItem )
641     {
642         SvLBoxContextBmp* pCloneBitmap = static_cast< SvLBoxContextBmp* >( pClone->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
643         if ( pCloneBitmap )
644         {
645             pCloneBitmap->SetBitmap1( pBmpItem->GetBitmap1( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
646             pCloneBitmap->SetBitmap2( pBmpItem->GetBitmap2( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
647         }
648     }
649 
650     return pClone;
651 }
652 
653 // *********************************************************************
654 // *********************************************************************
655 
656 
657 void SvTreeListBox::ShowExpandBitmapOnCursor( sal_Bool bYes )
658 {
659     DBG_CHKTHIS(SvTreeListBox,0);
660     if( bYes )
661         aContextBmpMode = SVLISTENTRYFLAG_FOCUSED;
662     else
663         aContextBmpMode = SVLISTENTRYFLAG_EXPANDED;
664 }
665 
666 void SvTreeListBox::SetIndent( short nNewIndent )
667 {
668     DBG_CHKTHIS(SvTreeListBox,0);
669     nIndent = nNewIndent;
670     SetTabs();
671     if( IsUpdateMode() )
672         Invalidate();
673 }
674 
675 const Image& SvTreeListBox::GetDefaultExpandedEntryBmp( BmpColorMode _eMode ) const
676 {
677     return pImp->GetDefaultEntryExpBmp( _eMode );
678 }
679 
680 const Image& SvTreeListBox::GetDefaultCollapsedEntryBmp( BmpColorMode _eMode ) const
681 {
682     return pImp->GetDefaultEntryColBmp( _eMode );
683 }
684 
685 void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image& aBmp, BmpColorMode _eMode )
686 {
687     DBG_CHKTHIS(SvTreeListBox,0);
688     Size aSize = aBmp.GetSizePixel();
689     if( aSize.Width() > nContextBmpWidthMax )
690         nContextBmpWidthMax = (short)aSize.Width();
691     SetTabs();
692 
693     pImp->SetDefaultEntryExpBmp( aBmp, _eMode );
694 }
695 
696 void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp, BmpColorMode _eMode )
697 {
698     DBG_CHKTHIS(SvTreeListBox,0);
699     Size aSize = aBmp.GetSizePixel();
700     if( aSize.Width() > nContextBmpWidthMax )
701         nContextBmpWidthMax = (short)aSize.Width();
702     SetTabs();
703 
704     pImp->SetDefaultEntryColBmp( aBmp, _eMode );
705 }
706 
707 void SvTreeListBox::EnableCheckButton( SvLBoxButtonData* pData )
708 {
709     DBG_CHKTHIS(SvTreeListBox,0);
710     DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0");
711     if( !pData )
712         nTreeFlags &= (~TREEFLAG_CHKBTN);
713     else
714     {
715         SetCheckButtonData( pData );
716         nTreeFlags |= TREEFLAG_CHKBTN;
717         pData->SetLink( LINK(this, SvTreeListBox, CheckButtonClick));
718     }
719 
720     SetTabs();
721     if( IsUpdateMode() )
722         Invalidate();
723 }
724 
725 void SvTreeListBox::SetCheckButtonData( SvLBoxButtonData* pData )
726 {
727     DBG_CHKTHIS(SvTreeListBox,0);
728     if ( pData )
729         pCheckButtonData = pData;
730 }
731 
732 const Image& SvTreeListBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode )
733 {
734     return SvImpLBox::GetDefaultExpandedNodeImage( _eMode );
735 }
736 
737 const Image& SvTreeListBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode )
738 {
739     return SvImpLBox::GetDefaultCollapsedNodeImage( _eMode );
740 }
741 
742 void SvTreeListBox::SetNodeBitmaps( const Image& rCollapsedNodeBmp, const Image& rExpandedNodeBmp, BmpColorMode _eMode )
743 {
744     DBG_CHKTHIS(SvTreeListBox,0);
745     SetExpandedNodeBmp( rExpandedNodeBmp, _eMode );
746     SetCollapsedNodeBmp( rCollapsedNodeBmp, _eMode );
747     SetTabs();
748 }
749 
750 void SvTreeListBox::SetDontKnowNodeBitmap( const Image& rDontKnowBmp, BmpColorMode _eMode )
751 {
752     pImp->SetDontKnowNodeBmp( rDontKnowBmp, _eMode );
753 }
754 
755 sal_Bool SvTreeListBox::EditingEntry( SvLBoxEntry*, Selection& )
756 {
757     DBG_CHKTHIS(SvTreeListBox,0);
758     return sal_True;
759 }
760 
761 sal_Bool SvTreeListBox::EditedEntry( SvLBoxEntry* /*pEntry*/,const XubString& /*rNewText*/)
762 {
763     DBG_CHKTHIS(SvTreeListBox,0);
764     return sal_True;
765 }
766 
767 void SvTreeListBox::EnableInplaceEditing( sal_Bool bOn )
768 {
769     DBG_CHKTHIS(SvTreeListBox,0);
770     SvLBox::EnableInplaceEditing( bOn );
771 }
772 
773 void SvTreeListBox::KeyInput( const KeyEvent& rKEvt )
774 {
775     DBG_CHKTHIS(SvTreeListBox,0);
776     // unter OS/2 bekommen wir auch beim Editieren Key-Up/Down
777     if( IsEditingActive() )
778         return;
779 
780     nImpFlags |= SVLBOX_IS_TRAVELSELECT;
781 
782 #ifdef OVDEBUG
783     sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
784     switch ( nCode )
785     {
786         case KEY_F1:
787         {
788             SvLBoxEntry* pEntry = First();
789             pEntry = NextVisible( pEntry );
790             SetEntryText( pEntry, "SetEntryText" );
791             Sound::Beep();
792         }
793         break;
794     }
795 #endif
796 
797     if( !pImp->KeyInput( rKEvt ) )
798         SvLBox::KeyInput( rKEvt );
799 
800     nImpFlags &= ~SVLBOX_IS_TRAVELSELECT;
801 }
802 
803 void SvTreeListBox::RequestingChilds( SvLBoxEntry* pParent )
804 {
805     DBG_CHKTHIS(SvTreeListBox,0);
806     if( !pParent->HasChilds() )
807         InsertEntry( String::CreateFromAscii("<dummy>"), pParent, sal_False, LIST_APPEND );
808 }
809 
810 void SvTreeListBox::GetFocus()
811 {
812     DBG_CHKTHIS(SvTreeListBox,0);
813     pImp->GetFocus();
814     SvLBox::GetFocus();
815 
816     SvLBoxEntry* pEntry = FirstSelected();
817     if ( pEntry )
818         pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
819 
820 }
821 
822 void SvTreeListBox::LoseFocus()
823 {
824     DBG_CHKTHIS(SvTreeListBox,0);
825     pImp->LoseFocus();
826     SvLBox::LoseFocus();
827 }
828 
829 void SvTreeListBox::ModelHasCleared()
830 {
831     DBG_CHKTHIS(SvTreeListBox,0);
832     pImp->pCursor = 0; //sonst Absturz beim Inplace-Editieren im GetFocus
833     delete pEdCtrl;
834     pEdCtrl = NULL;
835     pImp->Clear();
836     nFocusWidth = -1;
837 
838     nContextBmpWidthMax = 0;
839     SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() );
840     SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() );
841 
842     if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT ))
843         nEntryHeight = 0;
844     AdjustEntryHeight( GetFont() );
845     AdjustEntryHeight( GetDefaultExpandedEntryBmp() );
846     AdjustEntryHeight( GetDefaultCollapsedEntryBmp() );
847 
848     SvLBox::ModelHasCleared();
849 //  if( IsUpdateMode() )
850 //      Invalidate();
851 }
852 
853 void SvTreeListBox::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool /* bShow  */ )
854 {
855     DBG_CHKTHIS(SvTreeListBox,0);
856     pImp->PaintDDCursor( pEntry );
857 }
858 
859 void SvTreeListBox::ScrollOutputArea( short nDeltaEntries )
860 {
861     DBG_CHKTHIS(SvTreeListBox,0);
862     if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() )
863         return;
864 
865     long nThumb = pImp->aVerSBar.GetThumbPos();
866     long nMax = pImp->aVerSBar.GetRange().Max();
867 
868     NotifyBeginScroll();
869     if( nDeltaEntries < 0 )
870     {
871         // das Fenster nach oben verschieben
872         nDeltaEntries *= -1;
873         long nVis = pImp->aVerSBar.GetVisibleSize();
874         long nTemp = nThumb + nVis;
875         if( nDeltaEntries > (nMax - nTemp) )
876             nDeltaEntries = (short)(nMax - nTemp);
877         pImp->PageDown( (sal_uInt16)nDeltaEntries );
878     }
879     else
880     {
881         if( nDeltaEntries > nThumb )
882             nDeltaEntries = (short)nThumb;
883         pImp->PageUp( (sal_uInt16)nDeltaEntries );
884     }
885     pImp->SyncVerThumb();
886     NotifyEndScroll();
887 }
888 
889 void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode )
890 {
891     DBG_CHKTHIS(SvTreeListBox,0);
892     SvLBox::SetSelectionMode( eSelectMode );
893     pImp->SetSelectionMode( eSelectMode );
894 }
895 
896 void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode )
897 {
898     DBG_CHKTHIS(SvTreeListBox,0);
899     SvLBox::SetDragDropMode( nDDMode );
900     pImp->SetDragDropMode( nDDMode );
901 }
902 
903 short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic )
904 {
905     DBG_CHKTHIS(SvTreeListBox,0);
906     short nOffset = 0;
907     aSizeLogic = rBmp.GetSizePixel();
908     if( GetEntryHeight() > aSizeLogic.Height() )
909         nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
910     return nOffset;
911 }
912 
913 short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic )
914 {
915     DBG_CHKTHIS(SvTreeListBox,0);
916     short nOffset = 0;
917     aSizeLogic = Size(GetTextWidth('X'), GetTextHeight());
918     if( GetEntryHeight() > aSizeLogic.Height() )
919         nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
920     return nOffset;
921 }
922 
923 void SvTreeListBox::SetEntryHeight( SvLBoxEntry* pEntry )
924 {
925     DBG_CHKTHIS(SvTreeListBox,0);
926     short nHeight, nHeightMax=0;
927     sal_uInt16 nCount = pEntry->ItemCount();
928     sal_uInt16 nCur = 0;
929     SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
930     while( nCur < nCount )
931     {
932         SvLBoxItem* pItem = pEntry->GetItem( nCur );
933         nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height());
934         if( nHeight > nHeightMax )
935             nHeightMax = nHeight;
936         nCur++;
937     }
938 
939     if( nHeightMax > nEntryHeight )
940     {
941         nEntryHeight = nHeightMax;
942         SvLBox::SetFont( GetFont() );
943         pImp->SetEntryHeight( nHeightMax );
944     }
945 }
946 
947 void SvTreeListBox::SetEntryHeight( short nHeight, sal_Bool bAlways )
948 {
949     DBG_CHKTHIS(SvTreeListBox,0);
950 
951     if( bAlways || nHeight > nEntryHeight )
952     {
953         nEntryHeight = nHeight;
954         if( nEntryHeight )
955             nTreeFlags |= TREEFLAG_FIXEDHEIGHT;
956         else
957             nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT;
958         SvLBox::SetFont( GetFont() );
959         pImp->SetEntryHeight( nHeight );
960     }
961 }
962 
963 
964 void SvTreeListBox::AdjustEntryHeight( const Image& rBmp )
965 {
966     DBG_CHKTHIS(SvTreeListBox,0);
967     Size aSize;
968     GetHeightOffset( rBmp, aSize );
969     if( aSize.Height() > nEntryHeight )
970     {
971         nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
972         pImp->SetEntryHeight( nEntryHeight );
973     }
974 }
975 
976 void SvTreeListBox::AdjustEntryHeight( const Font& rFont )
977 {
978     DBG_CHKTHIS(SvTreeListBox,0);
979     Size aSize;
980     GetHeightOffset( rFont, aSize );
981     if( aSize.Height()  >  nEntryHeight )
982     {
983         nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
984         pImp->SetEntryHeight( nEntryHeight );
985     }
986 }
987 
988 sal_Bool SvTreeListBox::Expand( SvLBoxEntry* pParent )
989 {
990     DBG_CHKTHIS(SvTreeListBox,0);
991     pHdlEntry = pParent;
992     sal_Bool bExpanded = sal_False;
993     sal_uInt16 nFlags;
994 
995     if( pParent->HasChildsOnDemand() )
996         RequestingChilds( pParent );
997     if( pParent->HasChilds() )
998     {
999         nImpFlags |= SVLBOX_IS_EXPANDING;
1000         if( ExpandingHdl() )
1001         {
1002             bExpanded = sal_True;
1003             SvListView::Expand( pParent );
1004             pImp->EntryExpanded( pParent );
1005             pHdlEntry = pParent;
1006             ExpandedHdl();
1007         }
1008         nFlags = pParent->GetFlags();
1009         nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
1010         nFlags |= SV_ENTRYFLAG_HAD_CHILDREN;
1011         pParent->SetFlags( nFlags );
1012     }
1013     else
1014     {
1015         nFlags = pParent->GetFlags();
1016         nFlags |= SV_ENTRYFLAG_NO_NODEBMP;
1017         pParent->SetFlags( nFlags );
1018         GetModel()->InvalidateEntry( pParent ); // neu zeichnen
1019     }
1020 
1021     // --> OD 2009-04-01 #i92103#
1022     if ( bExpanded )
1023     {
1024         pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent );
1025     }
1026     // <--
1027 
1028     return bExpanded;
1029 }
1030 
1031 sal_Bool SvTreeListBox::Collapse( SvLBoxEntry* pParent )
1032 {
1033     DBG_CHKTHIS(SvTreeListBox,0);
1034     nImpFlags &= ~SVLBOX_IS_EXPANDING;
1035     pHdlEntry = pParent;
1036     sal_Bool bCollapsed = sal_False;
1037 
1038     if( ExpandingHdl() )
1039     {
1040         bCollapsed = sal_True;
1041         pImp->CollapsingEntry( pParent );
1042         SvListView::Collapse( pParent );
1043         pImp->EntryCollapsed( pParent );
1044         pHdlEntry = pParent;
1045         ExpandedHdl();
1046     }
1047 
1048     // --> OD 2009-04-01 #i92103#
1049     if ( bCollapsed )
1050     {
1051         pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent );
1052     }
1053     // <--
1054 
1055     return bCollapsed;
1056 }
1057 
1058 sal_Bool SvTreeListBox::Select( SvLBoxEntry* pEntry, sal_Bool bSelect )
1059 {
1060     DBG_CHKTHIS(SvTreeListBox,0);
1061     DBG_ASSERT(pEntry,"Select: Null-Ptr");
1062     sal_Bool bRetVal = SvListView::Select( pEntry, bSelect );
1063     DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed");
1064     if( bRetVal )
1065     {
1066         pImp->EntrySelected( pEntry, bSelect );
1067         pHdlEntry = pEntry;
1068         if( bSelect )
1069         {
1070             SelectHdl();
1071             pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
1072         }
1073         else
1074             DeselectHdl();
1075     }
1076     return bRetVal;
1077 }
1078 
1079 sal_uLong SvTreeListBox::SelectChilds( SvLBoxEntry* pParent, sal_Bool bSelect )
1080 {
1081     DBG_CHKTHIS(SvTreeListBox,0);
1082     pImp->DestroyAnchor();
1083     sal_uLong nRet = 0;
1084     if( !pParent->HasChilds() )
1085         return 0;
1086     sal_uInt16 nRefDepth = pModel->GetDepth( pParent );
1087     SvLBoxEntry* pChild = FirstChild( pParent );
1088     do {
1089         nRet++;
1090         Select( pChild, bSelect );
1091         pChild = Next( pChild );
1092     } while( pChild && pModel->GetDepth( pChild ) > nRefDepth );
1093     return nRet;
1094 }
1095 
1096 void SvTreeListBox::SelectAll( sal_Bool bSelect, sal_Bool )
1097 {
1098     DBG_CHKTHIS(SvTreeListBox,0);
1099     pImp->SelAllDestrAnch(
1100         bSelect,
1101         sal_True,       // Anker loeschen,
1102         sal_True );     // auch bei SINGLE_SELECTION den Cursor deselektieren
1103 }
1104 
1105 void SvTreeListBox::ModelHasInsertedTree( SvListEntry* pEntry )
1106 {
1107     DBG_CHKTHIS(SvTreeListBox,0);
1108     sal_uInt16 nRefDepth = pModel->GetDepth( (SvLBoxEntry*)pEntry );
1109     SvLBoxEntry* pTmp = (SvLBoxEntry*)pEntry;
1110     do
1111     {
1112         ImpEntryInserted( pTmp );
1113         pTmp = Next( pTmp );
1114     } while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) );
1115     pImp->TreeInserted( (SvLBoxEntry*)pEntry );
1116 }
1117 
1118 void SvTreeListBox::ModelHasInserted( SvListEntry* pEntry )
1119 {
1120     DBG_CHKTHIS(SvTreeListBox,0);
1121     ImpEntryInserted( (SvLBoxEntry*)pEntry );
1122     pImp->EntryInserted( (SvLBoxEntry*)pEntry );
1123 }
1124 
1125 void SvTreeListBox::ModelIsMoving(SvListEntry* pSource,
1126                                         SvListEntry* /* pTargetParent */,
1127                                         sal_uLong /* nChildPos */ )
1128 {
1129     DBG_CHKTHIS(SvTreeListBox,0);
1130     pImp->MovingEntry( (SvLBoxEntry*)pSource );
1131 }
1132 
1133 void SvTreeListBox::ModelHasMoved( SvListEntry* pSource )
1134 {
1135     DBG_CHKTHIS(SvTreeListBox,0);
1136     pImp->EntryMoved( (SvLBoxEntry*)pSource );
1137 }
1138 
1139 void SvTreeListBox::ModelIsRemoving( SvListEntry* pEntry )
1140 {
1141     DBG_CHKTHIS(SvTreeListBox,0);
1142     if(pEdEntry == pEntry)
1143         pEdEntry = NULL;
1144 
1145     pImp->RemovingEntry( (SvLBoxEntry*)pEntry );
1146     NotifyRemoving( (SvLBoxEntry*)pEntry );
1147 }
1148 
1149 void SvTreeListBox::ModelHasRemoved( SvListEntry* pEntry  )
1150 {
1151     DBG_CHKTHIS(SvTreeListBox,0);
1152     if ( pEntry == pHdlEntry)
1153         pHdlEntry = NULL;
1154     pImp->EntryRemoved();
1155 }
1156 
1157 void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp, BmpColorMode _eMode )
1158 {
1159     DBG_CHKTHIS(SvTreeListBox,0);
1160     AdjustEntryHeight( rBmp );
1161     pImp->SetCollapsedNodeBmp( rBmp, _eMode );
1162 }
1163 
1164 void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp, BmpColorMode _eMode )
1165 {
1166     DBG_CHKTHIS(SvTreeListBox,0);
1167     AdjustEntryHeight( rBmp );
1168     pImp->SetExpandedNodeBmp( rBmp, _eMode );
1169 }
1170 
1171 
1172 void SvTreeListBox::SetFont( const Font& rFont )
1173 {
1174     DBG_CHKTHIS(SvTreeListBox,0);
1175     Font aTempFont( rFont );
1176     aTempFont.SetTransparent( sal_True );
1177     Control::SetFont( aTempFont );
1178     AdjustEntryHeight( aTempFont );
1179     // immer Invalidieren, sonst fallen wir
1180     // bei SetEntryHeight auf die Nase
1181     RecalcViewData();
1182 }
1183 
1184 
1185 void SvTreeListBox::Paint( const Rectangle& rRect )
1186 {
1187     DBG_CHKTHIS(SvTreeListBox,0);
1188     SvLBox::Paint( rRect );
1189     if( nTreeFlags & TREEFLAG_RECALCTABS )
1190         SetTabs();
1191     pImp->Paint( rRect );
1192 }
1193 
1194 void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt )
1195 {
1196     DBG_CHKTHIS(SvTreeListBox,0);
1197     pImp->MouseButtonDown( rMEvt );
1198 }
1199 
1200 void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt )
1201 {
1202     DBG_CHKTHIS(SvTreeListBox,0);
1203     pImp->MouseButtonUp( rMEvt );
1204 }
1205 
1206 void SvTreeListBox::MouseMove( const MouseEvent& rMEvt )
1207 {
1208     DBG_CHKTHIS(SvTreeListBox,0);
1209     pImp->MouseMove( rMEvt );
1210 }
1211 
1212 
1213 void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate )
1214 {
1215     DBG_CHKTHIS(SvTreeListBox,0);
1216     pImp->SetUpdateMode( bUpdate );
1217 }
1218 
1219 void SvTreeListBox::SetUpdateModeFast( sal_Bool bUpdate )
1220 {
1221     DBG_CHKTHIS(SvTreeListBox,0);
1222     pImp->SetUpdateModeFast( bUpdate );
1223 }
1224 
1225 void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic )
1226 {
1227     DBG_CHKTHIS(SvTreeListBox,0);
1228     if( nOffsLogic != nEntryHeightOffs )
1229     {
1230         nEntryHeight = nEntryHeight - nEntryHeightOffs;
1231         nEntryHeightOffs = (short)nOffsLogic;
1232         nEntryHeight = nEntryHeight + nOffsLogic;
1233         AdjustEntryHeight( GetFont() );
1234         RecalcViewData();
1235         pImp->SetEntryHeight( nEntryHeight );
1236     }
1237 }
1238 
1239 void SvTreeListBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect )
1240 {
1241     DBG_CHKTHIS(SvTreeListBox,0);
1242     pImp->SetCursor(pEntry, bForceNoSelect);
1243 }
1244 
1245 void SvTreeListBox::SetCurEntry( SvLBoxEntry* pEntry )
1246 {
1247     DBG_CHKTHIS(SvTreeListBox,0);
1248     pImp->SetCurEntry( pEntry );
1249 }
1250 
1251 Image SvTreeListBox::GetCollapsedNodeBmp( BmpColorMode _eMode ) const
1252 {
1253     return pImp->GetCollapsedNodeBmp( _eMode );
1254 }
1255 
1256 Image SvTreeListBox::GetExpandedNodeBmp( BmpColorMode _eMode ) const
1257 {
1258     return pImp->GetExpandedNodeBmp( _eMode );
1259 }
1260 
1261 Point SvTreeListBox::GetEntryPosition( SvLBoxEntry* pEntry ) const
1262 {
1263     return pImp->GetEntryPosition( pEntry );
1264 }
1265 
1266 void SvTreeListBox::ShowEntry( SvLBoxEntry* pEntry )
1267 {
1268     MakeVisible( pEntry );
1269 }
1270 
1271 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry )
1272 {
1273     pImp->MakeVisible(pEntry);
1274 }
1275 
1276 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop )
1277 {
1278     pImp->MakeVisible( pEntry, bMoveToTop );
1279 }
1280 
1281 void SvTreeListBox::ModelHasEntryInvalidated( SvListEntry* pEntry )
1282 {
1283     DBG_CHKTHIS(SvTreeListBox,0);
1284     // die einzelnen Items des Entries reinitialisieren
1285     SvLBox::ModelHasEntryInvalidated( pEntry );
1286     // repainten
1287     pImp->InvalidateEntry( (SvLBoxEntry*)pEntry );
1288 }
1289 
1290 void SvTreeListBox::EditItemText( SvLBoxEntry* pEntry, SvLBoxString* pItem,
1291     const Selection& rSelection )
1292 {
1293     DBG_CHKTHIS(SvTreeListBox,0);
1294     DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params");
1295     if( IsSelected( pEntry ))
1296     {
1297         pImp->ShowCursor( sal_False );
1298         SvListView::Select( pEntry, sal_False );
1299         PaintEntry( pEntry );
1300         SvListView::Select( pEntry, sal_True );
1301         pImp->ShowCursor( sal_True );
1302     }
1303     pEdEntry = pEntry;
1304     pEdItem = pItem;
1305     SvLBoxTab* pTab = GetTab( pEntry, pItem );
1306     DBG_ASSERT(pTab,"EditItemText:Tab not found");
1307 
1308     Size aItemSize( pItem->GetSize(this, pEntry) );
1309     Point aPos = GetEntryPosition( pEntry );
1310     aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2;
1311     aPos.X() = GetTabPos( pEntry, pTab );
1312     long nOutputWidth = pImp->GetOutputSize().Width();
1313     Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() );
1314     sal_uInt16 nPos = aTabs.GetPos( pTab );
1315     if( nPos+1 < aTabs.Count() )
1316     {
1317         SvLBoxTab* pRightTab = (SvLBoxTab*)aTabs.GetObject( nPos + 1 );
1318         long nRight = GetTabPos( pEntry, pRightTab );
1319         if( nRight <= nOutputWidth )
1320             aSize.Width() = nRight - aPos.X();
1321     }
1322     Point aOrigin( GetMapMode().GetOrigin() );
1323     aPos += aOrigin; // in Win-Koord umrechnen
1324     aSize.Width() -= aOrigin.X();
1325     Rectangle aRect( aPos, aSize );
1326 #ifdef OS2
1327     // Platz lassen fuer WB_BORDER
1328     aRect.Left() -= 2;
1329     aRect.Top() -= 3;
1330     aRect.Bottom() += 3;
1331 #endif
1332     EditText( pItem->GetText(), aRect, rSelection );
1333 }
1334 
1335 void SvTreeListBox::CancelEditing()
1336 {
1337     DBG_CHKTHIS(SvTreeListBox,0);
1338     SvLBox::CancelTextEditing();
1339 }
1340 
1341 void SvTreeListBox::EditEntry( SvLBoxEntry* pEntry )
1342 {
1343     pImp->aEditClickPos = Point( -1, -1 );
1344     ImplEditEntry( pEntry );
1345 }
1346 
1347 void SvTreeListBox::ImplEditEntry( SvLBoxEntry* pEntry )
1348 {
1349     DBG_CHKTHIS(SvTreeListBox,0);
1350     if( IsEditingActive() )
1351         EndEditing();
1352     if( !pEntry )
1353         pEntry = GetCurEntry();
1354     if( pEntry )
1355     {
1356         long nClickX = pImp->aEditClickPos.X();
1357         bool bIsMouseTriggered = nClickX >= 0;
1358 
1359         SvLBoxString* pItem = NULL;
1360         sal_uInt16 nCount = pEntry->ItemCount();
1361         for( sal_uInt16 i = 0 ; i < nCount ; i++ )
1362         {
1363             SvLBoxItem* pTmpItem = pEntry->GetItem( i );
1364             if( pTmpItem->IsA() != SV_ITEM_ID_LBOXSTRING )
1365                 continue;
1366 
1367             SvLBoxTab* pTab = GetTab( pEntry, pTmpItem );
1368             long nTabPos = pTab->GetPos();
1369             long nNextTabPos = -1;
1370             if( i < nCount - 1 )
1371             {
1372                 SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 );
1373                 SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem );
1374                 nNextTabPos = pNextTab->GetPos();
1375             }
1376 
1377             if( pTab && pTab->IsEditable() )
1378             {
1379                 if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) )
1380                 {
1381                     pItem = static_cast<SvLBoxString*>( pTmpItem );
1382                     break;
1383                 }
1384             }
1385         }
1386 
1387         Selection aSel( SELECTION_MIN, SELECTION_MAX );
1388         if( pItem && EditingEntry( pEntry, aSel ) )
1389         {
1390             SelectAll( sal_False );
1391             MakeVisible( pEntry );
1392             EditItemText( pEntry, pItem, aSel );
1393         }
1394     }
1395 }
1396 
1397 sal_Bool SvTreeListBox::AreChildrenTransient() const
1398 {
1399     return pImp->AreChildrenTransient();
1400 }
1401 
1402 void SvTreeListBox::SetChildrenNotTransient()
1403 {
1404     pImp->SetChildrenNotTransient();
1405 }
1406 
1407 void SvTreeListBox::EditedText( const XubString& rStr )
1408 
1409 {
1410     DBG_CHKTHIS(SvTreeListBox,0);
1411     if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing
1412     {
1413         Point aPos = GetEntryPosition( pEdEntry );
1414         if( EditedEntry( pEdEntry, rStr ) )
1415         {
1416             ((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr );
1417             pModel->InvalidateEntry( pEdEntry );
1418         }
1419         //if( GetSelectionMode() == SINGLE_SELECTION )
1420         //{
1421         if( GetSelectionCount() == 0 )
1422             Select( pEdEntry );
1423         if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() )
1424             SetCurEntry( pEdEntry );
1425         //}
1426     }
1427 }
1428 
1429 void SvTreeListBox::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem,
1430                                     const Point& )
1431 {
1432     DBG_CHKTHIS(SvTreeListBox,0);
1433     if( IsEditingActive() )
1434         EndEditing();
1435     if( pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
1436     {
1437         Selection aSel( SELECTION_MIN, SELECTION_MAX );
1438         if( EditingEntry( pEntry, aSel ) )
1439         {
1440             SelectAll( sal_False );
1441             EditItemText( pEntry, (SvLBoxString*)pItem, aSel );
1442         }
1443     }
1444 }
1445 
1446 
1447 
1448 SvLBoxEntry* SvTreeListBox::GetDropTarget( const Point& rPos )
1449 {
1450     DBG_CHKTHIS(SvTreeListBox,0);
1451     // Scrollen
1452     if( rPos.Y() < 12 )
1453     {
1454         SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False );
1455         ScrollOutputArea( +1 );
1456     }
1457     else
1458     {
1459         Size aSize( pImp->GetOutputSize() );
1460         if( rPos.Y() > aSize.Height() - 12 )
1461         {
1462             SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False );
1463             ScrollOutputArea( -1 );
1464         }
1465     }
1466 
1467     SvLBoxEntry* pTarget = pImp->GetEntry( rPos );
1468     // bei Droppen in leere Flaeche -> den letzten Eintrag nehmen
1469     if( !pTarget )
1470         return (SvLBoxEntry*)LastVisible();
1471     else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) &&
1472              pTarget == First() && rPos.Y() < 6 )
1473         return 0;
1474 
1475     return pTarget;
1476 }
1477 
1478 
1479 SvLBoxEntry* SvTreeListBox::GetEntry( const Point& rPos, sal_Bool bHit ) const
1480 {
1481     DBG_CHKTHIS(SvTreeListBox,0);
1482     SvLBoxEntry* pEntry = pImp->GetEntry( rPos );
1483     if( pEntry && bHit )
1484     {
1485         long nLine = pImp->GetEntryLine( pEntry );
1486         if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) )
1487             return 0;
1488     }
1489     return pEntry;
1490 }
1491 
1492 SvLBoxEntry* SvTreeListBox::GetCurEntry() const
1493 {
1494     DBG_CHKTHIS(SvTreeListBox,0);
1495     return pImp->GetCurEntry();
1496 }
1497 
1498 void SvTreeListBox::ImplInitStyle()
1499 {
1500     DBG_CHKTHIS(SvTreeListBox,0);
1501 
1502     const WinBits nWindowStyle = GetStyle();
1503 
1504     nTreeFlags |= TREEFLAG_RECALCTABS;
1505     if( nWindowStyle & WB_SORT )
1506     {
1507         GetModel()->SetSortMode( SortAscending );
1508         GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare));
1509     }
1510     else
1511     {
1512         GetModel()->SetSortMode( SortNone );
1513         GetModel()->SetCompareHdl( Link() );
1514     }
1515 #ifdef OS2
1516     nWindowStyle |= WB_VSCROLL;
1517 #endif
1518     pImp->SetStyle( nWindowStyle );
1519     pImp->Resize();
1520     Invalidate();
1521 }
1522 
1523 void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry )
1524 {
1525     DBG_CHKTHIS(SvTreeListBox,0);
1526     DBG_ASSERT(pEntry,"PaintEntry:No Entry");
1527     if( pEntry )
1528         pImp->PaintEntry( pEntry );
1529 }
1530 
1531 void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry )
1532 {
1533     DBG_CHKTHIS(SvTreeListBox,0);
1534     DBG_ASSERT(pEntry,"InvalidateEntry:No Entry");
1535     if( pEntry )
1536     {
1537         GetModel()->InvalidateEntry( pEntry );
1538     //  pImp->InvalidateEntry( pEntry );
1539     }
1540 }
1541 
1542 
1543 long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags)
1544 {
1545     return PaintEntry1(pEntry,nLine,nTabFlags);
1546 }
1547 
1548 #define SV_TAB_BORDER 8
1549 
1550 long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags,
1551     sal_Bool bHasClipRegion )
1552 {
1553     DBG_CHKTHIS(SvTreeListBox,0);
1554 
1555     Rectangle aRect; // multi purpose
1556 
1557     sal_Bool bHorSBar = pImp->HasHorScrollBar();
1558     PreparePaint( pEntry );
1559 
1560     // #97680# ------------------
1561     pImp->UpdateContextBmpWidthMax( pEntry );
1562 
1563     if( nTreeFlags & TREEFLAG_RECALCTABS )
1564         SetTabs();
1565 
1566     short nTempEntryHeight = GetEntryHeight();
1567     long nWidth = pImp->GetOutputSize().Width();
1568 
1569     // wurde innerhalb des PreparePaints die horizontale ScrollBar
1570     // angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden
1571     if( !bHorSBar && pImp->HasHorScrollBar() )
1572         SetClipRegion( Region(pImp->GetClipRegionRect()) );
1573 
1574     Point aEntryPos( GetMapMode().GetOrigin() );
1575     aEntryPos.X() *= -1; // Umrechnung Dokumentkoord.
1576     long nMaxRight = nWidth + aEntryPos.X() - 1;
1577 
1578     Color aBackupTextColor( GetTextColor() );
1579     Font aBackupFont( GetFont() );
1580     Color aBackupColor = GetFillColor();
1581 
1582     bool bCurFontIsSel = false;
1583     sal_Bool bInUse = pEntry->HasInUseEmphasis();
1584     // wenn eine ClipRegion von aussen gesetzt wird, dann
1585     // diese nicht zuruecksetzen
1586     const WinBits nWindowStyle = GetStyle();
1587     const sal_Bool bResetClipRegion = !bHasClipRegion;
1588     const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0;
1589     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
1590 
1591     Font aHighlightFont( GetFont() );
1592     const Color aHighlightTextColor( rSettings.GetHighlightTextColor() );
1593     aHighlightFont.SetColor( aHighlightTextColor );
1594 
1595     Size aRectSize( 0, nTempEntryHeight );
1596 
1597     if( !bHasClipRegion && nWindowStyle & WB_HSCROLL )
1598     {
1599         SetClipRegion( Region(pImp->GetClipRegionRect()) );
1600         bHasClipRegion = sal_True;
1601     }
1602 
1603     SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry );
1604 
1605     sal_uInt16 nTabCount = aTabs.Count();
1606     sal_uInt16 nItemCount = pEntry->ItemCount();
1607     sal_uInt16 nCurTab = 0;
1608     sal_uInt16 nCurItem = 0;
1609 
1610     while( nCurTab < nTabCount && nCurItem < nItemCount )
1611     {
1612         SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab );
1613         sal_uInt16 nNextTab = nCurTab + 1;
1614         SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
1615         SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0;
1616 
1617         sal_uInt16 nFlags = pTab->nFlags;
1618         Size aSize( pItem->GetSize( pViewDataEntry, nCurItem ));
1619         long nTabPos = GetTabPos( pEntry, pTab );
1620 
1621         long nNextTabPos;
1622         if( pNextTab )
1623             nNextTabPos = GetTabPos( pEntry, pNextTab );
1624         else
1625         {
1626             nNextTabPos = nMaxRight;
1627             if( nTabPos > nMaxRight )
1628                 nNextTabPos += 50;
1629         }
1630 
1631         long nX;
1632         if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT )
1633             //verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird
1634             nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos);
1635         else
1636             nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos);
1637 
1638         if( nFlags & nTabFlags )
1639         {
1640             if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight )
1641             {
1642                 SetClipRegion( Region(pImp->GetClipRegionRect()) );
1643                 bHasClipRegion = sal_True;
1644             }
1645             aEntryPos.X() = nX;
1646             aEntryPos.Y() = nLine;
1647 
1648             // Hintergrund-Muster & Farbe bestimmen
1649 
1650             Wallpaper aWallpaper = GetBackground();
1651 
1652             int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION;
1653             sal_uInt16 nItemType = pItem->IsA();
1654 
1655             if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() )
1656             {
1657                 Color aNewWallColor = rSettings.GetHighlightColor();
1658                 if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP )
1659                 {
1660                     // if the face color is bright then the deactive color is also bright
1661                     // -> so you can't see any deactive selection
1662                     if ( bHideSelection && !rSettings.GetFaceColor().IsBright() &&
1663                          aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() )
1664                         aNewWallColor = rSettings.GetDeactiveColor();
1665                     // set font color to highlight
1666                     if ( !bCurFontIsSel )
1667                     {
1668                         SetTextColor( aHighlightTextColor );
1669                         SetFont( aHighlightFont );
1670                         bCurFontIsSel = true;
1671                     }
1672                 }
1673                 aWallpaper.SetColor( aNewWallColor );
1674             }
1675             else  // keine Selektion
1676             {
1677                 if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP )
1678                     aWallpaper.SetColor( rSettings.GetFieldColor() );
1679                 else if( bCurFontIsSel )
1680                 {
1681                     bCurFontIsSel = false;
1682                     SetTextColor( aBackupTextColor );
1683                     SetFont( aBackupFont );
1684                 }
1685             }
1686 
1687             // Hintergrund zeichnen
1688             if( !(nTreeFlags & TREEFLAG_USESEL))
1689             {
1690                 // nur den Bereich zeichnen, den das Item einnimmt
1691                 aRectSize.Width() = aSize.Width();
1692                 aRect.SetPos( aEntryPos );
1693                 aRect.SetSize( aRectSize );
1694             }
1695             else
1696             {
1697                 // vom aktuellen bis zum naechsten Tab zeichnen
1698                 if( nCurTab != 0 )
1699                     aRect.Left() = nTabPos;
1700                 else
1701                     // beim nullten Tab immer ab Spalte 0 zeichnen
1702                     // (sonst Probleme bei Tabs mit Zentrierung)
1703                     aRect.Left() = 0;
1704                 aRect.Top() = nLine;
1705                 aRect.Bottom() = nLine + nTempEntryHeight - 1;
1706                 if( pNextTab )
1707                 {
1708                     long nRight;
1709                     nRight = GetTabPos(pEntry,pNextTab)-1;
1710                     if( nRight > nMaxRight )
1711                         nRight = nMaxRight;
1712                     aRect.Right() = nRight;
1713                 }
1714                 else
1715                     aRect.Right() = nMaxRight;
1716             }
1717             // bei anwenderdefinierter Selektion, die bei einer Tabposition
1718             // groesser 0 beginnt den Hintergrund des 0.ten Items nicht
1719             // fuellen, da sonst z.B. TablistBoxen mit Linien nicht
1720             // realisiert werden koennen.
1721             if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) )
1722             {
1723                 SetFillColor( aWallpaper.GetColor() );
1724                 // Bei kleinen hor. Resizes tritt dieser Fall auf
1725                 if( aRect.Left() < aRect.Right() )
1726                     DrawRect( aRect );
1727             }
1728             // Item zeichnen
1729             // vertikal zentrieren
1730             aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2;
1731             pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry );
1732 
1733             // Trennungslinie zwischen Tabs
1734             if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING &&
1735                 // nicht am rechten Fensterrand!
1736                 aRect.Right() < nMaxRight )
1737             {
1738                 aRect.Left() = aRect.Right() - SV_TAB_BORDER;
1739                 DrawRect( aRect );
1740             }
1741 
1742             SetFillColor( aBackupColor );
1743         }
1744         nCurItem++;
1745         nCurTab++;
1746     }
1747     if( pViewDataEntry->IsCursored() && !HasFocus() )
1748     {
1749         // Cursor-Emphasis
1750         SetFillColor();
1751         Color aOldLineColor = GetLineColor();
1752         SetLineColor( Color( COL_BLACK ) );
1753         aRect = GetFocusRect( pEntry, nLine );
1754         aRect.Top()++;
1755         aRect.Bottom()--;
1756         DrawRect( aRect );
1757         SetLineColor( aOldLineColor );
1758         SetFillColor( aBackupColor );
1759     }
1760 
1761     if( bCurFontIsSel )
1762     {
1763         SetTextColor( aBackupTextColor );
1764         SetFont( aBackupFont );
1765     }
1766 
1767     sal_uInt16 nFirstDynTabPos;
1768     SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos );
1769     long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab );
1770     nDynTabPos += pImp->nNodeBmpTabDistance;
1771     nDynTabPos += pImp->nNodeBmpWidth / 2;
1772     nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap
1773                      // nicht zu nah am naechsten Tab steht
1774 
1775     if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) &&
1776         (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab &&
1777         ( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) )
1778     {
1779         // ersten festen Tab suchen, und pruefen ob die Node-Bitmap
1780         // in ihn hineinragt
1781         sal_uInt16 nNextTab = nFirstDynTabPos;
1782         SvLBoxTab* pNextTab;
1783         do
1784         {
1785             nNextTab++;
1786             pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
1787         } while( pNextTab && pNextTab->IsDynamic() );
1788 
1789         if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) )
1790         {
1791             if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0)
1792             {
1793                 Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine );
1794                 aPos.X() += pImp->nNodeBmpTabDistance;
1795 
1796                 const Image* pImg = 0;
1797                 BmpColorMode eBitmapMode = BMP_COLOR_NORMAL;
1798                 if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
1799                     eBitmapMode = BMP_COLOR_HIGHCONTRAST;
1800 
1801                 if( IsExpanded(pEntry) )
1802                     pImg = &pImp->GetExpandedNodeBmp( eBitmapMode );
1803                 else
1804                 {
1805                     if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
1806                         (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
1807                         pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
1808                         pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode );
1809                     else
1810                         pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode );
1811                 }
1812                 aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2;
1813 
1814                 sal_uInt16 nStyle = 0;
1815                 if ( !IsEnabled() )
1816                     nStyle |= IMAGE_DRAW_DISABLE;
1817 
1818                 //native
1819                 sal_Bool bNativeOK = sal_False;
1820                 if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) )
1821                 {
1822                     ImplControlValue    aControlValue;
1823                     Rectangle           aCtrlRegion( aPos,  pImg->GetSizePixel() );
1824                     ControlState        nState = 0;
1825 
1826                     if ( IsEnabled() )  nState |= CTRL_STATE_ENABLED;
1827 
1828                     if ( IsExpanded(pEntry) )
1829                         aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node
1830                     else
1831                     {
1832                         if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
1833                             (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
1834                             pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
1835                             aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know
1836                         else
1837                             aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node
1838                     }
1839 
1840                     bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL,
1841                                             aCtrlRegion, nState, aControlValue, rtl::OUString() );
1842                 }
1843 
1844                 if( !bNativeOK) {
1845                 //non native
1846                     DrawImage( aPos, *pImg ,nStyle);
1847                 }
1848             }
1849         }
1850     }
1851 
1852 
1853     if( bHasClipRegion && bResetClipRegion )
1854         SetClipRegion();
1855     return 0; // nRowLen;
1856 }
1857 
1858 void SvTreeListBox::PreparePaint( SvLBoxEntry* )
1859 {
1860 }
1861 
1862 Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine )
1863 {
1864     DBG_CHKTHIS(SvTreeListBox,0);
1865     Size aSize;
1866     Rectangle aRect;
1867     aRect.Top() = nLine;
1868     aSize.Height() = GetEntryHeight();
1869 
1870     long nRealWidth = pImp->GetOutputSize().Width();
1871     nRealWidth -= GetMapMode().GetOrigin().X();
1872 
1873     sal_uInt16 nCurTab;
1874     SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab );
1875     long nTabPos = 0;
1876     if( pTab )
1877         nTabPos = GetTabPos( pEntry, pTab );
1878     long nNextTabPos;
1879     if( pTab && nCurTab < aTabs.Count() - 1 )
1880     {
1881         SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 );
1882         nNextTabPos = GetTabPos( pEntry, pNextTab );
1883     }
1884     else
1885     {
1886         nNextTabPos = nRealWidth;
1887         if( nTabPos > nRealWidth )
1888             nNextTabPos += 50;
1889     }
1890 
1891     sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0;
1892     if( !bUserSelection )
1893     {
1894         if( pTab && nCurTab < pEntry->ItemCount() )
1895         {
1896             SvLBoxItem* pItem = pEntry->GetItem( nCurTab );
1897             aSize.Width() = pItem->GetSize( this, pEntry ).Width();
1898             if( !aSize.Width() )
1899                 aSize.Width() = 15;
1900             long nX = nTabPos; //GetTabPos( pEntry, pTab );
1901             // Ausrichtung
1902             nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos );
1903             aRect.Left() = nX;
1904             // damit erster & letzter Buchstabe nicht angeknabbert werden
1905             aRect.SetSize( aSize );
1906             if( aRect.Left() > 0 )
1907                 aRect.Left()--;
1908             aRect.Right()++;
1909         }
1910     }
1911     else
1912     {
1913         // wenn erster SelTab != 0, dann muessen wir auch rechnen
1914         if( nFocusWidth == -1 || nFirstSelTab )
1915         {
1916             sal_uInt16 nLastTab;
1917             SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab);
1918             nLastTab++;
1919             if( nLastTab < aTabs.Count() ) // gibts noch einen ?
1920                 pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab );
1921             else
1922                 pLastTab = 0;  // ueber gesamte Breite selektieren
1923             aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff;
1924             nFocusWidth = (short)aSize.Width();
1925             if( pTab )
1926                 nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos();
1927         }
1928         else
1929         {
1930             aSize.Width() = nFocusWidth;
1931             if( pTab )
1932             {
1933                 if( nCurTab )
1934                     aSize.Width() += nTabPos;
1935                 else
1936                     aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links
1937             }
1938         }
1939         // wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen
1940         if( nCurTab != 0 )
1941         {
1942             aRect.Left() = nTabPos;
1943             aSize.Width() -= nTabPos;
1944         }
1945         aRect.SetSize( aSize );
1946     }
1947     // rechten Rand anpassen wg. Clipping
1948     if( aRect.Right() >= nRealWidth )
1949     {
1950         aRect.Right() = nRealWidth-1;
1951         nFocusWidth = (short)aRect.GetWidth();
1952     }
1953     return aRect;
1954 }
1955 
1956 
1957 long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab)
1958 {
1959     DBG_CHKTHIS(SvTreeListBox,0);
1960     DBG_ASSERT(pTab,"No Tab");
1961     long nPos = pTab->GetPos();
1962     if( pTab->IsDynamic() )
1963     {
1964         sal_uInt16 nDepth = pModel->GetDepth( pEntry );
1965         nDepth = nDepth * (sal_uInt16)nIndent;
1966         nPos += (long)nDepth;
1967     }
1968     return nPos;
1969 }
1970 
1971 SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX,
1972     SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth )
1973 {
1974     DBG_CHKTHIS(SvTreeListBox,0);
1975     SvLBoxItem* pItemClicked = 0;
1976     sal_uInt16 nTabCount = aTabs.Count();
1977     sal_uInt16 nItemCount = pEntry->ItemCount();
1978     SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
1979     SvLBoxItem* pItem = pEntry->GetItem(0);
1980     sal_uInt16 nNextItem = 1;
1981     nX -= GetMapMode().GetOrigin().X();
1982     long nRealWidth = pImp->GetOutputSize().Width();
1983     nRealWidth -= GetMapMode().GetOrigin().X();
1984 
1985     while( 1 )
1986     {
1987         SvLBoxTab* pNextTab=nNextItem<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0;
1988         long nStart = GetTabPos( pEntry, pTab );
1989 
1990         long nNextTabPos;
1991         if( pNextTab )
1992             nNextTabPos = GetTabPos( pEntry, pNextTab );
1993         else
1994         {
1995             nNextTabPos = nRealWidth;
1996             if( nStart > nRealWidth )
1997                 nNextTabPos += 50;
1998         }
1999 
2000         Size aItemSize( pItem->GetSize(this, pEntry));
2001         nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart );
2002         long nLen = aItemSize.Width();
2003         if( pNextTab )
2004         {
2005             long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart;
2006             if( nTabWidth < nLen )
2007                 nLen = nTabWidth;
2008         }
2009 
2010         if( !nLen )
2011             nLen = nEmptyWidth;
2012 
2013         if( nX >= nStart && nX < (nStart+nLen ) )
2014         {
2015             pItemClicked = pItem;
2016             if( ppTab )
2017             {
2018                 *ppTab = pTab;
2019                 break;
2020             }
2021         }
2022         if( nNextItem >= nItemCount || nNextItem >= nTabCount)
2023             break;
2024         pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem );
2025         pItem = pEntry->GetItem( nNextItem );
2026         nNextItem++;
2027     }
2028     return pItemClicked;
2029 }
2030 
2031 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab)
2032 {
2033     return GetItem_Impl( pEntry, nX, ppTab, 0 );
2034 }
2035 
2036 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX )
2037 {
2038     DBG_CHKTHIS(SvTreeListBox,0);
2039     SvLBoxTab* pDummyTab;
2040     return GetItem_Impl( pEntry, nX, &pDummyTab, 0 );
2041 }
2042 
2043 SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry )
2044 {
2045     DBG_CHKTHIS(SvTreeListBox,0);
2046 
2047     SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
2048     SvLBoxItem* pItem = pEntry->GetItem(0);
2049     sal_uInt16 nTabCount = aTabs.Count();
2050 
2051     sal_uInt16 nNext = 1;
2052     while ( !pTab->IsDynamic() && nNext < nTabCount )
2053     {
2054         pItem = pEntry->GetItem( nNext );
2055         pTab = (SvLBoxTab*)aTabs.GetObject( nNext );
2056         nNext++;
2057     }
2058     return pItem;
2059 }
2060 
2061 void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData )
2062 {
2063     DBG_CHKTHIS(SvTreeListBox,0);
2064     nFocusWidth = -1;
2065     SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags );
2066     pTab->SetUserData( pUserData );
2067     aTabs.Insert( pTab, aTabs.Count() );
2068     if( nTreeFlags & TREEFLAG_USESEL )
2069     {
2070         sal_uInt16 nPos = aTabs.Count() - 1;
2071         if( nPos >= nFirstSelTab && nPos <= nLastSelTab )
2072             pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION;
2073         else
2074             // String-Items werden normalerweise immer selektiert
2075             // deshalb explizit ausschalten
2076             pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION;
2077     }
2078 }
2079 
2080 
2081 
2082 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const
2083 {
2084     DBG_CHKTHIS(SvTreeListBox,0);
2085     sal_uInt16 nCurTab = 0;
2086     sal_uInt16 nTabCount = aTabs.Count();
2087     while( nCurTab < nTabCount )
2088     {
2089         SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab);
2090         if( pTab->nFlags & SV_LBOXTAB_DYNAMIC )
2091         {
2092             rPos = nCurTab;
2093             return pTab;
2094         }
2095         nCurTab++;
2096     }
2097     return 0;
2098 }
2099 
2100 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const
2101 {
2102     sal_uInt16 nDummy;
2103     return GetFirstDynamicTab( nDummy );
2104 }
2105 
2106 SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const
2107 {
2108     DBG_CHKTHIS(SvTreeListBox,0);
2109     sal_uInt16 nPos = pEntry->GetPos( pItem );
2110     return (SvLBoxTab*)aTabs.GetObject( nPos );
2111 }
2112 
2113 void SvTreeListBox::ClearTabList()
2114 {
2115     DBG_CHKTHIS(SvTreeListBox,0);
2116     sal_uInt16 nTabCount = aTabs.Count();
2117     while( nTabCount )
2118     {
2119         nTabCount--;
2120         SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount );
2121         delete pDelTab;
2122     }
2123     aTabs.Remove(0,aTabs.Count());
2124 }
2125 
2126 
2127 Size SvTreeListBox::GetOutputSizePixel() const
2128 {
2129     DBG_CHKTHIS(SvTreeListBox,0);
2130     Size aSize = pImp->GetOutputSize();
2131     return aSize;
2132 }
2133 
2134 void SvTreeListBox::NotifyBeginScroll()
2135 {
2136     DBG_CHKTHIS(SvTreeListBox,0);
2137 }
2138 
2139 void SvTreeListBox::NotifyEndScroll()
2140 {
2141     DBG_CHKTHIS(SvTreeListBox,0);
2142 }
2143 
2144 void SvTreeListBox::NotifyScrolling( long )
2145 {
2146     DBG_CHKTHIS(SvTreeListBox,0);
2147 }
2148 
2149 void SvTreeListBox::NotifyScrolled()
2150 {
2151     DBG_CHKTHIS(SvTreeListBox,0);
2152     aScrolledHdl.Call( this );
2153 }
2154 
2155 void SvTreeListBox::NotifyInvalidating()
2156 {
2157     DBG_CHKTHIS(SvTreeListBox,0);
2158 }
2159 
2160 void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags )
2161 {
2162     DBG_CHKTHIS(SvTreeListBox,0);
2163     if( nFocusWidth == -1 )
2164         // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
2165         pImp->RecalcFocusRect();
2166     NotifyInvalidating();
2167     SvLBox::Invalidate( nInvalidateFlags );
2168     pImp->Invalidate();
2169 }
2170 
2171 void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags )
2172 {
2173     DBG_CHKTHIS(SvTreeListBox,0);
2174     if( nFocusWidth == -1 )
2175         // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
2176         pImp->RecalcFocusRect();
2177     NotifyInvalidating();
2178     SvLBox::Invalidate( rRect, nInvalidateFlags );
2179 }
2180 
2181 
2182 void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd)
2183 {
2184     DBG_CHKTHIS(SvTreeListBox,0);
2185 
2186     sal_uInt16 nTemp;
2187     nTreeFlags |= TREEFLAG_USESEL;
2188     if( nStart > nEnd )
2189     {
2190         nTemp = nStart;
2191         nStart = nEnd;
2192         nEnd = nTemp;
2193     }
2194     // alle Tabs markieren, die im Bereich liegen
2195     nTreeFlags |= TREEFLAG_RECALCTABS;
2196     nFirstSelTab = nStart;
2197     nLastSelTab = nEnd;
2198     pImp->RecalcFocusRect();
2199 }
2200 
2201 void SvTreeListBox::RemoveHighlightRange()
2202 {
2203     DBG_CHKTHIS(SvTreeListBox,0);
2204     nTreeFlags &= (~TREEFLAG_USESEL);
2205     if( IsUpdateMode() )
2206         Invalidate();
2207 }
2208 
2209 sal_uLong SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
2210 {
2211     return LIST_APPEND;
2212 }
2213 
2214 sal_uLong SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
2215 {
2216     DBG_CHKTHIS(SvTreeListBox,0);
2217     return LIST_APPEND;
2218 }
2219 
2220 Region SvTreeListBox::GetDragRegion() const
2221 {
2222     DBG_CHKTHIS(SvTreeListBox,0);
2223     Rectangle aRect;
2224     SvLBoxEntry* pEntry = GetCurEntry();
2225     if( pEntry )
2226     {
2227         Point aPos = GetEntryPosition( pEntry );
2228         aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() );
2229     }
2230     Region aRegion( aRect );
2231     return aRegion;
2232 }
2233 
2234 
2235 void SvTreeListBox::Command( const CommandEvent& rCEvt )
2236 {
2237     DBG_CHKTHIS(SvTreeListBox,0);
2238     // FIXME gnumake2 resync to DEV300_m84
2239     pImp->Command( rCEvt );
2240 }
2241 
2242 
2243 void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent )
2244 {
2245     DBG_CHKTHIS(SvTreeListBox,0);
2246     DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent");
2247     SvLBoxEntry* pNewParent = GetParent( pParent );
2248     if( pParent->HasChilds())
2249     {
2250         SvLBoxEntry* pChild = FirstChild( pParent );
2251         while( pChild )
2252         {
2253             pModel->Move( pChild, pNewParent, LIST_APPEND );
2254             pChild = FirstChild( pParent );
2255         }
2256     }
2257     pModel->Remove( pParent );
2258 }
2259 
2260 SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos )
2261 {
2262     sal_uInt16 nTabCount = aTabs.Count();
2263     for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ )
2264     {
2265         SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos );
2266         if( (pTab->nFlags & nFlagMask) )
2267         {
2268             rPos = nPos;
2269             return pTab;
2270         }
2271     }
2272     rPos = 0xffff;
2273     return 0;
2274 }
2275 
2276 SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos )
2277 {
2278     short nTabCount = (short)aTabs.Count();
2279     if( nTabCount )
2280     {
2281         for( short nPos = nTabCount-1; nPos >= 0; nPos-- )
2282         {
2283             SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (sal_uInt16)nPos );
2284             if( (pTab->nFlags & nFlagMask) )
2285             {
2286                 rTabPos = (sal_uInt16)nPos;
2287                 return pTab;
2288             }
2289         }
2290     }
2291     rTabPos = 0xffff;
2292     return 0;
2293 }
2294 
2295 void SvTreeListBox::SetAddMode( sal_Bool bAdd )
2296 {
2297     pImp->SetAddMode( bAdd );
2298 }
2299 
2300 sal_Bool SvTreeListBox::IsAddMode() const
2301 {
2302     return pImp->IsAddMode();
2303 }
2304 
2305 void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt )
2306 {
2307     if( !pImp->RequestHelp( rHEvt ) )
2308         SvLBox::RequestHelp( rHEvt );
2309 }
2310 
2311 void SvTreeListBox::CursorMoved( SvLBoxEntry* )
2312 {
2313 }
2314 
2315 IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData )
2316 {
2317     SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft );
2318     SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight );
2319     String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
2320     String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
2321     // #102891# ----------------
2322     pImp->UpdateIntlWrapper();
2323     return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight );
2324 }
2325 
2326 void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1,
2327                         SvListEntry* pEntry2, sal_uLong nPos )
2328 {
2329     if( nActionId == LISTACTION_CLEARING )
2330         CancelTextEditing();
2331 
2332     SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos );
2333     switch( nActionId )
2334     {
2335         case LISTACTION_INSERTED:
2336         {
2337             SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) );
2338             ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" );
2339             SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
2340             if ( !pBmpItem )
2341                 break;
2342             const Image& rBitmap1( pBmpItem->GetBitmap1() );
2343             const Image& rBitmap2( pBmpItem->GetBitmap2() );
2344             short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) );
2345             nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth );
2346             if( nMaxWidth > nContextBmpWidthMax )
2347             {
2348                 nContextBmpWidthMax = nMaxWidth;
2349                 SetTabs();
2350             }
2351         }
2352         break;
2353 
2354         case LISTACTION_RESORTING:
2355             SetUpdateMode( sal_False );
2356             break;
2357 
2358         case LISTACTION_RESORTED:
2359             // nach Sortierung den ersten Eintrag anzeigen, dabei die
2360             // Selektion erhalten.
2361             MakeVisible( (SvLBoxEntry*)pModel->First(), sal_True );
2362             SetUpdateMode( sal_True );
2363             break;
2364 
2365         case LISTACTION_CLEARED:
2366             if( IsUpdateMode() )
2367                 Update();
2368             break;
2369     }
2370 }
2371 
2372 // bei Aenderungen SetTabs beruecksichtigen
2373 long SvTreeListBox::GetTextOffset() const
2374 {
2375     DBG_CHKTHIS(SvTreeListBox,0);
2376     const WinBits nWindowStyle = GetStyle();
2377     sal_Bool bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0;
2378     sal_Bool bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT |
2379                                               WB_HASBUTTONSATROOT))!=0;
2380     long nStartPos = TAB_STARTPOS;
2381     long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
2382 
2383     long nCheckWidth = 0;
2384     if( nTreeFlags & TREEFLAG_CHKBTN )
2385         nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width();
2386     long nCheckWidthDIV2 = nCheckWidth / 2;
2387 
2388     long nContextWidth = nContextBmpWidthMax;
2389     long nContextWidthDIV2 = nContextWidth / 2;
2390 
2391     int nCase = NO_BUTTONS;
2392     if( !(nTreeFlags & TREEFLAG_CHKBTN) )
2393     {
2394         if( bHasButtons )
2395             nCase = NODE_BUTTONS;
2396     }
2397     else
2398     {
2399         if( bHasButtons )
2400             nCase = NODE_AND_CHECK_BUTTONS;
2401          else
2402             nCase = CHECK_BUTTONS;
2403     }
2404 
2405     switch( nCase )
2406     {
2407         case NO_BUTTONS :
2408             nStartPos += nContextWidthDIV2;  // wg. Zentrierung
2409             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2410             if( nContextBmpWidthMax )
2411                 nStartPos += 5; // Abstand Context-Bmp - Text
2412             break;
2413 
2414         case NODE_BUTTONS :
2415             if( bHasButtonsAtRoot )
2416                 nStartPos += ( nIndent + (nNodeWidthPixel/2) );
2417             else
2418                 nStartPos += nContextWidthDIV2;
2419             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2420             if( nContextBmpWidthMax )
2421                 nStartPos += 5; // Abstand Context-Bmp - Text
2422             break;
2423 
2424         case NODE_AND_CHECK_BUTTONS :
2425             if( bHasButtonsAtRoot )
2426                 nStartPos += ( nIndent + nNodeWidthPixel );
2427             else
2428                 nStartPos += nCheckWidthDIV2;
2429             nStartPos += nCheckWidthDIV2;  // rechter Rand des CheckButtons
2430             nStartPos += 3;  // Abstand CheckButton Context-Bmp
2431             nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
2432             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2433             // Abstand setzen nur wenn Bitmaps da
2434             if( nContextBmpWidthMax )
2435                 nStartPos += 5; // Abstand Context-Bmp - Text
2436             break;
2437 
2438         case CHECK_BUTTONS :
2439             nStartPos += nCheckWidthDIV2;
2440             nStartPos += nCheckWidthDIV2;  // rechter Rand CheckButton
2441             nStartPos += 3;  // Abstand CheckButton Context-Bmp
2442             nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
2443             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2444             if( nContextBmpWidthMax )
2445                 nStartPos += 5; // Abstand Context-Bmp - Text
2446             break;
2447     }
2448     return nStartPos;
2449 }
2450 
2451 void SvTreeListBox::EndSelection()
2452 {
2453     pImp->EndSelection();
2454 }
2455 
2456 sal_Bool SvTreeListBox::IsNodeButton( const Point& rPos ) const
2457 {
2458     SvLBoxEntry* pEntry = GetEntry( rPos );
2459     if( pEntry )
2460         return pImp->IsNodeButton( rPos, pEntry );
2461     return sal_False;
2462 }
2463 
2464 void SvTreeListBox::RepaintScrollBars() const
2465 {
2466     ((SvTreeListBox*)this)->pImp->RepaintScrollBars();
2467 }
2468 
2469 ScrollBar *SvTreeListBox::GetVScroll()
2470 {
2471     return &((SvTreeListBox*)this)->pImp->aVerSBar;
2472 }
2473 
2474 ScrollBar *SvTreeListBox::GetHScroll()
2475 {
2476     return &((SvTreeListBox*)this)->pImp->aHorSBar;
2477 }
2478 
2479 void SvTreeListBox::EnableAsyncDrag( sal_Bool b )
2480 {
2481     pImp->EnableAsyncDrag( b );
2482 }
2483 
2484 SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const
2485 {
2486     Point aPos;
2487     return GetEntry( aPos );
2488 }
2489 
2490 SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const
2491 {
2492     SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry );
2493     if( pNext )
2494     {
2495         Point aPos( GetEntryPosition(pNext) );
2496         const Size& rSize = pImp->GetOutputSize();
2497         if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
2498             return 0;
2499     }
2500     return pNext;
2501 }
2502 
2503 void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry )
2504 {
2505     pImp->ShowFocusRect( pEntry );
2506 }
2507 
2508 void SvTreeListBox::SetTabBar( TabBar* pTabBar )
2509 {
2510     pImp->SetTabBar( pTabBar );
2511 }
2512 
2513 void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt )
2514 {
2515     if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
2516     {
2517         nEntryHeight = 0;   // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height
2518                             //  forces complete recalc of heights!
2519         InitSettings( sal_True, sal_True, sal_True );
2520         Invalidate();
2521     }
2522     else
2523         Control::DataChanged( rDCEvt );
2524 }
2525 
2526 void SvTreeListBox::StateChanged( StateChangedType i_nStateChange )
2527 {
2528     SvLBox::StateChanged( i_nStateChange );
2529     if ( i_nStateChange == STATE_CHANGE_STYLE )
2530         ImplInitStyle();
2531 }
2532 
2533 void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground)
2534 {
2535     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2536     if( bFont )
2537     {
2538         Font aFont;
2539         aFont = rStyleSettings.GetFieldFont();
2540         aFont.SetColor( rStyleSettings.GetWindowTextColor() );
2541         SetPointFont( aFont );
2542         AdjustEntryHeight( aFont );
2543         RecalcViewData();
2544     }
2545 
2546     if( bForeground || bFont )
2547     {
2548         SetTextColor( rStyleSettings.GetFieldTextColor() );
2549         SetTextFillColor();
2550     }
2551 
2552     if( bBackground )
2553         SetBackground( rStyleSettings.GetFieldColor() );
2554 
2555     // always try to re-create default-SvLBoxButtonData
2556     if( pCheckButtonData && pCheckButtonData->HasDefaultImages() )
2557         pCheckButtonData->SetDefaultImages( this );
2558 }
2559 
2560 sal_Bool SvTreeListBox::IsCellFocusEnabled() const
2561 {
2562     return pImp->IsCellFocusEnabled();
2563 }
2564 
2565 bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
2566 {
2567     return pImp->SetCurrentTabPos( _nNewPos );
2568 }
2569 
2570 sal_uInt16 SvTreeListBox::GetCurrentTabPos() const
2571 {
2572     return pImp->GetCurrentTabPos();
2573 }
2574 
2575 void SvTreeListBox::InitStartEntry()
2576 {
2577     if( !pImp->pStartEntry )
2578         pImp->pStartEntry = GetModel()->First();
2579 }
2580 
2581 void SvTreeListBox::CancelPendingEdit()
2582 {
2583     if( pImp )
2584         pImp->CancelPendingEdit();
2585 }
2586 
2587 PopupMenu* SvTreeListBox::CreateContextMenu( void )
2588 {
2589     return NULL;
2590 }
2591 
2592 void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 )
2593 {
2594     DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" );
2595 }
2596 
2597 void SvTreeListBox::EnableContextMenuHandling( void )
2598 {
2599     DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
2600 
2601     pImp->bContextMenuHandling = sal_True;
2602 }
2603 
2604 void SvTreeListBox::EnableContextMenuHandling( sal_Bool b )
2605 {
2606     DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
2607 
2608     pImp->bContextMenuHandling = b;
2609 }
2610 
2611 sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const
2612 {
2613     DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" );
2614 
2615     return pImp->bContextMenuHandling;
2616 }
2617 
2618 void SvTreeListBox::EnableList( bool _bEnable )
2619 {
2620     // call base class method
2621     Window::Enable( _bEnable != false );
2622     // then paint immediately
2623     Paint( Rectangle( Point(), GetSizePixel() ) );
2624 }
2625 
2626 ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible()
2627 {
2628     Window* pParent = GetAccessibleParentWindow();
2629     DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" );
2630 
2631     ::com::sun::star::uno::Reference< XAccessible > xAccessible;
2632     if ( pParent )
2633     {
2634         ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
2635         if ( xAccParent.is() )
2636         {
2637             // need to be done here to get the vclxwindow later on in the accessbile
2638             ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface());
2639             xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent );
2640         }
2641     }
2642     return xAccessible;
2643 }
2644 
2645 void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const
2646 {
2647     DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" );
2648 
2649     if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() )
2650     {
2651         rStateSet.AddState( AccessibleStateType::EXPANDABLE );
2652         if ( IsExpanded( pEntry ) )
2653             rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED );
2654     }
2655 
2656     if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED )
2657         rStateSet.AddState( AccessibleStateType::CHECKED );
2658     if ( IsEntryVisible( pEntry ) )
2659         rStateSet.AddState( AccessibleStateType::VISIBLE );
2660     if ( IsSelected( pEntry ) )
2661         rStateSet.AddState( AccessibleStateType::SELECTED );
2662 }
2663 
2664 Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry )
2665 {
2666     Point aPos = GetEntryPosition( pEntry );
2667     Rectangle aRect = GetFocusRect( pEntry, aPos.Y() );
2668     return aRect;
2669 }
2670 
2671 void SvTreeListBox::EnableCellFocus()
2672 {
2673     pImp->EnableCellFocus();
2674 }
2675 
2676 void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData)
2677 {
2678     CallEventListeners(nEvent, pData);
2679 }
2680 
2681 void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const
2682 {
2683       SvLBox::FillAccessibleStateSet( rStateSet );
2684 }
2685