xref: /trunk/main/svtools/source/contnr/svtreebx.cxx (revision 1c78a5d6c0093dece4c096ba53051800fbad6e33)
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 #ifdef OS2
1512     nWindowStyle |= WB_VSCROLL;
1513 #endif
1514     pImp->SetStyle( nWindowStyle );
1515     pImp->Resize();
1516     Invalidate();
1517 }
1518 
1519 void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry )
1520 {
1521     DBG_CHKTHIS(SvTreeListBox,0);
1522     DBG_ASSERT(pEntry,"PaintEntry:No Entry");
1523     if( pEntry )
1524         pImp->PaintEntry( pEntry );
1525 }
1526 
1527 void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry )
1528 {
1529     DBG_CHKTHIS(SvTreeListBox,0);
1530     DBG_ASSERT(pEntry,"InvalidateEntry:No Entry");
1531     if( pEntry )
1532     {
1533         GetModel()->InvalidateEntry( pEntry );
1534     //  pImp->InvalidateEntry( pEntry );
1535     }
1536 }
1537 
1538 
1539 long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags)
1540 {
1541     return PaintEntry1(pEntry,nLine,nTabFlags);
1542 }
1543 
1544 #define SV_TAB_BORDER 8
1545 
1546 long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags,
1547     sal_Bool bHasClipRegion )
1548 {
1549     DBG_CHKTHIS(SvTreeListBox,0);
1550 
1551     Rectangle aRect; // multi purpose
1552 
1553     sal_Bool bHorSBar = pImp->HasHorScrollBar();
1554     PreparePaint( pEntry );
1555 
1556     // #97680# ------------------
1557     pImp->UpdateContextBmpWidthMax( pEntry );
1558 
1559     if( nTreeFlags & TREEFLAG_RECALCTABS )
1560         SetTabs();
1561 
1562     short nTempEntryHeight = GetEntryHeight();
1563     long nWidth = pImp->GetOutputSize().Width();
1564 
1565     // wurde innerhalb des PreparePaints die horizontale ScrollBar
1566     // angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden
1567     if( !bHorSBar && pImp->HasHorScrollBar() )
1568         SetClipRegion( Region(pImp->GetClipRegionRect()) );
1569 
1570     Point aEntryPos( GetMapMode().GetOrigin() );
1571     aEntryPos.X() *= -1; // Umrechnung Dokumentkoord.
1572     long nMaxRight = nWidth + aEntryPos.X() - 1;
1573 
1574     Color aBackupTextColor( GetTextColor() );
1575     Font aBackupFont( GetFont() );
1576     Color aBackupColor = GetFillColor();
1577 
1578     bool bCurFontIsSel = false;
1579     sal_Bool bInUse = pEntry->HasInUseEmphasis();
1580     // wenn eine ClipRegion von aussen gesetzt wird, dann
1581     // diese nicht zuruecksetzen
1582     const WinBits nWindowStyle = GetStyle();
1583     const sal_Bool bResetClipRegion = !bHasClipRegion;
1584     const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0;
1585     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
1586 
1587     Font aHighlightFont( GetFont() );
1588     const Color aHighlightTextColor( rSettings.GetHighlightTextColor() );
1589     aHighlightFont.SetColor( aHighlightTextColor );
1590 
1591     Size aRectSize( 0, nTempEntryHeight );
1592 
1593     if( !bHasClipRegion && nWindowStyle & WB_HSCROLL )
1594     {
1595         SetClipRegion( Region(pImp->GetClipRegionRect()) );
1596         bHasClipRegion = sal_True;
1597     }
1598 
1599     SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry );
1600 
1601     sal_uInt16 nTabCount = aTabs.Count();
1602     sal_uInt16 nItemCount = pEntry->ItemCount();
1603     sal_uInt16 nCurTab = 0;
1604     sal_uInt16 nCurItem = 0;
1605 
1606     while( nCurTab < nTabCount && nCurItem < nItemCount )
1607     {
1608         SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab );
1609         sal_uInt16 nNextTab = nCurTab + 1;
1610         SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
1611         SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0;
1612 
1613         sal_uInt16 nFlags = pTab->nFlags;
1614         Size aSize( pItem->GetSize( pViewDataEntry, nCurItem ));
1615         long nTabPos = GetTabPos( pEntry, pTab );
1616 
1617         long nNextTabPos;
1618         if( pNextTab )
1619             nNextTabPos = GetTabPos( pEntry, pNextTab );
1620         else
1621         {
1622             nNextTabPos = nMaxRight;
1623             if( nTabPos > nMaxRight )
1624                 nNextTabPos += 50;
1625         }
1626 
1627         long nX;
1628         if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT )
1629             //verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird
1630             nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos);
1631         else
1632             nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos);
1633 
1634         if( nFlags & nTabFlags )
1635         {
1636             if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight )
1637             {
1638                 SetClipRegion( Region(pImp->GetClipRegionRect()) );
1639                 bHasClipRegion = sal_True;
1640             }
1641             aEntryPos.X() = nX;
1642             aEntryPos.Y() = nLine;
1643 
1644             // Hintergrund-Muster & Farbe bestimmen
1645 
1646             Wallpaper aWallpaper = GetBackground();
1647 
1648             int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION;
1649             sal_uInt16 nItemType = pItem->IsA();
1650 
1651             if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() )
1652             {
1653                 Color aNewWallColor = rSettings.GetHighlightColor();
1654                 if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP )
1655                 {
1656                     // if the face color is bright then the deactive color is also bright
1657                     // -> so you can't see any deactive selection
1658                     if ( bHideSelection && !rSettings.GetFaceColor().IsBright() &&
1659                          aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() )
1660                         aNewWallColor = rSettings.GetDeactiveColor();
1661                     // set font color to highlight
1662                     if ( !bCurFontIsSel )
1663                     {
1664                         SetTextColor( aHighlightTextColor );
1665                         SetFont( aHighlightFont );
1666                         bCurFontIsSel = true;
1667                     }
1668                 }
1669                 aWallpaper.SetColor( aNewWallColor );
1670             }
1671             else  // keine Selektion
1672             {
1673                 if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP )
1674                     aWallpaper.SetColor( rSettings.GetFieldColor() );
1675                 else if( bCurFontIsSel )
1676                 {
1677                     bCurFontIsSel = false;
1678                     SetTextColor( aBackupTextColor );
1679                     SetFont( aBackupFont );
1680                 }
1681             }
1682 
1683             // Hintergrund zeichnen
1684             if( !(nTreeFlags & TREEFLAG_USESEL))
1685             {
1686                 // nur den Bereich zeichnen, den das Item einnimmt
1687                 aRectSize.Width() = aSize.Width();
1688                 aRect.SetPos( aEntryPos );
1689                 aRect.SetSize( aRectSize );
1690             }
1691             else
1692             {
1693                 // vom aktuellen bis zum naechsten Tab zeichnen
1694                 if( nCurTab != 0 )
1695                     aRect.Left() = nTabPos;
1696                 else
1697                     // beim nullten Tab immer ab Spalte 0 zeichnen
1698                     // (sonst Probleme bei Tabs mit Zentrierung)
1699                     aRect.Left() = 0;
1700                 aRect.Top() = nLine;
1701                 aRect.Bottom() = nLine + nTempEntryHeight - 1;
1702                 if( pNextTab )
1703                 {
1704                     long nRight;
1705                     nRight = GetTabPos(pEntry,pNextTab)-1;
1706                     if( nRight > nMaxRight )
1707                         nRight = nMaxRight;
1708                     aRect.Right() = nRight;
1709                 }
1710                 else
1711                     aRect.Right() = nMaxRight;
1712             }
1713             // bei anwenderdefinierter Selektion, die bei einer Tabposition
1714             // groesser 0 beginnt den Hintergrund des 0.ten Items nicht
1715             // fuellen, da sonst z.B. TablistBoxen mit Linien nicht
1716             // realisiert werden koennen.
1717             if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) )
1718             {
1719                 SetFillColor( aWallpaper.GetColor() );
1720                 // Bei kleinen hor. Resizes tritt dieser Fall auf
1721                 if( aRect.Left() < aRect.Right() )
1722                     DrawRect( aRect );
1723             }
1724             // Item zeichnen
1725             // vertikal zentrieren
1726             aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2;
1727             pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry );
1728 
1729             // Trennungslinie zwischen Tabs
1730             if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING &&
1731                 // nicht am rechten Fensterrand!
1732                 aRect.Right() < nMaxRight )
1733             {
1734                 aRect.Left() = aRect.Right() - SV_TAB_BORDER;
1735                 DrawRect( aRect );
1736             }
1737 
1738             SetFillColor( aBackupColor );
1739         }
1740         nCurItem++;
1741         nCurTab++;
1742     }
1743     if( pViewDataEntry->IsCursored() && !HasFocus() )
1744     {
1745         // Cursor-Emphasis
1746         SetFillColor();
1747         Color aOldLineColor = GetLineColor();
1748         SetLineColor( Color( COL_BLACK ) );
1749         aRect = GetFocusRect( pEntry, nLine );
1750         aRect.Top()++;
1751         aRect.Bottom()--;
1752         DrawRect( aRect );
1753         SetLineColor( aOldLineColor );
1754         SetFillColor( aBackupColor );
1755     }
1756 
1757     if( bCurFontIsSel )
1758     {
1759         SetTextColor( aBackupTextColor );
1760         SetFont( aBackupFont );
1761     }
1762 
1763     sal_uInt16 nFirstDynTabPos;
1764     SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos );
1765     long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab );
1766     nDynTabPos += pImp->nNodeBmpTabDistance;
1767     nDynTabPos += pImp->nNodeBmpWidth / 2;
1768     nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap
1769                      // nicht zu nah am naechsten Tab steht
1770 
1771     if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) &&
1772         (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab &&
1773         ( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) )
1774     {
1775         // ersten festen Tab suchen, und pruefen ob die Node-Bitmap
1776         // in ihn hineinragt
1777         sal_uInt16 nNextTab = nFirstDynTabPos;
1778         SvLBoxTab* pNextTab;
1779         do
1780         {
1781             nNextTab++;
1782             pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
1783         } while( pNextTab && pNextTab->IsDynamic() );
1784 
1785         if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) )
1786         {
1787             if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0)
1788             {
1789                 Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine );
1790                 aPos.X() += pImp->nNodeBmpTabDistance;
1791 
1792                 const Image* pImg = 0;
1793                 BmpColorMode eBitmapMode = BMP_COLOR_NORMAL;
1794                 if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
1795                     eBitmapMode = BMP_COLOR_HIGHCONTRAST;
1796 
1797                 if( IsExpanded(pEntry) )
1798                     pImg = &pImp->GetExpandedNodeBmp( eBitmapMode );
1799                 else
1800                 {
1801                     if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
1802                         (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
1803                         pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
1804                         pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode );
1805                     else
1806                         pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode );
1807                 }
1808                 aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2;
1809 
1810                 sal_uInt16 nStyle = 0;
1811                 if ( !IsEnabled() )
1812                     nStyle |= IMAGE_DRAW_DISABLE;
1813 
1814                 //native
1815                 sal_Bool bNativeOK = sal_False;
1816                 if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) )
1817                 {
1818                     ImplControlValue    aControlValue;
1819                     Rectangle           aCtrlRegion( aPos,  pImg->GetSizePixel() );
1820                     ControlState        nState = 0;
1821 
1822                     if ( IsEnabled() )  nState |= CTRL_STATE_ENABLED;
1823 
1824                     if ( IsExpanded(pEntry) )
1825                         aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node
1826                     else
1827                     {
1828                         if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
1829                             (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
1830                             pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
1831                             aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know
1832                         else
1833                             aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node
1834                     }
1835 
1836                     bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL,
1837                                             aCtrlRegion, nState, aControlValue, rtl::OUString() );
1838                 }
1839 
1840                 if( !bNativeOK) {
1841                 //non native
1842                     DrawImage( aPos, *pImg ,nStyle);
1843                 }
1844             }
1845         }
1846     }
1847 
1848 
1849     if( bHasClipRegion && bResetClipRegion )
1850         SetClipRegion();
1851     return 0; // nRowLen;
1852 }
1853 
1854 void SvTreeListBox::PreparePaint( SvLBoxEntry* )
1855 {
1856 }
1857 
1858 Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine )
1859 {
1860     DBG_CHKTHIS(SvTreeListBox,0);
1861     Size aSize;
1862     Rectangle aRect;
1863     aRect.Top() = nLine;
1864     aSize.Height() = GetEntryHeight();
1865 
1866     long nRealWidth = pImp->GetOutputSize().Width();
1867     nRealWidth -= GetMapMode().GetOrigin().X();
1868 
1869     sal_uInt16 nCurTab;
1870     SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab );
1871     long nTabPos = 0;
1872     if( pTab )
1873         nTabPos = GetTabPos( pEntry, pTab );
1874     long nNextTabPos;
1875     if( pTab && nCurTab < aTabs.Count() - 1 )
1876     {
1877         SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 );
1878         nNextTabPos = GetTabPos( pEntry, pNextTab );
1879     }
1880     else
1881     {
1882         nNextTabPos = nRealWidth;
1883         if( nTabPos > nRealWidth )
1884             nNextTabPos += 50;
1885     }
1886 
1887     sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0;
1888     if( !bUserSelection )
1889     {
1890         if( pTab && nCurTab < pEntry->ItemCount() )
1891         {
1892             SvLBoxItem* pItem = pEntry->GetItem( nCurTab );
1893             aSize.Width() = pItem->GetSize( this, pEntry ).Width();
1894             if( !aSize.Width() )
1895                 aSize.Width() = 15;
1896             long nX = nTabPos; //GetTabPos( pEntry, pTab );
1897             // Ausrichtung
1898             nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos );
1899             aRect.Left() = nX;
1900             // damit erster & letzter Buchstabe nicht angeknabbert werden
1901             aRect.SetSize( aSize );
1902             if( aRect.Left() > 0 )
1903                 aRect.Left()--;
1904             aRect.Right()++;
1905         }
1906     }
1907     else
1908     {
1909         // wenn erster SelTab != 0, dann muessen wir auch rechnen
1910         if( nFocusWidth == -1 || nFirstSelTab )
1911         {
1912             sal_uInt16 nLastTab;
1913             SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab);
1914             nLastTab++;
1915             if( nLastTab < aTabs.Count() ) // gibts noch einen ?
1916                 pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab );
1917             else
1918                 pLastTab = 0;  // ueber gesamte Breite selektieren
1919             aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff;
1920             nFocusWidth = (short)aSize.Width();
1921             if( pTab )
1922                 nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos();
1923         }
1924         else
1925         {
1926             aSize.Width() = nFocusWidth;
1927             if( pTab )
1928             {
1929                 if( nCurTab )
1930                     aSize.Width() += nTabPos;
1931                 else
1932                     aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links
1933             }
1934         }
1935         // wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen
1936         if( nCurTab != 0 )
1937         {
1938             aRect.Left() = nTabPos;
1939             aSize.Width() -= nTabPos;
1940         }
1941         aRect.SetSize( aSize );
1942     }
1943     // rechten Rand anpassen wg. Clipping
1944     if( aRect.Right() >= nRealWidth )
1945     {
1946         aRect.Right() = nRealWidth-1;
1947         nFocusWidth = (short)aRect.GetWidth();
1948     }
1949     return aRect;
1950 }
1951 
1952 
1953 long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab)
1954 {
1955     DBG_CHKTHIS(SvTreeListBox,0);
1956     DBG_ASSERT(pTab,"No Tab");
1957     long nPos = pTab->GetPos();
1958     if( pTab->IsDynamic() )
1959     {
1960         sal_uInt16 nDepth = pModel->GetDepth( pEntry );
1961         nDepth = nDepth * (sal_uInt16)nIndent;
1962         nPos += (long)nDepth;
1963     }
1964     return nPos;
1965 }
1966 
1967 SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX,
1968     SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth )
1969 {
1970     DBG_CHKTHIS(SvTreeListBox,0);
1971     SvLBoxItem* pItemClicked = 0;
1972     sal_uInt16 nTabCount = aTabs.Count();
1973     sal_uInt16 nItemCount = pEntry->ItemCount();
1974     SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
1975     SvLBoxItem* pItem = pEntry->GetItem(0);
1976     sal_uInt16 nNextItem = 1;
1977     nX -= GetMapMode().GetOrigin().X();
1978     long nRealWidth = pImp->GetOutputSize().Width();
1979     nRealWidth -= GetMapMode().GetOrigin().X();
1980 
1981     while( 1 )
1982     {
1983         SvLBoxTab* pNextTab=nNextItem<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0;
1984         long nStart = GetTabPos( pEntry, pTab );
1985 
1986         long nNextTabPos;
1987         if( pNextTab )
1988             nNextTabPos = GetTabPos( pEntry, pNextTab );
1989         else
1990         {
1991             nNextTabPos = nRealWidth;
1992             if( nStart > nRealWidth )
1993                 nNextTabPos += 50;
1994         }
1995 
1996         Size aItemSize( pItem->GetSize(this, pEntry));
1997         nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart );
1998         long nLen = aItemSize.Width();
1999         if( pNextTab )
2000         {
2001             long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart;
2002             if( nTabWidth < nLen )
2003                 nLen = nTabWidth;
2004         }
2005 
2006         if( !nLen )
2007             nLen = nEmptyWidth;
2008 
2009         if( nX >= nStart && nX < (nStart+nLen ) )
2010         {
2011             pItemClicked = pItem;
2012             if( ppTab )
2013             {
2014                 *ppTab = pTab;
2015                 break;
2016             }
2017         }
2018         if( nNextItem >= nItemCount || nNextItem >= nTabCount)
2019             break;
2020         pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem );
2021         pItem = pEntry->GetItem( nNextItem );
2022         nNextItem++;
2023     }
2024     return pItemClicked;
2025 }
2026 
2027 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab)
2028 {
2029     return GetItem_Impl( pEntry, nX, ppTab, 0 );
2030 }
2031 
2032 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX )
2033 {
2034     DBG_CHKTHIS(SvTreeListBox,0);
2035     SvLBoxTab* pDummyTab;
2036     return GetItem_Impl( pEntry, nX, &pDummyTab, 0 );
2037 }
2038 
2039 SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry )
2040 {
2041     DBG_CHKTHIS(SvTreeListBox,0);
2042 
2043     SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
2044     SvLBoxItem* pItem = pEntry->GetItem(0);
2045     sal_uInt16 nTabCount = aTabs.Count();
2046 
2047     sal_uInt16 nNext = 1;
2048     while ( !pTab->IsDynamic() && nNext < nTabCount )
2049     {
2050         pItem = pEntry->GetItem( nNext );
2051         pTab = (SvLBoxTab*)aTabs.GetObject( nNext );
2052         nNext++;
2053     }
2054     return pItem;
2055 }
2056 
2057 void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData )
2058 {
2059     DBG_CHKTHIS(SvTreeListBox,0);
2060     nFocusWidth = -1;
2061     SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags );
2062     pTab->SetUserData( pUserData );
2063     aTabs.Insert( pTab, aTabs.Count() );
2064     if( nTreeFlags & TREEFLAG_USESEL )
2065     {
2066         sal_uInt16 nPos = aTabs.Count() - 1;
2067         if( nPos >= nFirstSelTab && nPos <= nLastSelTab )
2068             pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION;
2069         else
2070             // String-Items werden normalerweise immer selektiert
2071             // deshalb explizit ausschalten
2072             pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION;
2073     }
2074 }
2075 
2076 
2077 
2078 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const
2079 {
2080     DBG_CHKTHIS(SvTreeListBox,0);
2081     sal_uInt16 nCurTab = 0;
2082     sal_uInt16 nTabCount = aTabs.Count();
2083     while( nCurTab < nTabCount )
2084     {
2085         SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab);
2086         if( pTab->nFlags & SV_LBOXTAB_DYNAMIC )
2087         {
2088             rPos = nCurTab;
2089             return pTab;
2090         }
2091         nCurTab++;
2092     }
2093     return 0;
2094 }
2095 
2096 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const
2097 {
2098     sal_uInt16 nDummy;
2099     return GetFirstDynamicTab( nDummy );
2100 }
2101 
2102 SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const
2103 {
2104     DBG_CHKTHIS(SvTreeListBox,0);
2105     sal_uInt16 nPos = pEntry->GetPos( pItem );
2106     return (SvLBoxTab*)aTabs.GetObject( nPos );
2107 }
2108 
2109 void SvTreeListBox::ClearTabList()
2110 {
2111     DBG_CHKTHIS(SvTreeListBox,0);
2112     sal_uInt16 nTabCount = aTabs.Count();
2113     while( nTabCount )
2114     {
2115         nTabCount--;
2116         SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount );
2117         delete pDelTab;
2118     }
2119     aTabs.Remove(0,aTabs.Count());
2120 }
2121 
2122 
2123 Size SvTreeListBox::GetOutputSizePixel() const
2124 {
2125     DBG_CHKTHIS(SvTreeListBox,0);
2126     Size aSize = pImp->GetOutputSize();
2127     return aSize;
2128 }
2129 
2130 void SvTreeListBox::NotifyBeginScroll()
2131 {
2132     DBG_CHKTHIS(SvTreeListBox,0);
2133 }
2134 
2135 void SvTreeListBox::NotifyEndScroll()
2136 {
2137     DBG_CHKTHIS(SvTreeListBox,0);
2138 }
2139 
2140 void SvTreeListBox::NotifyScrolling( long )
2141 {
2142     DBG_CHKTHIS(SvTreeListBox,0);
2143 }
2144 
2145 void SvTreeListBox::NotifyScrolled()
2146 {
2147     DBG_CHKTHIS(SvTreeListBox,0);
2148     aScrolledHdl.Call( this );
2149 }
2150 
2151 void SvTreeListBox::NotifyInvalidating()
2152 {
2153     DBG_CHKTHIS(SvTreeListBox,0);
2154 }
2155 
2156 void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags )
2157 {
2158     DBG_CHKTHIS(SvTreeListBox,0);
2159     if( nFocusWidth == -1 )
2160         // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
2161         pImp->RecalcFocusRect();
2162     NotifyInvalidating();
2163     SvLBox::Invalidate( nInvalidateFlags );
2164     pImp->Invalidate();
2165 }
2166 
2167 void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags )
2168 {
2169     DBG_CHKTHIS(SvTreeListBox,0);
2170     if( nFocusWidth == -1 )
2171         // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
2172         pImp->RecalcFocusRect();
2173     NotifyInvalidating();
2174     SvLBox::Invalidate( rRect, nInvalidateFlags );
2175 }
2176 
2177 
2178 void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd)
2179 {
2180     DBG_CHKTHIS(SvTreeListBox,0);
2181 
2182     sal_uInt16 nTemp;
2183     nTreeFlags |= TREEFLAG_USESEL;
2184     if( nStart > nEnd )
2185     {
2186         nTemp = nStart;
2187         nStart = nEnd;
2188         nEnd = nTemp;
2189     }
2190     // alle Tabs markieren, die im Bereich liegen
2191     nTreeFlags |= TREEFLAG_RECALCTABS;
2192     nFirstSelTab = nStart;
2193     nLastSelTab = nEnd;
2194     pImp->RecalcFocusRect();
2195 }
2196 
2197 void SvTreeListBox::RemoveHighlightRange()
2198 {
2199     DBG_CHKTHIS(SvTreeListBox,0);
2200     nTreeFlags &= (~TREEFLAG_USESEL);
2201     if( IsUpdateMode() )
2202         Invalidate();
2203 }
2204 
2205 sal_uLong SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
2206 {
2207     return LIST_APPEND;
2208 }
2209 
2210 sal_uLong SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
2211 {
2212     DBG_CHKTHIS(SvTreeListBox,0);
2213     return LIST_APPEND;
2214 }
2215 
2216 Region SvTreeListBox::GetDragRegion() const
2217 {
2218     DBG_CHKTHIS(SvTreeListBox,0);
2219     Rectangle aRect;
2220     SvLBoxEntry* pEntry = GetCurEntry();
2221     if( pEntry )
2222     {
2223         Point aPos = GetEntryPosition( pEntry );
2224         aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() );
2225     }
2226     Region aRegion( aRect );
2227     return aRegion;
2228 }
2229 
2230 
2231 void SvTreeListBox::Command( const CommandEvent& rCEvt )
2232 {
2233     DBG_CHKTHIS(SvTreeListBox,0);
2234     // FIXME gnumake2 resync to DEV300_m84
2235     pImp->Command( rCEvt );
2236 }
2237 
2238 
2239 void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent )
2240 {
2241     DBG_CHKTHIS(SvTreeListBox,0);
2242     DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent");
2243     SvLBoxEntry* pNewParent = GetParent( pParent );
2244     if( pParent->HasChilds())
2245     {
2246         SvLBoxEntry* pChild = FirstChild( pParent );
2247         while( pChild )
2248         {
2249             pModel->Move( pChild, pNewParent, LIST_APPEND );
2250             pChild = FirstChild( pParent );
2251         }
2252     }
2253     pModel->Remove( pParent );
2254 }
2255 
2256 SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos )
2257 {
2258     sal_uInt16 nTabCount = aTabs.Count();
2259     for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ )
2260     {
2261         SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos );
2262         if( (pTab->nFlags & nFlagMask) )
2263         {
2264             rPos = nPos;
2265             return pTab;
2266         }
2267     }
2268     rPos = 0xffff;
2269     return 0;
2270 }
2271 
2272 SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos )
2273 {
2274     short nTabCount = (short)aTabs.Count();
2275     if( nTabCount )
2276     {
2277         for( short nPos = nTabCount-1; nPos >= 0; nPos-- )
2278         {
2279             SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (sal_uInt16)nPos );
2280             if( (pTab->nFlags & nFlagMask) )
2281             {
2282                 rTabPos = (sal_uInt16)nPos;
2283                 return pTab;
2284             }
2285         }
2286     }
2287     rTabPos = 0xffff;
2288     return 0;
2289 }
2290 
2291 void SvTreeListBox::SetAddMode( sal_Bool bAdd )
2292 {
2293     pImp->SetAddMode( bAdd );
2294 }
2295 
2296 sal_Bool SvTreeListBox::IsAddMode() const
2297 {
2298     return pImp->IsAddMode();
2299 }
2300 
2301 void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt )
2302 {
2303     if( !pImp->RequestHelp( rHEvt ) )
2304         SvLBox::RequestHelp( rHEvt );
2305 }
2306 
2307 void SvTreeListBox::CursorMoved( SvLBoxEntry* )
2308 {
2309 }
2310 
2311 IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData )
2312 {
2313     SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft );
2314     SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight );
2315     String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
2316     String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
2317     // #102891# ----------------
2318     pImp->UpdateIntlWrapper();
2319     return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight );
2320 }
2321 
2322 void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1,
2323                         SvListEntry* pEntry2, sal_uLong nPos )
2324 {
2325     if( nActionId == LISTACTION_CLEARING )
2326         CancelTextEditing();
2327 
2328     SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos );
2329     switch( nActionId )
2330     {
2331         case LISTACTION_INSERTED:
2332         {
2333             SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) );
2334             ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" );
2335             SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
2336             if ( !pBmpItem )
2337                 break;
2338             const Image& rBitmap1( pBmpItem->GetBitmap1() );
2339             const Image& rBitmap2( pBmpItem->GetBitmap2() );
2340             short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) );
2341             nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth );
2342             if( nMaxWidth > nContextBmpWidthMax )
2343             {
2344                 nContextBmpWidthMax = nMaxWidth;
2345                 SetTabs();
2346             }
2347         }
2348         break;
2349 
2350         case LISTACTION_RESORTING:
2351             SetUpdateMode( sal_False );
2352             break;
2353 
2354         case LISTACTION_RESORTED:
2355             // nach Sortierung den ersten Eintrag anzeigen, dabei die
2356             // Selektion erhalten.
2357             MakeVisible( (SvLBoxEntry*)pModel->First(), sal_True );
2358             SetUpdateMode( sal_True );
2359             break;
2360 
2361         case LISTACTION_CLEARED:
2362             if( IsUpdateMode() )
2363                 Update();
2364             break;
2365     }
2366 }
2367 
2368 // bei Aenderungen SetTabs beruecksichtigen
2369 long SvTreeListBox::GetTextOffset() const
2370 {
2371     DBG_CHKTHIS(SvTreeListBox,0);
2372     const WinBits nWindowStyle = GetStyle();
2373     sal_Bool bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0;
2374     sal_Bool bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT |
2375                                               WB_HASBUTTONSATROOT))!=0;
2376     long nStartPos = TAB_STARTPOS;
2377     long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
2378 
2379     long nCheckWidth = 0;
2380     if( nTreeFlags & TREEFLAG_CHKBTN )
2381         nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width();
2382     long nCheckWidthDIV2 = nCheckWidth / 2;
2383 
2384     long nContextWidth = nContextBmpWidthMax;
2385     long nContextWidthDIV2 = nContextWidth / 2;
2386 
2387     int nCase = NO_BUTTONS;
2388     if( !(nTreeFlags & TREEFLAG_CHKBTN) )
2389     {
2390         if( bHasButtons )
2391             nCase = NODE_BUTTONS;
2392     }
2393     else
2394     {
2395         if( bHasButtons )
2396             nCase = NODE_AND_CHECK_BUTTONS;
2397          else
2398             nCase = CHECK_BUTTONS;
2399     }
2400 
2401     switch( nCase )
2402     {
2403         case NO_BUTTONS :
2404             nStartPos += nContextWidthDIV2;  // wg. Zentrierung
2405             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2406             if( nContextBmpWidthMax )
2407                 nStartPos += 5; // Abstand Context-Bmp - Text
2408             break;
2409 
2410         case NODE_BUTTONS :
2411             if( bHasButtonsAtRoot )
2412                 nStartPos += ( nIndent + (nNodeWidthPixel/2) );
2413             else
2414                 nStartPos += nContextWidthDIV2;
2415             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2416             if( nContextBmpWidthMax )
2417                 nStartPos += 5; // Abstand Context-Bmp - Text
2418             break;
2419 
2420         case NODE_AND_CHECK_BUTTONS :
2421             if( bHasButtonsAtRoot )
2422                 nStartPos += ( nIndent + nNodeWidthPixel );
2423             else
2424                 nStartPos += nCheckWidthDIV2;
2425             nStartPos += nCheckWidthDIV2;  // rechter Rand des CheckButtons
2426             nStartPos += 3;  // Abstand CheckButton Context-Bmp
2427             nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
2428             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2429             // Abstand setzen nur wenn Bitmaps da
2430             if( nContextBmpWidthMax )
2431                 nStartPos += 5; // Abstand Context-Bmp - Text
2432             break;
2433 
2434         case CHECK_BUTTONS :
2435             nStartPos += nCheckWidthDIV2;
2436             nStartPos += nCheckWidthDIV2;  // rechter Rand CheckButton
2437             nStartPos += 3;  // Abstand CheckButton Context-Bmp
2438             nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
2439             nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2440             if( nContextBmpWidthMax )
2441                 nStartPos += 5; // Abstand Context-Bmp - Text
2442             break;
2443     }
2444     return nStartPos;
2445 }
2446 
2447 void SvTreeListBox::EndSelection()
2448 {
2449     pImp->EndSelection();
2450 }
2451 
2452 sal_Bool SvTreeListBox::IsNodeButton( const Point& rPos ) const
2453 {
2454     SvLBoxEntry* pEntry = GetEntry( rPos );
2455     if( pEntry )
2456         return pImp->IsNodeButton( rPos, pEntry );
2457     return sal_False;
2458 }
2459 
2460 void SvTreeListBox::RepaintScrollBars() const
2461 {
2462     ((SvTreeListBox*)this)->pImp->RepaintScrollBars();
2463 }
2464 
2465 ScrollBar *SvTreeListBox::GetVScroll()
2466 {
2467     return &((SvTreeListBox*)this)->pImp->aVerSBar;
2468 }
2469 
2470 ScrollBar *SvTreeListBox::GetHScroll()
2471 {
2472     return &((SvTreeListBox*)this)->pImp->aHorSBar;
2473 }
2474 
2475 void SvTreeListBox::EnableAsyncDrag( sal_Bool b )
2476 {
2477     pImp->EnableAsyncDrag( b );
2478 }
2479 
2480 SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const
2481 {
2482     Point aPos;
2483     return GetEntry( aPos );
2484 }
2485 
2486 SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const
2487 {
2488     SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry );
2489     if( pNext )
2490     {
2491         Point aPos( GetEntryPosition(pNext) );
2492         const Size& rSize = pImp->GetOutputSize();
2493         if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
2494             return 0;
2495     }
2496     return pNext;
2497 }
2498 
2499 void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry )
2500 {
2501     pImp->ShowFocusRect( pEntry );
2502 }
2503 
2504 void SvTreeListBox::SetTabBar( TabBar* pTabBar )
2505 {
2506     pImp->SetTabBar( pTabBar );
2507 }
2508 
2509 void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt )
2510 {
2511     if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
2512     {
2513         nEntryHeight = 0;   // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height
2514                             //  forces complete recalc of heights!
2515         InitSettings( sal_True, sal_True, sal_True );
2516         Invalidate();
2517     }
2518     else
2519         Control::DataChanged( rDCEvt );
2520 }
2521 
2522 void SvTreeListBox::StateChanged( StateChangedType i_nStateChange )
2523 {
2524     SvLBox::StateChanged( i_nStateChange );
2525     if ( i_nStateChange == STATE_CHANGE_STYLE )
2526         ImplInitStyle();
2527 }
2528 
2529 void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground)
2530 {
2531     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2532     if( bFont )
2533     {
2534         Font aFont;
2535         aFont = rStyleSettings.GetFieldFont();
2536         aFont.SetColor( rStyleSettings.GetWindowTextColor() );
2537         SetPointFont( aFont );
2538         AdjustEntryHeight( aFont );
2539         RecalcViewData();
2540     }
2541 
2542     if( bForeground || bFont )
2543     {
2544         SetTextColor( rStyleSettings.GetFieldTextColor() );
2545         SetTextFillColor();
2546     }
2547 
2548     if( bBackground )
2549         SetBackground( rStyleSettings.GetFieldColor() );
2550 
2551     // always try to re-create default-SvLBoxButtonData
2552     if( pCheckButtonData && pCheckButtonData->HasDefaultImages() )
2553         pCheckButtonData->SetDefaultImages( this );
2554 }
2555 
2556 sal_Bool SvTreeListBox::IsCellFocusEnabled() const
2557 {
2558     return pImp->IsCellFocusEnabled();
2559 }
2560 
2561 bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
2562 {
2563     return pImp->SetCurrentTabPos( _nNewPos );
2564 }
2565 
2566 sal_uInt16 SvTreeListBox::GetCurrentTabPos() const
2567 {
2568     return pImp->GetCurrentTabPos();
2569 }
2570 
2571 void SvTreeListBox::InitStartEntry()
2572 {
2573     if( !pImp->pStartEntry )
2574         pImp->pStartEntry = GetModel()->First();
2575 }
2576 
2577 void SvTreeListBox::CancelPendingEdit()
2578 {
2579     if( pImp )
2580         pImp->CancelPendingEdit();
2581 }
2582 
2583 PopupMenu* SvTreeListBox::CreateContextMenu( void )
2584 {
2585     return NULL;
2586 }
2587 
2588 void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 )
2589 {
2590     DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" );
2591 }
2592 
2593 void SvTreeListBox::EnableContextMenuHandling( void )
2594 {
2595     DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
2596 
2597     pImp->bContextMenuHandling = sal_True;
2598 }
2599 
2600 void SvTreeListBox::EnableContextMenuHandling( sal_Bool b )
2601 {
2602     DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
2603 
2604     pImp->bContextMenuHandling = b;
2605 }
2606 
2607 sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const
2608 {
2609     DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" );
2610 
2611     return pImp->bContextMenuHandling;
2612 }
2613 
2614 void SvTreeListBox::EnableList( bool _bEnable )
2615 {
2616     // call base class method
2617     Window::Enable( _bEnable != false );
2618     // then paint immediately
2619     Paint( Rectangle( Point(), GetSizePixel() ) );
2620 }
2621 
2622 ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible()
2623 {
2624     Window* pParent = GetAccessibleParentWindow();
2625     DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" );
2626 
2627     ::com::sun::star::uno::Reference< XAccessible > xAccessible;
2628     if ( pParent )
2629     {
2630         ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
2631         if ( xAccParent.is() )
2632         {
2633             // need to be done here to get the vclxwindow later on in the accessbile
2634             ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface());
2635             xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent );
2636         }
2637     }
2638     return xAccessible;
2639 }
2640 
2641 void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const
2642 {
2643     DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" );
2644 
2645     if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() )
2646     {
2647         rStateSet.AddState( AccessibleStateType::EXPANDABLE );
2648         if ( IsExpanded( pEntry ) )
2649             rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED );
2650     }
2651 
2652     if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED )
2653         rStateSet.AddState( AccessibleStateType::CHECKED );
2654     if ( IsEntryVisible( pEntry ) )
2655         rStateSet.AddState( AccessibleStateType::VISIBLE );
2656     if ( IsSelected( pEntry ) )
2657         rStateSet.AddState( AccessibleStateType::SELECTED );
2658 }
2659 
2660 Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry )
2661 {
2662     Point aPos = GetEntryPosition( pEntry );
2663     Rectangle aRect = GetFocusRect( pEntry, aPos.Y() );
2664     return aRect;
2665 }
2666 
2667 void SvTreeListBox::EnableCellFocus()
2668 {
2669     pImp->EnableCellFocus();
2670 }
2671 
2672 void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData)
2673 {
2674     CallEventListeners(nEvent, pData);
2675 }
2676 
2677 void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const
2678 {
2679       SvLBox::FillAccessibleStateSet( rStateSet );
2680 }
2681