xref: /aoo41x/main/svtools/source/contnr/svlbox.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 /*
32 	Todo:
33 		- Anker loeschen in SelectionEngine bei manuellem Selektieren
34 		- SelectAll( sal_False ), nur die deselektierten Entries repainten
35 */
36 
37 #include <string.h>
38 #include <svtools/svlbox.hxx>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <vcl/svapp.hxx>
41 #include <vcl/accel.hxx>
42 #include <vcl/i18nhelp.hxx>
43 #include <sot/formats.hxx>
44 #include <unotools/accessiblestatesethelper.hxx>
45 #include <rtl/instance.hxx>
46 
47 #define _SVSTDARR_ULONGSSORT
48 #include <svl/svstdarr.hxx>
49 
50 #ifndef _SVEDI_HXX
51 #include <svtools/svmedit.hxx>
52 #endif
53 #include <svtools/svlbitm.hxx>
54 
55 using namespace ::com::sun::star::accessibility;
56 
57 // Drag&Drop
58 static SvLBox* pDDSource = NULL;
59 static SvLBox* pDDTarget = NULL;
60 
61 DBG_NAME(SvInplaceEdit)
62 DBG_NAME(SvInplaceEdit2)
63 
64 #define SVLBOX_ACC_RETURN 1
65 #define SVLBOX_ACC_ESCAPE 2
66 
67 SvInplaceEdit::SvInplaceEdit
68 (
69 	Window*				pParent,
70 	const Point&		rPos,
71 	const Size&			rSize,
72 	const String&		rData,
73 	const Link&			rNotifyEditEnd,
74 	const Selection&	rSelection
75 ) :
76 
77 	Edit( pParent, WB_LEFT ),
78 
79 	aCallBackHdl		( rNotifyEditEnd ),
80 	bCanceled			( sal_False ),
81 	bAlreadyInCallBack	( sal_False )
82 
83 {
84 	DBG_CTOR(SvInplaceEdit,0);
85 
86 	Font aFont( pParent->GetFont() );
87 	aFont.SetTransparent( sal_False );
88 	Color aColor( pParent->GetBackground().GetColor() );
89 	aFont.SetFillColor(aColor );
90 	SetFont( aFont );
91 	SetBackground( pParent->GetBackground() );
92 	SetPosPixel( rPos );
93 	SetSizePixel( rSize );
94 	SetText( rData );
95 	SetSelection( rSelection );
96 	SaveValue();
97 
98 	aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
99 	aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
100 
101 	aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit, ReturnHdl_Impl) );
102 	aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit, EscapeHdl_Impl) );
103 	GetpApp()->InsertAccel( &aAccReturn  );
104 	GetpApp()->InsertAccel( &aAccEscape );
105 
106 	Show();
107 	GrabFocus();
108 }
109 
110 SvInplaceEdit::~SvInplaceEdit()
111 {
112 	DBG_DTOR(SvInplaceEdit,0);
113 	if( !bAlreadyInCallBack )
114 	{
115 		GetpApp()->RemoveAccel( &aAccReturn );
116 		GetpApp()->RemoveAccel( &aAccEscape );
117 	}
118 }
119 
120 IMPL_LINK_INLINE_START( SvInplaceEdit, ReturnHdl_Impl, Accelerator *, EMPTYARG )
121 {
122 	DBG_CHKTHIS(SvInplaceEdit,0);
123 	bCanceled = sal_False;
124 	CallCallBackHdl_Impl();
125 	return 1;
126 }
127 IMPL_LINK_INLINE_END( SvInplaceEdit, ReturnHdl_Impl, Accelerator *, EMPTYARG )
128 
129 IMPL_LINK_INLINE_START( SvInplaceEdit, EscapeHdl_Impl, Accelerator *, EMPTYARG )
130 {
131 	DBG_CHKTHIS(SvInplaceEdit,0);
132 	bCanceled = sal_True;
133 	CallCallBackHdl_Impl();
134 	return 1;
135 }
136 IMPL_LINK_INLINE_END( SvInplaceEdit, EscapeHdl_Impl, Accelerator *, EMPTYARG )
137 
138 void SvInplaceEdit::KeyInput( const KeyEvent& rKEvt )
139 {
140 	DBG_CHKTHIS(SvInplaceEdit,0);
141 	sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
142 	switch ( nCode )
143 	{
144 		case KEY_ESCAPE:
145 			bCanceled = sal_True;
146 			CallCallBackHdl_Impl();
147 			break;
148 
149 		case KEY_RETURN:
150 			bCanceled = sal_False;
151 			CallCallBackHdl_Impl();
152 			break;
153 
154 		default:
155 			Edit::KeyInput( rKEvt );
156 	}
157 }
158 
159 void SvInplaceEdit::StopEditing( sal_Bool bCancel )
160 {
161 	DBG_CHKTHIS(SvInplaceEdit,0);
162 	if ( !bAlreadyInCallBack )
163 	{
164 		bCanceled = bCancel;
165 		CallCallBackHdl_Impl();
166 	}
167 }
168 
169 void SvInplaceEdit::LoseFocus()
170 {
171 	DBG_CHKTHIS(SvInplaceEdit,0);
172 	if ( !bAlreadyInCallBack )
173 	{
174 		bCanceled = sal_False;
175 		aTimer.SetTimeout(10);
176 		aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit,Timeout_Impl));
177 		aTimer.Start();
178 	}
179 }
180 
181 IMPL_LINK_INLINE_START( SvInplaceEdit, Timeout_Impl, Timer *, EMPTYARG )
182 {
183 	DBG_CHKTHIS(SvInplaceEdit,0);
184 	CallCallBackHdl_Impl();
185 	return 0;
186 }
187 IMPL_LINK_INLINE_END( SvInplaceEdit, Timeout_Impl, Timer *, EMPTYARG )
188 
189 void SvInplaceEdit::CallCallBackHdl_Impl()
190 {
191 	DBG_CHKTHIS(SvInplaceEdit,0);
192 	aTimer.Stop();
193 	if ( !bAlreadyInCallBack )
194 	{
195 		bAlreadyInCallBack = sal_True;
196 		GetpApp()->RemoveAccel( &aAccReturn );
197 		GetpApp()->RemoveAccel( &aAccEscape );
198 		Hide();
199 		aCallBackHdl.Call( this );
200 		// bAlreadyInCallBack = sal_False;
201 	}
202 }
203 
204 
205 // ***************************************************************
206 
207 class MyEdit_Impl : public Edit
208 {
209 	SvInplaceEdit2* pOwner;
210 public:
211 				 MyEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
212 	virtual void KeyInput( const KeyEvent& rKEvt );
213 	virtual void LoseFocus();
214 };
215 
216 class MyMultiEdit_Impl : public MultiLineEdit
217 {
218 	SvInplaceEdit2* pOwner;
219 public:
220 				 MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
221 	virtual void KeyInput( const KeyEvent& rKEvt );
222 	virtual void LoseFocus();
223 };
224 
225 MyEdit_Impl::MyEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner ) :
226 
227 	Edit( pParent, WB_LEFT ),
228 
229 	pOwner( _pOwner )
230 
231 {
232 }
233 
234 void MyEdit_Impl::KeyInput( const KeyEvent& rKEvt )
235 {
236 	if( !pOwner->KeyInput( rKEvt ))
237 		Edit::KeyInput( rKEvt );
238 }
239 
240 void MyEdit_Impl::LoseFocus()
241 {
242 	pOwner->LoseFocus();
243 }
244 
245 MyMultiEdit_Impl::MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner )
246 	: MultiLineEdit( pParent,
247 	WB_CENTER
248 	), pOwner(_pOwner)
249 {
250 }
251 
252 void MyMultiEdit_Impl::KeyInput( const KeyEvent& rKEvt )
253 {
254 	if( !pOwner->KeyInput( rKEvt ))
255 		MultiLineEdit::KeyInput( rKEvt );
256 }
257 
258 void MyMultiEdit_Impl::LoseFocus()
259 {
260 	pOwner->LoseFocus();
261 }
262 
263 
264 SvInplaceEdit2::SvInplaceEdit2
265 (
266 	Window* pParent, const Point& rPos,
267 	const Size& rSize,
268 	const String& rData,
269 	const Link& rNotifyEditEnd,
270 	const Selection& rSelection,
271 	sal_Bool bMulti
272 ) :
273 
274 	 aCallBackHdl		( rNotifyEditEnd ),
275 	bCanceled			( sal_False ),
276 	bAlreadyInCallBack	( sal_False ),
277 	bMultiLine			( bMulti )
278 
279 {
280 	DBG_CTOR(SvInplaceEdit2,0);
281 
282 	if( bMulti )
283 		pEdit = new MyMultiEdit_Impl( pParent, this );
284 	else
285 		pEdit = new MyEdit_Impl( pParent, this );
286 
287 	Font aFont( pParent->GetFont() );
288 	aFont.SetTransparent( sal_False );
289 	Color aColor( pParent->GetBackground().GetColor() );
290 	aFont.SetFillColor(aColor );
291 	pEdit->SetFont( aFont );
292 	pEdit->SetBackground( pParent->GetBackground() );
293 	pEdit->SetPosPixel( rPos );
294 	pEdit->SetSizePixel( rSize );
295 	pEdit->SetText( rData );
296 	pEdit->SetSelection( rSelection );
297 	pEdit->SaveValue();
298 
299 	aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
300 	aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
301 
302 	aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit2, ReturnHdl_Impl) );
303 	aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit2, EscapeHdl_Impl) );
304 	GetpApp()->InsertAccel( &aAccReturn );
305 	GetpApp()->InsertAccel( &aAccEscape );
306 
307 	pEdit->Show();
308 	pEdit->GrabFocus();
309 }
310 
311 SvInplaceEdit2::~SvInplaceEdit2()
312 {
313 	DBG_DTOR(SvInplaceEdit2,0);
314 	if( !bAlreadyInCallBack )
315 	{
316 		GetpApp()->RemoveAccel( &aAccReturn );
317 		GetpApp()->RemoveAccel( &aAccEscape );
318 	}
319 	delete pEdit;
320 }
321 
322 String SvInplaceEdit2::GetSavedValue() const
323 {
324 	return pEdit->GetSavedValue();
325 }
326 
327 void SvInplaceEdit2::Hide()
328 {
329 	pEdit->Hide();
330 }
331 
332 
333 IMPL_LINK_INLINE_START( SvInplaceEdit2, ReturnHdl_Impl, Accelerator *, EMPTYARG )
334 {
335 	DBG_CHKTHIS(SvInplaceEdit2,0);
336 	bCanceled = sal_False;
337 	CallCallBackHdl_Impl();
338 	return 1;
339 }
340 IMPL_LINK_INLINE_END( SvInplaceEdit2, ReturnHdl_Impl, Accelerator *, EMPTYARG )
341 
342 IMPL_LINK_INLINE_START( SvInplaceEdit2, EscapeHdl_Impl, Accelerator *, EMPTYARG )
343 {
344 	DBG_CHKTHIS(SvInplaceEdit2,0);
345 	bCanceled = sal_True;
346 	CallCallBackHdl_Impl();
347 	return 1;
348 }
349 IMPL_LINK_INLINE_END( SvInplaceEdit2, EscapeHdl_Impl, Accelerator *, EMPTYARG )
350 
351 
352 sal_Bool SvInplaceEdit2::KeyInput( const KeyEvent& rKEvt )
353 {
354 	DBG_CHKTHIS(SvInplaceEdit2,0);
355 	KeyCode aCode = rKEvt.GetKeyCode();
356 	sal_uInt16 nCode = aCode.GetCode();
357 
358 	switch ( nCode )
359 	{
360 		case KEY_ESCAPE:
361 			bCanceled = sal_True;
362 			CallCallBackHdl_Impl();
363 			return sal_True;
364 
365 		case KEY_RETURN:
366             bCanceled = sal_False;
367             CallCallBackHdl_Impl();
368             return sal_True;
369 	}
370 	return sal_False;
371 }
372 
373 void SvInplaceEdit2::StopEditing( sal_Bool bCancel )
374 {
375 	DBG_CHKTHIS(SvInplaceEdit2,0);
376 	if ( !bAlreadyInCallBack )
377 	{
378 		bCanceled = bCancel;
379 		CallCallBackHdl_Impl();
380 	}
381 }
382 
383 void SvInplaceEdit2::LoseFocus()
384 {
385 	DBG_CHKTHIS(SvInplaceEdit2,0);
386 	if ( !bAlreadyInCallBack
387 	&& ((!Application::GetFocusWindow()) || !pEdit->IsChild( Application::GetFocusWindow()) )
388 	)
389 	{
390 		bCanceled = sal_False;
391 		aTimer.SetTimeout(10);
392 		aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit2,Timeout_Impl));
393 		aTimer.Start();
394 	}
395 }
396 
397 IMPL_LINK_INLINE_START( SvInplaceEdit2, Timeout_Impl, Timer *, EMPTYARG )
398 {
399 	DBG_CHKTHIS(SvInplaceEdit2,0);
400 	CallCallBackHdl_Impl();
401 	return 0;
402 }
403 IMPL_LINK_INLINE_END( SvInplaceEdit2, Timeout_Impl, Timer *, EMPTYARG )
404 
405 void SvInplaceEdit2::CallCallBackHdl_Impl()
406 {
407 	DBG_CHKTHIS(SvInplaceEdit2,0);
408 	aTimer.Stop();
409 	if ( !bAlreadyInCallBack )
410 	{
411 		bAlreadyInCallBack = sal_True;
412 		GetpApp()->RemoveAccel( &aAccReturn );
413 		GetpApp()->RemoveAccel( &aAccEscape );
414 		pEdit->Hide();
415 		aCallBackHdl.Call( this );
416 	}
417 }
418 
419 String SvInplaceEdit2::GetText() const
420 {
421 	return pEdit->GetText();
422 }
423 
424 // ***************************************************************
425 // class SvLBoxTab
426 // ***************************************************************
427 
428 DBG_NAME(SvLBoxTab);
429 
430 SvLBoxTab::SvLBoxTab()
431 {
432 	DBG_CTOR(SvLBoxTab,0);
433 	nPos = 0;
434 	pUserData = 0;
435 	nFlags = 0;
436 }
437 
438 SvLBoxTab::SvLBoxTab( long nPosition, sal_uInt16 nTabFlags )
439 {
440 	DBG_CTOR(SvLBoxTab,0);
441 	nPos = nPosition;
442 	pUserData = 0;
443 	nFlags = nTabFlags;
444 }
445 
446 SvLBoxTab::SvLBoxTab( const SvLBoxTab& rTab )
447 {
448 	DBG_CTOR(SvLBoxTab,0);
449 	nPos = rTab.nPos;
450 	pUserData = rTab.pUserData;
451 	nFlags = rTab.nFlags;
452 }
453 
454 SvLBoxTab::~SvLBoxTab()
455 {
456 	DBG_DTOR(SvLBoxTab,0);
457 }
458 
459 
460 long SvLBoxTab::CalcOffset( long nItemWidth, long nTabWidth )
461 {
462 	DBG_CHKTHIS(SvLBoxTab,0);
463 	long nOffset = 0;
464 	if ( nFlags & SV_LBOXTAB_ADJUST_RIGHT )
465 	{
466 		nOffset = nTabWidth - nItemWidth;
467 		if( nOffset < 0 )
468 			nOffset = 0;
469 	}
470 	else if ( nFlags & SV_LBOXTAB_ADJUST_CENTER )
471 	{
472 		if( nFlags & SV_LBOXTAB_FORCE )
473 		{
474 			//richtige Implementierung der Zentrierung
475 			nOffset = ( nTabWidth - nItemWidth ) / 2;
476 			if( nOffset < 0 )
477 				nOffset = 0;
478 		}
479 		else
480 		{
481 			// historisch gewachsene falsche Berechnung des Tabs, auf die sich
482 			// Abo-Tabbox, Extras/Optionen/Anpassen etc. verlassen
483 			nItemWidth++;
484 			nOffset = -( nItemWidth / 2 );
485 		}
486 	}
487 	return nOffset;
488 }
489 
490 /*
491 long SvLBoxTab::CalcOffset( const String& rStr, const OutputDevice& rOutDev )
492 {
493 	DBG_CHKTHIS(SvLBoxTab,0);
494 	long nWidth;
495 	if ( nFlags & SV_LBOXTAB_ADJUST_NUMERIC )
496 	{
497 		sal_uInt16 nPos = rStr.Search( '.' );
498 		if ( nPos == STRING_NOTFOUND )
499 			nPos = rStr.Search( ',' );
500 		if ( nPos == STRING_NOTFOUND )
501 			nPos = STRING_LEN;
502 
503 		nWidth = rOutDev.GetTextSize( rStr, 0, nPos ).Width();
504 		nWidth *= -1;
505 	}
506 	else
507 	{
508 		nWidth = rOutDev.GetTextSize( rStr ).Width();
509 		nWidth = CalcOffset( nWidth );
510 	}
511 	return nWidth;
512 }
513 */
514 
515 // ***************************************************************
516 // class SvLBoxItem
517 // ***************************************************************
518 
519 DBG_NAME(SvLBoxItem);
520 
521 SvLBoxItem::SvLBoxItem( SvLBoxEntry*, sal_uInt16 )
522 {
523 	DBG_CTOR(SvLBoxItem,0);
524 }
525 
526 SvLBoxItem::SvLBoxItem()
527 {
528 	DBG_CTOR(SvLBoxItem,0);
529 }
530 
531 SvLBoxItem::~SvLBoxItem()
532 {
533 	DBG_DTOR(SvLBoxItem,0);
534 }
535 
536 const Size& SvLBoxItem::GetSize( SvLBox* pView,SvLBoxEntry* pEntry )
537 {
538 	DBG_CHKTHIS(SvLBoxItem,0);
539 	SvViewDataItem*	pViewData = pView->GetViewDataItem( pEntry, this );
540 	return pViewData->aSize;
541 }
542 
543 const Size& SvLBoxItem::GetSize( SvLBoxEntry* pEntry, SvViewDataEntry* pViewData)
544 {
545 	DBG_CHKTHIS(SvLBoxItem,0);
546 	sal_uInt16 nItemPos = pEntry->GetPos( this );
547 	SvViewDataItem* pItemData = pViewData->pItemData+nItemPos;
548 	return pItemData->aSize;
549 }
550 
551 DBG_NAME(SvViewDataItem);
552 
553 SvViewDataItem::SvViewDataItem()
554 {
555 	DBG_CTOR(SvViewDataItem,0);
556 }
557 
558 SvViewDataItem::~SvViewDataItem()
559 {
560 	DBG_DTOR(SvViewDataItem,0);
561 }
562 
563 
564 
565 // ***************************************************************
566 // class SvLBoxEntry
567 // ***************************************************************
568 
569 DBG_NAME(SvLBoxEntry);
570 
571 SvLBoxEntry::SvLBoxEntry() : aItems()
572 {
573 	DBG_CTOR(SvLBoxEntry,0);
574 	nEntryFlags = 0;
575 	pUserData = 0;
576 }
577 
578 SvLBoxEntry::~SvLBoxEntry()
579 {
580 	DBG_DTOR(SvLBoxEntry,0);
581 	DeleteItems_Impl();
582 }
583 
584 void SvLBoxEntry::DeleteItems_Impl()
585 {
586 	DBG_CHKTHIS(SvLBoxEntry,0);
587 	sal_uInt16 nCount = aItems.Count();
588 	while( nCount )
589 	{
590 		nCount--;
591 		SvLBoxItem* pItem = (SvLBoxItem*)aItems.GetObject( nCount );
592 		delete pItem;
593 	}
594 	aItems.Remove(0, aItems.Count() );
595 }
596 
597 
598 void SvLBoxEntry::AddItem( SvLBoxItem* pItem )
599 {
600 	DBG_CHKTHIS(SvLBoxEntry,0);
601 	aItems.Insert( pItem, aItems.Count() );
602 }
603 
604 void SvLBoxEntry::Clone( SvListEntry* pSource )
605 {
606 	DBG_CHKTHIS(SvLBoxEntry,0);
607 	SvListEntry::Clone( pSource );
608 	SvLBoxItem* pNewItem;
609 	DeleteItems_Impl();
610 	sal_uInt16 nCount = ((SvLBoxEntry*)pSource)->ItemCount();
611 	sal_uInt16 nCurPos = 0;
612 	while( nCurPos < nCount )
613 	{
614 		SvLBoxItem* pItem = ((SvLBoxEntry*)pSource)->GetItem( nCurPos );
615 		pNewItem = pItem->Create();
616 		pNewItem->Clone( pItem );
617 		AddItem( pNewItem );
618 		nCurPos++;
619 	}
620 	pUserData = ((SvLBoxEntry*)pSource)->GetUserData();
621 	nEntryFlags = ((SvLBoxEntry*)pSource)->nEntryFlags;
622 }
623 
624 void SvLBoxEntry::EnableChildsOnDemand( sal_Bool bEnable )
625 {
626 	DBG_CHKTHIS(SvLBoxEntry,0);
627 	if ( bEnable )
628 		nEntryFlags |= SV_ENTRYFLAG_CHILDS_ON_DEMAND;
629 	else
630 		nEntryFlags &= (~SV_ENTRYFLAG_CHILDS_ON_DEMAND);
631 }
632 
633 void SvLBoxEntry::ReplaceItem( SvLBoxItem* pNewItem, sal_uInt16 nPos )
634 {
635 	DBG_CHKTHIS(SvLBoxEntry,0);
636 	DBG_ASSERT(pNewItem,"ReplaceItem:No Item");
637 	SvLBoxItem* pOld = GetItem( nPos );
638 	if ( pOld )
639 	{
640 		aItems.Remove( nPos );
641 		aItems.Insert( pNewItem, nPos );
642 		delete pOld;
643 	}
644 }
645 
646 SvLBoxItem* SvLBoxEntry::GetFirstItem( sal_uInt16 nId )
647 {
648 	sal_uInt16 nCount = aItems.Count();
649 	sal_uInt16 nCur = 0;
650 	SvLBoxItem* pItem;
651 	while( nCur < nCount )
652 	{
653 		pItem = GetItem( nCur );
654 		if( pItem->IsA() == nId )
655 			return pItem;
656 		nCur++;
657 	}
658 	return 0;
659 }
660 
661 // ***************************************************************
662 // class SvLBoxViewData
663 // ***************************************************************
664 
665 DBG_NAME(SvViewDataEntry);
666 
667 SvViewDataEntry::SvViewDataEntry()
668 	: SvViewData()
669 {
670 	DBG_CTOR(SvViewDataEntry,0);
671 	pItemData = 0;
672 }
673 
674 SvViewDataEntry::~SvViewDataEntry()
675 {
676 	DBG_DTOR(SvViewDataEntry,0);
677 	delete [] pItemData;
678 }
679 
680 // ***************************************************************
681 // struct SvLBox_Impl
682 // ***************************************************************
683 SvLBox_Impl::SvLBox_Impl( SvLBox& _rBox )
684     :m_bIsEmptyTextAllowed( true )
685     ,m_bEntryMnemonicsEnabled( false )
686     ,m_bDoingQuickSelection( false )
687     ,m_pLink( NULL )
688     ,m_aMnemonicEngine( _rBox )
689     ,m_aQuickSelectionEngine( _rBox )
690 {
691 }
692 
693 // ***************************************************************
694 // class SvLBox
695 // ***************************************************************
696 
697 DBG_NAME(SvLBox);
698 
699 SvLBox::SvLBox( Window* pParent, WinBits nWinStyle	) :
700 	Control( pParent, nWinStyle | WB_CLIPCHILDREN ),
701     DropTargetHelper( this ), DragSourceHelper( this ), eSelMode( NO_SELECTION )
702 {
703 	DBG_CTOR(SvLBox,0);
704 	nDragOptions =  DND_ACTION_COPYMOVE | DND_ACTION_LINK;
705 	nImpFlags = 0;
706 	pTargetEntry = 0;
707 	nDragDropMode = 0;
708     pLBoxImpl = new SvLBox_Impl( *this );
709 	SvLBoxTreeList* pTempModel = new SvLBoxTreeList;
710 	pTempModel->SetRefCount( 0 );
711 	SetModel( pTempModel );
712 	pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
713 	pModel->InsertView( this );
714 	pHdlEntry = 0;
715 	pEdCtrl = 0;
716 	SetSelectionMode( SINGLE_SELECTION );  // pruefen ob TreeListBox gecallt wird
717 	SetDragDropMode( SV_DRAGDROP_NONE );
718 	SetType(WINDOW_TREELISTBOX);
719 }
720 
721 SvLBox::SvLBox( Window* pParent, const ResId& rResId ) :
722 	Control( pParent, rResId ),
723     DropTargetHelper( this ), DragSourceHelper( this ), eSelMode( NO_SELECTION )
724 {
725 	DBG_CTOR(SvLBox,0);
726 	pTargetEntry = 0;
727 	nImpFlags = 0;
728     pLBoxImpl = new SvLBox_Impl( *this );
729 	nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
730 	nDragDropMode = 0;
731 	SvLBoxTreeList* pTempModel = new SvLBoxTreeList;
732 	pTempModel->SetRefCount( 0 );
733 	SetModel( pTempModel );
734 	pModel->InsertView( this );
735 	pHdlEntry = 0;
736 	pEdCtrl = 0;
737 	pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
738 	SetType(WINDOW_TREELISTBOX);
739 }
740 
741 __EXPORT SvLBox::~SvLBox()
742 {
743 	DBG_DTOR(SvLBox,0);
744 	delete pEdCtrl;
745 	pEdCtrl = 0;
746 	pModel->RemoveView( this );
747 	if ( pModel->GetRefCount() == 0 )
748 	{
749 		pModel->Clear();
750 		delete pModel;
751 		pModel = NULL;
752 	}
753 
754 	SvLBox::RemoveBoxFromDDList_Impl( *this );
755 
756 	if( this == pDDSource )
757 		pDDSource = 0;
758 	if( this == pDDTarget )
759 		pDDTarget = 0;
760     delete pLBoxImpl;
761 }
762 
763 void SvLBox::SetModel( SvLBoxTreeList* pNewModel )
764 {
765 	DBG_CHKTHIS(SvLBox,0);
766 	// erledigt das ganz CleanUp
767 	SvListView::SetModel( pNewModel );
768 	pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
769 	SvLBoxEntry* pEntry = First();
770 	while( pEntry )
771 	{
772 		ModelHasInserted( pEntry );
773 		pEntry = Next( pEntry );
774 	}
775 }
776 
777 void SvLBox::DisconnectFromModel()
778 {
779 	DBG_CHKTHIS(SvLBox,0);
780 	SvLBoxTreeList* pNewModel = new SvLBoxTreeList;
781 	pNewModel->SetRefCount( 0 );	// else this will never be deleted
782 	SvListView::SetModel( pNewModel );
783 }
784 
785 void SvLBox::Clear()
786 {
787 	DBG_CHKTHIS(SvLBox,0);
788 	pModel->Clear();  // Model ruft SvLBox::ModelHasCleared() auf
789 }
790 
791 void SvLBox::EnableEntryMnemonics( bool _bEnable )
792 {
793     if ( _bEnable == IsEntryMnemonicsEnabled() )
794         return;
795 
796     pLBoxImpl->m_bEntryMnemonicsEnabled = _bEnable;
797     Invalidate();
798 }
799 
800 bool SvLBox::IsEntryMnemonicsEnabled() const
801 {
802     return pLBoxImpl->m_bEntryMnemonicsEnabled;
803 }
804 
805 sal_uInt16 SvLBox::IsA()
806 {
807 	DBG_CHKTHIS(SvLBox,0);
808 	return SVLISTBOX_ID_LBOX;
809 }
810 
811 IMPL_LINK_INLINE_START( SvLBox, CloneHdl_Impl, SvListEntry*, pEntry )
812 {
813 	DBG_CHKTHIS(SvLBox,0);
814 	return (long)(CloneEntry((SvLBoxEntry*)pEntry));
815 }
816 IMPL_LINK_INLINE_END( SvLBox, CloneHdl_Impl, SvListEntry*, pEntry )
817 
818 sal_uLong SvLBox::Insert( SvLBoxEntry* pEntry, SvLBoxEntry* pParent, sal_uLong nPos )
819 {
820 	DBG_CHKTHIS(SvLBox,0);
821 	sal_uLong nInsPos = pModel->Insert( pEntry, pParent, nPos );
822 	return nInsPos;
823 }
824 
825 sal_uLong SvLBox::Insert( SvLBoxEntry* pEntry,sal_uLong nRootPos )
826 {
827 	DBG_CHKTHIS(SvLBox,0);
828 	sal_uLong nInsPos = pModel->Insert( pEntry, nRootPos );
829 	return nInsPos;
830 }
831 
832 long SvLBox::ExpandingHdl()
833 {
834 	DBG_CHKTHIS(SvLBox,0);
835 	return aExpandingHdl.IsSet() ? aExpandingHdl.Call( this ) : 1;
836 }
837 
838 void SvLBox::ExpandedHdl()
839 {
840 	DBG_CHKTHIS(SvLBox,0);
841 	aExpandedHdl.Call( this );
842 }
843 
844 void SvLBox::SelectHdl()
845 {
846 	DBG_CHKTHIS(SvLBox,0);
847 	aSelectHdl.Call( this );
848 }
849 
850 void SvLBox::DeselectHdl()
851 {
852 	DBG_CHKTHIS(SvLBox,0);
853 	aDeselectHdl.Call( this );
854 }
855 
856 sal_Bool SvLBox::DoubleClickHdl()
857 {
858 	DBG_CHKTHIS(SvLBox,0);
859 	aDoubleClickHdl.Call( this );
860 	return sal_True;
861 }
862 
863 
864 sal_Bool SvLBox::CheckDragAndDropMode( SvLBox* pSource, sal_Int8 nAction )
865 {
866 	DBG_CHKTHIS(SvLBox,0);
867 	if ( pSource == this )
868 	{
869 		if ( !(nDragDropMode & (SV_DRAGDROP_CTRL_MOVE | SV_DRAGDROP_CTRL_COPY) ) )
870 			return sal_False; // D&D innerhalb der Liste gesperrt
871 		if( DND_ACTION_MOVE == nAction )
872 		{
873 			if ( !(nDragDropMode & SV_DRAGDROP_CTRL_MOVE) )
874 				 return sal_False; // kein lokales Move
875 		}
876 		else
877 		{
878 			if ( !(nDragDropMode & SV_DRAGDROP_CTRL_COPY))
879 				return sal_False; // kein lokales Copy
880 		}
881 	}
882 	else
883 	{
884 		if ( !(nDragDropMode & SV_DRAGDROP_APP_DROP ) )
885 			return sal_False; // kein Drop
886 		if ( DND_ACTION_MOVE == nAction )
887 		{
888 			if ( !(nDragDropMode & SV_DRAGDROP_APP_MOVE) )
889 				return sal_False; // kein globales Move
890 		}
891 		else
892 		{
893 			if ( !(nDragDropMode & SV_DRAGDROP_APP_COPY))
894 				return sal_False; // kein globales Copy
895 		}
896 	}
897 	return sal_True;
898 }
899 
900 
901 
902 
903 void SvLBox::NotifyRemoving( SvLBoxEntry* )
904 {
905 	DBG_CHKTHIS(SvLBox,0);
906 }
907 
908 /*
909 	NotifyMoving/Copying
910 	====================
911 
912 	Standard-Verhalten:
913 
914 	1. Target hat keine Childs
915 		- Entry wird Sibling des Targets. Entry steht hinter dem
916 		  Target (->Fenster: Unter dem Target)
917 	2. Target ist ein aufgeklappter Parent
918 		- Entry wird an den Anfang der Target-Childlist gehaengt
919 	3. Target ist ein zugeklappter Parent
920 		- Entry wird an das Ende der Target-Childlist gehaengt
921 */
922 #ifdef DBG_UTIL
923 sal_Bool SvLBox::NotifyMoving(
924 	SvLBoxEntry*  pTarget,		 // D&D-Drop-Position in this->GetModel()
925 	SvLBoxEntry*  pEntry,		 // Zu verschiebender Entry aus
926 								 // GetSourceListBox()->GetModel()
927 	SvLBoxEntry*& rpNewParent,   // Neuer Target-Parent
928 	sal_uLong&		  rNewChildPos)  // Position in Childlist des Target-Parents
929 #else
930 sal_Bool SvLBox::NotifyMoving(
931 	SvLBoxEntry*  pTarget,		 // D&D-Drop-Position in this->GetModel()
932 	SvLBoxEntry*,        		 // Zu verschiebender Entry aus
933 								 // GetSourceListBox()->GetModel()
934 	SvLBoxEntry*& rpNewParent,   // Neuer Target-Parent
935 	sal_uLong&		  rNewChildPos)  // Position in Childlist des Target-Parents
936 #endif
937 {
938 	DBG_CHKTHIS(SvLBox,0);
939 	DBG_ASSERT(pEntry,"NotifyMoving:SoureEntry?");
940 	if( !pTarget )
941 	{
942 		rpNewParent = 0;
943 		rNewChildPos = 0;
944 		return sal_True;
945 	}
946 	if ( !pTarget->HasChilds() && !pTarget->HasChildsOnDemand() )
947 	{
948 		// Fall 1
949 		rpNewParent = GetParent( pTarget );
950 		rNewChildPos = pModel->GetRelPos( pTarget ) + 1;
951 		rNewChildPos += nCurEntrySelPos;
952 		nCurEntrySelPos++;
953 	}
954 	else
955 	{
956 		// Faelle 2 & 3
957 		rpNewParent = pTarget;
958 		if( IsExpanded(pTarget))
959 			rNewChildPos = 0;
960 		else
961 			rNewChildPos = LIST_APPEND;
962 	}
963 	return sal_True;
964 }
965 
966 sal_Bool SvLBox::NotifyCopying(
967 	SvLBoxEntry*  pTarget,		 // D&D-Drop-Position in this->GetModel()
968 	SvLBoxEntry*  pEntry,		 // Zu kopierender Entry aus
969 								 // GetSourceListBox()->GetModel()
970 	SvLBoxEntry*& rpNewParent,   // Neuer Target-Parent
971 	sal_uLong&		  rNewChildPos)  // Position in Childlist des Target-Parents
972 {
973 	DBG_CHKTHIS(SvLBox,0);
974 	return NotifyMoving(pTarget,pEntry,rpNewParent,rNewChildPos);
975 	/*
976 	DBG_ASSERT(pEntry,"NotifyCopying:SourceEntry?");
977 	if( !pTarget )
978 	{
979 		rpNewParent = 0;
980 		rNewChildPos = 0;
981 		return sal_True;
982 	}
983 	if ( !pTarget->HasChilds() && !pTarget->HasChildsOnDemand() )
984 	{
985 		// Fall 1
986 		rpNewParent = GetParent( pTarget );
987 		rNewChildPos = GetRelPos( pTarget ) + 1;
988 	}
989 	else
990 	{
991 		// Faelle 2 & 3
992 		rpNewParent = pTarget;
993 		if( IsExpanded(pTarget))
994 			rNewChildPos = 0;
995 		else
996 			rNewChildPos = LIST_APPEND;
997 	}
998 	return sal_True;
999 	*/
1000 }
1001 
1002 SvLBoxEntry* SvLBox::CloneEntry( SvLBoxEntry* pSource )
1003 {
1004 	DBG_CHKTHIS(SvLBox,0);
1005 	SvLBoxEntry* pEntry = (SvLBoxEntry*)CreateEntry(); // new SvLBoxEntry;
1006 	pEntry->Clone( (SvListEntry*)pSource );
1007 	return pEntry;
1008 }
1009 
1010 
1011 // Rueckgabe: Alle Entries wurden kopiert
1012 sal_Bool SvLBox::CopySelection( SvLBox* pSource, SvLBoxEntry* pTarget )
1013 {
1014 	DBG_CHKTHIS(SvLBox,0);
1015 	nCurEntrySelPos = 0; // Selektionszaehler fuer NotifyMoving/Copying
1016 	sal_Bool bSuccess = sal_True;
1017 	SvTreeEntryList aList;
1018 	sal_Bool bClone = (sal_Bool)( (sal_uLong)(pSource->GetModel()) != (sal_uLong)GetModel() );
1019 	Link aCloneLink( pModel->GetCloneLink() );
1020 	pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
1021 
1022 	// Selektion zwischenspeichern, um bei D&D-Austausch
1023 	// innerhalb der gleichen Listbox das Iterieren ueber
1024 	// die Selektion zu vereinfachen
1025 	SvLBoxEntry* pSourceEntry = pSource->FirstSelected();
1026 	while ( pSourceEntry )
1027 	{
1028 		// Childs werden automatisch mitkopiert
1029 		pSource->SelectChilds( pSourceEntry, sal_False );
1030 		aList.Insert( pSourceEntry, LIST_APPEND );
1031 		pSourceEntry = pSource->NextSelected( pSourceEntry );
1032 	}
1033 
1034 	pSourceEntry = (SvLBoxEntry*)aList.First();
1035 	while ( pSourceEntry )
1036 	{
1037 		SvLBoxEntry* pNewParent = 0;
1038 		sal_uLong nInsertionPos = LIST_APPEND;
1039 		sal_Bool bOk=NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
1040 		if ( bOk )
1041 		{
1042 			if ( bClone )
1043 			{
1044 				sal_uLong nCloneCount = 0;
1045 				pSourceEntry = (SvLBoxEntry*)
1046 					pModel->Clone( (SvListEntry*)pSourceEntry, nCloneCount );
1047 				pModel->InsertTree( (SvListEntry*)pSourceEntry,
1048 									(SvListEntry*)pNewParent, nInsertionPos );
1049 			}
1050 			else
1051 			{
1052 				sal_uLong nListPos = pModel->Copy( (SvListEntry*)pSourceEntry,
1053 					(SvListEntry*)pNewParent, nInsertionPos );
1054 				pSourceEntry = GetEntry( pNewParent, nListPos );
1055 			}
1056 		}
1057 		else
1058 			bSuccess = sal_False;
1059 
1060 		if( bOk == (sal_Bool)2 )  // !!!HACK  verschobenen Entry sichtbar machen?
1061 			MakeVisible( pSourceEntry );
1062 
1063 		pSourceEntry = (SvLBoxEntry*)aList.Next();
1064 	}
1065 	pModel->SetCloneLink( aCloneLink );
1066 	return bSuccess;
1067 }
1068 
1069 // Rueckgabe: Alle Entries wurden verschoben
1070 sal_Bool SvLBox::MoveSelection( SvLBox* pSource, SvLBoxEntry* pTarget )
1071 {
1072 	return MoveSelectionCopyFallbackPossible( pSource, pTarget, sal_False );
1073 }
1074 
1075 sal_Bool SvLBox::MoveSelectionCopyFallbackPossible( SvLBox* pSource, SvLBoxEntry* pTarget, sal_Bool bAllowCopyFallback )
1076 {
1077 	DBG_CHKTHIS(SvLBox,0);
1078 	nCurEntrySelPos = 0; // Selektionszaehler fuer NotifyMoving/Copying
1079 	sal_Bool bSuccess = sal_True;
1080 	SvTreeEntryList aList;
1081 	sal_Bool bClone = (sal_Bool)( (sal_uLong)(pSource->GetModel()) != (sal_uLong)GetModel() );
1082 	Link aCloneLink( pModel->GetCloneLink() );
1083 	if ( bClone )
1084 		pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
1085 
1086 	SvLBoxEntry* pSourceEntry = pSource->FirstSelected();
1087 	while ( pSourceEntry )
1088 	{
1089 		// Childs werden automatisch mitbewegt
1090 		pSource->SelectChilds( pSourceEntry, sal_False );
1091 		aList.Insert( pSourceEntry, LIST_APPEND );
1092 		pSourceEntry = pSource->NextSelected( pSourceEntry );
1093 	}
1094 
1095 	pSourceEntry = (SvLBoxEntry*)aList.First();
1096 	while ( pSourceEntry )
1097 	{
1098 		SvLBoxEntry* pNewParent = 0;
1099 		sal_uLong nInsertionPos = LIST_APPEND;
1100 		sal_Bool bOk = NotifyMoving(pTarget,pSourceEntry,pNewParent,nInsertionPos);
1101 		sal_Bool bCopyOk = bOk;
1102 		if ( !bOk && bAllowCopyFallback )
1103 		{
1104 			nInsertionPos = LIST_APPEND;
1105 			bCopyOk = NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
1106 		}
1107 
1108 		if ( bOk || bCopyOk )
1109 		{
1110 			if ( bClone )
1111 			{
1112 				sal_uLong nCloneCount = 0;
1113 				pSourceEntry = (SvLBoxEntry*)
1114 					pModel->Clone( (SvListEntry*)pSourceEntry, nCloneCount );
1115 				pModel->InsertTree( (SvListEntry*)pSourceEntry,
1116 									(SvListEntry*)pNewParent, nInsertionPos );
1117 			}
1118 			else
1119 			{
1120 				if ( bOk )
1121 					pModel->Move( (SvListEntry*)pSourceEntry,
1122 								  (SvListEntry*)pNewParent, nInsertionPos );
1123 				else
1124 					pModel->Copy( (SvListEntry*)pSourceEntry,
1125 								  (SvListEntry*)pNewParent, nInsertionPos );
1126 			}
1127 		}
1128 		else
1129 			bSuccess = sal_False;
1130 
1131 		if( bOk == (sal_Bool)2 )  // !!!HACK  verschobenen Entry sichtbar machen?
1132 			MakeVisible( pSourceEntry );
1133 
1134 		pSourceEntry = (SvLBoxEntry*)aList.Next();
1135 	}
1136 	pModel->SetCloneLink( aCloneLink );
1137 	return bSuccess;
1138 }
1139 
1140 void SvLBox::RemoveSelection()
1141 {
1142 	DBG_CHKTHIS(SvLBox,0);
1143 	SvTreeEntryList aList;
1144 	// Selektion zwischenspeichern, da die Impl bei
1145 	// dem ersten Remove alles deselektiert!
1146 	SvLBoxEntry* pEntry = FirstSelected();
1147 	while ( pEntry )
1148 	{
1149 		aList.Insert( pEntry );
1150 		if ( pEntry->HasChilds() )
1151 			// Remove loescht Childs automatisch
1152 			SelectChilds( pEntry, sal_False );
1153 		pEntry = NextSelected( pEntry );
1154 	}
1155 	pEntry = (SvLBoxEntry*)aList.First();
1156 	while ( pEntry )
1157 	{
1158 		pModel->Remove( pEntry );
1159 		pEntry = (SvLBoxEntry*)aList.Next();
1160 	}
1161 }
1162 
1163 SvLBox* SvLBox::GetSourceView() const
1164 {
1165 	return pDDSource;
1166 }
1167 
1168 SvLBox* SvLBox::GetTargetView() const
1169 {
1170 	return pDDTarget;
1171 }
1172 
1173 void SvLBox::RequestingChilds( SvLBoxEntry*  )
1174 {
1175 	DBG_CHKTHIS(SvLBox,0);
1176 	DBG_ERROR("Child-Request-Hdl not implemented!");
1177 }
1178 
1179 void SvLBox::RecalcViewData()
1180 {
1181 	DBG_CHKTHIS(SvLBox,0);
1182 	SvLBoxEntry* pEntry = First();
1183 	while( pEntry )
1184 	{
1185 		sal_uInt16 nCount = pEntry->ItemCount();
1186 		sal_uInt16 nCurPos = 0;
1187 		while ( nCurPos < nCount )
1188 		{
1189 			SvLBoxItem* pItem = pEntry->GetItem( nCurPos );
1190 			pItem->InitViewData( this, pEntry );
1191 			nCurPos++;
1192 		}
1193 		ViewDataInitialized( pEntry );
1194 		pEntry = Next( pEntry );
1195 	}
1196 }
1197 
1198 void SvLBox::ViewDataInitialized( SvLBoxEntry* )
1199 {
1200 	DBG_CHKTHIS(SvLBox,0);
1201 }
1202 
1203 void SvLBox::StateChanged( StateChangedType eType )
1204 {
1205     if( eType == STATE_CHANGE_ENABLE )
1206         Invalidate( INVALIDATE_CHILDREN );
1207     Control::StateChanged( eType );
1208 }
1209 
1210 void SvLBox::ImplShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool bShow)
1211 {
1212 	DBG_CHKTHIS(SvLBox,0);
1213 	if ( bShow && (nImpFlags & SVLBOX_TARGEMPH_VIS) )
1214 		return;
1215 	if ( !bShow && !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
1216 		return;
1217 	ShowTargetEmphasis( pEntry, bShow );
1218 	if( bShow )
1219 		nImpFlags |= SVLBOX_TARGEMPH_VIS;
1220 	else
1221 		nImpFlags &= ~SVLBOX_TARGEMPH_VIS;
1222 }
1223 
1224 void SvLBox::ShowTargetEmphasis( SvLBoxEntry*, sal_Bool /* bShow */ )
1225 {
1226 	DBG_CHKTHIS(SvLBox,0);
1227 }
1228 
1229 
1230 sal_Bool SvLBox::Expand( SvLBoxEntry* )
1231 {
1232 	DBG_CHKTHIS(SvLBox,0);
1233 	return sal_True;
1234 }
1235 
1236 sal_Bool SvLBox::Collapse( SvLBoxEntry* )
1237 {
1238 	DBG_CHKTHIS(SvLBox,0);
1239 	return sal_True;
1240 }
1241 
1242 sal_Bool SvLBox::Select( SvLBoxEntry*, sal_Bool  )
1243 {
1244 	DBG_CHKTHIS(SvLBox,0);
1245 	return sal_False;
1246 }
1247 
1248 sal_uLong SvLBox::SelectChilds( SvLBoxEntry* , sal_Bool  )
1249 {
1250 	DBG_CHKTHIS(SvLBox,0);
1251 	return 0;
1252 }
1253 
1254 void SvLBox::OnCurrentEntryChanged()
1255 {
1256     if ( !pLBoxImpl->m_bDoingQuickSelection )
1257         pLBoxImpl->m_aQuickSelectionEngine.Reset();
1258 }
1259 
1260 void SvLBox::SelectAll( sal_Bool /* bSelect */ , sal_Bool /* bPaint */ )
1261 {
1262 	DBG_CHKTHIS(SvLBox,0);
1263 }
1264 
1265 SvLBoxEntry* SvLBox::GetEntryFromPath( const ::std::deque< sal_Int32 >& _rPath ) const
1266 {
1267 	DBG_CHKTHIS(SvLBox,0);
1268 
1269 	SvLBoxEntry* pEntry = NULL;
1270 	SvLBoxEntry* pParent = NULL;
1271 	for( ::std::deque< sal_Int32 >::const_iterator pItem = _rPath.begin(); pItem != _rPath.end(); ++pItem )
1272 	{
1273 		pEntry = GetEntry( pParent, *pItem );
1274 		if ( !pEntry )
1275 			break;
1276 		pParent = pEntry;
1277 	}
1278 
1279 	return pEntry;
1280 }
1281 
1282 void SvLBox::FillEntryPath( SvLBoxEntry* pEntry, ::std::deque< sal_Int32 >& _rPath ) const
1283 {
1284 	DBG_CHKTHIS(SvLBox,0);
1285 
1286 	if ( pEntry )
1287 	{
1288 		SvLBoxEntry* pParentEntry = GetParent( pEntry );
1289 		while ( sal_True )
1290 		{
1291 			sal_uLong i, nCount = GetLevelChildCount( pParentEntry );
1292 			for ( i = 0; i < nCount; ++i )
1293 			{
1294 				SvLBoxEntry* pTemp = GetEntry( pParentEntry, i );
1295 				DBG_ASSERT( pEntry, "invalid entry" );
1296 				if ( pEntry == pTemp )
1297 				{
1298 					_rPath.push_front( (sal_Int32)i );
1299 					break;
1300 				}
1301 			}
1302 
1303 			if ( pParentEntry )
1304 			{
1305 				pEntry = pParentEntry;
1306 				pParentEntry = GetParent( pParentEntry );
1307 			}
1308 			else
1309 				break;
1310 		}
1311 	}
1312 }
1313 
1314 String SvLBox::GetEntryText( SvLBoxEntry* ) const
1315 {
1316 	DBG_CHKTHIS(SvLBox,0);
1317 
1318 	return String();
1319 }
1320 
1321 sal_uLong SvLBox::GetLevelChildCount( SvLBoxEntry* _pParent ) const
1322 {
1323 	DBG_CHKTHIS(SvLBox,0);
1324 
1325 	sal_uLong nCount = 0;
1326 	SvLBoxEntry* pEntry = FirstChild( _pParent );
1327 	while ( pEntry )
1328 	{
1329 		++nCount;
1330 		pEntry = NextSibling( pEntry );
1331 	}
1332 
1333 	return nCount;
1334 }
1335 
1336 void SvLBox::SetSelectionMode( SelectionMode eSelectMode )
1337 {
1338 	DBG_CHKTHIS(SvLBox,0);
1339 	eSelMode = eSelectMode;
1340 }
1341 
1342 void SvLBox::SetDragDropMode( DragDropMode nDDMode )
1343 {
1344 	DBG_CHKTHIS(SvLBox,0);
1345 	nDragDropMode = nDDMode;
1346 }
1347 
1348 SvViewData* SvLBox::CreateViewData( SvListEntry* )
1349 {
1350 	DBG_CHKTHIS(SvLBox,0);
1351 	SvViewDataEntry* pEntryData = new SvViewDataEntry;
1352 	return (SvViewData*)pEntryData;
1353 }
1354 
1355 void SvLBox::InitViewData( SvViewData* pData, SvListEntry* pEntry )
1356 {
1357 	DBG_CHKTHIS(SvLBox,0);
1358 	SvLBoxEntry* pInhEntry = (SvLBoxEntry*)pEntry;
1359 	SvViewDataEntry* pEntryData = (SvViewDataEntry*)pData;
1360 
1361 	pEntryData->pItemData = new SvViewDataItem[ pInhEntry->ItemCount() ];
1362 	SvViewDataItem* pItemData = pEntryData->pItemData;
1363 	pEntryData->nItmCnt = pInhEntry->ItemCount(); // Anzahl Items fuer delete
1364 	sal_uInt16 nCount = pInhEntry->ItemCount();
1365 	sal_uInt16 nCurPos = 0;
1366 	while( nCurPos < nCount )
1367 	{
1368 		SvLBoxItem* pItem = pInhEntry->GetItem( nCurPos );
1369 		pItem->InitViewData( this, pInhEntry, pItemData );
1370 		pItemData++;
1371 		nCurPos++;
1372 	}
1373 }
1374 
1375 
1376 
1377 void SvLBox::EnableSelectionAsDropTarget( sal_Bool bEnable, sal_Bool bWithChilds )
1378 {
1379 	DBG_CHKTHIS(SvLBox,0);
1380 	sal_uInt16 nRefDepth;
1381 	SvLBoxEntry* pTemp;
1382 
1383 	SvLBoxEntry* pSelEntry = FirstSelected();
1384 	while( pSelEntry )
1385 	{
1386 		if ( !bEnable )
1387 		{
1388 			pSelEntry->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
1389 			if ( bWithChilds )
1390 			{
1391 				nRefDepth = pModel->GetDepth( pSelEntry );
1392 				pTemp = Next( pSelEntry );
1393 				while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
1394 				{
1395 					pTemp->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
1396 					pTemp = Next( pTemp );
1397 				}
1398 			}
1399 		}
1400 		else
1401 		{
1402 			pSelEntry->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
1403 			if ( bWithChilds )
1404 			{
1405 				nRefDepth = pModel->GetDepth( pSelEntry );
1406 				pTemp = Next( pSelEntry );
1407 				while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
1408 				{
1409 					pTemp->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
1410 					pTemp = Next( pTemp );
1411 				}
1412 			}
1413 		}
1414 		pSelEntry = NextSelected( pSelEntry );
1415 	}
1416 }
1417 
1418 SvLBoxEntry* SvLBox::GetDropTarget( const Point& )
1419 {
1420 	DBG_CHKTHIS(SvLBox,0);
1421 	return 0;
1422 }
1423 
1424 // ******************************************************************
1425 // InplaceEditing
1426 // ******************************************************************
1427 
1428 void SvLBox::EditText( const String& rStr, const Rectangle& rRect,
1429 	const Selection& rSel )
1430 {
1431 	EditText( rStr, rRect, rSel, sal_False );
1432 }
1433 
1434 void SvLBox::EditText( const String& rStr, const Rectangle& rRect,
1435 	const Selection& rSel, sal_Bool bMulti )
1436 {
1437 	DBG_CHKTHIS(SvLBox,0);
1438 	if( pEdCtrl )
1439 		delete pEdCtrl;
1440 	nImpFlags |= SVLBOX_IN_EDT;
1441 	nImpFlags &= ~SVLBOX_EDTEND_CALLED;
1442 	HideFocus();
1443 	pEdCtrl = new SvInplaceEdit2(
1444 		this, rRect.TopLeft(), rRect.GetSize(), rStr,
1445 		LINK( this, SvLBox, TextEditEndedHdl_Impl ),
1446 		rSel, bMulti );
1447 }
1448 
1449 IMPL_LINK( SvLBox, TextEditEndedHdl_Impl, SvInplaceEdit2 *, EMPTYARG )
1450 {
1451 	DBG_CHKTHIS(SvLBox,0);
1452 	if ( nImpFlags & SVLBOX_EDTEND_CALLED ) // Nesting verhindern
1453 		return 0;
1454 	nImpFlags |= SVLBOX_EDTEND_CALLED;
1455 	String aStr;
1456 	if ( !pEdCtrl->EditingCanceled() )
1457 		aStr = pEdCtrl->GetText();
1458 	else
1459 		aStr = pEdCtrl->GetSavedValue();
1460     if ( IsEmptyTextAllowed() || aStr.Len() > 0 )
1461         EditedText( aStr );
1462 	// Hide darf erst gerufen werden, nachdem der neue Text in den
1463 	// Entry gesetzt wurde, damit im GetFocus der ListBox nicht
1464 	// der Selecthandler mit dem alten EntryText gerufen wird.
1465 	pEdCtrl->Hide();
1466 	// delete pEdCtrl;
1467 	// pEdCtrl = 0;
1468 	nImpFlags &= (~SVLBOX_IN_EDT);
1469 	GrabFocus();
1470 	return 0;
1471 }
1472 
1473 void SvLBox::CancelTextEditing()
1474 {
1475 	DBG_CHKTHIS(SvLBox,0);
1476 	if ( pEdCtrl )
1477 		pEdCtrl->StopEditing( sal_True );
1478 	nImpFlags &= (~SVLBOX_IN_EDT);
1479 }
1480 
1481 void SvLBox::EndEditing( sal_Bool bCancel )
1482 {
1483 	DBG_CHKTHIS(SvLBox,0);
1484 	if( pEdCtrl )
1485 		pEdCtrl->StopEditing( bCancel );
1486 	nImpFlags &= (~SVLBOX_IN_EDT);
1487 }
1488 
1489 
1490 bool SvLBox::IsEmptyTextAllowed() const
1491 {
1492     DBG_CHKTHIS(SvLBox,0);
1493     return pLBoxImpl->m_bIsEmptyTextAllowed;
1494 }
1495 
1496 void SvLBox::ForbidEmptyText()
1497 {
1498     DBG_CHKTHIS(SvLBox,0);
1499     pLBoxImpl->m_bIsEmptyTextAllowed = false;
1500 }
1501 
1502 void SvLBox::EditedText( const String& )
1503 {
1504     DBG_CHKTHIS(SvLBox,0);
1505 }
1506 
1507 void SvLBox::EditingRequest( SvLBoxEntry*, SvLBoxItem*,const Point& )
1508 {
1509 	DBG_CHKTHIS(SvLBox,0);
1510 }
1511 
1512 
1513 SvLBoxEntry* SvLBox::CreateEntry() const
1514 {
1515 	DBG_CHKTHIS(SvLBox,0);
1516 	return new SvLBoxEntry;
1517 }
1518 
1519 void SvLBox::MakeVisible( SvLBoxEntry* )
1520 {
1521 	DBG_CHKTHIS(SvLBox,0);
1522 }
1523 
1524 void SvLBox::Command( const CommandEvent& i_rCommandEvent )
1525 {
1526 	DBG_CHKTHIS(SvLBox,0);
1527 
1528     if ( COMMAND_STARTDRAG == i_rCommandEvent.GetCommand() )
1529     {
1530         Point aEventPos( i_rCommandEvent.GetMousePosPixel() );
1531 	    MouseEvent aMouseEvt( aEventPos, 1, MOUSE_SELECT, MOUSE_LEFT );
1532 		MouseButtonUp( aMouseEvt );
1533     }
1534     Control::Command( i_rCommandEvent );
1535 }
1536 
1537 void SvLBox::KeyInput( const KeyEvent& rKEvt )
1538 {
1539     bool bHandled = HandleKeyInput( rKEvt );
1540     if ( !bHandled )
1541 		Control::KeyInput( rKEvt );
1542 }
1543 
1544 const void* SvLBox::FirstSearchEntry( String& _rEntryText ) const
1545 {
1546     SvLBoxEntry* pEntry = GetCurEntry();
1547     if ( pEntry )
1548         pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( NextSearchEntry( pEntry, _rEntryText ) ) );
1549     else
1550     {
1551         pEntry = FirstSelected();
1552         if ( !pEntry )
1553             pEntry = First();
1554     }
1555 
1556     if ( pEntry )
1557         _rEntryText = GetEntryText( pEntry );
1558 
1559     return pEntry;
1560 }
1561 
1562 const void* SvLBox::NextSearchEntry( const void* _pCurrentSearchEntry, String& _rEntryText ) const
1563 {
1564     SvLBoxEntry* pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( _pCurrentSearchEntry ) );
1565 
1566     if  (   (   ( GetChildCount( pEntry ) > 0 )
1567             ||  ( pEntry->HasChildsOnDemand() )
1568             )
1569         &&  !IsExpanded( pEntry )
1570         )
1571     {
1572         pEntry = NextSibling( pEntry );
1573     }
1574     else
1575     {
1576         pEntry = Next( pEntry );
1577     }
1578 
1579     if ( !pEntry )
1580         pEntry = First();
1581 
1582     if ( pEntry )
1583         _rEntryText = GetEntryText( pEntry );
1584 
1585     return pEntry;
1586 }
1587 
1588 void SvLBox::SelectSearchEntry( const void* _pEntry )
1589 {
1590     SvLBoxEntry* pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( _pEntry ) );
1591     DBG_ASSERT( pEntry, "SvLBox::SelectSearchEntry: invalid entry!" );
1592     if ( !pEntry )
1593         return;
1594 
1595     SelectAll( sal_False );
1596     SetCurEntry( pEntry );
1597     Select( pEntry );
1598 }
1599 
1600 void SvLBox::ExecuteSearchEntry( const void* /*_pEntry*/ ) const
1601 {
1602     // nothing to do here, we have no "execution"
1603 }
1604 
1605 ::vcl::StringEntryIdentifier SvLBox::CurrentEntry( String& _out_entryText ) const
1606 {
1607     // always accept the current entry if there is one
1608     SvLBoxEntry* pCurrentEntry( GetCurEntry() );
1609     if ( pCurrentEntry )
1610     {
1611         _out_entryText = GetEntryText( pCurrentEntry );
1612         return pCurrentEntry;
1613     }
1614     return FirstSearchEntry( _out_entryText );
1615 }
1616 
1617 ::vcl::StringEntryIdentifier SvLBox::NextEntry( ::vcl::StringEntryIdentifier _currentEntry, String& _out_entryText ) const
1618 {
1619     return NextSearchEntry( _currentEntry, _out_entryText );
1620 }
1621 
1622 void SvLBox::SelectEntry( ::vcl::StringEntryIdentifier _entry )
1623 {
1624     SelectSearchEntry( _entry );
1625 }
1626 
1627 bool SvLBox::HandleKeyInput( const KeyEvent& _rKEvt )
1628 {
1629     if  (   IsEntryMnemonicsEnabled()
1630         &&  pLBoxImpl->m_aMnemonicEngine.HandleKeyEvent( _rKEvt )
1631         )
1632         return true;
1633 
1634     if ( ( GetStyle() & WB_QUICK_SEARCH ) != 0 )
1635     {
1636         pLBoxImpl->m_bDoingQuickSelection = true;
1637         const bool bHandled = pLBoxImpl->m_aQuickSelectionEngine.HandleKeyEvent( _rKEvt );
1638         pLBoxImpl->m_bDoingQuickSelection = false;
1639         if ( bHandled )
1640             return true;
1641     }
1642 
1643     return false;
1644 }
1645 
1646 SvLBoxEntry* SvLBox::GetEntry( const Point&, sal_Bool ) const
1647 {
1648 	DBG_CHKTHIS(SvLBox,0);
1649 	return 0;
1650 }
1651 
1652 void SvLBox::ModelHasEntryInvalidated( SvListEntry* pEntry )
1653 {
1654 	DBG_CHKTHIS(SvLBox,0);
1655 	sal_uInt16 nCount = ((SvLBoxEntry*)pEntry)->ItemCount();
1656 	for( sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++ )
1657 	{
1658 		SvLBoxItem*	pItem = ((SvLBoxEntry*)pEntry)->GetItem( nIdx );
1659 		pItem->InitViewData( this, (SvLBoxEntry*)pEntry, 0 );
1660 	}
1661 }
1662 
1663 void SvLBox::SetInUseEmphasis( SvLBoxEntry* pEntry, sal_Bool bInUse )
1664 {
1665 	DBG_CHKTHIS(SvLBox,0);
1666 	DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
1667 	if( bInUse )
1668 	{
1669 		if( !pEntry->HasInUseEmphasis() )
1670 		{
1671 			pEntry->nEntryFlags |= SV_ENTRYFLAG_IN_USE;
1672 			pModel->InvalidateEntry( pEntry );
1673 		}
1674 	}
1675 	else
1676 	{
1677 		if( pEntry->HasInUseEmphasis() )
1678 		{
1679 			pEntry->nEntryFlags &= (~SV_ENTRYFLAG_IN_USE);
1680 			pModel->InvalidateEntry( pEntry );
1681 		}
1682 	}
1683 }
1684 
1685 void SvLBox::SetCursorEmphasis( SvLBoxEntry* pEntry, sal_Bool bCursored )
1686 {
1687 	DBG_CHKTHIS(SvLBox,0);
1688 	DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
1689 	SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
1690 	if( pViewData && (bCursored != pViewData->IsCursored()) )
1691 	{
1692 		pViewData->SetCursored( bCursored );
1693 		// paintet in allen Views
1694 		// pModel->InvalidateEntry( pEntry );
1695 		// invalidiert nur in dieser View
1696 		ModelHasEntryInvalidated( pEntry );
1697 	}
1698 }
1699 
1700 sal_Bool SvLBox::HasCursorEmphasis( SvLBoxEntry* pEntry ) const
1701 {
1702 	DBG_CHKTHIS(SvLBox,0);
1703 	DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
1704 	SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
1705 	DBG_ASSERT(pViewData,"Entry not in View");
1706 	return pViewData->IsCursored();
1707 }
1708 
1709 void SvLBox::WriteDragServerInfo( const Point&, SvLBoxDDInfo* )
1710 {
1711 	DBG_CHKTHIS(SvLBox,0);
1712 }
1713 
1714 void SvLBox::ReadDragServerInfo(const Point&, SvLBoxDDInfo* )
1715 {
1716 	DBG_CHKTHIS(SvLBox,0);
1717 }
1718 
1719 sal_Bool SvLBox::EditingCanceled() const
1720 {
1721 	if( pEdCtrl && pEdCtrl->EditingCanceled() )
1722 		return sal_True;
1723 	return sal_False;
1724 }
1725 
1726 
1727 //JP 28.3.2001: new Drag & Drop API
1728 sal_Int8 SvLBox::AcceptDrop( const AcceptDropEvent& rEvt )
1729 {
1730 	DBG_CHKTHIS(SvLBox,0);
1731 	sal_Int8 nRet = DND_ACTION_NONE;
1732 
1733 	if( rEvt.mbLeaving || !CheckDragAndDropMode( pDDSource, rEvt.mnAction ) )
1734 	{
1735 		ImplShowTargetEmphasis( pTargetEntry, sal_False );
1736 	}
1737 	else if( !nDragDropMode )
1738 	{
1739 		DBG_ERRORFILE( "SvLBox::QueryDrop(): no target" );
1740 	}
1741 	else
1742 	{
1743 		SvLBoxEntry* pEntry = GetDropTarget( rEvt.maPosPixel );
1744 		if( !IsDropFormatSupported( SOT_FORMATSTR_ID_TREELISTBOX ) )
1745 		{
1746 			DBG_ERRORFILE( "SvLBox::QueryDrop(): no format" );
1747 		}
1748 		else
1749 		{
1750 			DBG_ASSERT( pDDSource, "SvLBox::QueryDrop(): SourceBox == 0 (__EXPORT?)" );
1751 			if( !( pEntry && pDDSource->GetModel() == this->GetModel()
1752 					&& DND_ACTION_MOVE == rEvt.mnAction
1753 					&& ( pEntry->nEntryFlags & SV_ENTRYFLAG_DISABLE_DROP ) ))
1754 			{
1755 				if( NotifyAcceptDrop( pEntry ))
1756 					nRet = rEvt.mnAction;
1757 			}
1758 		}
1759 
1760 		// **** Emphasis zeichnen ****
1761 		if( DND_ACTION_NONE == nRet )
1762 	   		ImplShowTargetEmphasis( pTargetEntry, sal_False );
1763 		else if( pEntry != pTargetEntry || !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
1764 		{
1765 			ImplShowTargetEmphasis( pTargetEntry, sal_False );
1766 			pTargetEntry = pEntry;
1767 			ImplShowTargetEmphasis( pTargetEntry, sal_True );
1768 		}
1769 	}
1770 	return nRet;
1771 }
1772 
1773 sal_Int8 SvLBox::ExecuteDrop( const ExecuteDropEvent& rEvt, SvLBox* pSourceView )
1774 {
1775 	DBG_CHKTHIS(SvLBox,0);
1776 	sal_Int8 nRet = DND_ACTION_NONE;
1777 
1778 	DBG_ASSERT( pSourceView, "SvLBox::ExecuteDrop(): no source view" );
1779 	pSourceView->EnableSelectionAsDropTarget( sal_True, sal_True );
1780 
1781 	ImplShowTargetEmphasis( pTargetEntry, sal_False );
1782 	pDDTarget = this;
1783 
1784 	SvLBoxDDInfo aDDInfo;
1785 
1786 	TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
1787 	if( aData.HasFormat( SOT_FORMATSTR_ID_TREELISTBOX ))
1788 	{
1789 		::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
1790 		if( aData.GetSequence( SOT_FORMATSTR_ID_TREELISTBOX, aSeq ) &&
1791 			sizeof(SvLBoxDDInfo) == aSeq.getLength() )
1792 		{
1793 			memcpy( &aDDInfo, aSeq.getConstArray(), sizeof(SvLBoxDDInfo) );
1794 			nRet = rEvt.mnAction;
1795 		}
1796 	}
1797 
1798 	if( DND_ACTION_NONE != nRet )
1799 	{
1800 		nRet = DND_ACTION_NONE;
1801 
1802 		ReadDragServerInfo( rEvt.maPosPixel, &aDDInfo );
1803 
1804 		SvLBoxEntry* pTarget = pTargetEntry; // !!! kann 0 sein !!!
1805 
1806 		if( DND_ACTION_COPY == rEvt.mnAction )
1807 		{
1808 			if ( CopySelection( aDDInfo.pSource, pTarget ) )
1809 				nRet = rEvt.mnAction;
1810 		}
1811 		else if( DND_ACTION_MOVE == rEvt.mnAction )
1812 		{
1813 			if ( MoveSelection( aDDInfo.pSource, pTarget ) )
1814 				nRet = rEvt.mnAction;
1815 		}
1816 		else if( DND_ACTION_COPYMOVE == rEvt.mnAction )
1817 		{
1818 			if ( MoveSelectionCopyFallbackPossible( aDDInfo.pSource, pTarget, sal_True ) )
1819 				nRet = rEvt.mnAction;
1820 		}
1821 	}
1822 	return nRet;
1823 }
1824 
1825 sal_Int8 SvLBox::ExecuteDrop( const ExecuteDropEvent& rEvt )
1826 {
1827 	DBG_CHKTHIS(SvLBox,0);
1828 	return ExecuteDrop( rEvt, GetSourceView() );
1829 }
1830 
1831 void SvLBox::StartDrag( sal_Int8, const Point& rPosPixel )
1832 {
1833 	DBG_CHKTHIS(SvLBox,0);
1834 
1835     Point aEventPos( rPosPixel );
1836     MouseEvent aMouseEvt( aEventPos, 1, MOUSE_SELECT, MOUSE_LEFT );
1837     MouseButtonUp( aMouseEvt );
1838 
1839 	nOldDragMode = GetDragDropMode();
1840     if ( !nOldDragMode )
1841         return;
1842 
1843 	ReleaseMouse();
1844 
1845 	SvLBoxEntry* pEntry = GetEntry( rPosPixel ); // GetDropTarget( rPos );
1846 	if( !pEntry )
1847 	{
1848 		DragFinished( DND_ACTION_NONE );
1849 		return;
1850 	}
1851 
1852 	TransferDataContainer* pContainer = new TransferDataContainer;
1853 	::com::sun::star::uno::Reference<
1854 		::com::sun::star::datatransfer::XTransferable > xRef( pContainer );
1855 
1856 	nDragDropMode = NotifyStartDrag( *pContainer, pEntry );
1857 	if( !nDragDropMode || 0 == GetSelectionCount() )
1858 	{
1859 		nDragDropMode = nOldDragMode;
1860 		DragFinished( DND_ACTION_NONE );
1861 		return;
1862 	}
1863 
1864 	SvLBoxDDInfo aDDInfo;
1865 	memset(&aDDInfo,0,sizeof(SvLBoxDDInfo));
1866 	aDDInfo.pApp = GetpApp();
1867 	aDDInfo.pSource = this;
1868 	aDDInfo.pDDStartEntry = pEntry;
1869 	// abgeleitete Views zum Zuge kommen lassen
1870 	WriteDragServerInfo( rPosPixel, &aDDInfo );
1871 
1872 	pContainer->CopyAnyData( SOT_FORMATSTR_ID_TREELISTBOX,
1873 						(sal_Char*)&aDDInfo, sizeof(SvLBoxDDInfo) );
1874 	pDDSource = this;
1875 	pDDTarget = 0;
1876 
1877 	sal_Bool bOldUpdateMode = Control::IsUpdateMode();
1878 	Control::SetUpdateMode( sal_True );
1879 	Update();
1880 	Control::SetUpdateMode( bOldUpdateMode );
1881 
1882 	// Selektion & deren Childs im Model als DropTargets sperren
1883 	// Wichtig: Wenn im DropHandler die Selektion der
1884 	// SourceListBox veraendert wird, muessen vorher die Eintraege
1885 	// als DropTargets wieder freigeschaltet werden:
1886 	// (GetSourceListBox()->EnableSelectionAsDropTarget( sal_True, sal_True );)
1887 	EnableSelectionAsDropTarget( sal_False, sal_True /* with Childs */ );
1888 
1889 	pContainer->StartDrag( this, nDragOptions, GetDragFinishedHdl() );
1890 }
1891 
1892 void SvLBox::DragFinished( sal_Int8
1893 #ifndef UNX
1894 nAction
1895 #endif
1896 )
1897 {
1898 	EnableSelectionAsDropTarget( sal_True, sal_True );
1899 
1900 #ifndef UNX
1901 	if( (nAction == DND_ACTION_MOVE) && ( (pDDTarget &&
1902 		((sal_uLong)(pDDTarget->GetModel())!=(sal_uLong)(this->GetModel()))) ||
1903 		!pDDTarget ))
1904 	{
1905 		RemoveSelection();
1906 	}
1907 #endif
1908 
1909 	ImplShowTargetEmphasis( pTargetEntry, sal_False );
1910 	pDDSource = 0;
1911 	pDDTarget = 0;
1912 	pTargetEntry = 0;
1913 	nDragDropMode = nOldDragMode;
1914 }
1915 
1916 DragDropMode SvLBox::NotifyStartDrag( TransferDataContainer&, SvLBoxEntry* )
1917 {
1918 	DBG_CHKTHIS(SvLBox,0);
1919 	return (DragDropMode)0xffff;
1920 }
1921 
1922 sal_Bool SvLBox::NotifyAcceptDrop( SvLBoxEntry* )
1923 {
1924 	DBG_CHKTHIS(SvLBox,0);
1925 	return sal_True;
1926 }
1927 
1928 // handler and methods for Drag - finished handler.
1929 // The with get GetDragFinishedHdl() get link can set on the
1930 // TransferDataContainer. This link is a callback for the DragFinished
1931 // call. AddBox method is called from the GetDragFinishedHdl() and the
1932 // remove is called in link callback and in the destructor. So it can't
1933 // called to a deleted object.
1934 
1935 namespace
1936 {
1937     struct SortLBoxes : public rtl::Static<SvULongsSort, SortLBoxes> {};
1938 }
1939 
1940 void SvLBox::AddBoxToDDList_Impl( const SvLBox& rB )
1941 {
1942 	sal_uLong nVal = (sal_uLong)&rB;
1943 	SortLBoxes::get().Insert( nVal );
1944 }
1945 
1946 void SvLBox::RemoveBoxFromDDList_Impl( const SvLBox& rB )
1947 {
1948 	sal_uLong nVal = (sal_uLong)&rB;
1949 	SortLBoxes::get().Remove( nVal );
1950 }
1951 
1952 IMPL_STATIC_LINK( SvLBox, DragFinishHdl_Impl, sal_Int8*, pAction )
1953 {
1954 	sal_uLong nVal = (sal_uLong)pThis;
1955 	sal_uInt16 nFnd;
1956     SvULongsSort &rSortLBoxes = SortLBoxes::get();
1957 	if( rSortLBoxes.Seek_Entry( nVal, &nFnd ) )
1958 	{
1959 		pThis->DragFinished( *pAction );
1960 		rSortLBoxes.Remove( nFnd, 1 );
1961 	}
1962 	return 0;
1963 }
1964 
1965 Link SvLBox::GetDragFinishedHdl() const
1966 {
1967 	AddBoxToDDList_Impl( *this );
1968 	return STATIC_LINK( this, SvLBox, DragFinishHdl_Impl );
1969 }
1970 
1971 void SvLBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& ) const
1972 {
1973 }
1974 
1975 ::com::sun::star::uno::Reference< XAccessible > SvLBox::CreateAccessible()
1976 {
1977 	return ::com::sun::star::uno::Reference< XAccessible >();
1978 }
1979 
1980 Rectangle SvLBox::GetBoundingRect( SvLBoxEntry* )
1981 {
1982 	return Rectangle();
1983 }
1984 
1985