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