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