xref: /aoo41x/main/svtools/source/contnr/svtreebx.cxx (revision 3ea0c3d5)
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_TREEFOCUS, pEntry );
911 
912 }
913 
914 void SvTreeListBox::LoseFocus()
915 {
916 	DBG_CHKTHIS(SvTreeListBox,0);
917 	//Solution:If there is no item in the tree,delete visual focus.
918 	if( !SvLBox::First())
919 	{
920 		Invalidate();
921 	}
922 	pImp->LoseFocus();
923 	SvLBox::LoseFocus();
924 }
925 
926 void SvTreeListBox::ModelHasCleared()
927 {
928 	DBG_CHKTHIS(SvTreeListBox,0);
929 	pImp->pCursor = 0; //sonst Absturz beim Inplace-Editieren im GetFocus
930 	delete pEdCtrl;
931     pEdCtrl = NULL;
932 	pImp->Clear();
933 	nFocusWidth = -1;
934 
935 	nContextBmpWidthMax = 0;
936 	SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() );
937 	SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() );
938 
939 	if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT ))
940 		nEntryHeight = 0;
941 	AdjustEntryHeight( GetFont() );
942 	AdjustEntryHeight( GetDefaultExpandedEntryBmp() );
943 	AdjustEntryHeight( GetDefaultCollapsedEntryBmp() );
944 
945 	SvLBox::ModelHasCleared();
946 //	if( IsUpdateMode() )
947 //		Invalidate();
948 }
949 
950 void SvTreeListBox::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool /* bShow  */ )
951 {
952 	DBG_CHKTHIS(SvTreeListBox,0);
953 	pImp->PaintDDCursor( pEntry );
954 }
955 
956 void SvTreeListBox::ScrollOutputArea( short nDeltaEntries )
957 {
958 	DBG_CHKTHIS(SvTreeListBox,0);
959 	if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() )
960 		return;
961 
962 	long nThumb = pImp->aVerSBar.GetThumbPos();
963 	long nMax = pImp->aVerSBar.GetRange().Max();
964 
965 	NotifyBeginScroll();
966 	if( nDeltaEntries < 0 )
967 	{
968 		// das Fenster nach oben verschieben
969 		nDeltaEntries *= -1;
970 		long nVis = pImp->aVerSBar.GetVisibleSize();
971 		long nTemp = nThumb + nVis;
972 		if( nDeltaEntries > (nMax - nTemp) )
973 			nDeltaEntries = (short)(nMax - nTemp);
974 		pImp->PageDown( (sal_uInt16)nDeltaEntries );
975 	}
976 	else
977 	{
978 		if( nDeltaEntries > nThumb )
979 			nDeltaEntries = (short)nThumb;
980 		pImp->PageUp( (sal_uInt16)nDeltaEntries );
981 	}
982 	pImp->SyncVerThumb();
983 	NotifyEndScroll();
984 }
985 
986 void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode )
987 {
988 	DBG_CHKTHIS(SvTreeListBox,0);
989 	SvLBox::SetSelectionMode( eSelectMode );
990 	pImp->SetSelectionMode( eSelectMode );
991 }
992 
993 void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode )
994 {
995 	DBG_CHKTHIS(SvTreeListBox,0);
996 	SvLBox::SetDragDropMode( nDDMode );
997 	pImp->SetDragDropMode( nDDMode );
998 }
999 
1000 short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic )
1001 {
1002 	DBG_CHKTHIS(SvTreeListBox,0);
1003 	short nOffset = 0;
1004 	aSizeLogic = rBmp.GetSizePixel();
1005 	if( GetEntryHeight() > aSizeLogic.Height() )
1006 		nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
1007 	return nOffset;
1008 }
1009 
1010 short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic )
1011 {
1012 	DBG_CHKTHIS(SvTreeListBox,0);
1013 	short nOffset = 0;
1014 	aSizeLogic = Size(GetTextWidth('X'), GetTextHeight());
1015 	if( GetEntryHeight() > aSizeLogic.Height() )
1016 		nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
1017 	return nOffset;
1018 }
1019 
1020 void SvTreeListBox::SetEntryHeight( SvLBoxEntry* pEntry )
1021 {
1022 	DBG_CHKTHIS(SvTreeListBox,0);
1023 	short nHeight, nHeightMax=0;
1024 	sal_uInt16 nCount = pEntry->ItemCount();
1025 	sal_uInt16 nCur = 0;
1026 	SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
1027 	while( nCur < nCount )
1028 	{
1029 		SvLBoxItem* pItem = pEntry->GetItem( nCur );
1030 		nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height());
1031 		if( nHeight > nHeightMax )
1032 			nHeightMax = nHeight;
1033 		nCur++;
1034 	}
1035 
1036 	if( nHeightMax > nEntryHeight )
1037 	{
1038 		nEntryHeight = nHeightMax;
1039 		SvLBox::SetFont( GetFont() );
1040 		pImp->SetEntryHeight( nHeightMax );
1041 	}
1042 }
1043 
1044 void SvTreeListBox::SetEntryHeight( short nHeight, sal_Bool bAlways )
1045 {
1046 	DBG_CHKTHIS(SvTreeListBox,0);
1047 
1048 	if( bAlways || nHeight > nEntryHeight )
1049 	{
1050 		nEntryHeight = nHeight;
1051 		if( nEntryHeight )
1052 			nTreeFlags |= TREEFLAG_FIXEDHEIGHT;
1053 		else
1054 			nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT;
1055 		SvLBox::SetFont( GetFont() );
1056 		pImp->SetEntryHeight( nHeight );
1057 	}
1058 }
1059 
1060 
1061 void SvTreeListBox::AdjustEntryHeight( const Image& rBmp )
1062 {
1063 	DBG_CHKTHIS(SvTreeListBox,0);
1064 	Size aSize;
1065 	GetHeightOffset( rBmp, aSize );
1066 	if( aSize.Height() > nEntryHeight )
1067 	{
1068 		nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
1069 		pImp->SetEntryHeight( nEntryHeight );
1070 	}
1071 }
1072 
1073 void SvTreeListBox::AdjustEntryHeight( const Font& rFont )
1074 {
1075 	DBG_CHKTHIS(SvTreeListBox,0);
1076 	Size aSize;
1077 	GetHeightOffset( rFont, aSize );
1078 	if( aSize.Height()  >  nEntryHeight )
1079 	{
1080 		nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
1081 		pImp->SetEntryHeight( nEntryHeight );
1082 	}
1083 }
1084 
1085 sal_Bool SvTreeListBox::Expand( SvLBoxEntry* pParent )
1086 {
1087 	DBG_CHKTHIS(SvTreeListBox,0);
1088 	pHdlEntry = pParent;
1089 	sal_Bool bExpanded = sal_False;
1090 	sal_uInt16 nFlags;
1091 
1092 	if( pParent->HasChildsOnDemand() )
1093 		RequestingChilds( pParent );
1094 	if( pParent->HasChilds() )
1095 	{
1096 		nImpFlags |= SVLBOX_IS_EXPANDING;
1097 		if( ExpandingHdl() )
1098 		{
1099 			bExpanded = sal_True;
1100 			SvListView::Expand( pParent );
1101 			pImp->EntryExpanded( pParent );
1102 			pHdlEntry = pParent;
1103 			ExpandedHdl();
1104 		}
1105 		nFlags = pParent->GetFlags();
1106 		nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
1107 		nFlags |= SV_ENTRYFLAG_HAD_CHILDREN;
1108 		pParent->SetFlags( nFlags );
1109 	}
1110 	else
1111 	{
1112 		nFlags = pParent->GetFlags();
1113 		nFlags |= SV_ENTRYFLAG_NO_NODEBMP;
1114 		pParent->SetFlags( nFlags );
1115 		GetModel()->InvalidateEntry( pParent ); // neu zeichnen
1116 	}
1117 
1118     // --> OD 2009-04-01 #i92103#
1119     if ( bExpanded )
1120     {
1121         pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent );
1122     }
1123     // <--
1124 
1125     return bExpanded;
1126 }
1127 
1128 sal_Bool SvTreeListBox::Collapse( SvLBoxEntry* pParent )
1129 {
1130 	DBG_CHKTHIS(SvTreeListBox,0);
1131 	nImpFlags &= ~SVLBOX_IS_EXPANDING;
1132 	pHdlEntry = pParent;
1133 	sal_Bool bCollapsed = sal_False;
1134 
1135 	if(	ExpandingHdl() )
1136 	{
1137 		bCollapsed = sal_True;
1138 		pImp->CollapsingEntry( pParent );
1139 		SvListView::Collapse( pParent );
1140 		pImp->EntryCollapsed( pParent );
1141 		pHdlEntry = pParent;
1142 		ExpandedHdl();
1143 	}
1144 
1145     // --> OD 2009-04-01 #i92103#
1146     if ( bCollapsed )
1147     {
1148         pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent );
1149     }
1150     // <--
1151 
1152     return bCollapsed;
1153 }
1154 
1155 sal_Bool SvTreeListBox::Select( SvLBoxEntry* pEntry, sal_Bool bSelect )
1156 {
1157 	DBG_CHKTHIS(SvTreeListBox,0);
1158 	DBG_ASSERT(pEntry,"Select: Null-Ptr");
1159 	sal_Bool bRetVal = SvListView::Select( pEntry, bSelect );
1160 	DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed");
1161 	if( bRetVal )
1162 	{
1163 		pImp->EntrySelected( pEntry, bSelect );
1164 		pHdlEntry = pEntry;
1165 		if( bSelect )
1166 		{
1167 			SelectHdl();
1168 			// pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
1169 			CallEventListeners( VCLEVENT_LISTBOX_TREESELECT, pEntry);
1170 		}
1171 		else
1172 			DeselectHdl();
1173 	}
1174 	return bRetVal;
1175 }
1176 
1177 sal_uLong SvTreeListBox::SelectChilds( SvLBoxEntry* pParent, sal_Bool bSelect )
1178 {
1179 	DBG_CHKTHIS(SvTreeListBox,0);
1180 	pImp->DestroyAnchor();
1181 	sal_uLong nRet = 0;
1182 	if( !pParent->HasChilds() )
1183 		return 0;
1184 	sal_uInt16 nRefDepth = pModel->GetDepth( pParent );
1185 	SvLBoxEntry* pChild = FirstChild( pParent );
1186 	do {
1187 		nRet++;
1188 		Select( pChild, bSelect );
1189 		pChild = Next( pChild );
1190 	} while( pChild && pModel->GetDepth( pChild ) > nRefDepth );
1191 	return nRet;
1192 }
1193 
1194 void SvTreeListBox::SelectAll( sal_Bool bSelect, sal_Bool )
1195 {
1196 	DBG_CHKTHIS(SvTreeListBox,0);
1197 	pImp->SelAllDestrAnch(
1198 		bSelect,
1199 		sal_True,		// Anker loeschen,
1200 		sal_True );		// auch bei SINGLE_SELECTION den Cursor deselektieren
1201 }
1202 
1203 void SvTreeListBox::ModelHasInsertedTree( SvListEntry* pEntry )
1204 {
1205 	DBG_CHKTHIS(SvTreeListBox,0);
1206 	sal_uInt16 nRefDepth = pModel->GetDepth( (SvLBoxEntry*)pEntry );
1207 	SvLBoxEntry* pTmp = (SvLBoxEntry*)pEntry;
1208 	do
1209 	{
1210 		ImpEntryInserted( pTmp );
1211 		pTmp = Next( pTmp );
1212 	} while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) );
1213 	pImp->TreeInserted( (SvLBoxEntry*)pEntry );
1214 }
1215 
1216 void SvTreeListBox::ModelHasInserted( SvListEntry* pEntry )
1217 {
1218 	DBG_CHKTHIS(SvTreeListBox,0);
1219 	ImpEntryInserted( (SvLBoxEntry*)pEntry );
1220 	pImp->EntryInserted( (SvLBoxEntry*)pEntry );
1221 }
1222 
1223 void SvTreeListBox::ModelIsMoving(SvListEntry* pSource,
1224 										SvListEntry* /* pTargetParent */,
1225 										sal_uLong /* nChildPos */ )
1226 {
1227 	DBG_CHKTHIS(SvTreeListBox,0);
1228 	pImp->MovingEntry( (SvLBoxEntry*)pSource );
1229 }
1230 
1231 void SvTreeListBox::ModelHasMoved( SvListEntry* pSource )
1232 {
1233 	DBG_CHKTHIS(SvTreeListBox,0);
1234 	pImp->EntryMoved( (SvLBoxEntry*)pSource );
1235 }
1236 
1237 void SvTreeListBox::ModelIsRemoving( SvListEntry* pEntry )
1238 {
1239 	DBG_CHKTHIS(SvTreeListBox,0);
1240 	if(pEdEntry == pEntry)
1241 		pEdEntry = NULL;
1242 
1243 	pImp->RemovingEntry( (SvLBoxEntry*)pEntry );
1244 	NotifyRemoving( (SvLBoxEntry*)pEntry );
1245 }
1246 
1247 void SvTreeListBox::ModelHasRemoved( SvListEntry* pEntry  )
1248 {
1249 	DBG_CHKTHIS(SvTreeListBox,0);
1250     if ( pEntry == pHdlEntry)
1251         pHdlEntry = NULL;
1252 	pImp->EntryRemoved();
1253 }
1254 
1255 void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp, BmpColorMode _eMode )
1256 {
1257 	DBG_CHKTHIS(SvTreeListBox,0);
1258 	AdjustEntryHeight( rBmp );
1259 	pImp->SetCollapsedNodeBmp( rBmp, _eMode );
1260 }
1261 
1262 void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp, BmpColorMode _eMode )
1263 {
1264 	DBG_CHKTHIS(SvTreeListBox,0);
1265 	AdjustEntryHeight( rBmp );
1266 	pImp->SetExpandedNodeBmp( rBmp, _eMode );
1267 }
1268 
1269 
1270 void SvTreeListBox::SetFont( const Font& rFont )
1271 {
1272 	DBG_CHKTHIS(SvTreeListBox,0);
1273 	Font aTempFont( rFont );
1274 	aTempFont.SetTransparent( sal_True );
1275 	Control::SetFont( aTempFont );
1276 	AdjustEntryHeight( aTempFont );
1277 	// immer Invalidieren, sonst fallen wir
1278 	// bei SetEntryHeight auf die Nase
1279 	RecalcViewData();
1280 }
1281 
1282 
1283 void SvTreeListBox::Paint( const Rectangle& rRect )
1284 {
1285 	DBG_CHKTHIS(SvTreeListBox,0);
1286 	SvLBox::Paint( rRect );
1287 	if( nTreeFlags & TREEFLAG_RECALCTABS )
1288 		SetTabs();
1289 	pImp->Paint( rRect );
1290 	//Solution:Add visual focus draw
1291 	if( !SvLBox::First() )
1292 	{
1293 		if( HasFocus() )
1294 		{
1295 			long tempHeight = GetTextHeight();
1296 			Rectangle tempRect(
1297 								Point(0,0),Size(GetSizePixel().Width(),tempHeight)
1298 							   );
1299 			ShowFocus(tempRect);
1300 		}
1301 
1302 		else{
1303 			HideFocus();
1304 		}
1305 	}
1306 }
1307 
1308 void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt )
1309 {
1310 	DBG_CHKTHIS(SvTreeListBox,0);
1311 	pImp->MouseButtonDown( rMEvt );
1312 }
1313 
1314 void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt )
1315 {
1316 	DBG_CHKTHIS(SvTreeListBox,0);
1317 	pImp->MouseButtonUp( rMEvt );
1318 }
1319 
1320 void SvTreeListBox::MouseMove( const MouseEvent& rMEvt )
1321 {
1322 	DBG_CHKTHIS(SvTreeListBox,0);
1323 	pImp->MouseMove( rMEvt );
1324 }
1325 
1326 
1327 void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate )
1328 {
1329 	DBG_CHKTHIS(SvTreeListBox,0);
1330 	pImp->SetUpdateMode( bUpdate );
1331 }
1332 
1333 void SvTreeListBox::SetUpdateModeFast( sal_Bool bUpdate )
1334 {
1335 	DBG_CHKTHIS(SvTreeListBox,0);
1336 	pImp->SetUpdateModeFast( bUpdate );
1337 }
1338 
1339 void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic )
1340 {
1341 	DBG_CHKTHIS(SvTreeListBox,0);
1342 	if( nOffsLogic != nEntryHeightOffs )
1343 	{
1344 		nEntryHeight = nEntryHeight - nEntryHeightOffs;
1345 		nEntryHeightOffs = (short)nOffsLogic;
1346 		nEntryHeight = nEntryHeight + nOffsLogic;
1347 		AdjustEntryHeight( GetFont() );
1348 		RecalcViewData();
1349 		pImp->SetEntryHeight( nEntryHeight );
1350 	}
1351 }
1352 
1353 void SvTreeListBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect )
1354 {
1355 	DBG_CHKTHIS(SvTreeListBox,0);
1356 	pImp->SetCursor(pEntry, bForceNoSelect);
1357 }
1358 
1359 void SvTreeListBox::SetCurEntry( SvLBoxEntry* pEntry )
1360 {
1361 	DBG_CHKTHIS(SvTreeListBox,0);
1362 	pImp->SetCurEntry( pEntry );
1363 }
1364 
1365 Image SvTreeListBox::GetCollapsedNodeBmp( BmpColorMode _eMode ) const
1366 {
1367 	return pImp->GetCollapsedNodeBmp( _eMode );
1368 }
1369 
1370 Image SvTreeListBox::GetExpandedNodeBmp( BmpColorMode _eMode ) const
1371 {
1372 	return pImp->GetExpandedNodeBmp( _eMode );
1373 }
1374 
1375 Point SvTreeListBox::GetEntryPosition( SvLBoxEntry* pEntry ) const
1376 {
1377 	return pImp->GetEntryPosition( pEntry );
1378 }
1379 
1380 void SvTreeListBox::ShowEntry( SvLBoxEntry* pEntry )
1381 {
1382 	MakeVisible( pEntry );
1383 }
1384 
1385 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry )
1386 {
1387 	pImp->MakeVisible(pEntry);
1388 }
1389 
1390 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop )
1391 {
1392 	pImp->MakeVisible( pEntry, bMoveToTop );
1393 }
1394 
1395 void SvTreeListBox::ModelHasEntryInvalidated( SvListEntry* pEntry )
1396 {
1397 	DBG_CHKTHIS(SvTreeListBox,0);
1398 	// die einzelnen Items des Entries reinitialisieren
1399 	SvLBox::ModelHasEntryInvalidated( pEntry );
1400 	// repainten
1401 	pImp->InvalidateEntry( (SvLBoxEntry*)pEntry );
1402 }
1403 
1404 void SvTreeListBox::EditItemText( SvLBoxEntry* pEntry, SvLBoxString* pItem,
1405 	const Selection& rSelection )
1406 {
1407 	DBG_CHKTHIS(SvTreeListBox,0);
1408 	DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params");
1409 	if( IsSelected( pEntry ))
1410 	{
1411 		pImp->ShowCursor( sal_False );
1412 		SvListView::Select( pEntry, sal_False );
1413 		PaintEntry( pEntry );
1414 		SvListView::Select( pEntry, sal_True );
1415 		pImp->ShowCursor( sal_True );
1416 	}
1417 	pEdEntry = pEntry;
1418 	pEdItem = pItem;
1419 	SvLBoxTab* pTab = GetTab( pEntry, pItem );
1420 	DBG_ASSERT(pTab,"EditItemText:Tab not found");
1421 
1422 	Size aItemSize( pItem->GetSize(this, pEntry) );
1423 	Point aPos = GetEntryPosition( pEntry );
1424 	aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2;
1425 	aPos.X() = GetTabPos( pEntry, pTab );
1426 	long nOutputWidth = pImp->GetOutputSize().Width();
1427 	Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() );
1428 	sal_uInt16 nPos = aTabs.GetPos( pTab );
1429 	if( nPos+1 < aTabs.Count() )
1430 	{
1431 		SvLBoxTab* pRightTab = (SvLBoxTab*)aTabs.GetObject( nPos + 1 );
1432 		long nRight = GetTabPos( pEntry, pRightTab );
1433 		if( nRight <= nOutputWidth )
1434 			aSize.Width() = nRight - aPos.X();
1435 	}
1436 	Point aOrigin( GetMapMode().GetOrigin() );
1437 	aPos += aOrigin; // in Win-Koord umrechnen
1438 	aSize.Width() -= aOrigin.X();
1439 	Rectangle aRect( aPos, aSize );
1440 #ifdef OS2
1441 	// Platz lassen fuer WB_BORDER
1442 	aRect.Left() -= 2;
1443 	aRect.Top() -= 3;
1444 	aRect.Bottom() += 3;
1445 #endif
1446 	EditText( pItem->GetText(), aRect, rSelection );
1447 }
1448 
1449 void SvTreeListBox::CancelEditing()
1450 {
1451 	DBG_CHKTHIS(SvTreeListBox,0);
1452 	SvLBox::CancelTextEditing();
1453 }
1454 
1455 void SvTreeListBox::EditEntry( SvLBoxEntry* pEntry )
1456 {
1457     pImp->aEditClickPos = Point( -1, -1 );
1458     ImplEditEntry( pEntry );
1459 }
1460 
1461 void SvTreeListBox::ImplEditEntry( SvLBoxEntry* pEntry )
1462 {
1463 	DBG_CHKTHIS(SvTreeListBox,0);
1464 	if( IsEditingActive() )
1465 		EndEditing();
1466 	if( !pEntry )
1467 		pEntry = GetCurEntry();
1468 	if( pEntry )
1469 	{
1470 		long nClickX = pImp->aEditClickPos.X();
1471 		bool bIsMouseTriggered = nClickX >= 0;
1472 
1473 		SvLBoxString* pItem = NULL;
1474 		sal_uInt16 nCount = pEntry->ItemCount();
1475 		for( sal_uInt16 i = 0 ; i < nCount ; i++ )
1476 		{
1477 			SvLBoxItem* pTmpItem = pEntry->GetItem( i );
1478 			if( pTmpItem->IsA() != SV_ITEM_ID_LBOXSTRING )
1479 				continue;
1480 
1481 			SvLBoxTab* pTab = GetTab( pEntry, pTmpItem );
1482 			long nTabPos = pTab->GetPos();
1483 			long nNextTabPos = -1;
1484 			if( i < nCount - 1 )
1485 			{
1486 				SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 );
1487 				SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem );
1488 				nNextTabPos = pNextTab->GetPos();
1489 			}
1490 
1491 			if( pTab && pTab->IsEditable() )
1492 			{
1493 				if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) )
1494 				{
1495 					pItem = static_cast<SvLBoxString*>( pTmpItem );
1496 					break;
1497 				}
1498 			}
1499 		}
1500 
1501 		Selection aSel( SELECTION_MIN, SELECTION_MAX );
1502 		if( pItem && EditingEntry( pEntry, aSel ) )
1503 		{
1504 			SelectAll( sal_False );
1505 			MakeVisible( pEntry );
1506 			EditItemText( pEntry, pItem, aSel );
1507 		}
1508 	}
1509 }
1510 
1511 sal_Bool SvTreeListBox::AreChildrenTransient() const
1512 {
1513     return pImp->AreChildrenTransient();
1514 }
1515 
1516 void SvTreeListBox::SetChildrenNotTransient()
1517 {
1518     pImp->SetChildrenNotTransient();
1519 }
1520 
1521 void SvTreeListBox::EditedText( const XubString& rStr )
1522 
1523 {
1524 	DBG_CHKTHIS(SvTreeListBox,0);
1525 	if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing
1526 	{
1527 		Point aPos = GetEntryPosition( pEdEntry );
1528 		if( EditedEntry( pEdEntry, rStr ) )
1529 		{
1530 			((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr );
1531 			pModel->InvalidateEntry( pEdEntry );
1532 		}
1533 		//if( GetSelectionMode() == SINGLE_SELECTION )
1534 		//{
1535 		if( GetSelectionCount() == 0 )
1536 			Select( pEdEntry );
1537 		if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() )
1538 			SetCurEntry( pEdEntry );
1539 		//}
1540 	}
1541 }
1542 
1543 void SvTreeListBox::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem,
1544 									const Point& )
1545 {
1546 	DBG_CHKTHIS(SvTreeListBox,0);
1547 	if( IsEditingActive() )
1548 		EndEditing();
1549 	if( pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
1550 	{
1551 		Selection aSel( SELECTION_MIN, SELECTION_MAX );
1552 		if( EditingEntry( pEntry, aSel ) )
1553 		{
1554 			SelectAll( sal_False );
1555 			EditItemText( pEntry, (SvLBoxString*)pItem, aSel );
1556 		}
1557 	}
1558 }
1559 
1560 
1561 
1562 SvLBoxEntry* SvTreeListBox::GetDropTarget( const Point& rPos )
1563 {
1564 	DBG_CHKTHIS(SvTreeListBox,0);
1565 	// Scrollen
1566 	if( rPos.Y() < 12 )
1567 	{
1568 		SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False );
1569 		ScrollOutputArea( +1 );
1570 	}
1571 	else
1572 	{
1573 		Size aSize( pImp->GetOutputSize() );
1574 		if( rPos.Y() > aSize.Height() - 12 )
1575 		{
1576 			SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False );
1577 			ScrollOutputArea( -1 );
1578 		}
1579 	}
1580 
1581 	SvLBoxEntry* pTarget = pImp->GetEntry( rPos );
1582 	// bei Droppen in leere Flaeche -> den letzten Eintrag nehmen
1583 	if( !pTarget )
1584 		return (SvLBoxEntry*)LastVisible();
1585 	else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) &&
1586 			 pTarget == First() && rPos.Y() < 6 )
1587 		return 0;
1588 
1589 	return pTarget;
1590 }
1591 
1592 
1593 SvLBoxEntry* SvTreeListBox::GetEntry( const Point& rPos, sal_Bool bHit ) const
1594 {
1595 	DBG_CHKTHIS(SvTreeListBox,0);
1596 	SvLBoxEntry* pEntry = pImp->GetEntry( rPos );
1597 	if( pEntry && bHit )
1598 	{
1599 		long nLine = pImp->GetEntryLine( pEntry );
1600 		if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) )
1601 			return 0;
1602 	}
1603 	return pEntry;
1604 }
1605 
1606 SvLBoxEntry* SvTreeListBox::GetCurEntry() const
1607 {
1608 	DBG_CHKTHIS(SvTreeListBox,0);
1609 	return pImp->GetCurEntry();
1610 }
1611 
1612 void SvTreeListBox::ImplInitStyle()
1613 {
1614 	DBG_CHKTHIS(SvTreeListBox,0);
1615 
1616     const WinBits nWindowStyle = GetStyle();
1617 
1618 	nTreeFlags |= TREEFLAG_RECALCTABS;
1619 	if( nWindowStyle & WB_SORT )
1620 	{
1621 		GetModel()->SetSortMode( SortAscending );
1622 		GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare));
1623 	}
1624 	else
1625 	{
1626 		GetModel()->SetSortMode( SortNone );
1627 		GetModel()->SetCompareHdl( Link() );
1628 	}
1629 	pImp->SetStyle( nWindowStyle );
1630 	pImp->Resize();
1631 	Invalidate();
1632 }
1633 
1634 void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry )
1635 {
1636 	DBG_CHKTHIS(SvTreeListBox,0);
1637 	DBG_ASSERT(pEntry,"PaintEntry:No Entry");
1638 	if( pEntry )
1639 		pImp->PaintEntry( pEntry );
1640 }
1641 
1642 void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry )
1643 {
1644 	DBG_CHKTHIS(SvTreeListBox,0);
1645 	DBG_ASSERT(pEntry,"InvalidateEntry:No Entry");
1646 	if( pEntry )
1647 	{
1648 		GetModel()->InvalidateEntry( pEntry );
1649 	//	pImp->InvalidateEntry( pEntry );
1650 	}
1651 }
1652 
1653 
1654 long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags)
1655 {
1656 	return PaintEntry1(pEntry,nLine,nTabFlags);
1657 }
1658 
1659 #define SV_TAB_BORDER 8
1660 
1661 long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags,
1662 	sal_Bool bHasClipRegion )
1663 {
1664 	DBG_CHKTHIS(SvTreeListBox,0);
1665 
1666 	Rectangle aRect; // multi purpose
1667 
1668 	sal_Bool bHorSBar = pImp->HasHorScrollBar();
1669 	PreparePaint( pEntry );
1670 
1671 	// #97680# ------------------
1672 	pImp->UpdateContextBmpWidthMax( pEntry );
1673 
1674 	if( nTreeFlags & TREEFLAG_RECALCTABS )
1675 		SetTabs();
1676 
1677 	short nTempEntryHeight = GetEntryHeight();
1678 	long nWidth = pImp->GetOutputSize().Width();
1679 
1680 	// wurde innerhalb des PreparePaints die horizontale ScrollBar
1681 	// angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden
1682 	if( !bHorSBar && pImp->HasHorScrollBar() )
1683 		SetClipRegion( Region(pImp->GetClipRegionRect()) );
1684 
1685 	Point aEntryPos( GetMapMode().GetOrigin() );
1686 	aEntryPos.X() *= -1; // Umrechnung Dokumentkoord.
1687 	long nMaxRight = nWidth + aEntryPos.X() - 1;
1688 
1689 	Color aBackupTextColor( GetTextColor() );
1690     Font aBackupFont( GetFont() );
1691 	Color aBackupColor = GetFillColor();
1692 
1693 	bool bCurFontIsSel = false;
1694 	sal_Bool bInUse = pEntry->HasInUseEmphasis();
1695 	// wenn eine ClipRegion von aussen gesetzt wird, dann
1696 	// diese nicht zuruecksetzen
1697     const WinBits nWindowStyle = GetStyle();
1698 	const sal_Bool bResetClipRegion = !bHasClipRegion;
1699 	const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0;
1700 	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
1701 
1702     Font aHighlightFont( GetFont() );
1703     const Color aHighlightTextColor( rSettings.GetHighlightTextColor() );
1704     aHighlightFont.SetColor( aHighlightTextColor );
1705 
1706 	Size aRectSize( 0, nTempEntryHeight );
1707 
1708 	if( !bHasClipRegion && nWindowStyle & WB_HSCROLL )
1709 	{
1710 		SetClipRegion( Region(pImp->GetClipRegionRect()) );
1711 		bHasClipRegion = sal_True;
1712 	}
1713 
1714 	SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry );
1715 
1716 	sal_uInt16 nTabCount = aTabs.Count();
1717 	sal_uInt16 nItemCount = pEntry->ItemCount();
1718 	sal_uInt16 nCurTab = 0;
1719 	sal_uInt16 nCurItem = 0;
1720 
1721 	while( nCurTab < nTabCount && nCurItem < nItemCount )
1722 	{
1723 		SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab );
1724 		sal_uInt16 nNextTab = nCurTab + 1;
1725 		SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
1726 		SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0;
1727 
1728 		sal_uInt16 nFlags = pTab->nFlags;
1729 		Size aSize( pItem->GetSize( pViewDataEntry, nCurItem ));
1730 		long nTabPos = GetTabPos( pEntry, pTab );
1731 
1732 		long nNextTabPos;
1733 		if( pNextTab )
1734 			nNextTabPos = GetTabPos( pEntry, pNextTab );
1735 		else
1736 		{
1737 			nNextTabPos = nMaxRight;
1738 			if( nTabPos > nMaxRight )
1739 				nNextTabPos += 50;
1740 		}
1741 
1742 		long nX;
1743 		if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT )
1744 			//verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird
1745 			nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos);
1746 		else
1747 			nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos);
1748 
1749 		if( nFlags & nTabFlags )
1750 		{
1751 			if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight )
1752 			{
1753 				SetClipRegion( Region(pImp->GetClipRegionRect()) );
1754 				bHasClipRegion = sal_True;
1755 			}
1756 			aEntryPos.X() = nX;
1757 			aEntryPos.Y() = nLine;
1758 
1759 			// Hintergrund-Muster & Farbe bestimmen
1760 
1761 			Wallpaper aWallpaper = GetBackground();
1762 
1763 			int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION;
1764 			sal_uInt16 nItemType = pItem->IsA();
1765 
1766             if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() )
1767 			{
1768                 Color aNewWallColor = rSettings.GetHighlightColor();
1769                 if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP )
1770 				{
1771 					// if the face color is bright then the deactive color is also bright
1772 					// -> so you can't see any deactive selection
1773                     if ( bHideSelection && !rSettings.GetFaceColor().IsBright() &&
1774                          aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() )
1775                         aNewWallColor = rSettings.GetDeactiveColor();
1776 					// set font color to highlight
1777                     if ( !bCurFontIsSel )
1778 					{
1779 						SetTextColor( aHighlightTextColor );
1780                         SetFont( aHighlightFont );
1781 						bCurFontIsSel = true;
1782 					}
1783 				}
1784                 aWallpaper.SetColor( aNewWallColor );
1785 			}
1786 			else  // keine Selektion
1787 			{
1788 				if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP )
1789 					aWallpaper.SetColor( rSettings.GetFieldColor() );
1790 				else if( bCurFontIsSel )
1791 				{
1792 					bCurFontIsSel = false;
1793                     SetTextColor( aBackupTextColor );
1794                     SetFont( aBackupFont );
1795 				}
1796 			}
1797 
1798 			// Hintergrund zeichnen
1799 			if( !(nTreeFlags & TREEFLAG_USESEL))
1800 			{
1801 				// nur den Bereich zeichnen, den das Item einnimmt
1802 				aRectSize.Width() = aSize.Width();
1803 				aRect.SetPos( aEntryPos );
1804 				aRect.SetSize( aRectSize );
1805 			}
1806 			else
1807 			{
1808 				// vom aktuellen bis zum naechsten Tab zeichnen
1809 				if( nCurTab != 0 )
1810 					aRect.Left() = nTabPos;
1811 				else
1812 					// beim nullten Tab immer ab Spalte 0 zeichnen
1813 					// (sonst Probleme bei Tabs mit Zentrierung)
1814 					aRect.Left() = 0;
1815 				aRect.Top() = nLine;
1816 				aRect.Bottom() = nLine + nTempEntryHeight - 1;
1817 				if( pNextTab )
1818 				{
1819 					long nRight;
1820 					nRight = GetTabPos(pEntry,pNextTab)-1;
1821 					if( nRight > nMaxRight )
1822 						nRight = nMaxRight;
1823 					aRect.Right() = nRight;
1824 				}
1825 				else
1826 					aRect.Right() = nMaxRight;
1827 			}
1828 			// bei anwenderdefinierter Selektion, die bei einer Tabposition
1829 			// groesser 0 beginnt den Hintergrund des 0.ten Items nicht
1830 			// fuellen, da sonst z.B. TablistBoxen mit Linien nicht
1831 			// realisiert werden koennen.
1832 			if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) )
1833 			{
1834 				SetFillColor( aWallpaper.GetColor() );
1835 				// Bei kleinen hor. Resizes tritt dieser Fall auf
1836 				if( aRect.Left() < aRect.Right() )
1837 					DrawRect( aRect );
1838 			}
1839 			// Item zeichnen
1840 			// vertikal zentrieren
1841 			aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2;
1842 			pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry );
1843 
1844 			// Trennungslinie zwischen Tabs
1845 			if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING &&
1846 				// nicht am rechten Fensterrand!
1847 				aRect.Right() < nMaxRight )
1848 			{
1849 				aRect.Left() = aRect.Right() - SV_TAB_BORDER;
1850 				DrawRect( aRect );
1851 			}
1852 
1853 			SetFillColor( aBackupColor );
1854 		}
1855 		nCurItem++;
1856 		nCurTab++;
1857 	}
1858 	if( pViewDataEntry->IsCursored() && !HasFocus() )
1859 	{
1860 		// Cursor-Emphasis
1861 		SetFillColor();
1862 		Color aOldLineColor = GetLineColor();
1863 		SetLineColor( Color( COL_BLACK ) );
1864 		aRect = GetFocusRect( pEntry, nLine );
1865 		aRect.Top()++;
1866 		aRect.Bottom()--;
1867 		DrawRect( aRect );
1868 		SetLineColor( aOldLineColor );
1869 		SetFillColor( aBackupColor );
1870 	}
1871 
1872 	if( bCurFontIsSel )
1873     {
1874 		SetTextColor( aBackupTextColor );
1875         SetFont( aBackupFont );
1876     }
1877 
1878 	sal_uInt16 nFirstDynTabPos;
1879 	SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos );
1880 	long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab );
1881 	nDynTabPos += pImp->nNodeBmpTabDistance;
1882 	nDynTabPos += pImp->nNodeBmpWidth / 2;
1883 	nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap
1884 					 // nicht zu nah am naechsten Tab steht
1885 
1886 	if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) &&
1887 		(nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab &&
1888 		( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) )
1889 	{
1890 		// ersten festen Tab suchen, und pruefen ob die Node-Bitmap
1891 		// in ihn hineinragt
1892 		sal_uInt16 nNextTab = nFirstDynTabPos;
1893 		SvLBoxTab* pNextTab;
1894 		do
1895 		{
1896 			nNextTab++;
1897 			pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
1898 		} while( pNextTab && pNextTab->IsDynamic() );
1899 
1900 		if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) )
1901 		{
1902 			if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0)
1903 			{
1904 				Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine );
1905 				aPos.X() += pImp->nNodeBmpTabDistance;
1906 
1907 				const Image* pImg = 0;
1908 				BmpColorMode eBitmapMode = BMP_COLOR_NORMAL;
1909 				if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
1910 					eBitmapMode = BMP_COLOR_HIGHCONTRAST;
1911 
1912 				if( IsExpanded(pEntry) )
1913 					pImg = &pImp->GetExpandedNodeBmp( eBitmapMode );
1914 				else
1915 				{
1916 					if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
1917 						(!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
1918 						pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
1919 						pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode );
1920 					else
1921 						pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode );
1922 				}
1923 				aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2;
1924 
1925 				sal_uInt16 nStyle = 0;
1926 				if ( !IsEnabled() )
1927 					nStyle |= IMAGE_DRAW_DISABLE;
1928 
1929 				//native
1930 				sal_Bool bNativeOK = sal_False;
1931 				if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) )
1932 				{
1933 					ImplControlValue	aControlValue;
1934 					Rectangle           aCtrlRegion( aPos,  pImg->GetSizePixel() );
1935 					ControlState		nState = 0;
1936 
1937 					if ( IsEnabled() )	nState |= CTRL_STATE_ENABLED;
1938 
1939 					if ( IsExpanded(pEntry) )
1940 						aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node
1941 					else
1942 					{
1943 						if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
1944 							(!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
1945 							pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
1946 							aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know
1947 						else
1948 							aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node
1949 					}
1950 
1951 					bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL,
1952 											aCtrlRegion, nState, aControlValue, rtl::OUString() );
1953 				}
1954 
1955 				if( !bNativeOK) {
1956 				//non native
1957 					DrawImage( aPos, *pImg ,nStyle);
1958 				}
1959 			}
1960 		}
1961 	}
1962 
1963 
1964 	if( bHasClipRegion && bResetClipRegion )
1965 		SetClipRegion();
1966 	return 0; // nRowLen;
1967 }
1968 
1969 void SvTreeListBox::PreparePaint( SvLBoxEntry* )
1970 {
1971 }
1972 
1973 Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine )
1974 {
1975 	DBG_CHKTHIS(SvTreeListBox,0);
1976 	Size aSize;
1977 	Rectangle aRect;
1978 	aRect.Top() = nLine;
1979 	aSize.Height() = GetEntryHeight();
1980 
1981 	long nRealWidth = pImp->GetOutputSize().Width();
1982 	nRealWidth -= GetMapMode().GetOrigin().X();
1983 
1984 	sal_uInt16 nCurTab;
1985 	SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab );
1986 	long nTabPos = 0;
1987 	if( pTab )
1988 		nTabPos = GetTabPos( pEntry, pTab );
1989 	long nNextTabPos;
1990 	if( pTab && nCurTab < aTabs.Count() - 1 )
1991 	{
1992 		SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 );
1993 		nNextTabPos = GetTabPos( pEntry, pNextTab );
1994 	}
1995 	else
1996 	{
1997 		nNextTabPos = nRealWidth;
1998 		if( nTabPos > nRealWidth )
1999 			nNextTabPos += 50;
2000 	}
2001 
2002 	sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0;
2003 	if( !bUserSelection )
2004 	{
2005 		if( pTab && nCurTab < pEntry->ItemCount() )
2006 		{
2007 			SvLBoxItem* pItem = pEntry->GetItem( nCurTab );
2008 			aSize.Width() = pItem->GetSize( this, pEntry ).Width();
2009 			if( !aSize.Width() )
2010 				aSize.Width() = 15;
2011 			long nX = nTabPos; //GetTabPos( pEntry, pTab );
2012 			// Ausrichtung
2013 			nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos );
2014 			aRect.Left() = nX;
2015 			// damit erster & letzter Buchstabe nicht angeknabbert werden
2016 			aRect.SetSize( aSize );
2017 			if( aRect.Left() > 0 )
2018 				aRect.Left()--;
2019 			aRect.Right()++;
2020 		}
2021 	}
2022 	else
2023 	{
2024 		// wenn erster SelTab != 0, dann muessen wir auch rechnen
2025 		if( nFocusWidth == -1 || nFirstSelTab )
2026 		{
2027 			sal_uInt16 nLastTab;
2028 			SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab);
2029 			nLastTab++;
2030 			if( nLastTab < aTabs.Count() ) // gibts noch einen ?
2031 				pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab );
2032 			else
2033 				pLastTab = 0;  // ueber gesamte Breite selektieren
2034 			aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff;
2035 			nFocusWidth = (short)aSize.Width();
2036 			if( pTab )
2037 				nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos();
2038 		}
2039 		else
2040 		{
2041 			aSize.Width() = nFocusWidth;
2042 			if( pTab )
2043 			{
2044 				if( nCurTab )
2045 					aSize.Width() += nTabPos;
2046 				else
2047 					aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links
2048 			}
2049 		}
2050 		// wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen
2051 		if( nCurTab != 0 )
2052 		{
2053 			aRect.Left() = nTabPos;
2054 			aSize.Width() -= nTabPos;
2055 		}
2056 		aRect.SetSize( aSize );
2057 	}
2058 	// rechten Rand anpassen wg. Clipping
2059 	if( aRect.Right() >= nRealWidth )
2060 	{
2061 		aRect.Right() = nRealWidth-1;
2062 		nFocusWidth = (short)aRect.GetWidth();
2063 	}
2064 	return aRect;
2065 }
2066 
2067 
2068 long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab)
2069 {
2070 	DBG_CHKTHIS(SvTreeListBox,0);
2071 	DBG_ASSERT(pTab,"No Tab");
2072 	long nPos = pTab->GetPos();
2073 	if( pTab->IsDynamic() )
2074 	{
2075 		sal_uInt16 nDepth = pModel->GetDepth( pEntry );
2076 		nDepth = nDepth * (sal_uInt16)nIndent;
2077 		nPos += (long)nDepth;
2078 	}
2079 	return nPos;
2080 }
2081 
2082 SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX,
2083 	SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth )
2084 {
2085 	DBG_CHKTHIS(SvTreeListBox,0);
2086 	SvLBoxItem* pItemClicked = 0;
2087 	sal_uInt16 nTabCount = aTabs.Count();
2088 	sal_uInt16 nItemCount = pEntry->ItemCount();
2089 	SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
2090 	SvLBoxItem* pItem = pEntry->GetItem(0);
2091 	sal_uInt16 nNextItem = 1;
2092 	nX -= GetMapMode().GetOrigin().X();
2093 	long nRealWidth = pImp->GetOutputSize().Width();
2094 	nRealWidth -= GetMapMode().GetOrigin().X();
2095 
2096 	while( 1 )
2097 	{
2098 		SvLBoxTab* pNextTab=nNextItem<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0;
2099 		long nStart = GetTabPos( pEntry, pTab );
2100 
2101 		long nNextTabPos;
2102 		if( pNextTab )
2103 			nNextTabPos = GetTabPos( pEntry, pNextTab );
2104 		else
2105 		{
2106 			nNextTabPos = nRealWidth;
2107 			if( nStart > nRealWidth )
2108 				nNextTabPos += 50;
2109 		}
2110 
2111 		Size aItemSize( pItem->GetSize(this, pEntry));
2112 		nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart );
2113 		long nLen = aItemSize.Width();
2114 		if( pNextTab )
2115 		{
2116 			long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart;
2117 			if( nTabWidth < nLen )
2118 				nLen = nTabWidth;
2119 		}
2120 
2121 		if( !nLen )
2122 			nLen = nEmptyWidth;
2123 
2124 		if( nX >= nStart && nX < (nStart+nLen ) )
2125 		{
2126 			pItemClicked = pItem;
2127 			if( ppTab )
2128 			{
2129 				*ppTab = pTab;
2130 				break;
2131 			}
2132 		}
2133 		if( nNextItem >= nItemCount || nNextItem >= nTabCount)
2134 			break;
2135 		pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem );
2136 		pItem = pEntry->GetItem( nNextItem );
2137 		nNextItem++;
2138 	}
2139 	return pItemClicked;
2140 }
2141 
2142 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab)
2143 {
2144 	return GetItem_Impl( pEntry, nX, ppTab, 0 );
2145 }
2146 
2147 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX )
2148 {
2149 	DBG_CHKTHIS(SvTreeListBox,0);
2150 	SvLBoxTab* pDummyTab;
2151 	return GetItem_Impl( pEntry, nX, &pDummyTab, 0 );
2152 }
2153 
2154 SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry )
2155 {
2156 	DBG_CHKTHIS(SvTreeListBox,0);
2157 
2158 	SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
2159 	SvLBoxItem* pItem = pEntry->GetItem(0);
2160 	sal_uInt16 nTabCount = aTabs.Count();
2161 
2162 	sal_uInt16 nNext = 1;
2163 	while ( !pTab->IsDynamic() && nNext < nTabCount )
2164 	{
2165 		pItem = pEntry->GetItem( nNext );
2166 		pTab = (SvLBoxTab*)aTabs.GetObject( nNext );
2167 		nNext++;
2168 	}
2169 	return pItem;
2170 }
2171 
2172 void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData )
2173 {
2174 	DBG_CHKTHIS(SvTreeListBox,0);
2175 	nFocusWidth = -1;
2176 	SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags );
2177 	pTab->SetUserData( pUserData );
2178 	aTabs.Insert( pTab, aTabs.Count() );
2179 	if( nTreeFlags & TREEFLAG_USESEL )
2180 	{
2181 		sal_uInt16 nPos = aTabs.Count() - 1;
2182 		if( nPos >= nFirstSelTab && nPos <= nLastSelTab )
2183 			pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION;
2184 		else
2185 			// String-Items werden normalerweise immer selektiert
2186 			// deshalb explizit ausschalten
2187 			pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION;
2188 	}
2189 }
2190 
2191 
2192 
2193 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const
2194 {
2195 	DBG_CHKTHIS(SvTreeListBox,0);
2196 	sal_uInt16 nCurTab = 0;
2197 	sal_uInt16 nTabCount = aTabs.Count();
2198 	while( nCurTab < nTabCount )
2199 	{
2200 		SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab);
2201 		if( pTab->nFlags & SV_LBOXTAB_DYNAMIC )
2202 		{
2203 			rPos = nCurTab;
2204 			return pTab;
2205 		}
2206 		nCurTab++;
2207 	}
2208 	return 0;
2209 }
2210 
2211 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const
2212 {
2213 	sal_uInt16 nDummy;
2214 	return GetFirstDynamicTab( nDummy );
2215 }
2216 
2217 SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const
2218 {
2219 	DBG_CHKTHIS(SvTreeListBox,0);
2220 	sal_uInt16 nPos = pEntry->GetPos( pItem );
2221 	return (SvLBoxTab*)aTabs.GetObject( nPos );
2222 }
2223 
2224 void SvTreeListBox::ClearTabList()
2225 {
2226 	DBG_CHKTHIS(SvTreeListBox,0);
2227 	sal_uInt16 nTabCount = aTabs.Count();
2228 	while( nTabCount )
2229 	{
2230 		nTabCount--;
2231 		SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount );
2232 		delete pDelTab;
2233 	}
2234 	aTabs.Remove(0,aTabs.Count());
2235 }
2236 
2237 
2238 Size SvTreeListBox::GetOutputSizePixel() const
2239 {
2240 	DBG_CHKTHIS(SvTreeListBox,0);
2241 	Size aSize = pImp->GetOutputSize();
2242 	return aSize;
2243 }
2244 
2245 void SvTreeListBox::NotifyBeginScroll()
2246 {
2247 	DBG_CHKTHIS(SvTreeListBox,0);
2248 }
2249 
2250 void SvTreeListBox::NotifyEndScroll()
2251 {
2252 	DBG_CHKTHIS(SvTreeListBox,0);
2253 }
2254 
2255 void SvTreeListBox::NotifyScrolling( long )
2256 {
2257 	DBG_CHKTHIS(SvTreeListBox,0);
2258 }
2259 
2260 void SvTreeListBox::NotifyScrolled()
2261 {
2262 	DBG_CHKTHIS(SvTreeListBox,0);
2263 	aScrolledHdl.Call( this );
2264 }
2265 
2266 void SvTreeListBox::NotifyInvalidating()
2267 {
2268 	DBG_CHKTHIS(SvTreeListBox,0);
2269 }
2270 
2271 void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags )
2272 {
2273 	DBG_CHKTHIS(SvTreeListBox,0);
2274 	if( nFocusWidth == -1 )
2275 		// damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
2276 		pImp->RecalcFocusRect();
2277 	NotifyInvalidating();
2278 	SvLBox::Invalidate( nInvalidateFlags );
2279 	pImp->Invalidate();
2280 }
2281 
2282 void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags )
2283 {
2284 	DBG_CHKTHIS(SvTreeListBox,0);
2285 	if( nFocusWidth == -1 )
2286 		// damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
2287 		pImp->RecalcFocusRect();
2288 	NotifyInvalidating();
2289 	SvLBox::Invalidate( rRect, nInvalidateFlags );
2290 }
2291 
2292 
2293 void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd)
2294 {
2295 	DBG_CHKTHIS(SvTreeListBox,0);
2296 
2297 	sal_uInt16 nTemp;
2298 	nTreeFlags |= TREEFLAG_USESEL;
2299 	if( nStart > nEnd )
2300 	{
2301 		nTemp = nStart;
2302 		nStart = nEnd;
2303 		nEnd = nTemp;
2304 	}
2305 	// alle Tabs markieren, die im Bereich liegen
2306 	nTreeFlags |= TREEFLAG_RECALCTABS;
2307 	nFirstSelTab = nStart;
2308 	nLastSelTab = nEnd;
2309 	pImp->RecalcFocusRect();
2310 }
2311 
2312 void SvTreeListBox::RemoveHighlightRange()
2313 {
2314 	DBG_CHKTHIS(SvTreeListBox,0);
2315 	nTreeFlags &= (~TREEFLAG_USESEL);
2316 	if( IsUpdateMode() )
2317 		Invalidate();
2318 }
2319 
2320 sal_uLong SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
2321 {
2322 	return LIST_APPEND;
2323 }
2324 
2325 sal_uLong SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
2326 {
2327 	DBG_CHKTHIS(SvTreeListBox,0);
2328 	return LIST_APPEND;
2329 }
2330 
2331 Region SvTreeListBox::GetDragRegion() const
2332 {
2333 	DBG_CHKTHIS(SvTreeListBox,0);
2334 	Rectangle aRect;
2335 	SvLBoxEntry* pEntry = GetCurEntry();
2336 	if( pEntry )
2337 	{
2338 		Point aPos = GetEntryPosition( pEntry );
2339 		aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() );
2340 	}
2341 	Region aRegion( aRect );
2342 	return aRegion;
2343 }
2344 
2345 
2346 void SvTreeListBox::Command( const CommandEvent& rCEvt )
2347 {
2348 	DBG_CHKTHIS(SvTreeListBox,0);
2349     // FIXME gnumake2 resync to DEV300_m84
2350 	pImp->Command( rCEvt );
2351 }
2352 
2353 
2354 void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent )
2355 {
2356 	DBG_CHKTHIS(SvTreeListBox,0);
2357 	DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent");
2358 	SvLBoxEntry* pNewParent = GetParent( pParent );
2359 	if( pParent->HasChilds())
2360 	{
2361 		SvLBoxEntry* pChild = FirstChild( pParent );
2362 		while( pChild )
2363 		{
2364 			pModel->Move( pChild, pNewParent, LIST_APPEND );
2365 			pChild = FirstChild( pParent );
2366 		}
2367 	}
2368 	pModel->Remove( pParent );
2369 }
2370 
2371 SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos )
2372 {
2373 	sal_uInt16 nTabCount = aTabs.Count();
2374 	for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ )
2375 	{
2376 		SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos );
2377 		if( (pTab->nFlags & nFlagMask) )
2378 		{
2379 			rPos = nPos;
2380 			return pTab;
2381 		}
2382 	}
2383 	rPos = 0xffff;
2384 	return 0;
2385 }
2386 
2387 SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos )
2388 {
2389 	short nTabCount = (short)aTabs.Count();
2390 	if( nTabCount )
2391 	{
2392 		for( short nPos = nTabCount-1; nPos >= 0; nPos-- )
2393 		{
2394 			SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (sal_uInt16)nPos );
2395 			if( (pTab->nFlags & nFlagMask) )
2396 			{
2397 				rTabPos = (sal_uInt16)nPos;
2398 				return pTab;
2399 			}
2400 		}
2401 	}
2402 	rTabPos = 0xffff;
2403 	return 0;
2404 }
2405 
2406 void SvTreeListBox::SetAddMode( sal_Bool bAdd )
2407 {
2408 	pImp->SetAddMode( bAdd );
2409 }
2410 
2411 sal_Bool SvTreeListBox::IsAddMode() const
2412 {
2413 	return pImp->IsAddMode();
2414 }
2415 
2416 void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt )
2417 {
2418 	if( !pImp->RequestHelp( rHEvt ) )
2419 		SvLBox::RequestHelp( rHEvt );
2420 }
2421 
2422 void SvTreeListBox::CursorMoved( SvLBoxEntry* )
2423 {
2424 }
2425 
2426 IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData )
2427 {
2428 	SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft );
2429 	SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight );
2430 	String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
2431 	String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
2432 	// #102891# ----------------
2433 	pImp->UpdateIntlWrapper();
2434 	return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight );
2435 }
2436 
2437 void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1,
2438 						SvListEntry* pEntry2, sal_uLong nPos )
2439 {
2440 	if( nActionId == LISTACTION_CLEARING )
2441 		CancelTextEditing();
2442 
2443 	SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos );
2444 	switch( nActionId )
2445 	{
2446         case LISTACTION_INSERTED:
2447         {
2448             SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) );
2449             ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" );
2450             SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
2451             if ( !pBmpItem )
2452                 break;
2453             const Image& rBitmap1( pBmpItem->GetBitmap1() );
2454             const Image& rBitmap2( pBmpItem->GetBitmap2() );
2455             short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) );
2456 	        nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth );
2457 	        if( nMaxWidth > nContextBmpWidthMax )
2458 	        {
2459 		        nContextBmpWidthMax = nMaxWidth;
2460 		        SetTabs();
2461 	        }
2462         }
2463         break;
2464 
2465 		case LISTACTION_RESORTING:
2466 			SetUpdateMode( sal_False );
2467 			break;
2468 
2469 		case LISTACTION_RESORTED:
2470 			// nach Sortierung den ersten Eintrag anzeigen, dabei die
2471 			// Selektion erhalten.
2472 			MakeVisible( (SvLBoxEntry*)pModel->First(), sal_True );
2473 			SetUpdateMode( sal_True );
2474 			break;
2475 
2476 		case LISTACTION_CLEARED:
2477 			if( IsUpdateMode() )
2478 				Update();
2479 			break;
2480 	}
2481 }
2482 
2483 // bei Aenderungen SetTabs beruecksichtigen
2484 long SvTreeListBox::GetTextOffset() const
2485 {
2486 	DBG_CHKTHIS(SvTreeListBox,0);
2487     const WinBits nWindowStyle = GetStyle();
2488 	sal_Bool bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0;
2489 	sal_Bool bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT |
2490 											  WB_HASBUTTONSATROOT))!=0;
2491 	long nStartPos = TAB_STARTPOS;
2492 	long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
2493 
2494 	long nCheckWidth = 0;
2495 	if( nTreeFlags & TREEFLAG_CHKBTN )
2496 		nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width();
2497 	long nCheckWidthDIV2 = nCheckWidth / 2;
2498 
2499 	long nContextWidth = nContextBmpWidthMax;
2500 	long nContextWidthDIV2 = nContextWidth / 2;
2501 
2502 	int nCase = NO_BUTTONS;
2503 	if( !(nTreeFlags & TREEFLAG_CHKBTN) )
2504 	{
2505 		if( bHasButtons )
2506 			nCase = NODE_BUTTONS;
2507 	}
2508 	else
2509 	{
2510 		if( bHasButtons )
2511 			nCase = NODE_AND_CHECK_BUTTONS;
2512 		 else
2513 			nCase = CHECK_BUTTONS;
2514 	}
2515 
2516 	switch( nCase )
2517 	{
2518 		case NO_BUTTONS :
2519 			nStartPos += nContextWidthDIV2;  // wg. Zentrierung
2520 			nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2521 			if( nContextBmpWidthMax )
2522 				nStartPos += 5; // Abstand Context-Bmp - Text
2523 			break;
2524 
2525 		case NODE_BUTTONS :
2526 			if( bHasButtonsAtRoot )
2527 				nStartPos += ( nIndent + (nNodeWidthPixel/2) );
2528 			else
2529 				nStartPos += nContextWidthDIV2;
2530 			nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2531 			if( nContextBmpWidthMax )
2532 				nStartPos += 5; // Abstand Context-Bmp - Text
2533 			break;
2534 
2535 		case NODE_AND_CHECK_BUTTONS :
2536 			if( bHasButtonsAtRoot )
2537 				nStartPos += ( nIndent + nNodeWidthPixel );
2538 			else
2539 				nStartPos += nCheckWidthDIV2;
2540 			nStartPos += nCheckWidthDIV2;  // rechter Rand des CheckButtons
2541 			nStartPos += 3;  // Abstand CheckButton Context-Bmp
2542 			nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
2543 			nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2544 			// Abstand setzen nur wenn Bitmaps da
2545 			if( nContextBmpWidthMax )
2546 				nStartPos += 5; // Abstand Context-Bmp - Text
2547 			break;
2548 
2549 		case CHECK_BUTTONS :
2550 			nStartPos += nCheckWidthDIV2;
2551 			nStartPos += nCheckWidthDIV2;  // rechter Rand CheckButton
2552 			nStartPos += 3;  // Abstand CheckButton Context-Bmp
2553 			nStartPos += nContextWidthDIV2;  // Mitte der Context-Bmp
2554 			nStartPos += nContextWidthDIV2;  // rechter Rand der Context-Bmp
2555 			if( nContextBmpWidthMax )
2556 				nStartPos += 5; // Abstand Context-Bmp - Text
2557 			break;
2558 	}
2559 	return nStartPos;
2560 }
2561 
2562 void SvTreeListBox::EndSelection()
2563 {
2564 	pImp->EndSelection();
2565 }
2566 
2567 sal_Bool SvTreeListBox::IsNodeButton( const Point& rPos ) const
2568 {
2569 	SvLBoxEntry* pEntry = GetEntry( rPos );
2570 	if( pEntry )
2571 		return pImp->IsNodeButton( rPos, pEntry );
2572 	return sal_False;
2573 }
2574 
2575 void SvTreeListBox::RepaintScrollBars() const
2576 {
2577 	((SvTreeListBox*)this)->pImp->RepaintScrollBars();
2578 }
2579 
2580 ScrollBar *SvTreeListBox::GetVScroll()
2581 {
2582 	return &((SvTreeListBox*)this)->pImp->aVerSBar;
2583 }
2584 
2585 ScrollBar *SvTreeListBox::GetHScroll()
2586 {
2587 	return &((SvTreeListBox*)this)->pImp->aHorSBar;
2588 }
2589 
2590 void SvTreeListBox::EnableAsyncDrag( sal_Bool b )
2591 {
2592 	pImp->EnableAsyncDrag( b );
2593 }
2594 
2595 SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const
2596 {
2597 	Point aPos;
2598 	return GetEntry( aPos );
2599 }
2600 
2601 SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const
2602 {
2603 	SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry );
2604 	if( pNext )
2605 	{
2606 		Point aPos( GetEntryPosition(pNext) );
2607 		const Size& rSize = pImp->GetOutputSize();
2608 		if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
2609 			return 0;
2610 	}
2611 	return pNext;
2612 }
2613 
2614 void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry )
2615 {
2616 	pImp->ShowFocusRect( pEntry );
2617 }
2618 
2619 void SvTreeListBox::SetTabBar( TabBar* pTabBar )
2620 {
2621 	pImp->SetTabBar( pTabBar );
2622 }
2623 
2624 void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt )
2625 {
2626 	if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
2627 	{
2628 		nEntryHeight = 0;	// _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height
2629 							//	forces complete recalc of heights!
2630 		InitSettings( sal_True, sal_True, sal_True );
2631 		Invalidate();
2632 	}
2633 	else
2634 		Control::DataChanged( rDCEvt );
2635 }
2636 
2637 void SvTreeListBox::StateChanged( StateChangedType i_nStateChange )
2638 {
2639     SvLBox::StateChanged( i_nStateChange );
2640     if ( i_nStateChange == STATE_CHANGE_STYLE )
2641         ImplInitStyle();
2642 }
2643 
2644 void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground)
2645 {
2646 	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2647 	if( bFont )
2648 	{
2649 		Font aFont;
2650 		aFont = rStyleSettings.GetFieldFont();
2651 		aFont.SetColor( rStyleSettings.GetWindowTextColor() );
2652 		SetPointFont( aFont );
2653         AdjustEntryHeight( aFont );
2654         RecalcViewData();
2655 	}
2656 
2657 	if( bForeground || bFont )
2658 	{
2659 		SetTextColor( rStyleSettings.GetFieldTextColor() );
2660 		SetTextFillColor();
2661 	}
2662 
2663 	if( bBackground )
2664 		SetBackground( rStyleSettings.GetFieldColor() );
2665 
2666 	// always try to re-create default-SvLBoxButtonData
2667 	if( pCheckButtonData && pCheckButtonData->HasDefaultImages() )
2668 		pCheckButtonData->SetDefaultImages( this );
2669 }
2670 
2671 sal_Bool SvTreeListBox::IsCellFocusEnabled() const
2672 {
2673 	return pImp->IsCellFocusEnabled();
2674 }
2675 
2676 bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
2677 {
2678 	return pImp->SetCurrentTabPos( _nNewPos );
2679 }
2680 
2681 sal_uInt16 SvTreeListBox::GetCurrentTabPos() const
2682 {
2683 	return pImp->GetCurrentTabPos();
2684 }
2685 
2686 void SvTreeListBox::InitStartEntry()
2687 {
2688 	if( !pImp->pStartEntry )
2689 		pImp->pStartEntry = GetModel()->First();
2690 }
2691 
2692 void SvTreeListBox::CancelPendingEdit()
2693 {
2694 	if( pImp )
2695 		pImp->CancelPendingEdit();
2696 }
2697 
2698 PopupMenu* SvTreeListBox::CreateContextMenu( void )
2699 {
2700 	return NULL;
2701 }
2702 
2703 void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 )
2704 {
2705 	DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" );
2706 }
2707 
2708 void SvTreeListBox::EnableContextMenuHandling( void )
2709 {
2710 	DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
2711 
2712 	pImp->bContextMenuHandling = sal_True;
2713 }
2714 
2715 void SvTreeListBox::EnableContextMenuHandling( sal_Bool b )
2716 {
2717 	DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
2718 
2719 	pImp->bContextMenuHandling = b;
2720 }
2721 
2722 sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const
2723 {
2724 	DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" );
2725 
2726 	return pImp->bContextMenuHandling;
2727 }
2728 
2729 void SvTreeListBox::EnableList( bool _bEnable )
2730 {
2731     // call base class method
2732     Window::Enable( _bEnable != false );
2733     // then paint immediately
2734     Paint( Rectangle( Point(), GetSizePixel() ) );
2735 }
2736 
2737 ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible()
2738 {
2739     Window* pParent = GetAccessibleParentWindow();
2740     DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" );
2741 
2742     ::com::sun::star::uno::Reference< XAccessible > xAccessible;
2743     if ( pParent )
2744     {
2745         ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
2746         if ( xAccParent.is() )
2747 		{
2748 			// need to be done here to get the vclxwindow later on in the accessbile
2749 			::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface());
2750             xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent );
2751 		}
2752 	}
2753     return xAccessible;
2754 }
2755 
2756 void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const
2757 {
2758 	DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" );
2759 
2760 	if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() )
2761 	{
2762 		rStateSet.AddState( AccessibleStateType::EXPANDABLE );
2763 		if ( IsExpanded( pEntry ) )
2764 		    rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED );
2765 	}
2766 
2767 	if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED )
2768 		rStateSet.AddState( AccessibleStateType::CHECKED );
2769 	if ( IsEntryVisible( pEntry ) )
2770 		rStateSet.AddState( AccessibleStateType::VISIBLE );
2771 	if ( IsSelected( pEntry ) )
2772 		rStateSet.AddState( AccessibleStateType::SELECTED );
2773 	if ( IsEnabled() )
2774 	{
2775 		rStateSet.AddState( AccessibleStateType::ENABLED );
2776 		rStateSet.AddState( AccessibleStateType::FOCUSABLE );
2777 		rStateSet.AddState( AccessibleStateType::SELECTABLE );
2778 		SvViewDataEntry* pViewDataNewCur = 0;
2779 		if( pEntry )
2780 		{
2781 			pViewDataNewCur= GetViewDataEntry(pEntry);
2782 			if(pViewDataNewCur->HasFocus())
2783 				rStateSet.AddState( AccessibleStateType::FOCUSED );
2784 		}
2785 	}
2786 }
2787 
2788 Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry )
2789 {
2790 	Point aPos = GetEntryPosition( pEntry );
2791 	Rectangle aRect = GetFocusRect( pEntry, aPos.Y() );
2792 	return aRect;
2793 }
2794 
2795 void SvTreeListBox::EnableCellFocus()
2796 {
2797 	pImp->EnableCellFocus();
2798 }
2799 
2800 void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData)
2801 {
2802 	CallEventListeners(nEvent, pData);
2803 }
2804 
2805 void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const
2806 {
2807       SvLBox::FillAccessibleStateSet( rStateSet );
2808 }
2809 
2810