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