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