Update ooo320-m1
[ooovba.git] / svtools / source / contnr / svlbox.cxx
blobc518b78f9fe4145bf444fce4fb3d55e706994c32
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svlbox.cxx,v $
10 * $Revision: 1.33 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
35 Todo:
36 - Anker loeschen in SelectionEngine bei manuellem Selektieren
37 - SelectAll( FALSE ), nur die deselektierten Entries repainten
40 #include <string.h>
41 #include <svtools/svlbox.hxx>
42 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
43 #include <vcl/svapp.hxx>
44 #include <vcl/accel.hxx>
45 #include <vcl/i18nhelp.hxx>
46 #include <sot/formats.hxx>
47 #include <unotools/accessiblestatesethelper.hxx>
48 #include <rtl/instance.hxx>
50 #define _SVSTDARR_ULONGSSORT
51 #include <svtools/svstdarr.hxx>
53 #ifndef _SVEDI_HXX
54 #include <svtools/svmedit.hxx>
55 #endif
56 #include <svtools/svlbitm.hxx>
58 using namespace ::com::sun::star::accessibility;
60 // Drag&Drop
61 static SvLBox* pDDSource = NULL;
62 static SvLBox* pDDTarget = NULL;
64 DBG_NAME(SvInplaceEdit)
65 DBG_NAME(SvInplaceEdit2)
67 #define SVLBOX_ACC_RETURN 1
68 #define SVLBOX_ACC_ESCAPE 2
70 SvInplaceEdit::SvInplaceEdit
72 Window* pParent,
73 const Point& rPos,
74 const Size& rSize,
75 const String& rData,
76 const Link& rNotifyEditEnd,
77 const Selection& rSelection
78 ) :
80 Edit( pParent, WB_LEFT ),
82 aCallBackHdl ( rNotifyEditEnd ),
83 bCanceled ( FALSE ),
84 bAlreadyInCallBack ( FALSE )
87 DBG_CTOR(SvInplaceEdit,0);
89 Font aFont( pParent->GetFont() );
90 aFont.SetTransparent( FALSE );
91 Color aColor( pParent->GetBackground().GetColor() );
92 aFont.SetFillColor(aColor );
93 SetFont( aFont );
94 SetBackground( pParent->GetBackground() );
95 SetPosPixel( rPos );
96 SetSizePixel( rSize );
97 SetText( rData );
98 SetSelection( rSelection );
99 SaveValue();
101 aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
102 aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
104 aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit, ReturnHdl_Impl) );
105 aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit, EscapeHdl_Impl) );
106 GetpApp()->InsertAccel( &aAccReturn );
107 GetpApp()->InsertAccel( &aAccEscape );
109 Show();
110 GrabFocus();
113 SvInplaceEdit::~SvInplaceEdit()
115 DBG_DTOR(SvInplaceEdit,0);
116 if( !bAlreadyInCallBack )
118 GetpApp()->RemoveAccel( &aAccReturn );
119 GetpApp()->RemoveAccel( &aAccEscape );
123 IMPL_LINK_INLINE_START( SvInplaceEdit, ReturnHdl_Impl, Accelerator *, EMPTYARG )
125 DBG_CHKTHIS(SvInplaceEdit,0);
126 bCanceled = FALSE;
127 CallCallBackHdl_Impl();
128 return 1;
130 IMPL_LINK_INLINE_END( SvInplaceEdit, ReturnHdl_Impl, Accelerator *, EMPTYARG )
132 IMPL_LINK_INLINE_START( SvInplaceEdit, EscapeHdl_Impl, Accelerator *, EMPTYARG )
134 DBG_CHKTHIS(SvInplaceEdit,0);
135 bCanceled = TRUE;
136 CallCallBackHdl_Impl();
137 return 1;
139 IMPL_LINK_INLINE_END( SvInplaceEdit, EscapeHdl_Impl, Accelerator *, EMPTYARG )
141 void SvInplaceEdit::KeyInput( const KeyEvent& rKEvt )
143 DBG_CHKTHIS(SvInplaceEdit,0);
144 USHORT nCode = rKEvt.GetKeyCode().GetCode();
145 switch ( nCode )
147 case KEY_ESCAPE:
148 bCanceled = TRUE;
149 CallCallBackHdl_Impl();
150 break;
152 case KEY_RETURN:
153 bCanceled = FALSE;
154 CallCallBackHdl_Impl();
155 break;
157 default:
158 Edit::KeyInput( rKEvt );
162 void SvInplaceEdit::StopEditing( BOOL bCancel )
164 DBG_CHKTHIS(SvInplaceEdit,0);
165 if ( !bAlreadyInCallBack )
167 bCanceled = bCancel;
168 CallCallBackHdl_Impl();
172 void SvInplaceEdit::LoseFocus()
174 DBG_CHKTHIS(SvInplaceEdit,0);
175 if ( !bAlreadyInCallBack )
177 bCanceled = FALSE;
178 aTimer.SetTimeout(10);
179 aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit,Timeout_Impl));
180 aTimer.Start();
184 IMPL_LINK_INLINE_START( SvInplaceEdit, Timeout_Impl, Timer *, EMPTYARG )
186 DBG_CHKTHIS(SvInplaceEdit,0);
187 CallCallBackHdl_Impl();
188 return 0;
190 IMPL_LINK_INLINE_END( SvInplaceEdit, Timeout_Impl, Timer *, EMPTYARG )
192 void SvInplaceEdit::CallCallBackHdl_Impl()
194 DBG_CHKTHIS(SvInplaceEdit,0);
195 aTimer.Stop();
196 if ( !bAlreadyInCallBack )
198 bAlreadyInCallBack = TRUE;
199 GetpApp()->RemoveAccel( &aAccReturn );
200 GetpApp()->RemoveAccel( &aAccEscape );
201 Hide();
202 aCallBackHdl.Call( this );
203 // bAlreadyInCallBack = FALSE;
208 // ***************************************************************
210 class MyEdit_Impl : public Edit
212 SvInplaceEdit2* pOwner;
213 public:
214 MyEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
215 virtual void KeyInput( const KeyEvent& rKEvt );
216 virtual void LoseFocus();
219 class MyMultiEdit_Impl : public MultiLineEdit
221 SvInplaceEdit2* pOwner;
222 public:
223 MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
224 virtual void KeyInput( const KeyEvent& rKEvt );
225 virtual void LoseFocus();
228 MyEdit_Impl::MyEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner ) :
230 Edit( pParent, WB_LEFT ),
232 pOwner( _pOwner )
237 void MyEdit_Impl::KeyInput( const KeyEvent& rKEvt )
239 if( !pOwner->KeyInput( rKEvt ))
240 Edit::KeyInput( rKEvt );
243 void MyEdit_Impl::LoseFocus()
245 pOwner->LoseFocus();
248 MyMultiEdit_Impl::MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner )
249 : MultiLineEdit( pParent,
250 WB_CENTER
251 ), pOwner(_pOwner)
255 void MyMultiEdit_Impl::KeyInput( const KeyEvent& rKEvt )
257 if( !pOwner->KeyInput( rKEvt ))
258 MultiLineEdit::KeyInput( rKEvt );
261 void MyMultiEdit_Impl::LoseFocus()
263 pOwner->LoseFocus();
267 SvInplaceEdit2::SvInplaceEdit2
269 Window* pParent, const Point& rPos,
270 const Size& rSize,
271 const String& rData,
272 const Link& rNotifyEditEnd,
273 const Selection& rSelection,
274 BOOL bMulti
277 aCallBackHdl ( rNotifyEditEnd ),
278 bCanceled ( FALSE ),
279 bAlreadyInCallBack ( FALSE ),
280 bMultiLine ( bMulti )
283 DBG_CTOR(SvInplaceEdit2,0);
285 if( bMulti )
286 pEdit = new MyMultiEdit_Impl( pParent, this );
287 else
288 pEdit = new MyEdit_Impl( pParent, this );
290 Font aFont( pParent->GetFont() );
291 aFont.SetTransparent( FALSE );
292 Color aColor( pParent->GetBackground().GetColor() );
293 aFont.SetFillColor(aColor );
294 pEdit->SetFont( aFont );
295 pEdit->SetBackground( pParent->GetBackground() );
296 pEdit->SetPosPixel( rPos );
297 pEdit->SetSizePixel( rSize );
298 pEdit->SetText( rData );
299 pEdit->SetSelection( rSelection );
300 pEdit->SaveValue();
302 aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
303 aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
305 aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit2, ReturnHdl_Impl) );
306 aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit2, EscapeHdl_Impl) );
307 GetpApp()->InsertAccel( &aAccReturn );
308 GetpApp()->InsertAccel( &aAccEscape );
310 pEdit->Show();
311 pEdit->GrabFocus();
314 SvInplaceEdit2::~SvInplaceEdit2()
316 DBG_DTOR(SvInplaceEdit2,0);
317 if( !bAlreadyInCallBack )
319 GetpApp()->RemoveAccel( &aAccReturn );
320 GetpApp()->RemoveAccel( &aAccEscape );
322 delete pEdit;
325 String SvInplaceEdit2::GetSavedValue() const
327 return pEdit->GetSavedValue();
330 void SvInplaceEdit2::Hide()
332 pEdit->Hide();
336 IMPL_LINK_INLINE_START( SvInplaceEdit2, ReturnHdl_Impl, Accelerator *, EMPTYARG )
338 DBG_CHKTHIS(SvInplaceEdit2,0);
339 bCanceled = FALSE;
340 CallCallBackHdl_Impl();
341 return 1;
343 IMPL_LINK_INLINE_END( SvInplaceEdit2, ReturnHdl_Impl, Accelerator *, EMPTYARG )
345 IMPL_LINK_INLINE_START( SvInplaceEdit2, EscapeHdl_Impl, Accelerator *, EMPTYARG )
347 DBG_CHKTHIS(SvInplaceEdit2,0);
348 bCanceled = TRUE;
349 CallCallBackHdl_Impl();
350 return 1;
352 IMPL_LINK_INLINE_END( SvInplaceEdit2, EscapeHdl_Impl, Accelerator *, EMPTYARG )
355 BOOL SvInplaceEdit2::KeyInput( const KeyEvent& rKEvt )
357 DBG_CHKTHIS(SvInplaceEdit2,0);
358 KeyCode aCode = rKEvt.GetKeyCode();
359 USHORT nCode = aCode.GetCode();
361 switch ( nCode )
363 case KEY_ESCAPE:
364 bCanceled = TRUE;
365 CallCallBackHdl_Impl();
366 return TRUE;
368 case KEY_RETURN:
369 bCanceled = FALSE;
370 CallCallBackHdl_Impl();
371 return TRUE;
373 return FALSE;
376 void SvInplaceEdit2::StopEditing( BOOL bCancel )
378 DBG_CHKTHIS(SvInplaceEdit2,0);
379 if ( !bAlreadyInCallBack )
381 bCanceled = bCancel;
382 CallCallBackHdl_Impl();
386 void SvInplaceEdit2::LoseFocus()
388 DBG_CHKTHIS(SvInplaceEdit2,0);
389 if ( !bAlreadyInCallBack
390 && ((!Application::GetFocusWindow()) || !pEdit->IsChild( Application::GetFocusWindow()) )
393 bCanceled = FALSE;
394 aTimer.SetTimeout(10);
395 aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit2,Timeout_Impl));
396 aTimer.Start();
400 IMPL_LINK_INLINE_START( SvInplaceEdit2, Timeout_Impl, Timer *, EMPTYARG )
402 DBG_CHKTHIS(SvInplaceEdit2,0);
403 CallCallBackHdl_Impl();
404 return 0;
406 IMPL_LINK_INLINE_END( SvInplaceEdit2, Timeout_Impl, Timer *, EMPTYARG )
408 void SvInplaceEdit2::CallCallBackHdl_Impl()
410 DBG_CHKTHIS(SvInplaceEdit2,0);
411 aTimer.Stop();
412 if ( !bAlreadyInCallBack )
414 bAlreadyInCallBack = TRUE;
415 GetpApp()->RemoveAccel( &aAccReturn );
416 GetpApp()->RemoveAccel( &aAccEscape );
417 pEdit->Hide();
418 aCallBackHdl.Call( this );
422 String SvInplaceEdit2::GetText() const
424 return pEdit->GetText();
427 // ***************************************************************
428 // class SvLBoxTab
429 // ***************************************************************
431 DBG_NAME(SvLBoxTab);
433 SvLBoxTab::SvLBoxTab()
435 DBG_CTOR(SvLBoxTab,0);
436 nPos = 0;
437 pUserData = 0;
438 nFlags = 0;
441 SvLBoxTab::SvLBoxTab( long nPosition, USHORT nTabFlags )
443 DBG_CTOR(SvLBoxTab,0);
444 nPos = nPosition;
445 pUserData = 0;
446 nFlags = nTabFlags;
449 SvLBoxTab::SvLBoxTab( const SvLBoxTab& rTab )
451 DBG_CTOR(SvLBoxTab,0);
452 nPos = rTab.nPos;
453 pUserData = rTab.pUserData;
454 nFlags = rTab.nFlags;
457 SvLBoxTab::~SvLBoxTab()
459 DBG_DTOR(SvLBoxTab,0);
463 long SvLBoxTab::CalcOffset( long nItemWidth, long nTabWidth )
465 DBG_CHKTHIS(SvLBoxTab,0);
466 long nOffset = 0;
467 if ( nFlags & SV_LBOXTAB_ADJUST_RIGHT )
469 nOffset = nTabWidth - nItemWidth;
470 if( nOffset < 0 )
471 nOffset = 0;
473 else if ( nFlags & SV_LBOXTAB_ADJUST_CENTER )
475 if( nFlags & SV_LBOXTAB_FORCE )
477 //richtige Implementierung der Zentrierung
478 nOffset = ( nTabWidth - nItemWidth ) / 2;
479 if( nOffset < 0 )
480 nOffset = 0;
482 else
484 // historisch gewachsene falsche Berechnung des Tabs, auf die sich
485 // Abo-Tabbox, Extras/Optionen/Anpassen etc. verlassen
486 nItemWidth++;
487 nOffset = -( nItemWidth / 2 );
490 return nOffset;
494 long SvLBoxTab::CalcOffset( const String& rStr, const OutputDevice& rOutDev )
496 DBG_CHKTHIS(SvLBoxTab,0);
497 long nWidth;
498 if ( nFlags & SV_LBOXTAB_ADJUST_NUMERIC )
500 USHORT nPos = rStr.Search( '.' );
501 if ( nPos == STRING_NOTFOUND )
502 nPos = rStr.Search( ',' );
503 if ( nPos == STRING_NOTFOUND )
504 nPos = STRING_LEN;
506 nWidth = rOutDev.GetTextSize( rStr, 0, nPos ).Width();
507 nWidth *= -1;
509 else
511 nWidth = rOutDev.GetTextSize( rStr ).Width();
512 nWidth = CalcOffset( nWidth );
514 return nWidth;
518 // ***************************************************************
519 // class SvLBoxItem
520 // ***************************************************************
522 DBG_NAME(SvLBoxItem);
524 SvLBoxItem::SvLBoxItem( SvLBoxEntry*, USHORT )
526 DBG_CTOR(SvLBoxItem,0);
529 SvLBoxItem::SvLBoxItem()
531 DBG_CTOR(SvLBoxItem,0);
534 SvLBoxItem::~SvLBoxItem()
536 DBG_DTOR(SvLBoxItem,0);
539 const Size& SvLBoxItem::GetSize( SvLBox* pView,SvLBoxEntry* pEntry )
541 DBG_CHKTHIS(SvLBoxItem,0);
542 SvViewDataItem* pViewData = pView->GetViewDataItem( pEntry, this );
543 return pViewData->aSize;
546 const Size& SvLBoxItem::GetSize( SvLBoxEntry* pEntry, SvViewDataEntry* pViewData)
548 DBG_CHKTHIS(SvLBoxItem,0);
549 USHORT nItemPos = pEntry->GetPos( this );
550 SvViewDataItem* pItemData = pViewData->pItemData+nItemPos;
551 return pItemData->aSize;
554 DBG_NAME(SvViewDataItem);
556 SvViewDataItem::SvViewDataItem()
558 DBG_CTOR(SvViewDataItem,0);
561 SvViewDataItem::~SvViewDataItem()
563 DBG_DTOR(SvViewDataItem,0);
568 // ***************************************************************
569 // class SvLBoxEntry
570 // ***************************************************************
572 DBG_NAME(SvLBoxEntry);
574 SvLBoxEntry::SvLBoxEntry() : aItems()
576 DBG_CTOR(SvLBoxEntry,0);
577 nEntryFlags = 0;
578 pUserData = 0;
581 SvLBoxEntry::~SvLBoxEntry()
583 DBG_DTOR(SvLBoxEntry,0);
584 DeleteItems_Impl();
587 void SvLBoxEntry::DeleteItems_Impl()
589 DBG_CHKTHIS(SvLBoxEntry,0);
590 USHORT nCount = aItems.Count();
591 while( nCount )
593 nCount--;
594 SvLBoxItem* pItem = (SvLBoxItem*)aItems.GetObject( nCount );
595 delete pItem;
597 aItems.Remove(0, aItems.Count() );
601 void SvLBoxEntry::AddItem( SvLBoxItem* pItem )
603 DBG_CHKTHIS(SvLBoxEntry,0);
604 aItems.Insert( pItem, aItems.Count() );
607 void SvLBoxEntry::Clone( SvListEntry* pSource )
609 DBG_CHKTHIS(SvLBoxEntry,0);
610 SvListEntry::Clone( pSource );
611 SvLBoxItem* pNewItem;
612 DeleteItems_Impl();
613 USHORT nCount = ((SvLBoxEntry*)pSource)->ItemCount();
614 USHORT nCurPos = 0;
615 while( nCurPos < nCount )
617 SvLBoxItem* pItem = ((SvLBoxEntry*)pSource)->GetItem( nCurPos );
618 pNewItem = pItem->Create();
619 pNewItem->Clone( pItem );
620 AddItem( pNewItem );
621 nCurPos++;
623 pUserData = ((SvLBoxEntry*)pSource)->GetUserData();
624 nEntryFlags = ((SvLBoxEntry*)pSource)->nEntryFlags;
627 void SvLBoxEntry::EnableChildsOnDemand( BOOL bEnable )
629 DBG_CHKTHIS(SvLBoxEntry,0);
630 if ( bEnable )
631 nEntryFlags |= SV_ENTRYFLAG_CHILDS_ON_DEMAND;
632 else
633 nEntryFlags &= (~SV_ENTRYFLAG_CHILDS_ON_DEMAND);
636 void SvLBoxEntry::ReplaceItem( SvLBoxItem* pNewItem, USHORT nPos )
638 DBG_CHKTHIS(SvLBoxEntry,0);
639 DBG_ASSERT(pNewItem,"ReplaceItem:No Item");
640 SvLBoxItem* pOld = GetItem( nPos );
641 if ( pOld )
643 aItems.Remove( nPos );
644 aItems.Insert( pNewItem, nPos );
645 delete pOld;
649 SvLBoxItem* SvLBoxEntry::GetFirstItem( USHORT nId )
651 USHORT nCount = aItems.Count();
652 USHORT nCur = 0;
653 SvLBoxItem* pItem;
654 while( nCur < nCount )
656 pItem = GetItem( nCur );
657 if( pItem->IsA() == nId )
658 return pItem;
659 nCur++;
661 return 0;
664 // ***************************************************************
665 // class SvLBoxViewData
666 // ***************************************************************
668 DBG_NAME(SvViewDataEntry);
670 SvViewDataEntry::SvViewDataEntry()
671 : SvViewData()
673 DBG_CTOR(SvViewDataEntry,0);
674 pItemData = 0;
677 SvViewDataEntry::~SvViewDataEntry()
679 DBG_DTOR(SvViewDataEntry,0);
680 delete [] pItemData;
683 // ***************************************************************
684 // struct SvLBox_Impl
685 // ***************************************************************
686 SvLBox_Impl::SvLBox_Impl( SvLBox& _rBox )
687 :m_bIsEmptyTextAllowed( true )
688 ,m_bEntryMnemonicsEnabled( false )
689 ,m_pLink( NULL )
690 ,m_aMnemonicEngine( _rBox )
694 // ***************************************************************
695 // class SvLBox
696 // ***************************************************************
698 DBG_NAME(SvLBox);
700 SvLBox::SvLBox( Window* pParent, WinBits nWinStyle ) :
701 Control( pParent, nWinStyle | WB_CLIPCHILDREN ),
702 DropTargetHelper( this ), DragSourceHelper( this ), eSelMode( NO_SELECTION )
704 DBG_CTOR(SvLBox,0);
705 nWindowStyle = nWinStyle;
706 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
707 nImpFlags = 0;
708 pTargetEntry = 0;
709 nDragDropMode = 0;
710 pLBoxImpl = new SvLBox_Impl( *this );
711 SvLBoxTreeList* pTempModel = new SvLBoxTreeList;
712 pTempModel->SetRefCount( 0 );
713 SetModel( pTempModel );
714 pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
715 pModel->InsertView( this );
716 pHdlEntry = 0;
717 pEdCtrl = 0;
718 SetSelectionMode( SINGLE_SELECTION ); // pruefen ob TreeListBox gecallt wird
719 SetDragDropMode( SV_DRAGDROP_NONE );
720 SetType(WINDOW_TREELISTBOX);
723 SvLBox::SvLBox( Window* pParent, const ResId& rResId ) :
724 Control( pParent, rResId ),
725 DropTargetHelper( this ), DragSourceHelper( this ), eSelMode( NO_SELECTION )
727 DBG_CTOR(SvLBox,0);
728 pTargetEntry = 0;
729 nImpFlags = 0;
730 nWindowStyle = 0;
731 pLBoxImpl = new SvLBox_Impl( *this );
732 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
733 nDragDropMode = 0;
734 SvLBoxTreeList* pTempModel = new SvLBoxTreeList;
735 pTempModel->SetRefCount( 0 );
736 SetModel( pTempModel );
737 pModel->InsertView( this );
738 pHdlEntry = 0;
739 pEdCtrl = 0;
740 pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
741 SetType(WINDOW_TREELISTBOX);
744 __EXPORT SvLBox::~SvLBox()
746 DBG_DTOR(SvLBox,0);
747 delete pEdCtrl;
748 pEdCtrl = 0;
749 pModel->RemoveView( this );
750 if ( pModel->GetRefCount() == 0 )
752 pModel->Clear();
753 delete pModel;
754 pModel = NULL;
757 SvLBox::RemoveBoxFromDDList_Impl( *this );
759 if( this == pDDSource )
760 pDDSource = 0;
761 if( this == pDDTarget )
762 pDDTarget = 0;
763 delete pLBoxImpl;
766 void SvLBox::SetModel( SvLBoxTreeList* pNewModel )
768 DBG_CHKTHIS(SvLBox,0);
769 // erledigt das ganz CleanUp
770 SvListView::SetModel( pNewModel );
771 pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
772 SvLBoxEntry* pEntry = First();
773 while( pEntry )
775 ModelHasInserted( pEntry );
776 pEntry = Next( pEntry );
780 void SvLBox::DisconnectFromModel()
782 DBG_CHKTHIS(SvLBox,0);
783 SvLBoxTreeList* pNewModel = new SvLBoxTreeList;
784 pNewModel->SetRefCount( 0 ); // else this will never be deleted
785 SvListView::SetModel( pNewModel );
788 void SvLBox::Clear()
790 DBG_CHKTHIS(SvLBox,0);
791 pModel->Clear(); // Model ruft SvLBox::ModelHasCleared() auf
794 void SvLBox::EnableEntryMnemonics( bool _bEnable )
796 if ( _bEnable == IsEntryMnemonicsEnabled() )
797 return;
799 pLBoxImpl->m_bEntryMnemonicsEnabled = _bEnable;
800 Invalidate();
803 bool SvLBox::IsEntryMnemonicsEnabled() const
805 return pLBoxImpl->m_bEntryMnemonicsEnabled;
808 USHORT SvLBox::IsA()
810 DBG_CHKTHIS(SvLBox,0);
811 return SVLISTBOX_ID_LBOX;
814 IMPL_LINK_INLINE_START( SvLBox, CloneHdl_Impl, SvListEntry*, pEntry )
816 DBG_CHKTHIS(SvLBox,0);
817 return (long)(CloneEntry((SvLBoxEntry*)pEntry));
819 IMPL_LINK_INLINE_END( SvLBox, CloneHdl_Impl, SvListEntry*, pEntry )
821 ULONG SvLBox::Insert( SvLBoxEntry* pEntry, SvLBoxEntry* pParent, ULONG nPos )
823 DBG_CHKTHIS(SvLBox,0);
824 ULONG nInsPos = pModel->Insert( pEntry, pParent, nPos );
825 return nInsPos;
828 ULONG SvLBox::Insert( SvLBoxEntry* pEntry,ULONG nRootPos )
830 DBG_CHKTHIS(SvLBox,0);
831 ULONG nInsPos = pModel->Insert( pEntry, nRootPos );
832 return nInsPos;
835 long SvLBox::ExpandingHdl()
837 DBG_CHKTHIS(SvLBox,0);
838 return aExpandingHdl.IsSet() ? aExpandingHdl.Call( this ) : 1;
841 void SvLBox::ExpandedHdl()
843 DBG_CHKTHIS(SvLBox,0);
844 aExpandedHdl.Call( this );
847 void SvLBox::SelectHdl()
849 DBG_CHKTHIS(SvLBox,0);
850 aSelectHdl.Call( this );
853 void SvLBox::DeselectHdl()
855 DBG_CHKTHIS(SvLBox,0);
856 aDeselectHdl.Call( this );
859 BOOL SvLBox::DoubleClickHdl()
861 DBG_CHKTHIS(SvLBox,0);
862 aDoubleClickHdl.Call( this );
863 return TRUE;
867 BOOL SvLBox::CheckDragAndDropMode( SvLBox* pSource, sal_Int8 nAction )
869 DBG_CHKTHIS(SvLBox,0);
870 if ( pSource == this )
872 if ( !(nDragDropMode & (SV_DRAGDROP_CTRL_MOVE | SV_DRAGDROP_CTRL_COPY) ) )
873 return FALSE; // D&D innerhalb der Liste gesperrt
874 if( DND_ACTION_MOVE == nAction )
876 if ( !(nDragDropMode & SV_DRAGDROP_CTRL_MOVE) )
877 return FALSE; // kein lokales Move
879 else
881 if ( !(nDragDropMode & SV_DRAGDROP_CTRL_COPY))
882 return FALSE; // kein lokales Copy
885 else
887 if ( !(nDragDropMode & SV_DRAGDROP_APP_DROP ) )
888 return FALSE; // kein Drop
889 if ( DND_ACTION_MOVE == nAction )
891 if ( !(nDragDropMode & SV_DRAGDROP_APP_MOVE) )
892 return FALSE; // kein globales Move
894 else
896 if ( !(nDragDropMode & SV_DRAGDROP_APP_COPY))
897 return FALSE; // kein globales Copy
900 return TRUE;
906 void SvLBox::NotifyRemoving( SvLBoxEntry* )
908 DBG_CHKTHIS(SvLBox,0);
912 NotifyMoving/Copying
913 ====================
915 Standard-Verhalten:
917 1. Target hat keine Childs
918 - Entry wird Sibling des Targets. Entry steht hinter dem
919 Target (->Fenster: Unter dem Target)
920 2. Target ist ein aufgeklappter Parent
921 - Entry wird an den Anfang der Target-Childlist gehaengt
922 3. Target ist ein zugeklappter Parent
923 - Entry wird an das Ende der Target-Childlist gehaengt
925 #ifdef DBG_UTIL
926 BOOL SvLBox::NotifyMoving(
927 SvLBoxEntry* pTarget, // D&D-Drop-Position in this->GetModel()
928 SvLBoxEntry* pEntry, // Zu verschiebender Entry aus
929 // GetSourceListBox()->GetModel()
930 SvLBoxEntry*& rpNewParent, // Neuer Target-Parent
931 ULONG& rNewChildPos) // Position in Childlist des Target-Parents
932 #else
933 BOOL SvLBox::NotifyMoving(
934 SvLBoxEntry* pTarget, // D&D-Drop-Position in this->GetModel()
935 SvLBoxEntry*, // Zu verschiebender Entry aus
936 // GetSourceListBox()->GetModel()
937 SvLBoxEntry*& rpNewParent, // Neuer Target-Parent
938 ULONG& rNewChildPos) // Position in Childlist des Target-Parents
939 #endif
941 DBG_CHKTHIS(SvLBox,0);
942 DBG_ASSERT(pEntry,"NotifyMoving:SoureEntry?");
943 if( !pTarget )
945 rpNewParent = 0;
946 rNewChildPos = 0;
947 return TRUE;
949 if ( !pTarget->HasChilds() && !pTarget->HasChildsOnDemand() )
951 // Fall 1
952 rpNewParent = GetParent( pTarget );
953 rNewChildPos = pModel->GetRelPos( pTarget ) + 1;
954 rNewChildPos += nCurEntrySelPos;
955 nCurEntrySelPos++;
957 else
959 // Faelle 2 & 3
960 rpNewParent = pTarget;
961 if( IsExpanded(pTarget))
962 rNewChildPos = 0;
963 else
964 rNewChildPos = LIST_APPEND;
966 return TRUE;
969 BOOL SvLBox::NotifyCopying(
970 SvLBoxEntry* pTarget, // D&D-Drop-Position in this->GetModel()
971 SvLBoxEntry* pEntry, // Zu kopierender Entry aus
972 // GetSourceListBox()->GetModel()
973 SvLBoxEntry*& rpNewParent, // Neuer Target-Parent
974 ULONG& rNewChildPos) // Position in Childlist des Target-Parents
976 DBG_CHKTHIS(SvLBox,0);
977 return NotifyMoving(pTarget,pEntry,rpNewParent,rNewChildPos);
979 DBG_ASSERT(pEntry,"NotifyCopying:SourceEntry?");
980 if( !pTarget )
982 rpNewParent = 0;
983 rNewChildPos = 0;
984 return TRUE;
986 if ( !pTarget->HasChilds() && !pTarget->HasChildsOnDemand() )
988 // Fall 1
989 rpNewParent = GetParent( pTarget );
990 rNewChildPos = GetRelPos( pTarget ) + 1;
992 else
994 // Faelle 2 & 3
995 rpNewParent = pTarget;
996 if( IsExpanded(pTarget))
997 rNewChildPos = 0;
998 else
999 rNewChildPos = LIST_APPEND;
1001 return TRUE;
1005 SvLBoxEntry* SvLBox::CloneEntry( SvLBoxEntry* pSource )
1007 DBG_CHKTHIS(SvLBox,0);
1008 SvLBoxEntry* pEntry = (SvLBoxEntry*)CreateEntry(); // new SvLBoxEntry;
1009 pEntry->Clone( (SvListEntry*)pSource );
1010 return pEntry;
1014 // Rueckgabe: Alle Entries wurden kopiert
1015 BOOL SvLBox::CopySelection( SvLBox* pSource, SvLBoxEntry* pTarget )
1017 DBG_CHKTHIS(SvLBox,0);
1018 nCurEntrySelPos = 0; // Selektionszaehler fuer NotifyMoving/Copying
1019 BOOL bSuccess = TRUE;
1020 SvTreeEntryList aList;
1021 BOOL bClone = (BOOL)( (ULONG)(pSource->GetModel()) != (ULONG)GetModel() );
1022 Link aCloneLink( pModel->GetCloneLink() );
1023 pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
1025 // Selektion zwischenspeichern, um bei D&D-Austausch
1026 // innerhalb der gleichen Listbox das Iterieren ueber
1027 // die Selektion zu vereinfachen
1028 SvLBoxEntry* pSourceEntry = pSource->FirstSelected();
1029 while ( pSourceEntry )
1031 // Childs werden automatisch mitkopiert
1032 pSource->SelectChilds( pSourceEntry, FALSE );
1033 aList.Insert( pSourceEntry, LIST_APPEND );
1034 pSourceEntry = pSource->NextSelected( pSourceEntry );
1037 pSourceEntry = (SvLBoxEntry*)aList.First();
1038 while ( pSourceEntry )
1040 SvLBoxEntry* pNewParent = 0;
1041 ULONG nInsertionPos = LIST_APPEND;
1042 BOOL bOk=NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
1043 if ( bOk )
1045 if ( bClone )
1047 ULONG nCloneCount = 0;
1048 pSourceEntry = (SvLBoxEntry*)
1049 pModel->Clone( (SvListEntry*)pSourceEntry, nCloneCount );
1050 pModel->InsertTree( (SvListEntry*)pSourceEntry,
1051 (SvListEntry*)pNewParent, nInsertionPos );
1053 else
1055 ULONG nListPos = pModel->Copy( (SvListEntry*)pSourceEntry,
1056 (SvListEntry*)pNewParent, nInsertionPos );
1057 pSourceEntry = GetEntry( pNewParent, nListPos );
1060 else
1061 bSuccess = FALSE;
1063 if( bOk == (BOOL)2 ) // !!!HACK verschobenen Entry sichtbar machen?
1064 MakeVisible( pSourceEntry );
1066 pSourceEntry = (SvLBoxEntry*)aList.Next();
1068 pModel->SetCloneLink( aCloneLink );
1069 return bSuccess;
1072 // Rueckgabe: Alle Entries wurden verschoben
1073 BOOL SvLBox::MoveSelection( SvLBox* pSource, SvLBoxEntry* pTarget )
1075 return MoveSelectionCopyFallbackPossible( pSource, pTarget, sal_False );
1078 BOOL SvLBox::MoveSelectionCopyFallbackPossible( SvLBox* pSource, SvLBoxEntry* pTarget, sal_Bool bAllowCopyFallback )
1080 DBG_CHKTHIS(SvLBox,0);
1081 nCurEntrySelPos = 0; // Selektionszaehler fuer NotifyMoving/Copying
1082 BOOL bSuccess = TRUE;
1083 SvTreeEntryList aList;
1084 BOOL bClone = (BOOL)( (ULONG)(pSource->GetModel()) != (ULONG)GetModel() );
1085 Link aCloneLink( pModel->GetCloneLink() );
1086 if ( bClone )
1087 pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
1089 SvLBoxEntry* pSourceEntry = pSource->FirstSelected();
1090 while ( pSourceEntry )
1092 // Childs werden automatisch mitbewegt
1093 pSource->SelectChilds( pSourceEntry, FALSE );
1094 aList.Insert( pSourceEntry, LIST_APPEND );
1095 pSourceEntry = pSource->NextSelected( pSourceEntry );
1098 pSourceEntry = (SvLBoxEntry*)aList.First();
1099 while ( pSourceEntry )
1101 SvLBoxEntry* pNewParent = 0;
1102 ULONG nInsertionPos = LIST_APPEND;
1103 sal_Bool bOk = NotifyMoving(pTarget,pSourceEntry,pNewParent,nInsertionPos);
1104 sal_Bool bCopyOk = bOk;
1105 if ( !bOk && bAllowCopyFallback )
1107 nInsertionPos = LIST_APPEND;
1108 bCopyOk = NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
1111 if ( bOk || bCopyOk )
1113 if ( bClone )
1115 ULONG nCloneCount = 0;
1116 pSourceEntry = (SvLBoxEntry*)
1117 pModel->Clone( (SvListEntry*)pSourceEntry, nCloneCount );
1118 pModel->InsertTree( (SvListEntry*)pSourceEntry,
1119 (SvListEntry*)pNewParent, nInsertionPos );
1121 else
1123 if ( bOk )
1124 pModel->Move( (SvListEntry*)pSourceEntry,
1125 (SvListEntry*)pNewParent, nInsertionPos );
1126 else
1127 pModel->Copy( (SvListEntry*)pSourceEntry,
1128 (SvListEntry*)pNewParent, nInsertionPos );
1131 else
1132 bSuccess = FALSE;
1134 if( bOk == (BOOL)2 ) // !!!HACK verschobenen Entry sichtbar machen?
1135 MakeVisible( pSourceEntry );
1137 pSourceEntry = (SvLBoxEntry*)aList.Next();
1139 pModel->SetCloneLink( aCloneLink );
1140 return bSuccess;
1143 void SvLBox::RemoveSelection()
1145 DBG_CHKTHIS(SvLBox,0);
1146 SvTreeEntryList aList;
1147 // Selektion zwischenspeichern, da die Impl bei
1148 // dem ersten Remove alles deselektiert!
1149 SvLBoxEntry* pEntry = FirstSelected();
1150 while ( pEntry )
1152 aList.Insert( pEntry );
1153 if ( pEntry->HasChilds() )
1154 // Remove loescht Childs automatisch
1155 SelectChilds( pEntry, FALSE );
1156 pEntry = NextSelected( pEntry );
1158 pEntry = (SvLBoxEntry*)aList.First();
1159 while ( pEntry )
1161 pModel->Remove( pEntry );
1162 pEntry = (SvLBoxEntry*)aList.Next();
1166 SvLBox* SvLBox::GetSourceView() const
1168 return pDDSource;
1171 SvLBox* SvLBox::GetTargetView() const
1173 return pDDTarget;
1176 void SvLBox::RequestingChilds( SvLBoxEntry* )
1178 DBG_CHKTHIS(SvLBox,0);
1179 DBG_ERROR("Child-Request-Hdl not implemented!");
1182 void SvLBox::RecalcViewData()
1184 DBG_CHKTHIS(SvLBox,0);
1185 SvLBoxEntry* pEntry = First();
1186 while( pEntry )
1188 USHORT nCount = pEntry->ItemCount();
1189 USHORT nCurPos = 0;
1190 while ( nCurPos < nCount )
1192 SvLBoxItem* pItem = pEntry->GetItem( nCurPos );
1193 pItem->InitViewData( this, pEntry );
1194 nCurPos++;
1196 ViewDataInitialized( pEntry );
1197 pEntry = Next( pEntry );
1201 void SvLBox::ViewDataInitialized( SvLBoxEntry* )
1203 DBG_CHKTHIS(SvLBox,0);
1206 void SvLBox::StateChanged( StateChangedType eType )
1208 if( eType == STATE_CHANGE_ENABLE )
1209 Invalidate( INVALIDATE_CHILDREN );
1210 Control::StateChanged( eType );
1213 void SvLBox::ImplShowTargetEmphasis( SvLBoxEntry* pEntry, BOOL bShow)
1215 DBG_CHKTHIS(SvLBox,0);
1216 if ( bShow && (nImpFlags & SVLBOX_TARGEMPH_VIS) )
1217 return;
1218 if ( !bShow && !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
1219 return;
1220 ShowTargetEmphasis( pEntry, bShow );
1221 if( bShow )
1222 nImpFlags |= SVLBOX_TARGEMPH_VIS;
1223 else
1224 nImpFlags &= ~SVLBOX_TARGEMPH_VIS;
1227 void SvLBox::ShowTargetEmphasis( SvLBoxEntry*, BOOL /* bShow */ )
1229 DBG_CHKTHIS(SvLBox,0);
1233 BOOL SvLBox::Expand( SvLBoxEntry* )
1235 DBG_CHKTHIS(SvLBox,0);
1236 return TRUE;
1239 BOOL SvLBox::Collapse( SvLBoxEntry* )
1241 DBG_CHKTHIS(SvLBox,0);
1242 return TRUE;
1245 BOOL SvLBox::Select( SvLBoxEntry*, BOOL )
1247 DBG_CHKTHIS(SvLBox,0);
1248 return FALSE;
1251 ULONG SvLBox::SelectChilds( SvLBoxEntry* , BOOL )
1253 DBG_CHKTHIS(SvLBox,0);
1254 return 0;
1257 void SvLBox::SelectAll( BOOL /* bSelect */ , BOOL /* bPaint */ )
1259 DBG_CHKTHIS(SvLBox,0);
1262 SvLBoxEntry* SvLBox::GetEntryFromPath( const ::std::deque< sal_Int32 >& _rPath ) const
1264 DBG_CHKTHIS(SvLBox,0);
1266 SvLBoxEntry* pEntry = NULL;
1267 SvLBoxEntry* pParent = NULL;
1268 for( ::std::deque< sal_Int32 >::const_iterator pItem = _rPath.begin(); pItem != _rPath.end(); ++pItem )
1270 pEntry = GetEntry( pParent, *pItem );
1271 if ( !pEntry )
1272 break;
1273 pParent = pEntry;
1276 return pEntry;
1279 void SvLBox::FillEntryPath( SvLBoxEntry* pEntry, ::std::deque< sal_Int32 >& _rPath ) const
1281 DBG_CHKTHIS(SvLBox,0);
1283 if ( pEntry )
1285 SvLBoxEntry* pParentEntry = GetParent( pEntry );
1286 while ( TRUE )
1288 ULONG i, nCount = GetLevelChildCount( pParentEntry );
1289 for ( i = 0; i < nCount; ++i )
1291 SvLBoxEntry* pTemp = GetEntry( pParentEntry, i );
1292 DBG_ASSERT( pEntry, "invalid entry" );
1293 if ( pEntry == pTemp )
1295 _rPath.push_front( (sal_Int32)i );
1296 break;
1300 if ( pParentEntry )
1302 pEntry = pParentEntry;
1303 pParentEntry = GetParent( pParentEntry );
1305 else
1306 break;
1311 String SvLBox::GetEntryText( SvLBoxEntry* ) const
1313 DBG_CHKTHIS(SvLBox,0);
1315 return String();
1318 ULONG SvLBox::GetLevelChildCount( SvLBoxEntry* _pParent ) const
1320 DBG_CHKTHIS(SvLBox,0);
1322 ULONG nCount = 0;
1323 SvLBoxEntry* pEntry = FirstChild( _pParent );
1324 while ( pEntry )
1326 ++nCount;
1327 pEntry = NextSibling( pEntry );
1330 return nCount;
1333 void SvLBox::SetSelectionMode( SelectionMode eSelectMode )
1335 DBG_CHKTHIS(SvLBox,0);
1336 eSelMode = eSelectMode;
1339 void SvLBox::SetDragDropMode( DragDropMode nDDMode )
1341 DBG_CHKTHIS(SvLBox,0);
1342 nDragDropMode = nDDMode;
1345 SvViewData* SvLBox::CreateViewData( SvListEntry* )
1347 DBG_CHKTHIS(SvLBox,0);
1348 SvViewDataEntry* pEntryData = new SvViewDataEntry;
1349 return (SvViewData*)pEntryData;
1352 void SvLBox::InitViewData( SvViewData* pData, SvListEntry* pEntry )
1354 DBG_CHKTHIS(SvLBox,0);
1355 SvLBoxEntry* pInhEntry = (SvLBoxEntry*)pEntry;
1356 SvViewDataEntry* pEntryData = (SvViewDataEntry*)pData;
1358 pEntryData->pItemData = new SvViewDataItem[ pInhEntry->ItemCount() ];
1359 SvViewDataItem* pItemData = pEntryData->pItemData;
1360 pEntryData->nItmCnt = pInhEntry->ItemCount(); // Anzahl Items fuer delete
1361 USHORT nCount = pInhEntry->ItemCount();
1362 USHORT nCurPos = 0;
1363 while( nCurPos < nCount )
1365 SvLBoxItem* pItem = pInhEntry->GetItem( nCurPos );
1366 pItem->InitViewData( this, pInhEntry, pItemData );
1367 pItemData++;
1368 nCurPos++;
1374 void SvLBox::EnableSelectionAsDropTarget( BOOL bEnable, BOOL bWithChilds )
1376 DBG_CHKTHIS(SvLBox,0);
1377 USHORT nRefDepth;
1378 SvLBoxEntry* pTemp;
1380 SvLBoxEntry* pSelEntry = FirstSelected();
1381 while( pSelEntry )
1383 if ( !bEnable )
1385 pSelEntry->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
1386 if ( bWithChilds )
1388 nRefDepth = pModel->GetDepth( pSelEntry );
1389 pTemp = Next( pSelEntry );
1390 while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
1392 pTemp->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
1393 pTemp = Next( pTemp );
1397 else
1399 pSelEntry->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
1400 if ( bWithChilds )
1402 nRefDepth = pModel->GetDepth( pSelEntry );
1403 pTemp = Next( pSelEntry );
1404 while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
1406 pTemp->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
1407 pTemp = Next( pTemp );
1411 pSelEntry = NextSelected( pSelEntry );
1415 SvLBoxEntry* SvLBox::GetDropTarget( const Point& )
1417 DBG_CHKTHIS(SvLBox,0);
1418 return 0;
1421 // ******************************************************************
1422 // InplaceEditing
1423 // ******************************************************************
1425 void SvLBox::EditText( const String& rStr, const Rectangle& rRect,
1426 const Selection& rSel )
1428 EditText( rStr, rRect, rSel, FALSE );
1431 void SvLBox::EditText( const String& rStr, const Rectangle& rRect,
1432 const Selection& rSel, BOOL bMulti )
1434 DBG_CHKTHIS(SvLBox,0);
1435 if( pEdCtrl )
1436 delete pEdCtrl;
1437 nImpFlags |= SVLBOX_IN_EDT;
1438 nImpFlags &= ~SVLBOX_EDTEND_CALLED;
1439 HideFocus();
1440 pEdCtrl = new SvInplaceEdit2(
1441 this, rRect.TopLeft(), rRect.GetSize(), rStr,
1442 LINK( this, SvLBox, TextEditEndedHdl_Impl ),
1443 rSel, bMulti );
1446 IMPL_LINK( SvLBox, TextEditEndedHdl_Impl, SvInplaceEdit2 *, EMPTYARG )
1448 DBG_CHKTHIS(SvLBox,0);
1449 if ( nImpFlags & SVLBOX_EDTEND_CALLED ) // Nesting verhindern
1450 return 0;
1451 nImpFlags |= SVLBOX_EDTEND_CALLED;
1452 String aStr;
1453 if ( !pEdCtrl->EditingCanceled() )
1454 aStr = pEdCtrl->GetText();
1455 else
1456 aStr = pEdCtrl->GetSavedValue();
1457 if ( IsEmptyTextAllowed() || aStr.Len() > 0 )
1458 EditedText( aStr );
1459 // Hide darf erst gerufen werden, nachdem der neue Text in den
1460 // Entry gesetzt wurde, damit im GetFocus der ListBox nicht
1461 // der Selecthandler mit dem alten EntryText gerufen wird.
1462 pEdCtrl->Hide();
1463 // delete pEdCtrl;
1464 // pEdCtrl = 0;
1465 nImpFlags &= (~SVLBOX_IN_EDT);
1466 GrabFocus();
1467 return 0;
1470 void SvLBox::CancelTextEditing()
1472 DBG_CHKTHIS(SvLBox,0);
1473 if ( pEdCtrl )
1474 pEdCtrl->StopEditing( TRUE );
1475 nImpFlags &= (~SVLBOX_IN_EDT);
1478 void SvLBox::EndEditing( BOOL bCancel )
1480 DBG_CHKTHIS(SvLBox,0);
1481 if( pEdCtrl )
1482 pEdCtrl->StopEditing( bCancel );
1483 nImpFlags &= (~SVLBOX_IN_EDT);
1487 bool SvLBox::IsEmptyTextAllowed() const
1489 DBG_CHKTHIS(SvLBox,0);
1490 return pLBoxImpl->m_bIsEmptyTextAllowed;
1493 void SvLBox::ForbidEmptyText()
1495 DBG_CHKTHIS(SvLBox,0);
1496 pLBoxImpl->m_bIsEmptyTextAllowed = false;
1499 void SvLBox::EditedText( const String& )
1501 DBG_CHKTHIS(SvLBox,0);
1504 void SvLBox::EditingRequest( SvLBoxEntry*, SvLBoxItem*,const Point& )
1506 DBG_CHKTHIS(SvLBox,0);
1510 SvLBoxEntry* SvLBox::CreateEntry() const
1512 DBG_CHKTHIS(SvLBox,0);
1513 return new SvLBoxEntry;
1516 void SvLBox::MakeVisible( SvLBoxEntry* )
1518 DBG_CHKTHIS(SvLBox,0);
1521 void SvLBox::Command( const CommandEvent& )
1523 DBG_CHKTHIS(SvLBox,0);
1526 void SvLBox::KeyInput( const KeyEvent& rKEvt )
1528 bool bHandled = HandleKeyInput( rKEvt );
1529 if ( !bHandled )
1530 Control::KeyInput( rKEvt );
1533 const void* SvLBox::FirstSearchEntry( String& _rEntryText )
1535 SvLBoxEntry* pEntry = GetCurEntry();
1536 if ( pEntry )
1537 pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( NextSearchEntry( pEntry, _rEntryText ) ) );
1538 else
1540 if ( !pEntry )
1541 pEntry = FirstSelected();
1542 if ( !pEntry )
1543 pEntry = First();
1546 if ( pEntry )
1547 _rEntryText = GetEntryText( pEntry );
1549 return pEntry;
1552 const void* SvLBox::NextSearchEntry( const void* _pCurrentSearchEntry, String& _rEntryText )
1554 SvLBoxEntry* pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( _pCurrentSearchEntry ) );
1556 pEntry = Next( pEntry );
1557 if ( !pEntry )
1558 pEntry = First();
1560 if ( pEntry )
1561 _rEntryText = GetEntryText( pEntry );
1563 return pEntry;
1566 void SvLBox::SelectSearchEntry( const void* _pEntry )
1568 SvLBoxEntry* pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( _pEntry ) );
1569 DBG_ASSERT( pEntry, "SvLBox::SelectSearchEntry: invalid entry!" );
1570 if ( pEntry )
1571 return;
1573 SelectAll( FALSE );
1574 SetCurEntry( pEntry );
1575 Select( pEntry );
1578 void SvLBox::ExecuteSearchEntry( const void* /*_pEntry*/ )
1580 // nothing to do here, we have no "execution"
1583 bool SvLBox::HandleKeyInput( const KeyEvent& _rKEvt )
1585 if ( !IsEntryMnemonicsEnabled() )
1586 return false;
1588 return pLBoxImpl->m_aMnemonicEngine.HandleKeyEvent( _rKEvt );
1591 SvLBoxEntry* SvLBox::GetEntry( const Point&, BOOL ) const
1593 DBG_CHKTHIS(SvLBox,0);
1594 return 0;
1597 void SvLBox::ModelHasEntryInvalidated( SvListEntry* pEntry )
1599 DBG_CHKTHIS(SvLBox,0);
1600 USHORT nCount = ((SvLBoxEntry*)pEntry)->ItemCount();
1601 for( USHORT nIdx = 0; nIdx < nCount; nIdx++ )
1603 SvLBoxItem* pItem = ((SvLBoxEntry*)pEntry)->GetItem( nIdx );
1604 pItem->InitViewData( this, (SvLBoxEntry*)pEntry, 0 );
1608 void SvLBox::SetInUseEmphasis( SvLBoxEntry* pEntry, BOOL bInUse )
1610 DBG_CHKTHIS(SvLBox,0);
1611 DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
1612 if( bInUse )
1614 if( !pEntry->HasInUseEmphasis() )
1616 pEntry->nEntryFlags |= SV_ENTRYFLAG_IN_USE;
1617 pModel->InvalidateEntry( pEntry );
1620 else
1622 if( pEntry->HasInUseEmphasis() )
1624 pEntry->nEntryFlags &= (~SV_ENTRYFLAG_IN_USE);
1625 pModel->InvalidateEntry( pEntry );
1630 void SvLBox::SetCursorEmphasis( SvLBoxEntry* pEntry, BOOL bCursored )
1632 DBG_CHKTHIS(SvLBox,0);
1633 DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
1634 SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
1635 if( pViewData && (bCursored != pViewData->IsCursored()) )
1637 pViewData->SetCursored( bCursored );
1638 // paintet in allen Views
1639 // pModel->InvalidateEntry( pEntry );
1640 // invalidiert nur in dieser View
1641 ModelHasEntryInvalidated( pEntry );
1645 BOOL SvLBox::HasCursorEmphasis( SvLBoxEntry* pEntry ) const
1647 DBG_CHKTHIS(SvLBox,0);
1648 DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
1649 SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
1650 DBG_ASSERT(pViewData,"Entry not in View");
1651 return pViewData->IsCursored();
1654 void SvLBox::WriteDragServerInfo( const Point&, SvLBoxDDInfo* )
1656 DBG_CHKTHIS(SvLBox,0);
1659 void SvLBox::ReadDragServerInfo(const Point&, SvLBoxDDInfo* )
1661 DBG_CHKTHIS(SvLBox,0);
1664 BOOL SvLBox::EditingCanceled() const
1666 if( pEdCtrl && pEdCtrl->EditingCanceled() )
1667 return TRUE;
1668 return FALSE;
1672 //JP 28.3.2001: new Drag & Drop API
1673 sal_Int8 SvLBox::AcceptDrop( const AcceptDropEvent& rEvt )
1675 DBG_CHKTHIS(SvLBox,0);
1676 sal_Int8 nRet = DND_ACTION_NONE;
1678 if( rEvt.mbLeaving || !CheckDragAndDropMode( pDDSource, rEvt.mnAction ) )
1680 ImplShowTargetEmphasis( pTargetEntry, FALSE );
1682 else if( !nDragDropMode )
1684 DBG_ERRORFILE( "SvLBox::QueryDrop(): no target" );
1686 else
1688 SvLBoxEntry* pEntry = GetDropTarget( rEvt.maPosPixel );
1689 if( !IsDropFormatSupported( SOT_FORMATSTR_ID_TREELISTBOX ) )
1691 DBG_ERRORFILE( "SvLBox::QueryDrop(): no format" );
1693 else
1695 DBG_ASSERT( pDDSource, "SvLBox::QueryDrop(): SourceBox == 0 (__EXPORT?)" );
1696 if( !( pEntry && pDDSource->GetModel() == this->GetModel()
1697 && DND_ACTION_MOVE == rEvt.mnAction
1698 && ( pEntry->nEntryFlags & SV_ENTRYFLAG_DISABLE_DROP ) ))
1700 if( NotifyAcceptDrop( pEntry ))
1701 nRet = rEvt.mnAction;
1705 // **** Emphasis zeichnen ****
1706 if( DND_ACTION_NONE == nRet )
1707 ImplShowTargetEmphasis( pTargetEntry, FALSE );
1708 else if( pEntry != pTargetEntry || !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
1710 ImplShowTargetEmphasis( pTargetEntry, FALSE );
1711 pTargetEntry = pEntry;
1712 ImplShowTargetEmphasis( pTargetEntry, TRUE );
1715 return nRet;
1718 sal_Int8 SvLBox::ExecuteDrop( const ExecuteDropEvent& rEvt, SvLBox* pSourceView )
1720 DBG_CHKTHIS(SvLBox,0);
1721 sal_Int8 nRet = DND_ACTION_NONE;
1723 DBG_ASSERT( pSourceView, "SvLBox::ExecuteDrop(): no source view" );
1724 pSourceView->EnableSelectionAsDropTarget( TRUE, TRUE );
1726 ImplShowTargetEmphasis( pTargetEntry, FALSE );
1727 pDDTarget = this;
1729 SvLBoxDDInfo aDDInfo;
1731 TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
1732 if( aData.HasFormat( SOT_FORMATSTR_ID_TREELISTBOX ))
1734 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
1735 if( aData.GetSequence( SOT_FORMATSTR_ID_TREELISTBOX, aSeq ) &&
1736 sizeof(SvLBoxDDInfo) == aSeq.getLength() )
1738 memcpy( &aDDInfo, aSeq.getConstArray(), sizeof(SvLBoxDDInfo) );
1739 nRet = rEvt.mnAction;
1743 if( DND_ACTION_NONE != nRet )
1745 nRet = DND_ACTION_NONE;
1747 ReadDragServerInfo( rEvt.maPosPixel, &aDDInfo );
1749 SvLBoxEntry* pTarget = pTargetEntry; // !!! kann 0 sein !!!
1751 if( DND_ACTION_COPY == rEvt.mnAction )
1753 if ( CopySelection( aDDInfo.pSource, pTarget ) )
1754 nRet = rEvt.mnAction;
1756 else if( DND_ACTION_MOVE == rEvt.mnAction )
1758 if ( MoveSelection( aDDInfo.pSource, pTarget ) )
1759 nRet = rEvt.mnAction;
1761 else if( DND_ACTION_COPYMOVE == rEvt.mnAction )
1763 if ( MoveSelectionCopyFallbackPossible( aDDInfo.pSource, pTarget, sal_True ) )
1764 nRet = rEvt.mnAction;
1767 return nRet;
1770 sal_Int8 SvLBox::ExecuteDrop( const ExecuteDropEvent& rEvt )
1772 DBG_CHKTHIS(SvLBox,0);
1773 return ExecuteDrop( rEvt, GetSourceView() );
1776 void SvLBox::StartDrag( sal_Int8, const Point& rPosPixel )
1778 DBG_CHKTHIS(SvLBox,0);
1780 ReleaseMouse();
1781 SvLBoxEntry* pEntry = GetEntry( rPosPixel ); // GetDropTarget( rPos );
1782 nOldDragMode = GetDragDropMode();
1783 if( !pEntry || !nOldDragMode )
1785 DragFinished( DND_ACTION_NONE );
1786 return;
1789 TransferDataContainer* pContainer = new TransferDataContainer;
1790 ::com::sun::star::uno::Reference<
1791 ::com::sun::star::datatransfer::XTransferable > xRef( pContainer );
1793 nDragDropMode = NotifyStartDrag( *pContainer, pEntry );
1794 if( !nDragDropMode || 0 == GetSelectionCount() )
1796 nDragDropMode = nOldDragMode;
1797 DragFinished( DND_ACTION_NONE );
1798 return;
1801 SvLBoxDDInfo aDDInfo;
1802 memset(&aDDInfo,0,sizeof(SvLBoxDDInfo));
1803 aDDInfo.pApp = GetpApp();
1804 aDDInfo.pSource = this;
1805 aDDInfo.pDDStartEntry = pEntry;
1806 // abgeleitete Views zum Zuge kommen lassen
1807 WriteDragServerInfo( rPosPixel, &aDDInfo );
1809 pContainer->CopyAnyData( SOT_FORMATSTR_ID_TREELISTBOX,
1810 (sal_Char*)&aDDInfo, sizeof(SvLBoxDDInfo) );
1811 pDDSource = this;
1812 pDDTarget = 0;
1814 BOOL bOldUpdateMode = Control::IsUpdateMode();
1815 Control::SetUpdateMode( TRUE );
1816 Update();
1817 Control::SetUpdateMode( bOldUpdateMode );
1819 // Selektion & deren Childs im Model als DropTargets sperren
1820 // Wichtig: Wenn im DropHandler die Selektion der
1821 // SourceListBox veraendert wird, muessen vorher die Eintraege
1822 // als DropTargets wieder freigeschaltet werden:
1823 // (GetSourceListBox()->EnableSelectionAsDropTarget( TRUE, TRUE );)
1824 EnableSelectionAsDropTarget( FALSE, TRUE /* with Childs */ );
1826 pContainer->StartDrag( this, nDragOptions, GetDragFinishedHdl() );
1829 void SvLBox::DragFinished( sal_Int8
1830 #ifndef UNX
1831 nAction
1832 #endif
1835 EnableSelectionAsDropTarget( TRUE, TRUE );
1837 #ifndef UNX
1838 if( (nAction == DND_ACTION_MOVE) && ( (pDDTarget &&
1839 ((ULONG)(pDDTarget->GetModel())!=(ULONG)(this->GetModel()))) ||
1840 !pDDTarget ))
1842 RemoveSelection();
1844 #endif
1846 ImplShowTargetEmphasis( pTargetEntry, FALSE );
1847 pDDSource = 0;
1848 pDDTarget = 0;
1849 pTargetEntry = 0;
1850 nDragDropMode = nOldDragMode;
1853 DragDropMode SvLBox::NotifyStartDrag( TransferDataContainer&, SvLBoxEntry* )
1855 DBG_CHKTHIS(SvLBox,0);
1856 return (DragDropMode)0xffff;
1859 BOOL SvLBox::NotifyAcceptDrop( SvLBoxEntry* )
1861 DBG_CHKTHIS(SvLBox,0);
1862 return TRUE;
1865 // handler and methods for Drag - finished handler.
1866 // The with get GetDragFinishedHdl() get link can set on the
1867 // TransferDataContainer. This link is a callback for the DragFinished
1868 // call. AddBox method is called from the GetDragFinishedHdl() and the
1869 // remove is called in link callback and in the destructor. So it can't
1870 // called to a deleted object.
1872 namespace
1874 struct SortLBoxes : public rtl::Static<SvULongsSort, SortLBoxes> {};
1877 void SvLBox::AddBoxToDDList_Impl( const SvLBox& rB )
1879 ULONG nVal = (ULONG)&rB;
1880 SortLBoxes::get().Insert( nVal );
1883 void SvLBox::RemoveBoxFromDDList_Impl( const SvLBox& rB )
1885 ULONG nVal = (ULONG)&rB;
1886 SortLBoxes::get().Remove( nVal );
1889 IMPL_STATIC_LINK( SvLBox, DragFinishHdl_Impl, sal_Int8*, pAction )
1891 ULONG nVal = (ULONG)pThis;
1892 USHORT nFnd;
1893 SvULongsSort &rSortLBoxes = SortLBoxes::get();
1894 if( rSortLBoxes.Seek_Entry( nVal, &nFnd ) )
1896 pThis->DragFinished( *pAction );
1897 rSortLBoxes.Remove( nFnd, 1 );
1899 return 0;
1902 Link SvLBox::GetDragFinishedHdl() const
1904 AddBoxToDDList_Impl( *this );
1905 return STATIC_LINK( this, SvLBox, DragFinishHdl_Impl );
1908 void SvLBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& ) const
1912 ::com::sun::star::uno::Reference< XAccessible > SvLBox::CreateAccessible()
1914 return ::com::sun::star::uno::Reference< XAccessible >();
1917 Rectangle SvLBox::GetBoundingRect( SvLBoxEntry* )
1919 return Rectangle();