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