1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 - delete anchor in SelectionEngine when selecting manually
23 - SelectAll( sal_False ) => only repaint the delselected entries
26 #include <svtools/treelistbox.hxx>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <vcl/svapp.hxx>
29 #include <vcl/accel.hxx>
30 #include <vcl/i18nhelp.hxx>
31 #include <vcl/builder.hxx>
32 #include <sot/formats.hxx>
33 #include <unotools/accessiblestatesethelper.hxx>
34 #include <rtl/instance.hxx>
35 #include <comphelper/string.hxx>
37 #include <svtools/svmedit.hxx>
38 #include <svtools/svlbitm.hxx>
39 #include "svtools/treelistentry.hxx"
40 #include "svtools/viewdataentry.hxx"
41 #include "svimpbox.hxx"
47 using namespace ::com::sun::star::accessibility
;
50 static SvTreeListBox
* pDDSource
= NULL
;
51 static SvTreeListBox
* pDDTarget
= NULL
;
53 DBG_NAME(SvInplaceEdit2
)
55 #define SVLBOX_ACC_RETURN 1
56 #define SVLBOX_ACC_ESCAPE 2
58 // ***************************************************************
60 class MyEdit_Impl
: public Edit
62 SvInplaceEdit2
* pOwner
;
64 MyEdit_Impl( Window
* pParent
, SvInplaceEdit2
* pOwner
);
65 virtual void KeyInput( const KeyEvent
& rKEvt
);
66 virtual void LoseFocus();
69 class MyMultiEdit_Impl
: public MultiLineEdit
71 SvInplaceEdit2
* pOwner
;
73 MyMultiEdit_Impl( Window
* pParent
, SvInplaceEdit2
* pOwner
);
74 virtual void KeyInput( const KeyEvent
& rKEvt
);
75 virtual void LoseFocus();
78 MyEdit_Impl::MyEdit_Impl( Window
* pParent
, SvInplaceEdit2
* _pOwner
) :
80 Edit( pParent
, WB_LEFT
),
87 void MyEdit_Impl::KeyInput( const KeyEvent
& rKEvt
)
89 if( !pOwner
->KeyInput( rKEvt
))
90 Edit::KeyInput( rKEvt
);
93 void MyEdit_Impl::LoseFocus()
98 MyMultiEdit_Impl::MyMultiEdit_Impl( Window
* pParent
, SvInplaceEdit2
* _pOwner
)
99 : MultiLineEdit( pParent
,
105 void MyMultiEdit_Impl::KeyInput( const KeyEvent
& rKEvt
)
107 if( !pOwner
->KeyInput( rKEvt
))
108 MultiLineEdit::KeyInput( rKEvt
);
111 void MyMultiEdit_Impl::LoseFocus()
117 SvInplaceEdit2::SvInplaceEdit2
119 Window
* pParent
, const Point
& rPos
,
121 const OUString
& rData
,
122 const Link
& rNotifyEditEnd
,
123 const Selection
& rSelection
,
127 aCallBackHdl ( rNotifyEditEnd
),
128 bCanceled ( sal_False
),
129 bAlreadyInCallBack ( sal_False
)
132 DBG_CTOR(SvInplaceEdit2
,0);
135 pEdit
= new MyMultiEdit_Impl( pParent
, this );
137 pEdit
= new MyEdit_Impl( pParent
, this );
139 Font
aFont( pParent
->GetFont() );
140 aFont
.SetTransparent( sal_False
);
141 Color
aColor( pParent
->GetBackground().GetColor() );
142 aFont
.SetFillColor(aColor
);
143 pEdit
->SetFont( aFont
);
144 pEdit
->SetBackground( pParent
->GetBackground() );
145 pEdit
->SetPosPixel( rPos
);
146 pEdit
->SetSizePixel( rSize
);
147 pEdit
->SetText( rData
);
148 pEdit
->SetSelection( rSelection
);
151 aAccReturn
.InsertItem( SVLBOX_ACC_RETURN
, KeyCode(KEY_RETURN
) );
152 aAccEscape
.InsertItem( SVLBOX_ACC_ESCAPE
, KeyCode(KEY_ESCAPE
) );
154 aAccReturn
.SetActivateHdl( LINK( this, SvInplaceEdit2
, ReturnHdl_Impl
) );
155 aAccEscape
.SetActivateHdl( LINK( this, SvInplaceEdit2
, EscapeHdl_Impl
) );
156 GetpApp()->InsertAccel( &aAccReturn
);
157 GetpApp()->InsertAccel( &aAccEscape
);
163 SvInplaceEdit2::~SvInplaceEdit2()
165 DBG_DTOR(SvInplaceEdit2
,0);
166 if( !bAlreadyInCallBack
)
168 GetpApp()->RemoveAccel( &aAccReturn
);
169 GetpApp()->RemoveAccel( &aAccEscape
);
174 OUString
SvInplaceEdit2::GetSavedValue() const
176 return pEdit
->GetSavedValue();
179 void SvInplaceEdit2::Hide()
185 IMPL_LINK_NOARG_INLINE_START(SvInplaceEdit2
, ReturnHdl_Impl
)
187 DBG_CHKTHIS(SvInplaceEdit2
,0);
188 bCanceled
= sal_False
;
189 CallCallBackHdl_Impl();
192 IMPL_LINK_NOARG_INLINE_END(SvInplaceEdit2
, ReturnHdl_Impl
)
194 IMPL_LINK_NOARG_INLINE_START(SvInplaceEdit2
, EscapeHdl_Impl
)
196 DBG_CHKTHIS(SvInplaceEdit2
,0);
197 bCanceled
= sal_True
;
198 CallCallBackHdl_Impl();
201 IMPL_LINK_NOARG_INLINE_END(SvInplaceEdit2
, EscapeHdl_Impl
)
204 sal_Bool
SvInplaceEdit2::KeyInput( const KeyEvent
& rKEvt
)
206 DBG_CHKTHIS(SvInplaceEdit2
,0);
207 KeyCode aCode
= rKEvt
.GetKeyCode();
208 sal_uInt16 nCode
= aCode
.GetCode();
213 bCanceled
= sal_True
;
214 CallCallBackHdl_Impl();
218 bCanceled
= sal_False
;
219 CallCallBackHdl_Impl();
225 void SvInplaceEdit2::StopEditing( sal_Bool bCancel
)
227 DBG_CHKTHIS(SvInplaceEdit2
,0);
228 if ( !bAlreadyInCallBack
)
231 CallCallBackHdl_Impl();
235 void SvInplaceEdit2::LoseFocus()
237 DBG_CHKTHIS(SvInplaceEdit2
,0);
238 if ( !bAlreadyInCallBack
239 && ((!Application::GetFocusWindow()) || !pEdit
->IsChild( Application::GetFocusWindow()) )
242 bCanceled
= sal_False
;
243 aTimer
.SetTimeout(10);
244 aTimer
.SetTimeoutHdl(LINK(this,SvInplaceEdit2
,Timeout_Impl
));
249 IMPL_LINK_NOARG_INLINE_START(SvInplaceEdit2
, Timeout_Impl
)
251 DBG_CHKTHIS(SvInplaceEdit2
,0);
252 CallCallBackHdl_Impl();
255 IMPL_LINK_NOARG_INLINE_END(SvInplaceEdit2
, Timeout_Impl
)
257 void SvInplaceEdit2::CallCallBackHdl_Impl()
259 DBG_CHKTHIS(SvInplaceEdit2
,0);
261 if ( !bAlreadyInCallBack
)
263 bAlreadyInCallBack
= sal_True
;
264 GetpApp()->RemoveAccel( &aAccReturn
);
265 GetpApp()->RemoveAccel( &aAccEscape
);
267 aCallBackHdl
.Call( this );
271 OUString
SvInplaceEdit2::GetText() const
273 return pEdit
->GetText();
276 // ***************************************************************
278 // ***************************************************************
282 SvLBoxTab::SvLBoxTab()
284 DBG_CTOR(SvLBoxTab
,0);
290 SvLBoxTab::SvLBoxTab( long nPosition
, sal_uInt16 nTabFlags
)
292 DBG_CTOR(SvLBoxTab
,0);
298 SvLBoxTab::SvLBoxTab( const SvLBoxTab
& rTab
)
300 DBG_CTOR(SvLBoxTab
,0);
302 pUserData
= rTab
.pUserData
;
303 nFlags
= rTab
.nFlags
;
306 SvLBoxTab::~SvLBoxTab()
308 DBG_DTOR(SvLBoxTab
,0);
312 long SvLBoxTab::CalcOffset( long nItemWidth
, long nTabWidth
)
314 DBG_CHKTHIS(SvLBoxTab
,0);
316 if ( nFlags
& SV_LBOXTAB_ADJUST_RIGHT
)
318 nOffset
= nTabWidth
- nItemWidth
;
322 else if ( nFlags
& SV_LBOXTAB_ADJUST_CENTER
)
324 if( nFlags
& SV_LBOXTAB_FORCE
)
326 // correct implementation of centering
327 nOffset
= ( nTabWidth
- nItemWidth
) / 2;
333 // historically grown, wrong calculation of tabs which is needed by
334 // Abo-Tabbox, Tools/Options/Customize etc.
336 nOffset
= -( nItemWidth
/ 2 );
342 // ***************************************************************
344 // ***************************************************************
346 DBG_NAME(SvLBoxItem
);
348 SvLBoxItem::SvLBoxItem( SvTreeListEntry
*, sal_uInt16
)
350 DBG_CTOR(SvLBoxItem
,0);
353 SvLBoxItem::SvLBoxItem()
355 DBG_CTOR(SvLBoxItem
,0);
358 SvLBoxItem::~SvLBoxItem()
360 DBG_DTOR(SvLBoxItem
,0);
363 const Size
& SvLBoxItem::GetSize(const SvTreeListBox
* pView
, const SvTreeListEntry
* pEntry
) const
365 DBG_CHKTHIS(SvLBoxItem
,0);
366 const SvViewDataItem
* pViewData
= pView
->GetViewDataItem( pEntry
, this );
367 return pViewData
->maSize
;
370 const Size
& SvLBoxItem::GetSize(const SvViewDataEntry
* pData
, sal_uInt16 nItemPos
) const
372 const SvViewDataItem
* pIData
= pData
->GetItem(nItemPos
);
373 return pIData
->maSize
;
376 struct SvTreeListBoxImpl
378 bool m_bIsEmptyTextAllowed
:1;
379 bool m_bEntryMnemonicsEnabled
:1;
380 bool m_bDoingQuickSelection
:1;
384 vcl::MnemonicEngine m_aMnemonicEngine
;
385 vcl::QuickSelectionEngine m_aQuickSelectionEngine
;
387 SvTreeListBoxImpl(SvTreeListBox
& _rBox
) :
388 m_bIsEmptyTextAllowed(true),
389 m_bEntryMnemonicsEnabled(false),
390 m_bDoingQuickSelection(false),
392 m_aMnemonicEngine(_rBox
),
393 m_aQuickSelectionEngine(_rBox
) {}
396 DBG_NAME(SvTreeListBox
);
398 SvTreeListBox::SvTreeListBox(Window
* pParent
, WinBits nWinStyle
) :
399 Control(pParent
, nWinStyle
| WB_CLIPCHILDREN
),
400 DropTargetHelper(this),
401 DragSourceHelper(this),
402 mpImpl(new SvTreeListBoxImpl(*this)),
403 mbContextBmpExpanded(false),
404 eSelMode(NO_SELECTION
),
407 DBG_CTOR(SvTreeListBox
,0);
408 nDragOptions
= DND_ACTION_COPYMOVE
| DND_ACTION_LINK
;
412 SvTreeList
* pTempModel
= new SvTreeList
;
413 pTempModel
->SetRefCount( 0 );
414 SetBaseModel(pTempModel
);
415 pModel
->SetCloneLink( LINK(this, SvTreeListBox
, CloneHdl_Impl
));
416 pModel
->InsertView( this );
419 eSelMode
= SINGLE_SELECTION
;
420 nDragDropMode
= SV_DRAGDROP_NONE
;
421 SetType(WINDOW_TREELISTBOX
);
425 SetSublistOpenWithLeftRight();
428 SvTreeListBox::SvTreeListBox(Window
* pParent
, const ResId
& rResId
) :
429 Control(pParent
, rResId
),
430 DropTargetHelper(this),
431 DragSourceHelper(this),
432 mpImpl(new SvTreeListBoxImpl(*this)),
433 mbContextBmpExpanded(false),
434 eSelMode(NO_SELECTION
),
437 DBG_CTOR(SvTreeListBox
,0);
440 nDragOptions
= DND_ACTION_COPYMOVE
| DND_ACTION_LINK
;
442 SvTreeList
* pTempModel
= new SvTreeList
;
443 pTempModel
->SetRefCount( 0 );
444 SetBaseModel(pTempModel
);
445 pModel
->InsertView( this );
448 pModel
->SetCloneLink( LINK(this, SvTreeListBox
, CloneHdl_Impl
));
449 SetType(WINDOW_TREELISTBOX
);
454 SetSublistOpenWithLeftRight();
457 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeSvTreeListBox(Window
*pParent
, VclBuilder::stringmap
&rMap
)
459 WinBits nWinStyle
= WB_TABSTOP
;
460 OString sBorder
= VclBuilder::extractCustomProperty(rMap
);
461 if (!sBorder
.isEmpty())
462 nWinStyle
|= WB_BORDER
;
463 return new SvTreeListBox(pParent
, nWinStyle
);
466 void SvTreeListBox::Clear()
468 DBG_CHKTHIS(SvTreeListBox
,0);
469 pModel
->Clear(); // Model calls SvTreeListBox::ModelHasCleared()
472 void SvTreeListBox::EnableEntryMnemonics( bool _bEnable
)
474 if ( _bEnable
== IsEntryMnemonicsEnabled() )
477 mpImpl
->m_bEntryMnemonicsEnabled
= _bEnable
;
481 bool SvTreeListBox::IsEntryMnemonicsEnabled() const
483 return mpImpl
->m_bEntryMnemonicsEnabled
;
486 IMPL_LINK_INLINE_START( SvTreeListBox
, CloneHdl_Impl
, SvTreeListEntry
*, pEntry
)
488 DBG_CHKTHIS(SvTreeListBox
,0);
489 return (sal_IntPtr
)(CloneEntry((SvTreeListEntry
*)pEntry
));
491 IMPL_LINK_INLINE_END( SvTreeListBox
, CloneHdl_Impl
, SvTreeListEntry
*, pEntry
)
493 sal_uLong
SvTreeListBox::Insert( SvTreeListEntry
* pEntry
, SvTreeListEntry
* pParent
, sal_uLong nPos
)
495 DBG_CHKTHIS(SvTreeListBox
,0);
496 sal_uLong nInsPos
= pModel
->Insert( pEntry
, pParent
, nPos
);
500 sal_uLong
SvTreeListBox::Insert( SvTreeListEntry
* pEntry
,sal_uLong nRootPos
)
502 DBG_CHKTHIS(SvTreeListBox
,0);
503 sal_uLong nInsPos
= pModel
->Insert( pEntry
, nRootPos
);
507 long SvTreeListBox::ExpandingHdl()
509 DBG_CHKTHIS(SvTreeListBox
,0);
510 return aExpandingHdl
.IsSet() ? aExpandingHdl
.Call( this ) : 1;
513 void SvTreeListBox::ExpandedHdl()
515 DBG_CHKTHIS(SvTreeListBox
,0);
516 aExpandedHdl
.Call( this );
519 void SvTreeListBox::SelectHdl()
521 DBG_CHKTHIS(SvTreeListBox
,0);
522 aSelectHdl
.Call( this );
525 void SvTreeListBox::DeselectHdl()
527 DBG_CHKTHIS(SvTreeListBox
,0);
528 aDeselectHdl
.Call( this );
531 sal_Bool
SvTreeListBox::DoubleClickHdl()
533 DBG_CHKTHIS(SvTreeListBox
,0);
534 aDoubleClickHdl
.Call( this );
539 sal_Bool
SvTreeListBox::CheckDragAndDropMode( SvTreeListBox
* pSource
, sal_Int8 nAction
)
541 DBG_CHKTHIS(SvTreeListBox
,0);
542 if ( pSource
== this )
544 if ( !(nDragDropMode
& (SV_DRAGDROP_CTRL_MOVE
| SV_DRAGDROP_CTRL_COPY
) ) )
545 return sal_False
; // D&D locked within list
546 if( DND_ACTION_MOVE
== nAction
)
548 if ( !(nDragDropMode
& SV_DRAGDROP_CTRL_MOVE
) )
549 return sal_False
; // no local move
553 if ( !(nDragDropMode
& SV_DRAGDROP_CTRL_COPY
))
554 return sal_False
; // no local copy
559 if ( !(nDragDropMode
& SV_DRAGDROP_APP_DROP
) )
560 return sal_False
; // no drop
561 if ( DND_ACTION_MOVE
== nAction
)
563 if ( !(nDragDropMode
& SV_DRAGDROP_APP_MOVE
) )
564 return sal_False
; // no global move
568 if ( !(nDragDropMode
& SV_DRAGDROP_APP_COPY
))
569 return sal_False
; // no global copy
578 void SvTreeListBox::NotifyRemoving( SvTreeListEntry
* )
580 DBG_CHKTHIS(SvTreeListBox
,0);
589 1. target doesn't have children
590 - entry becomes sibling of target. entry comes after target
591 (->Window: below the target)
592 2. target is an expanded parent
593 - entry inserted at the beginning of the target childlist
594 3. target is a collapsed parent
595 - entry is inserted at the end of the target childlist
598 sal_Bool
SvTreeListBox::NotifyMoving(
599 SvTreeListEntry
* pTarget
, // D&D dropping position in this->GetModel()
600 SvTreeListEntry
* pEntry
, // entry that we want to move, from
601 // GetSourceListBox()->GetModel()
602 SvTreeListEntry
*& rpNewParent
, // new target parent
603 sal_uLong
& rNewChildPos
) // position in childlist of target parent
605 sal_Bool
SvTreeListBox::NotifyMoving(
606 SvTreeListEntry
* pTarget
, // D&D dropping position in this->GetModel()
607 SvTreeListEntry
*, // entry that we want to move, from
608 // GetSourceListBox()->GetModel()
609 SvTreeListEntry
*& rpNewParent
, // new target parent
610 sal_uLong
& rNewChildPos
) // position in childlist of target parent
613 DBG_CHKTHIS(SvTreeListBox
,0);
614 DBG_ASSERT(pEntry
,"NotifyMoving:SoureEntry?");
621 if ( !pTarget
->HasChildren() && !pTarget
->HasChildrenOnDemand() )
624 rpNewParent
= GetParent( pTarget
);
625 rNewChildPos
= pModel
->GetRelPos( pTarget
) + 1;
626 rNewChildPos
+= nCurEntrySelPos
;
632 rpNewParent
= pTarget
;
633 if( IsExpanded(pTarget
))
636 rNewChildPos
= LIST_APPEND
;
641 sal_Bool
SvTreeListBox::NotifyCopying(
642 SvTreeListEntry
* pTarget
, // D&D dropping position in this->GetModel()
643 SvTreeListEntry
* pEntry
, // entry that we want to move, from
644 // GetSourceListBox()->GetModel()
645 SvTreeListEntry
*& rpNewParent
, // new target parent
646 sal_uLong
& rNewChildPos
) // position in childlist of target parent
648 DBG_CHKTHIS(SvTreeListBox
,0);
649 return NotifyMoving(pTarget
,pEntry
,rpNewParent
,rNewChildPos
);
652 SvTreeListEntry
* SvTreeListBox::FirstChild( SvTreeListEntry
* pParent
) const
654 return pModel
->FirstChild(pParent
);
657 SvTreeListEntry
* SvTreeListBox::NextSibling( SvTreeListEntry
* pEntry
) const
659 return pModel
->NextSibling(pEntry
);
662 SvTreeListEntry
* SvTreeListBox::PrevSibling( SvTreeListEntry
* pEntry
) const
664 return pModel
->PrevSibling(pEntry
);
667 // return: all entries copied
668 sal_Bool
SvTreeListBox::CopySelection( SvTreeListBox
* pSource
, SvTreeListEntry
* pTarget
)
670 DBG_CHKTHIS(SvTreeListBox
,0);
671 nCurEntrySelPos
= 0; // selection counter for NotifyMoving/Copying
672 sal_Bool bSuccess
= sal_True
;
673 std::vector
<SvTreeListEntry
*> aList
;
674 sal_Bool bClone
= (sal_Bool
)( (sal_uLong
)(pSource
->GetModel()) != (sal_uLong
)GetModel() );
675 Link
aCloneLink( pModel
->GetCloneLink() );
676 pModel
->SetCloneLink( LINK(this, SvTreeListBox
, CloneHdl_Impl
));
678 // cache selection to simplify iterating over the selection when doing a D&D
679 // exchange within the same listbox
680 SvTreeListEntry
* pSourceEntry
= pSource
->FirstSelected();
681 while ( pSourceEntry
)
683 // children are copied automatically
684 pSource
->SelectChildren( pSourceEntry
, sal_False
);
685 aList
.push_back( pSourceEntry
);
686 pSourceEntry
= pSource
->NextSelected( pSourceEntry
);
689 std::vector
<SvTreeListEntry
*>::const_iterator it
= aList
.begin(), itEnd
= aList
.end();
690 for (; it
!= itEnd
; ++it
)
693 SvTreeListEntry
* pNewParent
= 0;
694 sal_uLong nInsertionPos
= ULONG_MAX
;
695 sal_Bool bOk
=NotifyCopying(pTarget
,pSourceEntry
,pNewParent
,nInsertionPos
);
700 sal_uLong nCloneCount
= 0;
701 pSourceEntry
= pModel
->Clone(pSourceEntry
, nCloneCount
);
702 pModel
->InsertTree(pSourceEntry
, pNewParent
, nInsertionPos
);
706 sal_uLong nListPos
= pModel
->Copy(pSourceEntry
, pNewParent
, nInsertionPos
);
707 pSourceEntry
= GetEntry( pNewParent
, nListPos
);
711 bSuccess
= sal_False
;
713 if( bOk
== (sal_Bool
)2 ) // HACK: make visible moved entry?
714 MakeVisible( pSourceEntry
);
716 pModel
->SetCloneLink( aCloneLink
);
720 // return: all entries were moved
721 sal_Bool
SvTreeListBox::MoveSelection( SvTreeListBox
* pSource
, SvTreeListEntry
* pTarget
)
723 return MoveSelectionCopyFallbackPossible( pSource
, pTarget
, sal_False
);
726 sal_Bool
SvTreeListBox::MoveSelectionCopyFallbackPossible( SvTreeListBox
* pSource
, SvTreeListEntry
* pTarget
, sal_Bool bAllowCopyFallback
)
728 DBG_CHKTHIS(SvTreeListBox
,0);
729 nCurEntrySelPos
= 0; // selection counter for NotifyMoving/Copying
730 sal_Bool bSuccess
= sal_True
;
731 std::vector
<SvTreeListEntry
*> aList
;
732 sal_Bool bClone
= (sal_Bool
)( (sal_uLong
)(pSource
->GetModel()) != (sal_uLong
)GetModel() );
733 Link
aCloneLink( pModel
->GetCloneLink() );
735 pModel
->SetCloneLink( LINK(this, SvTreeListBox
, CloneHdl_Impl
));
737 SvTreeListEntry
* pSourceEntry
= pSource
->FirstSelected();
738 while ( pSourceEntry
)
740 // children are automatically moved
741 pSource
->SelectChildren( pSourceEntry
, sal_False
);
742 aList
.push_back( pSourceEntry
);
743 pSourceEntry
= pSource
->NextSelected( pSourceEntry
);
746 std::vector
<SvTreeListEntry
*>::const_iterator it
= aList
.begin(), itEnd
= aList
.end();
747 for (; it
!= itEnd
; ++it
)
751 SvTreeListEntry
* pNewParent
= 0;
752 sal_uLong nInsertionPos
= ULONG_MAX
;
753 sal_Bool bOk
= NotifyMoving(pTarget
,pSourceEntry
,pNewParent
,nInsertionPos
);
754 sal_Bool bCopyOk
= bOk
;
755 if ( !bOk
&& bAllowCopyFallback
)
757 nInsertionPos
= LIST_APPEND
;
758 bCopyOk
= NotifyCopying(pTarget
,pSourceEntry
,pNewParent
,nInsertionPos
);
761 if ( bOk
|| bCopyOk
)
765 sal_uLong nCloneCount
= 0;
766 pSourceEntry
= pModel
->Clone(pSourceEntry
, nCloneCount
);
767 pModel
->InsertTree(pSourceEntry
, pNewParent
, nInsertionPos
);
772 pModel
->Move(pSourceEntry
, pNewParent
, nInsertionPos
);
774 pModel
->Copy(pSourceEntry
, pNewParent
, nInsertionPos
);
778 bSuccess
= sal_False
;
780 if( bOk
== (sal_Bool
)2 ) // HACK: make moved entry visible?
781 MakeVisible( pSourceEntry
);
783 pModel
->SetCloneLink( aCloneLink
);
787 void SvTreeListBox::RemoveSelection()
789 DBG_CHKTHIS(SvTreeListBox
,0);
790 std::vector
<const SvTreeListEntry
*> aList
;
791 // cache selection, as the implementation deselects everything on the first
793 SvTreeListEntry
* pEntry
= FirstSelected();
796 aList
.push_back( pEntry
);
797 if ( pEntry
->HasChildren() )
798 // remove deletes all children automatically
799 SelectChildren(pEntry
, false);
800 pEntry
= NextSelected( pEntry
);
803 std::vector
<const SvTreeListEntry
*>::const_iterator it
= aList
.begin(), itEnd
= aList
.end();
804 for (; it
!= itEnd
; ++it
)
808 SvTreeListBox
* SvTreeListBox::GetSourceView() const
813 void SvTreeListBox::RecalcViewData()
815 DBG_CHKTHIS(SvTreeListBox
,0);
816 SvTreeListEntry
* pEntry
= First();
819 sal_uInt16 nCount
= pEntry
->ItemCount();
820 sal_uInt16 nCurPos
= 0;
821 while ( nCurPos
< nCount
)
823 SvLBoxItem
* pItem
= pEntry
->GetItem( nCurPos
);
824 pItem
->InitViewData( this, pEntry
);
827 ViewDataInitialized( pEntry
);
828 pEntry
= Next( pEntry
);
832 void SvTreeListBox::ViewDataInitialized( SvTreeListEntry
* )
834 DBG_CHKTHIS(SvTreeListBox
,0);
837 void SvTreeListBox::ImplShowTargetEmphasis( SvTreeListEntry
* pEntry
, sal_Bool bShow
)
839 DBG_CHKTHIS(SvTreeListBox
,0);
840 if ( bShow
&& (nImpFlags
& SVLBOX_TARGEMPH_VIS
) )
842 if ( !bShow
&& !(nImpFlags
& SVLBOX_TARGEMPH_VIS
) )
844 ShowTargetEmphasis( pEntry
, bShow
);
846 nImpFlags
|= SVLBOX_TARGEMPH_VIS
;
848 nImpFlags
&= ~SVLBOX_TARGEMPH_VIS
;
851 void SvTreeListBox::OnCurrentEntryChanged()
853 if ( !mpImpl
->m_bDoingQuickSelection
)
854 mpImpl
->m_aQuickSelectionEngine
.Reset();
857 SvTreeListEntry
* SvTreeListBox::GetEntry( SvTreeListEntry
* pParent
, sal_uLong nPos
) const
859 return pModel
->GetEntry(pParent
, nPos
);
862 SvTreeListEntry
* SvTreeListBox::GetEntry( sal_uLong nRootPos
) const
864 return pModel
->GetEntry(nRootPos
);
867 SvTreeListEntry
* SvTreeListBox::GetEntryFromPath( const ::std::deque
< sal_Int32
>& _rPath
) const
869 DBG_CHKTHIS(SvTreeListBox
,0);
871 SvTreeListEntry
* pEntry
= NULL
;
872 SvTreeListEntry
* pParent
= NULL
;
873 for( ::std::deque
< sal_Int32
>::const_iterator pItem
= _rPath
.begin(); pItem
!= _rPath
.end(); ++pItem
)
875 pEntry
= GetEntry( pParent
, *pItem
);
884 void SvTreeListBox::FillEntryPath( SvTreeListEntry
* pEntry
, ::std::deque
< sal_Int32
>& _rPath
) const
886 DBG_CHKTHIS(SvTreeListBox
,0);
890 SvTreeListEntry
* pParentEntry
= GetParent( pEntry
);
893 sal_uLong i
, nCount
= GetLevelChildCount( pParentEntry
);
894 for ( i
= 0; i
< nCount
; ++i
)
896 SvTreeListEntry
* pTemp
= GetEntry( pParentEntry
, i
);
897 DBG_ASSERT( pEntry
, "invalid entry" );
898 if ( pEntry
== pTemp
)
900 _rPath
.push_front( (sal_Int32
)i
);
907 pEntry
= pParentEntry
;
908 pParentEntry
= GetParent( pParentEntry
);
916 const SvTreeListEntry
* SvTreeListBox::GetParent( const SvTreeListEntry
* pEntry
) const
918 return pModel
->GetParent(pEntry
);
921 SvTreeListEntry
* SvTreeListBox::GetParent( SvTreeListEntry
* pEntry
) const
923 return pModel
->GetParent(pEntry
);
926 SvTreeListEntry
* SvTreeListBox::GetRootLevelParent( SvTreeListEntry
* pEntry
) const
928 return pModel
->GetRootLevelParent(pEntry
);
931 sal_uLong
SvTreeListBox::GetChildCount( SvTreeListEntry
* pParent
) const
933 return pModel
->GetChildCount(pParent
);
936 sal_uLong
SvTreeListBox::GetLevelChildCount( SvTreeListEntry
* _pParent
) const
938 DBG_CHKTHIS(SvTreeListBox
,0);
940 sal_uLong nCount
= 0;
941 SvTreeListEntry
* pEntry
= FirstChild( _pParent
);
945 pEntry
= NextSibling( pEntry
);
951 SvViewDataEntry
* SvTreeListBox::GetViewDataEntry( SvTreeListEntry
* pEntry
) const
953 return (SvViewDataEntry
*)SvListView::GetViewData(pEntry
);
956 SvViewDataItem
* SvTreeListBox::GetViewDataItem(SvTreeListEntry
* pEntry
, SvLBoxItem
* pItem
)
958 return const_cast<SvViewDataItem
*>(static_cast<const SvTreeListBox
*>(this)->GetViewDataItem(pEntry
, pItem
));
961 const SvViewDataItem
* SvTreeListBox::GetViewDataItem(const SvTreeListEntry
* pEntry
, const SvLBoxItem
* pItem
) const
963 const SvViewDataEntry
* pEntryData
= (const SvViewDataEntry
*)SvListView::GetViewData(pEntry
);
964 DBG_ASSERT(pEntryData
,"Entry not in View");
965 sal_uInt16 nItemPos
= pEntry
->GetPos(pItem
);
966 return pEntryData
->GetItem(nItemPos
);
969 SvViewDataEntry
* SvTreeListBox::CreateViewData( SvTreeListEntry
* )
971 DBG_CHKTHIS(SvTreeListBox
,0);
972 SvViewDataEntry
* pEntryData
= new SvViewDataEntry
;
973 return (SvViewDataEntry
*)pEntryData
;
976 void SvTreeListBox::InitViewData( SvViewDataEntry
* pData
, SvTreeListEntry
* pEntry
)
978 DBG_CHKTHIS(SvTreeListBox
,0);
979 SvTreeListEntry
* pInhEntry
= (SvTreeListEntry
*)pEntry
;
980 SvViewDataEntry
* pEntryData
= (SvViewDataEntry
*)pData
;
982 pEntryData
->Init(pInhEntry
->ItemCount());
983 sal_uInt16 nCount
= pInhEntry
->ItemCount();
984 sal_uInt16 nCurPos
= 0;
985 while( nCurPos
< nCount
)
987 SvLBoxItem
* pItem
= pInhEntry
->GetItem( nCurPos
);
988 SvViewDataItem
* pItemData
= pEntryData
->GetItem(nCurPos
);
989 pItem
->InitViewData( this, pInhEntry
, pItemData
);
997 void SvTreeListBox::EnableSelectionAsDropTarget( sal_Bool bEnable
, sal_Bool bWithChildren
)
999 DBG_CHKTHIS(SvTreeListBox
,0);
1000 sal_uInt16 nRefDepth
;
1001 SvTreeListEntry
* pTemp
;
1003 SvTreeListEntry
* pSelEntry
= FirstSelected();
1008 pSelEntry
->nEntryFlags
|= SV_ENTRYFLAG_DISABLE_DROP
;
1009 if ( bWithChildren
)
1011 nRefDepth
= pModel
->GetDepth( pSelEntry
);
1012 pTemp
= Next( pSelEntry
);
1013 while( pTemp
&& pModel
->GetDepth( pTemp
) > nRefDepth
)
1015 pTemp
->nEntryFlags
|= SV_ENTRYFLAG_DISABLE_DROP
;
1016 pTemp
= Next( pTemp
);
1022 pSelEntry
->nEntryFlags
&= (~SV_ENTRYFLAG_DISABLE_DROP
);
1023 if ( bWithChildren
)
1025 nRefDepth
= pModel
->GetDepth( pSelEntry
);
1026 pTemp
= Next( pSelEntry
);
1027 while( pTemp
&& pModel
->GetDepth( pTemp
) > nRefDepth
)
1029 pTemp
->nEntryFlags
&= (~SV_ENTRYFLAG_DISABLE_DROP
);
1030 pTemp
= Next( pTemp
);
1034 pSelEntry
= NextSelected( pSelEntry
);
1038 // ******************************************************************
1040 // ******************************************************************
1042 void SvTreeListBox::EditText( const OUString
& rStr
, const Rectangle
& rRect
,
1043 const Selection
& rSel
)
1045 EditText( rStr
, rRect
, rSel
, sal_False
);
1048 void SvTreeListBox::EditText( const OUString
& rStr
, const Rectangle
& rRect
,
1049 const Selection
& rSel
, sal_Bool bMulti
)
1051 DBG_CHKTHIS(SvTreeListBox
,0);
1054 nImpFlags
|= SVLBOX_IN_EDT
;
1055 nImpFlags
&= ~SVLBOX_EDTEND_CALLED
;
1057 pEdCtrl
= new SvInplaceEdit2(
1058 this, rRect
.TopLeft(), rRect
.GetSize(), rStr
,
1059 LINK( this, SvTreeListBox
, TextEditEndedHdl_Impl
),
1063 IMPL_LINK_NOARG(SvTreeListBox
, TextEditEndedHdl_Impl
)
1065 DBG_CHKTHIS(SvTreeListBox
,0);
1066 if ( nImpFlags
& SVLBOX_EDTEND_CALLED
) // avoid nesting
1068 nImpFlags
|= SVLBOX_EDTEND_CALLED
;
1070 if ( !pEdCtrl
->EditingCanceled() )
1071 aStr
= pEdCtrl
->GetText();
1073 aStr
= pEdCtrl
->GetSavedValue();
1074 if ( IsEmptyTextAllowed() || !aStr
.isEmpty() )
1076 // Hide may only be called after the new text was put into the entry, so
1077 // that we don't call the selection handler in the GetFocus of the listbox
1078 // with the old entry text.
1082 nImpFlags
&= (~SVLBOX_IN_EDT
);
1087 void SvTreeListBox::CancelTextEditing()
1089 DBG_CHKTHIS(SvTreeListBox
,0);
1091 pEdCtrl
->StopEditing( sal_True
);
1092 nImpFlags
&= (~SVLBOX_IN_EDT
);
1095 void SvTreeListBox::EndEditing( bool bCancel
)
1097 DBG_CHKTHIS(SvTreeListBox
,0);
1099 pEdCtrl
->StopEditing( bCancel
);
1100 nImpFlags
&= (~SVLBOX_IN_EDT
);
1104 bool SvTreeListBox::IsEmptyTextAllowed() const
1106 DBG_CHKTHIS(SvTreeListBox
,0);
1107 return mpImpl
->m_bIsEmptyTextAllowed
;
1110 void SvTreeListBox::ForbidEmptyText()
1112 DBG_CHKTHIS(SvTreeListBox
,0);
1113 mpImpl
->m_bIsEmptyTextAllowed
= false;
1116 SvTreeListEntry
* SvTreeListBox::CreateEntry() const
1118 DBG_CHKTHIS(SvTreeListBox
,0);
1119 return new SvTreeListEntry
;
1122 const void* SvTreeListBox::FirstSearchEntry( OUString
& _rEntryText
) const
1124 SvTreeListEntry
* pEntry
= GetCurEntry();
1126 pEntry
= const_cast< SvTreeListEntry
* >( static_cast< const SvTreeListEntry
* >( NextSearchEntry( pEntry
, _rEntryText
) ) );
1129 pEntry
= FirstSelected();
1135 _rEntryText
= GetEntryText( pEntry
);
1140 const void* SvTreeListBox::NextSearchEntry( const void* _pCurrentSearchEntry
, OUString
& _rEntryText
) const
1142 SvTreeListEntry
* pEntry
= const_cast< SvTreeListEntry
* >( static_cast< const SvTreeListEntry
* >( _pCurrentSearchEntry
) );
1144 if ( ( ( GetChildCount( pEntry
) > 0 )
1145 || ( pEntry
->HasChildrenOnDemand() )
1147 && !IsExpanded( pEntry
)
1150 pEntry
= NextSibling( pEntry
);
1154 pEntry
= Next( pEntry
);
1161 _rEntryText
= GetEntryText( pEntry
);
1166 void SvTreeListBox::SelectSearchEntry( const void* _pEntry
)
1168 SvTreeListEntry
* pEntry
= const_cast< SvTreeListEntry
* >( static_cast< const SvTreeListEntry
* >( _pEntry
) );
1169 DBG_ASSERT( pEntry
, "SvTreeListBox::SelectSearchEntry: invalid entry!" );
1173 SelectAll( sal_False
);
1174 SetCurEntry( pEntry
);
1178 void SvTreeListBox::ExecuteSearchEntry( const void* /*_pEntry*/ ) const
1180 // nothing to do here, we have no "execution"
1183 ::vcl::StringEntryIdentifier
SvTreeListBox::CurrentEntry( OUString
& _out_entryText
) const
1185 // always accept the current entry if there is one
1186 SvTreeListEntry
* pCurrentEntry( GetCurEntry() );
1187 if ( pCurrentEntry
)
1189 _out_entryText
= GetEntryText( pCurrentEntry
);
1190 return pCurrentEntry
;
1192 return FirstSearchEntry( _out_entryText
);
1195 ::vcl::StringEntryIdentifier
SvTreeListBox::NextEntry( ::vcl::StringEntryIdentifier _currentEntry
, OUString
& _out_entryText
) const
1197 return NextSearchEntry( _currentEntry
, _out_entryText
);
1200 void SvTreeListBox::SelectEntry( ::vcl::StringEntryIdentifier _entry
)
1202 SelectSearchEntry( _entry
);
1205 bool SvTreeListBox::HandleKeyInput( const KeyEvent
& _rKEvt
)
1207 if ( IsEntryMnemonicsEnabled()
1208 && mpImpl
->m_aMnemonicEngine
.HandleKeyEvent( _rKEvt
)
1212 if ( ( GetStyle() & WB_QUICK_SEARCH
) != 0 )
1214 mpImpl
->m_bDoingQuickSelection
= true;
1215 const bool bHandled
= mpImpl
->m_aQuickSelectionEngine
.HandleKeyEvent( _rKEvt
);
1216 mpImpl
->m_bDoingQuickSelection
= false;
1224 void SvTreeListBox::WriteDragServerInfo( const Point
&, SvLBoxDDInfo
* )
1226 DBG_CHKTHIS(SvTreeListBox
,0);
1229 void SvTreeListBox::ReadDragServerInfo(const Point
&, SvLBoxDDInfo
* )
1231 DBG_CHKTHIS(SvTreeListBox
,0);
1234 sal_Bool
SvTreeListBox::EditingCanceled() const
1236 if( pEdCtrl
&& pEdCtrl
->EditingCanceled() )
1242 //JP 28.3.2001: new Drag & Drop API
1243 sal_Int8
SvTreeListBox::AcceptDrop( const AcceptDropEvent
& rEvt
)
1245 DBG_CHKTHIS(SvTreeListBox
,0);
1246 sal_Int8 nRet
= DND_ACTION_NONE
;
1248 if( rEvt
.mbLeaving
|| !CheckDragAndDropMode( pDDSource
, rEvt
.mnAction
) )
1250 ImplShowTargetEmphasis( pTargetEntry
, sal_False
);
1252 else if( !nDragDropMode
)
1254 SAL_WARN( "svtools.contnr", "SvTreeListBox::QueryDrop(): no target" );
1258 SvTreeListEntry
* pEntry
= GetDropTarget( rEvt
.maPosPixel
);
1259 if( !IsDropFormatSupported( SOT_FORMATSTR_ID_TREELISTBOX
) )
1261 SAL_WARN( "svtools.contnr", "SvTreeListBox::QueryDrop(): no format" );
1265 DBG_ASSERT( pDDSource
, "SvTreeListBox::QueryDrop(): SourceBox == 0" );
1266 if( !( pEntry
&& pDDSource
->GetModel() == this->GetModel()
1267 && DND_ACTION_MOVE
== rEvt
.mnAction
1268 && ( pEntry
->nEntryFlags
& SV_ENTRYFLAG_DISABLE_DROP
) ))
1270 if( NotifyAcceptDrop( pEntry
))
1271 nRet
= rEvt
.mnAction
;
1275 // **** draw emphasis ****
1276 if( DND_ACTION_NONE
== nRet
)
1277 ImplShowTargetEmphasis( pTargetEntry
, sal_False
);
1278 else if( pEntry
!= pTargetEntry
|| !(nImpFlags
& SVLBOX_TARGEMPH_VIS
) )
1280 ImplShowTargetEmphasis( pTargetEntry
, sal_False
);
1281 pTargetEntry
= pEntry
;
1282 ImplShowTargetEmphasis( pTargetEntry
, sal_True
);
1288 sal_Int8
SvTreeListBox::ExecuteDrop( const ExecuteDropEvent
& rEvt
, SvTreeListBox
* pSourceView
)
1290 DBG_CHKTHIS(SvTreeListBox
,0);
1291 sal_Int8 nRet
= DND_ACTION_NONE
;
1293 DBG_ASSERT( pSourceView
, "SvTreeListBox::ExecuteDrop(): no source view" );
1294 pSourceView
->EnableSelectionAsDropTarget( sal_True
, sal_True
);
1296 ImplShowTargetEmphasis( pTargetEntry
, sal_False
);
1299 SvLBoxDDInfo aDDInfo
;
1301 TransferableDataHelper
aData( rEvt
.maDropEvent
.Transferable
);
1302 if( aData
.HasFormat( SOT_FORMATSTR_ID_TREELISTBOX
))
1304 ::com::sun::star::uno::Sequence
< sal_Int8
> aSeq
;
1305 if( aData
.GetSequence( SOT_FORMATSTR_ID_TREELISTBOX
, aSeq
) &&
1306 sizeof(SvLBoxDDInfo
) == aSeq
.getLength() )
1308 memcpy( &aDDInfo
, aSeq
.getConstArray(), sizeof(SvLBoxDDInfo
) );
1309 nRet
= rEvt
.mnAction
;
1313 if( DND_ACTION_NONE
!= nRet
)
1315 nRet
= DND_ACTION_NONE
;
1317 ReadDragServerInfo( rEvt
.maPosPixel
, &aDDInfo
);
1319 SvTreeListEntry
* pTarget
= pTargetEntry
; // may be 0!
1321 if( DND_ACTION_COPY
== rEvt
.mnAction
)
1323 if ( CopySelection( aDDInfo
.pSource
, pTarget
) )
1324 nRet
= rEvt
.mnAction
;
1326 else if( DND_ACTION_MOVE
== rEvt
.mnAction
)
1328 if ( MoveSelection( aDDInfo
.pSource
, pTarget
) )
1329 nRet
= rEvt
.mnAction
;
1331 else if( DND_ACTION_COPYMOVE
== rEvt
.mnAction
)
1333 if ( MoveSelectionCopyFallbackPossible( aDDInfo
.pSource
, pTarget
, sal_True
) )
1334 nRet
= rEvt
.mnAction
;
1340 sal_Int8
SvTreeListBox::ExecuteDrop( const ExecuteDropEvent
& rEvt
)
1342 DBG_CHKTHIS(SvTreeListBox
,0);
1343 return ExecuteDrop( rEvt
, GetSourceView() );
1346 void SvTreeListBox::StartDrag( sal_Int8
, const Point
& rPosPixel
)
1348 DBG_CHKTHIS(SvTreeListBox
,0);
1350 Point
aEventPos( rPosPixel
);
1351 MouseEvent
aMouseEvt( aEventPos
, 1, MOUSE_SELECT
, MOUSE_LEFT
);
1352 MouseButtonUp( aMouseEvt
);
1354 nOldDragMode
= GetDragDropMode();
1355 if ( !nOldDragMode
)
1360 SvTreeListEntry
* pEntry
= GetEntry( rPosPixel
); // GetDropTarget( rPos );
1363 DragFinished( DND_ACTION_NONE
);
1367 TransferDataContainer
* pContainer
= new TransferDataContainer
;
1368 ::com::sun::star::uno::Reference
<
1369 ::com::sun::star::datatransfer::XTransferable
> xRef( pContainer
);
1371 nDragDropMode
= NotifyStartDrag( *pContainer
, pEntry
);
1372 if( !nDragDropMode
|| 0 == GetSelectionCount() )
1374 nDragDropMode
= nOldDragMode
;
1375 DragFinished( DND_ACTION_NONE
);
1379 SvLBoxDDInfo aDDInfo
;
1380 memset(&aDDInfo
,0,sizeof(SvLBoxDDInfo
));
1381 aDDInfo
.pApp
= GetpApp();
1382 aDDInfo
.pSource
= this;
1383 aDDInfo
.pDDStartEntry
= pEntry
;
1384 // let derived views do their thing
1385 WriteDragServerInfo( rPosPixel
, &aDDInfo
);
1387 pContainer
->CopyAnyData( SOT_FORMATSTR_ID_TREELISTBOX
,
1388 (sal_Char
*)&aDDInfo
, sizeof(SvLBoxDDInfo
) );
1392 sal_Bool bOldUpdateMode
= Control::IsUpdateMode();
1393 Control::SetUpdateMode( sal_True
);
1395 Control::SetUpdateMode( bOldUpdateMode
);
1397 // Disallow using the selection and its children as drop targets.
1398 // Important: If the selection of the SourceListBox is changed in the
1399 // DropHandler, the entries have to be allowed as drop targets again:
1400 // (GetSourceListBox()->EnableSelectionAsDropTarget( sal_True, sal_True );)
1401 EnableSelectionAsDropTarget( sal_False
, sal_True
/* with children */ );
1403 pContainer
->StartDrag( this, nDragOptions
, GetDragFinishedHdl() );
1406 void SvTreeListBox::DragFinished( sal_Int8
1412 EnableSelectionAsDropTarget( sal_True
, sal_True
);
1415 if( (nAction
== DND_ACTION_MOVE
) && ( (pDDTarget
&&
1416 ((sal_uLong
)(pDDTarget
->GetModel())!=(sal_uLong
)(this->GetModel()))) ||
1423 ImplShowTargetEmphasis( pTargetEntry
, sal_False
);
1427 nDragDropMode
= nOldDragMode
;
1430 DragDropMode
SvTreeListBox::NotifyStartDrag( TransferDataContainer
&, SvTreeListEntry
* )
1432 DBG_CHKTHIS(SvTreeListBox
,0);
1433 return (DragDropMode
)0xffff;
1436 sal_Bool
SvTreeListBox::NotifyAcceptDrop( SvTreeListEntry
* )
1438 DBG_CHKTHIS(SvTreeListBox
,0);
1442 // Handler and methods for Drag - finished handler.
1443 // The with get GetDragFinishedHdl() get link can set on the
1444 // TransferDataContainer. This link is a callback for the DragFinished
1445 // call. AddBox method is called from the GetDragFinishedHdl() and the
1446 // remove is called in link callback and in the destructor. So it can't
1447 // called to a deleted object.
1451 struct SortLBoxes
: public rtl::Static
<std::set
<sal_uLong
>, SortLBoxes
> {};
1454 void SvTreeListBox::AddBoxToDDList_Impl( const SvTreeListBox
& rB
)
1456 sal_uLong nVal
= (sal_uLong
)&rB
;
1457 SortLBoxes::get().insert( nVal
);
1460 void SvTreeListBox::RemoveBoxFromDDList_Impl( const SvTreeListBox
& rB
)
1462 sal_uLong nVal
= (sal_uLong
)&rB
;
1463 SortLBoxes::get().erase( nVal
);
1466 IMPL_STATIC_LINK( SvTreeListBox
, DragFinishHdl_Impl
, sal_Int8
*, pAction
)
1468 sal_uLong nVal
= (sal_uLong
)pThis
;
1469 std::set
<sal_uLong
> &rSortLBoxes
= SortLBoxes::get();
1470 std::set
<sal_uLong
>::const_iterator it
= rSortLBoxes
.find(nVal
);
1471 if( it
!= rSortLBoxes
.end() )
1473 pThis
->DragFinished( *pAction
);
1474 rSortLBoxes
.erase( it
);
1479 Link
SvTreeListBox::GetDragFinishedHdl() const
1481 AddBoxToDDList_Impl( *this );
1482 return STATIC_LINK( this, SvTreeListBox
, DragFinishHdl_Impl
);
1488 - calculate rectangle when editing in-place (bug with some fonts)
1489 - SetSpaceBetweenEntries: offset is not taken into account in SetEntryHeight
1492 #define TREEFLAG_FIXEDHEIGHT 0x0010
1494 #define SV_LBOX_DEFAULT_INDENT_PIXEL 20
1496 void SvTreeListBox::InitTreeView()
1498 DBG_CHKTHIS(SvTreeListBox
,0);
1499 pCheckButtonData
= NULL
;
1507 mnCheckboxItemWidth
= 0;
1509 Link
* pLink
= new Link( LINK(this,SvTreeListBox
, DefaultCompare
) );
1510 mpImpl
->m_pLink
= pLink
;
1512 nTreeFlags
= TREEFLAG_RECALCTABS
;
1513 nIndent
= SV_LBOX_DEFAULT_INDENT_PIXEL
;
1514 nEntryHeightOffs
= SV_ENTRYHEIGHTOFFS_PIXEL
;
1515 pImp
= new SvImpLBox( this, GetModel(), GetStyle() );
1517 mbContextBmpExpanded
= true;
1518 nContextBmpWidthMax
= 0;
1520 SetFont( GetFont() );
1521 AdjustEntryHeightAndRecalc( GetFont() );
1523 SetSpaceBetweenEntries( 0 );
1525 InitSettings( sal_True
, sal_True
, sal_True
);
1531 SvTreeListBox::~SvTreeListBox()
1533 DBG_DTOR(SvTreeListBox
,0);
1535 pImp
->CallEventListeners( VCLEVENT_OBJECT_DYING
);
1537 delete mpImpl
->m_pLink
;
1542 pModel
->RemoveView( this );
1543 if ( pModel
->GetRefCount() == 0 )
1550 SvTreeListBox::RemoveBoxFromDDList_Impl( *this );
1552 if( this == pDDSource
)
1554 if( this == pDDTarget
)
1559 void SvTreeListBox::SetExtendedWinBits( ExtendedWinBits _nBits
)
1561 pImp
->SetExtendedWindowBits( _nBits
);
1564 void SvTreeListBox::SetModel( SvTreeList
* pNewModel
)
1566 DBG_CHKTHIS(SvTreeListBox
,0);
1567 pImp
->SetModel( pNewModel
);
1568 SetBaseModel(pNewModel
);
1571 void SvTreeListBox::SetBaseModel( SvTreeList
* pNewModel
)
1574 SvListView::SetModel( pNewModel
);
1575 pModel
->SetCloneLink( LINK(this, SvTreeListBox
, CloneHdl_Impl
));
1576 SvTreeListEntry
* pEntry
= First();
1579 ModelHasInserted( pEntry
);
1580 pEntry
= Next( pEntry
);
1584 void SvTreeListBox::DisconnectFromModel()
1586 DBG_CHKTHIS(SvTreeListBox
,0);
1587 SvTreeList
* pNewModel
= new SvTreeList
;
1588 pNewModel
->SetRefCount( 0 ); // else this will never be deleted
1589 SvListView::SetModel( pNewModel
);
1591 pImp
->SetModel( GetModel() );
1594 void SvTreeListBox::SetSublistOpenWithReturn( sal_Bool b
)
1596 pImp
->bSubLstOpRet
= b
;
1599 void SvTreeListBox::SetSublistOpenWithLeftRight( sal_Bool b
)
1601 pImp
->bSubLstOpLR
= b
;
1604 void SvTreeListBox::Resize()
1606 DBG_CHKTHIS(SvTreeListBox
,0);
1607 if( IsEditingActive() )
1608 EndEditing( sal_True
);
1614 pImp
->ShowCursor( sal_False
);
1615 pImp
->ShowCursor( sal_True
);
1620 A) entries have bitmaps
1622 1. node buttons (can optionally also be on root items)
1623 2. node buttons (can optionally also be on root items) + CheckButton
1625 B) entries don't have bitmaps (=>via WindowBits because of D&D!)
1627 1. node buttons (can optionally also be on root items)
1628 2. node buttons (can optionally also be on root items) + CheckButton
1632 #define NO_BUTTONS 0
1633 #define NODE_BUTTONS 1
1634 #define NODE_AND_CHECK_BUTTONS 2
1635 #define CHECK_BUTTONS 3
1637 #define TABFLAGS_TEXT (SV_LBOXTAB_DYNAMIC | \
1638 SV_LBOXTAB_ADJUST_LEFT | \
1639 SV_LBOXTAB_EDITABLE | \
1640 SV_LBOXTAB_SHOW_SELECTION)
1642 #define TABFLAGS_CONTEXTBMP (SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER)
1644 #define TABFLAGS_CHECKBTN (SV_LBOXTAB_DYNAMIC | \
1645 SV_LBOXTAB_ADJUST_CENTER | \
1646 SV_LBOXTAB_PUSHABLE)
1648 #define TAB_STARTPOS 2
1650 // take care of GetTextOffset when doing changes
1651 void SvTreeListBox::SetTabs()
1653 DBG_CHKTHIS(SvTreeListBox
,0);
1654 if( IsEditingActive() )
1655 EndEditing( sal_True
);
1656 nTreeFlags
&= (~TREEFLAG_RECALCTABS
);
1658 const WinBits
nStyle( GetStyle() );
1659 sal_Bool bHasButtons
= (nStyle
& WB_HASBUTTONS
)!=0;
1660 sal_Bool bHasButtonsAtRoot
= (nStyle
& (WB_HASLINESATROOT
|
1661 WB_HASBUTTONSATROOT
))!=0;
1662 long nStartPos
= TAB_STARTPOS
;
1663 long nNodeWidthPixel
= GetExpandedNodeBmp().GetSizePixel().Width();
1665 // pCheckButtonData->Width() knows nothing about the native checkbox width,
1666 // so we have mnCheckboxItemWidth which becomes valid when something is added.
1667 long nCheckWidth
= 0;
1668 if( nTreeFlags
& TREEFLAG_CHKBTN
)
1669 nCheckWidth
= mnCheckboxItemWidth
;
1670 long nCheckWidthDIV2
= nCheckWidth
/ 2;
1672 long nContextWidth
= nContextBmpWidthMax
;
1673 long nContextWidthDIV2
= nContextWidth
/ 2;
1677 int nCase
= NO_BUTTONS
;
1678 if( !(nTreeFlags
& TREEFLAG_CHKBTN
) )
1681 nCase
= NODE_BUTTONS
;
1686 nCase
= NODE_AND_CHECK_BUTTONS
;
1688 nCase
= CHECK_BUTTONS
;
1694 nStartPos
+= nContextWidthDIV2
; // because of centering
1695 AddTab( nStartPos
, TABFLAGS_CONTEXTBMP
);
1696 nStartPos
+= nContextWidthDIV2
; // right edge of context bitmap
1697 // only set a distance if there are bitmaps
1698 if( nContextBmpWidthMax
)
1699 nStartPos
+= 5; // distance context bitmap to text
1700 AddTab( nStartPos
, TABFLAGS_TEXT
);
1704 if( bHasButtonsAtRoot
)
1705 nStartPos
+= ( nIndent
+ (nNodeWidthPixel
/2) );
1707 nStartPos
+= nContextWidthDIV2
;
1708 AddTab( nStartPos
, TABFLAGS_CONTEXTBMP
);
1709 nStartPos
+= nContextWidthDIV2
; // right edge of context bitmap
1710 // only set a distance if there are bitmaps
1711 if( nContextBmpWidthMax
)
1712 nStartPos
+= 5; // distance context bitmap to text
1713 AddTab( nStartPos
, TABFLAGS_TEXT
);
1716 case NODE_AND_CHECK_BUTTONS
:
1717 if( bHasButtonsAtRoot
)
1718 nStartPos
+= ( nIndent
+ nNodeWidthPixel
);
1720 nStartPos
+= nCheckWidthDIV2
;
1721 AddTab( nStartPos
, TABFLAGS_CHECKBTN
);
1722 nStartPos
+= nCheckWidthDIV2
; // right edge of CheckButton
1723 nStartPos
+= 3; // distance CheckButton to context bitmap
1724 nStartPos
+= nContextWidthDIV2
; // center of context bitmap
1725 AddTab( nStartPos
, TABFLAGS_CONTEXTBMP
);
1726 nStartPos
+= nContextWidthDIV2
; // right edge of context bitmap
1727 // only set a distance if there are bitmaps
1728 if( nContextBmpWidthMax
)
1729 nStartPos
+= 5; // distance context bitmap to text
1730 AddTab( nStartPos
, TABFLAGS_TEXT
);
1733 case CHECK_BUTTONS
:
1734 nStartPos
+= nCheckWidthDIV2
;
1735 AddTab( nStartPos
, TABFLAGS_CHECKBTN
);
1736 nStartPos
+= nCheckWidthDIV2
; // right edge of CheckButton
1737 nStartPos
+= 3; // distance CheckButton to context bitmap
1738 nStartPos
+= nContextWidthDIV2
; // center of context bitmap
1739 AddTab( nStartPos
, TABFLAGS_CONTEXTBMP
);
1740 nStartPos
+= nContextWidthDIV2
; // right edge of context bitmap
1741 // only set a distance if there are bitmaps
1742 if( nContextBmpWidthMax
)
1743 nStartPos
+= 5; // distance context bitmap to text
1744 AddTab( nStartPos
, TABFLAGS_TEXT
);
1747 pImp
->NotifyTabsChanged();
1750 void SvTreeListBox::InitEntry(SvTreeListEntry
* pEntry
,
1751 const OUString
& aStr
, const Image
& aCollEntryBmp
, const Image
& aExpEntryBmp
,
1752 SvLBoxButtonKind eButtonKind
)
1754 DBG_CHKTHIS(SvTreeListBox
,0);
1755 SvLBoxButton
* pButton
;
1756 SvLBoxString
* pString
;
1757 SvLBoxContextBmp
* pContextBmp
;
1759 if( nTreeFlags
& TREEFLAG_CHKBTN
)
1761 pButton
= new SvLBoxButton( pEntry
,eButtonKind
,0,pCheckButtonData
);
1762 pEntry
->AddItem( pButton
);
1765 pContextBmp
= new SvLBoxContextBmp(
1766 pEntry
,0, aCollEntryBmp
,aExpEntryBmp
, mbContextBmpExpanded
);
1767 pEntry
->AddItem( pContextBmp
);
1769 pString
= new SvLBoxString( pEntry
, 0, aStr
);
1770 pEntry
->AddItem( pString
);
1773 OUString
SvTreeListBox::GetEntryText(SvTreeListEntry
* pEntry
) const
1775 DBG_CHKTHIS(SvTreeListBox
,0);
1776 DBG_ASSERT( pEntry
, "SvTreeListBox::GetEntryText(): no entry" );
1777 SvLBoxString
* pItem
= (SvLBoxString
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXSTRING
));
1778 DBG_ASSERT( pEntry
, "SvTreeListBox::GetEntryText(): item not found" );
1779 return pItem
->GetText();
1782 OUString
SvTreeListBox::SearchEntryText( SvTreeListEntry
* pEntry
) const
1784 DBG_CHKTHIS(SvTreeListBox
,0);
1785 DBG_ASSERT( pEntry
, "SvTreeListBox::SearchEntryText(): no entry" );
1787 sal_uInt16 nCount
= pEntry
->ItemCount();
1788 sal_uInt16 nCur
= 0;
1790 while( nCur
< nCount
)
1792 pItem
= pEntry
->GetItem( nCur
);
1793 if (pItem
->GetType() == SV_ITEM_ID_LBOXSTRING
&& !static_cast<const SvLBoxString
*>(pItem
)->GetText().isEmpty())
1795 sRet
= static_cast<const SvLBoxString
*>(pItem
)->GetText();
1803 const Image
& SvTreeListBox::GetExpandedEntryBmp(const SvTreeListEntry
* pEntry
) const
1805 DBG_CHKTHIS(SvTreeListBox
,0);
1806 DBG_ASSERT(pEntry
,"Entry?");
1807 const SvLBoxContextBmp
* pItem
= static_cast<const SvLBoxContextBmp
*>(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP
));
1808 DBG_ASSERT(pItem
,"GetContextBmp:Item not found");
1809 return pItem
->GetBitmap2( );
1812 const Image
& SvTreeListBox::GetCollapsedEntryBmp( const SvTreeListEntry
* pEntry
) const
1814 DBG_CHKTHIS(SvTreeListBox
,0);
1815 DBG_ASSERT(pEntry
,"Entry?");
1816 const SvLBoxContextBmp
* pItem
= static_cast<const SvLBoxContextBmp
*>(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP
));
1817 DBG_ASSERT(pItem
,"GetContextBmp:Item not found");
1818 return pItem
->GetBitmap1( );
1821 IMPL_LINK_INLINE_START( SvTreeListBox
, CheckButtonClick
, SvLBoxButtonData
*, pData
)
1823 DBG_CHKTHIS(SvTreeListBox
,0);
1824 pHdlEntry
= pData
->GetActEntry();
1828 IMPL_LINK_INLINE_END( SvTreeListBox
, CheckButtonClick
, SvLBoxButtonData
*, pData
)
1830 SvTreeListEntry
* SvTreeListBox::InsertEntry(
1831 const OUString
& rText
,
1832 SvTreeListEntry
* pParent
,
1833 sal_Bool bChildrenOnDemand
, sal_uLong nPos
,
1835 SvLBoxButtonKind eButtonKind
1838 DBG_CHKTHIS(SvTreeListBox
,0);
1839 nTreeFlags
|= TREEFLAG_MANINS
;
1841 const Image
& rDefExpBmp
= pImp
->GetDefaultEntryExpBmp( );
1842 const Image
& rDefColBmp
= pImp
->GetDefaultEntryColBmp( );
1844 aCurInsertedExpBmp
= rDefExpBmp
;
1845 aCurInsertedColBmp
= rDefColBmp
;
1847 SvTreeListEntry
* pEntry
= CreateEntry();
1848 pEntry
->SetUserData( pUser
);
1849 InitEntry( pEntry
, rText
, rDefColBmp
, rDefExpBmp
, eButtonKind
);
1850 pEntry
->EnableChildrenOnDemand( bChildrenOnDemand
);
1853 Insert( pEntry
, nPos
);
1855 Insert( pEntry
, pParent
, nPos
);
1857 aPrevInsertedExpBmp
= rDefExpBmp
;
1858 aPrevInsertedColBmp
= rDefColBmp
;
1860 nTreeFlags
&= (~TREEFLAG_MANINS
);
1865 SvTreeListEntry
* SvTreeListBox::InsertEntry( const OUString
& rText
,
1866 const Image
& aExpEntryBmp
, const Image
& aCollEntryBmp
,
1867 SvTreeListEntry
* pParent
, sal_Bool bChildrenOnDemand
, sal_uLong nPos
, void* pUser
,
1868 SvLBoxButtonKind eButtonKind
)
1870 DBG_CHKTHIS(SvTreeListBox
,0);
1871 nTreeFlags
|= TREEFLAG_MANINS
;
1873 aCurInsertedExpBmp
= aExpEntryBmp
;
1874 aCurInsertedColBmp
= aCollEntryBmp
;
1876 SvTreeListEntry
* pEntry
= CreateEntry();
1877 pEntry
->SetUserData( pUser
);
1878 InitEntry( pEntry
, rText
, aCollEntryBmp
, aExpEntryBmp
, eButtonKind
);
1880 pEntry
->EnableChildrenOnDemand( bChildrenOnDemand
);
1883 Insert( pEntry
, nPos
);
1885 Insert( pEntry
, pParent
, nPos
);
1887 aPrevInsertedExpBmp
= aExpEntryBmp
;
1888 aPrevInsertedColBmp
= aCollEntryBmp
;
1890 nTreeFlags
&= (~TREEFLAG_MANINS
);
1895 void SvTreeListBox::SetEntryText(SvTreeListEntry
* pEntry
, const OUString
& rStr
)
1897 DBG_CHKTHIS(SvTreeListBox
,0);
1898 SvLBoxString
* pItem
= (SvLBoxString
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXSTRING
));
1899 DBG_ASSERT(pItem
,"SetText:Item not found");
1900 pItem
->SetText(rStr
);
1901 pItem
->InitViewData( this, pEntry
, 0 );
1902 GetModel()->InvalidateEntry( pEntry
);
1905 void SvTreeListBox::SetExpandedEntryBmp( SvTreeListEntry
* pEntry
, const Image
& aBmp
)
1907 DBG_CHKTHIS(SvTreeListBox
,0);
1908 SvLBoxContextBmp
* pItem
= (SvLBoxContextBmp
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP
));
1910 DBG_ASSERT(pItem
,"SetExpBmp:Item not found");
1911 pItem
->SetBitmap2( aBmp
);
1913 GetModel()->InvalidateEntry( pEntry
);
1914 SetEntryHeight( pEntry
);
1915 Size aSize
= aBmp
.GetSizePixel();
1916 short nWidth
= pImp
->UpdateContextBmpWidthVector( pEntry
, (short)aSize
.Width() );
1917 if( nWidth
> nContextBmpWidthMax
)
1919 nContextBmpWidthMax
= nWidth
;
1924 void SvTreeListBox::SetCollapsedEntryBmp(SvTreeListEntry
* pEntry
,const Image
& aBmp
)
1926 DBG_CHKTHIS(SvTreeListBox
,0);
1927 SvLBoxContextBmp
* pItem
= (SvLBoxContextBmp
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP
));
1929 DBG_ASSERT(pItem
,"SetExpBmp:Item not found");
1930 pItem
->SetBitmap1( aBmp
);
1932 GetModel()->InvalidateEntry( pEntry
);
1933 SetEntryHeight( pEntry
);
1934 Size aSize
= aBmp
.GetSizePixel();
1935 short nWidth
= pImp
->UpdateContextBmpWidthVector( pEntry
, (short)aSize
.Width() );
1936 if( nWidth
> nContextBmpWidthMax
)
1938 nContextBmpWidthMax
= nWidth
;
1943 void SvTreeListBox::ImpEntryInserted( SvTreeListEntry
* pEntry
)
1945 DBG_CHKTHIS(SvTreeListBox
,0);
1947 SvTreeListEntry
* pParent
= (SvTreeListEntry
*)pModel
->GetParent( pEntry
);
1950 sal_uInt16 nFlags
= pParent
->GetFlags();
1951 nFlags
&= ~SV_ENTRYFLAG_NO_NODEBMP
;
1952 pParent
->SetFlags( nFlags
);
1955 if(!((nTreeFlags
& TREEFLAG_MANINS
) &&
1956 (aPrevInsertedExpBmp
== aCurInsertedExpBmp
) &&
1957 (aPrevInsertedColBmp
== aCurInsertedColBmp
) ))
1959 Size aSize
= GetCollapsedEntryBmp( pEntry
).GetSizePixel();
1960 if( aSize
.Width() > nContextBmpWidthMax
)
1962 nContextBmpWidthMax
= (short)aSize
.Width();
1963 nTreeFlags
|= TREEFLAG_RECALCTABS
;
1965 aSize
= GetExpandedEntryBmp( pEntry
).GetSizePixel();
1966 if( aSize
.Width() > nContextBmpWidthMax
)
1968 nContextBmpWidthMax
= (short)aSize
.Width();
1969 nTreeFlags
|= TREEFLAG_RECALCTABS
;
1972 SetEntryHeight( (SvTreeListEntry
*)pEntry
);
1974 if( nTreeFlags
& TREEFLAG_CHKBTN
)
1976 SvLBoxButton
* pItem
= (SvLBoxButton
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
));
1979 long nWidth
= pItem
->GetSize(this, pEntry
).Width();
1980 if( mnCheckboxItemWidth
< nWidth
)
1982 mnCheckboxItemWidth
= nWidth
;
1983 nTreeFlags
|= TREEFLAG_RECALCTABS
;
1991 void SvTreeListBox::SetCheckButtonState( SvTreeListEntry
* pEntry
, SvButtonState eState
)
1993 DBG_CHKTHIS(SvTreeListBox
,0);
1994 if( nTreeFlags
& TREEFLAG_CHKBTN
)
1996 SvLBoxButton
* pItem
= (SvLBoxButton
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
));
1997 if(!(pItem
&& pItem
->CheckModification()))
2001 case SV_BUTTON_CHECKED
:
2002 pItem
->SetStateChecked();
2005 case SV_BUTTON_UNCHECKED
:
2006 pItem
->SetStateUnchecked();
2009 case SV_BUTTON_TRISTATE
:
2010 pItem
->SetStateTristate();
2013 InvalidateEntry( pEntry
);
2017 void SvTreeListBox::SetCheckButtonInvisible( SvTreeListEntry
* pEntry
)
2019 DBG_CHKTHIS(SvTreeListBox
,0);
2020 if( nTreeFlags
& TREEFLAG_CHKBTN
)
2022 SvLBoxButton
* pItem
= (SvLBoxButton
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
));
2023 pItem
->SetStateInvisible();
2024 InvalidateEntry( pEntry
);
2028 SvButtonState
SvTreeListBox::GetCheckButtonState( SvTreeListEntry
* pEntry
) const
2030 DBG_CHKTHIS(SvTreeListBox
,0);
2031 SvButtonState eState
= SV_BUTTON_UNCHECKED
;
2032 if( nTreeFlags
& TREEFLAG_CHKBTN
)
2034 SvLBoxButton
* pItem
= (SvLBoxButton
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
));
2036 return SV_BUTTON_TRISTATE
;
2037 sal_uInt16 nButtonFlags
= pItem
->GetButtonFlags();
2038 eState
= pCheckButtonData
->ConvertToButtonState( nButtonFlags
);
2043 void SvTreeListBox::CheckButtonHdl()
2045 DBG_CHKTHIS(SvTreeListBox
,0);
2046 aCheckButtonHdl
.Call( this );
2047 if ( pCheckButtonData
)
2048 pImp
->CallEventListeners( VCLEVENT_CHECKBOX_TOGGLE
, (void*)pCheckButtonData
->GetActEntry() );
2052 // TODO: Currently all data is cloned so that they conform to the default tree
2053 // view format. Actually, the model should be used as a reference here. This
2054 // leads to us _not_ calling SvTreeListEntry::Clone, but only its base class
2058 SvTreeListEntry
* SvTreeListBox::CloneEntry( SvTreeListEntry
* pSource
)
2060 DBG_CHKTHIS(SvTreeListBox
,0);
2062 Image aCollEntryBmp
;
2064 SvLBoxButtonKind eButtonKind
= SvLBoxButtonKind_enabledCheckbox
;
2066 SvLBoxString
* pStringItem
= (SvLBoxString
*)(pSource
->GetFirstItem(SV_ITEM_ID_LBOXSTRING
));
2068 aStr
= pStringItem
->GetText();
2069 SvLBoxContextBmp
* pBmpItem
= (SvLBoxContextBmp
*)(pSource
->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP
));
2072 aCollEntryBmp
= pBmpItem
->GetBitmap1( );
2073 aExpEntryBmp
= pBmpItem
->GetBitmap2( );
2075 SvLBoxButton
* pButtonItem
= (SvLBoxButton
*)(pSource
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
));
2077 eButtonKind
= pButtonItem
->GetKind();
2078 SvTreeListEntry
* pClone
= CreateEntry();
2079 InitEntry( pClone
, aStr
, aCollEntryBmp
, aExpEntryBmp
, eButtonKind
);
2080 pClone
->SvTreeListEntry::Clone( pSource
);
2081 pClone
->EnableChildrenOnDemand( pSource
->HasChildrenOnDemand() );
2082 pClone
->SetUserData( pSource
->GetUserData() );
2087 void SvTreeListBox::SetIndent( short nNewIndent
)
2089 DBG_CHKTHIS(SvTreeListBox
,0);
2090 nIndent
= nNewIndent
;
2092 if( IsUpdateMode() )
2096 const Image
& SvTreeListBox::GetDefaultExpandedEntryBmp( ) const
2098 return pImp
->GetDefaultEntryExpBmp( );
2101 const Image
& SvTreeListBox::GetDefaultCollapsedEntryBmp( ) const
2103 return pImp
->GetDefaultEntryColBmp( );
2106 void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image
& aBmp
)
2108 DBG_CHKTHIS(SvTreeListBox
,0);
2109 Size aSize
= aBmp
.GetSizePixel();
2110 if( aSize
.Width() > nContextBmpWidthMax
)
2111 nContextBmpWidthMax
= (short)aSize
.Width();
2114 pImp
->SetDefaultEntryExpBmp( aBmp
);
2117 void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image
& aBmp
)
2119 DBG_CHKTHIS(SvTreeListBox
,0);
2120 Size aSize
= aBmp
.GetSizePixel();
2121 if( aSize
.Width() > nContextBmpWidthMax
)
2122 nContextBmpWidthMax
= (short)aSize
.Width();
2125 pImp
->SetDefaultEntryColBmp( aBmp
);
2128 void SvTreeListBox::EnableCheckButton( SvLBoxButtonData
* pData
)
2130 DBG_CHKTHIS(SvTreeListBox
,0);
2131 DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0");
2133 nTreeFlags
&= (~TREEFLAG_CHKBTN
);
2136 SetCheckButtonData( pData
);
2137 nTreeFlags
|= TREEFLAG_CHKBTN
;
2138 pData
->SetLink( LINK(this, SvTreeListBox
, CheckButtonClick
));
2142 if( IsUpdateMode() )
2146 void SvTreeListBox::SetCheckButtonData( SvLBoxButtonData
* pData
)
2148 DBG_CHKTHIS(SvTreeListBox
,0);
2150 pCheckButtonData
= pData
;
2153 const Image
& SvTreeListBox::GetDefaultExpandedNodeImage( )
2155 return SvImpLBox::GetDefaultExpandedNodeImage( );
2158 const Image
& SvTreeListBox::GetDefaultCollapsedNodeImage( )
2160 return SvImpLBox::GetDefaultCollapsedNodeImage( );
2163 void SvTreeListBox::SetNodeBitmaps( const Image
& rCollapsedNodeBmp
, const Image
& rExpandedNodeBmp
)
2165 DBG_CHKTHIS(SvTreeListBox
,0);
2166 SetExpandedNodeBmp( rExpandedNodeBmp
);
2167 SetCollapsedNodeBmp( rCollapsedNodeBmp
);
2171 sal_Bool
SvTreeListBox::EditingEntry( SvTreeListEntry
*, Selection
& )
2173 DBG_CHKTHIS(SvTreeListBox
,0);
2177 sal_Bool
SvTreeListBox::EditedEntry( SvTreeListEntry
* /*pEntry*/,const OUString
& /*rNewText*/)
2179 DBG_CHKTHIS(SvTreeListBox
,0);
2183 void SvTreeListBox::EnableInplaceEditing( bool bOn
)
2185 DBG_CHKTHIS(SvTreeListBox
,0);
2187 nImpFlags
|= SVLBOX_EDT_ENABLED
;
2189 nImpFlags
&= ~SVLBOX_EDT_ENABLED
;
2192 void SvTreeListBox::KeyInput( const KeyEvent
& rKEvt
)
2194 DBG_CHKTHIS(SvTreeListBox
,0);
2195 // under OS/2, we get key up/down even while editing
2196 if( IsEditingActive() )
2199 nImpFlags
|= SVLBOX_IS_TRAVELSELECT
;
2202 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
2207 SvTreeListEntry
* pEntry
= First();
2208 pEntry
= NextVisible( pEntry
);
2209 SetEntryText( pEntry
, "SetEntryText" );
2215 if( !pImp
->KeyInput( rKEvt
) )
2217 bool bHandled
= HandleKeyInput( rKEvt
);
2219 Control::KeyInput( rKEvt
);
2222 nImpFlags
&= ~SVLBOX_IS_TRAVELSELECT
;
2225 void SvTreeListBox::RequestingChildren( SvTreeListEntry
* pParent
)
2227 DBG_CHKTHIS(SvTreeListBox
,0);
2228 if( !pParent
->HasChildren() )
2229 InsertEntry( OUString("<dummy>"), pParent
, sal_False
, LIST_APPEND
);
2232 void SvTreeListBox::GetFocus()
2234 DBG_CHKTHIS(SvTreeListBox
,0);
2236 Control::GetFocus();
2238 SvTreeListEntry
* pEntry
= FirstSelected();
2240 pImp
->CallEventListeners( VCLEVENT_LISTBOX_SELECT
, pEntry
);
2244 void SvTreeListBox::LoseFocus()
2246 DBG_CHKTHIS(SvTreeListBox
,0);
2248 Control::LoseFocus();
2251 void SvTreeListBox::ModelHasCleared()
2253 DBG_CHKTHIS(SvTreeListBox
,0);
2254 pImp
->pCursor
= 0; // else we crash in GetFocus when editing in-place
2260 nContextBmpWidthMax
= 0;
2261 SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() );
2262 SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() );
2264 if( !(nTreeFlags
& TREEFLAG_FIXEDHEIGHT
))
2266 AdjustEntryHeight( GetFont() );
2267 AdjustEntryHeight( GetDefaultExpandedEntryBmp() );
2268 AdjustEntryHeight( GetDefaultCollapsedEntryBmp() );
2270 SvListView::ModelHasCleared();
2273 void SvTreeListBox::ShowTargetEmphasis( SvTreeListEntry
* pEntry
, sal_Bool
/*bShow*/ )
2275 DBG_CHKTHIS(SvTreeListBox
,0);
2276 pImp
->PaintDDCursor( pEntry
);
2279 void SvTreeListBox::ScrollOutputArea( short nDeltaEntries
)
2281 DBG_CHKTHIS(SvTreeListBox
,0);
2282 if( !nDeltaEntries
|| !pImp
->aVerSBar
.IsVisible() )
2285 long nThumb
= pImp
->aVerSBar
.GetThumbPos();
2286 long nMax
= pImp
->aVerSBar
.GetRange().Max();
2288 NotifyBeginScroll();
2289 if( nDeltaEntries
< 0 )
2292 nDeltaEntries
*= -1;
2293 long nVis
= pImp
->aVerSBar
.GetVisibleSize();
2294 long nTemp
= nThumb
+ nVis
;
2295 if( nDeltaEntries
> (nMax
- nTemp
) )
2296 nDeltaEntries
= (short)(nMax
- nTemp
);
2297 pImp
->PageDown( (sal_uInt16
)nDeltaEntries
);
2301 if( nDeltaEntries
> nThumb
)
2302 nDeltaEntries
= (short)nThumb
;
2303 pImp
->PageUp( (sal_uInt16
)nDeltaEntries
);
2305 pImp
->SyncVerThumb();
2309 void SvTreeListBox::ScrollToAbsPos( long nPos
)
2311 pImp
->ScrollToAbsPos( nPos
);
2314 void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode
)
2316 DBG_CHKTHIS(SvTreeListBox
,0);
2317 eSelMode
= eSelectMode
;
2318 pImp
->SetSelectionMode( eSelectMode
);
2321 void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode
)
2323 DBG_CHKTHIS(SvTreeListBox
,0);
2324 nDragDropMode
= nDDMode
;
2325 pImp
->SetDragDropMode( nDDMode
);
2328 short SvTreeListBox::GetHeightOffset(const Image
& rBmp
, Size
& aSizeLogic
)
2330 DBG_CHKTHIS(SvTreeListBox
,0);
2332 aSizeLogic
= rBmp
.GetSizePixel();
2333 if( GetEntryHeight() > aSizeLogic
.Height() )
2334 nOffset
= ( GetEntryHeight() - (short)aSizeLogic
.Height()) / 2;
2338 short SvTreeListBox::GetHeightOffset(const Font
& /* rFont */, Size
& aSizeLogic
)
2340 DBG_CHKTHIS(SvTreeListBox
,0);
2342 aSizeLogic
= Size(GetTextWidth(OUString('X')), GetTextHeight());
2343 if( GetEntryHeight() > aSizeLogic
.Height() )
2344 nOffset
= ( GetEntryHeight() - (short)aSizeLogic
.Height()) / 2;
2348 void SvTreeListBox::SetEntryHeight( SvTreeListEntry
* pEntry
)
2350 DBG_CHKTHIS(SvTreeListBox
,0);
2351 short nHeight
, nHeightMax
=0;
2352 sal_uInt16 nCount
= pEntry
->ItemCount();
2353 sal_uInt16 nCur
= 0;
2354 SvViewDataEntry
* pViewData
= GetViewDataEntry( pEntry
);
2355 while( nCur
< nCount
)
2357 SvLBoxItem
* pItem
= pEntry
->GetItem( nCur
);
2358 nHeight
= (short)(pItem
->GetSize( pViewData
, nCur
).Height());
2359 if( nHeight
> nHeightMax
)
2360 nHeightMax
= nHeight
;
2364 if( nHeightMax
> nEntryHeight
)
2366 nEntryHeight
= nHeightMax
;
2367 Control::SetFont( GetFont() );
2368 pImp
->SetEntryHeight( nHeightMax
);
2372 void SvTreeListBox::SetEntryHeight( short nHeight
, sal_Bool bAlways
)
2374 DBG_CHKTHIS(SvTreeListBox
,0);
2376 if( bAlways
|| nHeight
> nEntryHeight
)
2378 nEntryHeight
= nHeight
;
2380 nTreeFlags
|= TREEFLAG_FIXEDHEIGHT
;
2382 nTreeFlags
&= ~TREEFLAG_FIXEDHEIGHT
;
2383 Control::SetFont( GetFont() );
2384 pImp
->SetEntryHeight( nHeight
);
2389 void SvTreeListBox::AdjustEntryHeight( const Image
& rBmp
)
2391 DBG_CHKTHIS(SvTreeListBox
,0);
2393 GetHeightOffset( rBmp
, aSize
);
2394 if( aSize
.Height() > nEntryHeight
)
2396 nEntryHeight
= (short)aSize
.Height() + nEntryHeightOffs
;
2397 pImp
->SetEntryHeight( nEntryHeight
);
2401 void SvTreeListBox::AdjustEntryHeight( const Font
& rFont
)
2403 DBG_CHKTHIS(SvTreeListBox
,0);
2405 GetHeightOffset( rFont
, aSize
);
2406 if( aSize
.Height() > nEntryHeight
)
2408 nEntryHeight
= (short)aSize
.Height() + nEntryHeightOffs
;
2409 pImp
->SetEntryHeight( nEntryHeight
);
2413 sal_Bool
SvTreeListBox::Expand( SvTreeListEntry
* pParent
)
2415 DBG_CHKTHIS(SvTreeListBox
,0);
2416 pHdlEntry
= pParent
;
2417 sal_Bool bExpanded
= sal_False
;
2420 if( pParent
->HasChildrenOnDemand() )
2421 RequestingChildren( pParent
);
2422 if( pParent
->HasChildren() )
2424 nImpFlags
|= SVLBOX_IS_EXPANDING
;
2425 if( ExpandingHdl() )
2427 bExpanded
= sal_True
;
2428 SvListView::Expand( pParent
);
2429 pImp
->EntryExpanded( pParent
);
2430 pHdlEntry
= pParent
;
2433 nFlags
= pParent
->GetFlags();
2434 nFlags
&= ~SV_ENTRYFLAG_NO_NODEBMP
;
2435 nFlags
|= SV_ENTRYFLAG_HAD_CHILDREN
;
2436 pParent
->SetFlags( nFlags
);
2440 nFlags
= pParent
->GetFlags();
2441 nFlags
|= SV_ENTRYFLAG_NO_NODEBMP
;
2442 pParent
->SetFlags( nFlags
);
2443 GetModel()->InvalidateEntry( pParent
); // repaint
2449 pImp
->CallEventListeners( VCLEVENT_ITEM_EXPANDED
, pParent
);
2455 sal_Bool
SvTreeListBox::Collapse( SvTreeListEntry
* pParent
)
2457 DBG_CHKTHIS(SvTreeListBox
,0);
2458 nImpFlags
&= ~SVLBOX_IS_EXPANDING
;
2459 pHdlEntry
= pParent
;
2460 sal_Bool bCollapsed
= sal_False
;
2462 if( ExpandingHdl() )
2464 bCollapsed
= sal_True
;
2465 pImp
->CollapsingEntry( pParent
);
2466 SvListView::Collapse( pParent
);
2467 pImp
->EntryCollapsed( pParent
);
2468 pHdlEntry
= pParent
;
2475 pImp
->CallEventListeners( VCLEVENT_ITEM_COLLAPSED
, pParent
);
2481 sal_Bool
SvTreeListBox::Select( SvTreeListEntry
* pEntry
, sal_Bool bSelect
)
2483 DBG_CHKTHIS(SvTreeListBox
,0);
2484 DBG_ASSERT(pEntry
,"Select: Null-Ptr");
2485 sal_Bool bRetVal
= SvListView::Select( pEntry
, bSelect
);
2486 DBG_ASSERT(IsSelected(pEntry
)==bSelect
,"Select failed");
2489 pImp
->EntrySelected( pEntry
, bSelect
);
2494 pImp
->CallEventListeners( VCLEVENT_LISTBOX_SELECT
, pEntry
);
2502 sal_uLong
SvTreeListBox::SelectChildren( SvTreeListEntry
* pParent
, sal_Bool bSelect
)
2504 DBG_CHKTHIS(SvTreeListBox
,0);
2505 pImp
->DestroyAnchor();
2507 if( !pParent
->HasChildren() )
2509 sal_uInt16 nRefDepth
= pModel
->GetDepth( pParent
);
2510 SvTreeListEntry
* pChild
= FirstChild( pParent
);
2513 Select( pChild
, bSelect
);
2514 pChild
= Next( pChild
);
2515 } while( pChild
&& pModel
->GetDepth( pChild
) > nRefDepth
);
2519 void SvTreeListBox::SelectAll( sal_Bool bSelect
, sal_Bool
)
2521 DBG_CHKTHIS(SvTreeListBox
,0);
2522 pImp
->SelAllDestrAnch(
2524 sal_True
, // delete anchor,
2525 sal_True
); // even when using SINGLE_SELECTION, deselect the cursor
2528 void SvTreeListBox::ModelHasInsertedTree( SvTreeListEntry
* pEntry
)
2530 DBG_CHKTHIS(SvTreeListBox
,0);
2531 sal_uInt16 nRefDepth
= pModel
->GetDepth( (SvTreeListEntry
*)pEntry
);
2532 SvTreeListEntry
* pTmp
= (SvTreeListEntry
*)pEntry
;
2535 ImpEntryInserted( pTmp
);
2536 pTmp
= Next( pTmp
);
2537 } while( pTmp
&& nRefDepth
< pModel
->GetDepth( pTmp
) );
2538 pImp
->TreeInserted( (SvTreeListEntry
*)pEntry
);
2541 void SvTreeListBox::ModelHasInserted( SvTreeListEntry
* pEntry
)
2543 DBG_CHKTHIS(SvTreeListBox
,0);
2544 ImpEntryInserted( (SvTreeListEntry
*)pEntry
);
2545 pImp
->EntryInserted( (SvTreeListEntry
*)pEntry
);
2548 void SvTreeListBox::ModelIsMoving(SvTreeListEntry
* pSource
,
2549 SvTreeListEntry
* /* pTargetParent */,
2550 sal_uLong
/* nChildPos */ )
2552 DBG_CHKTHIS(SvTreeListBox
,0);
2553 pImp
->MovingEntry( (SvTreeListEntry
*)pSource
);
2556 void SvTreeListBox::ModelHasMoved( SvTreeListEntry
* pSource
)
2558 DBG_CHKTHIS(SvTreeListBox
,0);
2559 pImp
->EntryMoved( (SvTreeListEntry
*)pSource
);
2562 void SvTreeListBox::ModelIsRemoving( SvTreeListEntry
* pEntry
)
2564 DBG_CHKTHIS(SvTreeListBox
,0);
2565 if(pEdEntry
== pEntry
)
2568 pImp
->RemovingEntry( (SvTreeListEntry
*)pEntry
);
2569 NotifyRemoving( (SvTreeListEntry
*)pEntry
);
2572 void SvTreeListBox::ModelHasRemoved( SvTreeListEntry
* pEntry
)
2574 DBG_CHKTHIS(SvTreeListBox
,0);
2575 if ( pEntry
== pHdlEntry
)
2577 pImp
->EntryRemoved();
2580 void SvTreeListBox::SetCollapsedNodeBmp( const Image
& rBmp
)
2582 DBG_CHKTHIS(SvTreeListBox
,0);
2583 AdjustEntryHeight( rBmp
);
2584 pImp
->SetCollapsedNodeBmp( rBmp
);
2587 void SvTreeListBox::SetExpandedNodeBmp( const Image
& rBmp
)
2589 DBG_CHKTHIS(SvTreeListBox
,0);
2590 AdjustEntryHeight( rBmp
);
2591 pImp
->SetExpandedNodeBmp( rBmp
);
2595 void SvTreeListBox::SetFont( const Font
& rFont
)
2597 DBG_CHKTHIS(SvTreeListBox
,0);
2599 Font
aTempFont( rFont
);
2600 Font
aOrigFont( GetFont() );
2601 aTempFont
.SetTransparent( sal_True
);
2602 if (aTempFont
== aOrigFont
)
2604 Control::SetFont( aTempFont
);
2606 aTempFont
.SetColor(aOrigFont
.GetColor());
2607 aTempFont
.SetFillColor(aOrigFont
.GetFillColor());
2608 aTempFont
.SetTransparent(aOrigFont
.IsTransparent());
2610 if (aTempFont
== aOrigFont
)
2613 AdjustEntryHeightAndRecalc( GetFont() );
2616 void SvTreeListBox::AdjustEntryHeightAndRecalc( const Font
& rFont
)
2618 DBG_CHKTHIS(SvTreeListBox
,0);
2619 AdjustEntryHeight( rFont
);
2620 // always invalidate, else things go wrong in SetEntryHeight
2624 void SvTreeListBox::Paint( const Rectangle
& rRect
)
2626 DBG_CHKTHIS(SvTreeListBox
,0);
2627 Control::Paint( rRect
);
2628 if( nTreeFlags
& TREEFLAG_RECALCTABS
)
2630 pImp
->Paint( rRect
);
2633 void SvTreeListBox::MouseButtonDown( const MouseEvent
& rMEvt
)
2635 DBG_CHKTHIS(SvTreeListBox
,0);
2636 pImp
->MouseButtonDown( rMEvt
);
2639 void SvTreeListBox::MouseButtonUp( const MouseEvent
& rMEvt
)
2641 DBG_CHKTHIS(SvTreeListBox
,0);
2642 pImp
->MouseButtonUp( rMEvt
);
2645 void SvTreeListBox::MouseMove( const MouseEvent
& rMEvt
)
2647 DBG_CHKTHIS(SvTreeListBox
,0);
2648 pImp
->MouseMove( rMEvt
);
2652 void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate
)
2654 DBG_CHKTHIS(SvTreeListBox
,0);
2655 pImp
->SetUpdateMode( bUpdate
);
2658 void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic
)
2660 DBG_CHKTHIS(SvTreeListBox
,0);
2661 if( nOffsLogic
!= nEntryHeightOffs
)
2663 nEntryHeight
= nEntryHeight
- nEntryHeightOffs
;
2664 nEntryHeightOffs
= (short)nOffsLogic
;
2665 nEntryHeight
= nEntryHeight
+ nOffsLogic
;
2666 AdjustEntryHeightAndRecalc( GetFont() );
2667 pImp
->SetEntryHeight( nEntryHeight
);
2671 void SvTreeListBox::SetCursor( SvTreeListEntry
* pEntry
, sal_Bool bForceNoSelect
)
2673 DBG_CHKTHIS(SvTreeListBox
,0);
2674 pImp
->SetCursor(pEntry
, bForceNoSelect
);
2677 void SvTreeListBox::SetCurEntry( SvTreeListEntry
* pEntry
)
2679 DBG_CHKTHIS(SvTreeListBox
,0);
2680 pImp
->SetCurEntry( pEntry
);
2683 Image
SvTreeListBox::GetExpandedNodeBmp( ) const
2685 return pImp
->GetExpandedNodeBmp( );
2688 Point
SvTreeListBox::GetEntryPosition( SvTreeListEntry
* pEntry
) const
2690 return pImp
->GetEntryPosition( pEntry
);
2693 void SvTreeListBox::ShowEntry( SvTreeListEntry
* pEntry
)
2695 MakeVisible( pEntry
);
2698 void SvTreeListBox::MakeVisible( SvTreeListEntry
* pEntry
)
2700 pImp
->MakeVisible(pEntry
);
2703 void SvTreeListBox::MakeVisible( SvTreeListEntry
* pEntry
, sal_Bool bMoveToTop
)
2705 pImp
->MakeVisible( pEntry
, bMoveToTop
);
2708 void SvTreeListBox::ModelHasEntryInvalidated( SvTreeListEntry
* pEntry
)
2710 DBG_CHKTHIS(SvTreeListBox
,0);
2712 // reinitialize the separate items of the entries
2713 sal_uInt16 nCount
= ((SvTreeListEntry
*)pEntry
)->ItemCount();
2714 for( sal_uInt16 nIdx
= 0; nIdx
< nCount
; nIdx
++ )
2716 SvLBoxItem
* pItem
= ((SvTreeListEntry
*)pEntry
)->GetItem( nIdx
);
2717 pItem
->InitViewData( this, (SvTreeListEntry
*)pEntry
, 0 );
2721 pImp
->InvalidateEntry( (SvTreeListEntry
*)pEntry
);
2724 void SvTreeListBox::EditItemText( SvTreeListEntry
* pEntry
, SvLBoxString
* pItem
,
2725 const Selection
& rSelection
)
2727 DBG_CHKTHIS(SvTreeListBox
,0);
2728 DBG_ASSERT(pEntry
&&pItem
,"EditItemText: Bad params");
2729 if( IsSelected( pEntry
))
2731 pImp
->ShowCursor( sal_False
);
2732 SvListView::Select( pEntry
, sal_False
);
2733 PaintEntry( pEntry
);
2734 SvListView::Select( pEntry
, sal_True
);
2735 pImp
->ShowCursor( sal_True
);
2739 SvLBoxTab
* pTab
= GetTab( pEntry
, pItem
);
2740 DBG_ASSERT(pTab
,"EditItemText:Tab not found");
2742 Size
aItemSize( pItem
->GetSize(this, pEntry
) );
2743 Point aPos
= GetEntryPosition( pEntry
);
2744 aPos
.Y() += ( nEntryHeight
- aItemSize
.Height() ) / 2;
2745 aPos
.X() = GetTabPos( pEntry
, pTab
);
2746 long nOutputWidth
= pImp
->GetOutputSize().Width();
2747 Size
aSize( nOutputWidth
- aPos
.X(), aItemSize
.Height() );
2748 sal_uInt16 nPos
= std::find( aTabs
.begin(), aTabs
.end(), pTab
) - aTabs
.begin();
2749 if( nPos
+1 < (sal_uInt16
)aTabs
.size() )
2751 SvLBoxTab
* pRightTab
= aTabs
[ nPos
+ 1 ];
2752 long nRight
= GetTabPos( pEntry
, pRightTab
);
2753 if( nRight
<= nOutputWidth
)
2754 aSize
.Width() = nRight
- aPos
.X();
2756 Point
aOrigin( GetMapMode().GetOrigin() );
2757 aPos
+= aOrigin
; // convert to win coordinates
2758 aSize
.Width() -= aOrigin
.X();
2759 Rectangle
aRect( aPos
, aSize
);
2760 EditText( pItem
->GetText(), aRect
, rSelection
);
2763 void SvTreeListBox::EditEntry( SvTreeListEntry
* pEntry
)
2765 pImp
->aEditClickPos
= Point( -1, -1 );
2766 ImplEditEntry( pEntry
);
2769 void SvTreeListBox::ImplEditEntry( SvTreeListEntry
* pEntry
)
2771 DBG_CHKTHIS(SvTreeListBox
,0);
2772 if( IsEditingActive() )
2775 pEntry
= GetCurEntry();
2778 long nClickX
= pImp
->aEditClickPos
.X();
2779 bool bIsMouseTriggered
= nClickX
>= 0;
2781 SvLBoxString
* pItem
= NULL
;
2782 sal_uInt16 nCount
= pEntry
->ItemCount();
2783 long nTabPos
, nNextTabPos
= 0;
2784 for( sal_uInt16 i
= 0 ; i
< nCount
; i
++ )
2786 SvLBoxItem
* pTmpItem
= pEntry
->GetItem( i
);
2787 if (pTmpItem
->GetType() != SV_ITEM_ID_LBOXSTRING
)
2790 SvLBoxTab
* pTab
= GetTab( pEntry
, pTmpItem
);
2792 if( i
< nCount
- 1 )
2794 SvLBoxItem
* pNextItem
= pEntry
->GetItem( i
+ 1 );
2795 SvLBoxTab
* pNextTab
= GetTab( pEntry
, pNextItem
);
2796 nNextTabPos
= pNextTab
->GetPos();
2799 if( pTab
&& pTab
->IsEditable() )
2801 nTabPos
= pTab
->GetPos();
2802 if( !bIsMouseTriggered
|| (nClickX
> nTabPos
&& (nNextTabPos
== -1 || nClickX
< nNextTabPos
) ) )
2804 pItem
= static_cast<SvLBoxString
*>( pTmpItem
);
2810 Selection
aSel( SELECTION_MIN
, SELECTION_MAX
);
2811 if( pItem
&& EditingEntry( pEntry
, aSel
) )
2813 SelectAll( sal_False
);
2814 MakeVisible( pEntry
);
2815 EditItemText( pEntry
, pItem
, aSel
);
2820 sal_Bool
SvTreeListBox::AreChildrenTransient() const
2822 return pImp
->AreChildrenTransient();
2825 void SvTreeListBox::SetChildrenNotTransient()
2827 pImp
->SetChildrenNotTransient();
2830 void SvTreeListBox::EditedText( const OUString
& rStr
)
2833 DBG_CHKTHIS(SvTreeListBox
,0);
2834 if(pEdEntry
) // we have to check if this entry is null that means that it is removed while editing
2836 if( EditedEntry( pEdEntry
, rStr
) )
2838 ((SvLBoxString
*)pEdItem
)->SetText( rStr
);
2839 pModel
->InvalidateEntry( pEdEntry
);
2841 if( GetSelectionCount() == 0 )
2843 if( GetSelectionMode() == MULTIPLE_SELECTION
&& !GetCurEntry() )
2844 SetCurEntry( pEdEntry
);
2848 SvTreeListEntry
* SvTreeListBox::GetDropTarget( const Point
& rPos
)
2850 DBG_CHKTHIS(SvTreeListBox
,0);
2854 ImplShowTargetEmphasis(pTargetEntry
, false);
2855 ScrollOutputArea( +1 );
2859 Size
aSize( pImp
->GetOutputSize() );
2860 if( rPos
.Y() > aSize
.Height() - 12 )
2862 ImplShowTargetEmphasis(pTargetEntry
, false);
2863 ScrollOutputArea( -1 );
2867 SvTreeListEntry
* pTarget
= pImp
->GetEntry( rPos
);
2868 // when dropping in a vacant space, use the last entry
2870 return (SvTreeListEntry
*)LastVisible();
2871 else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP
) &&
2872 pTarget
== First() && rPos
.Y() < 6 )
2879 SvTreeListEntry
* SvTreeListBox::GetEntry( const Point
& rPos
, sal_Bool bHit
) const
2881 DBG_CHKTHIS(SvTreeListBox
,0);
2882 SvTreeListEntry
* pEntry
= pImp
->GetEntry( rPos
);
2883 if( pEntry
&& bHit
)
2885 long nLine
= pImp
->GetEntryLine( pEntry
);
2886 if( !(pImp
->EntryReallyHit( pEntry
, rPos
, nLine
)) )
2892 SvTreeListEntry
* SvTreeListBox::GetCurEntry() const
2894 DBG_CHKTHIS(SvTreeListBox
,0);
2895 return pImp
->GetCurEntry();
2898 void SvTreeListBox::ImplInitStyle()
2900 DBG_CHKTHIS(SvTreeListBox
,0);
2902 const WinBits nWindowStyle
= GetStyle();
2904 nTreeFlags
|= TREEFLAG_RECALCTABS
;
2905 if( nWindowStyle
& WB_SORT
)
2907 GetModel()->SetSortMode( SortAscending
);
2908 GetModel()->SetCompareHdl( LINK(this,SvTreeListBox
,DefaultCompare
));
2912 GetModel()->SetSortMode( SortNone
);
2913 GetModel()->SetCompareHdl( Link() );
2915 pImp
->SetStyle( nWindowStyle
);
2920 void SvTreeListBox::PaintEntry( SvTreeListEntry
* pEntry
)
2922 DBG_CHKTHIS(SvTreeListBox
,0);
2923 DBG_ASSERT(pEntry
,"PaintEntry:No Entry");
2925 pImp
->PaintEntry( pEntry
);
2928 void SvTreeListBox::InvalidateEntry( SvTreeListEntry
* pEntry
)
2930 DBG_CHKTHIS(SvTreeListBox
,0);
2931 DBG_ASSERT(pEntry
,"InvalidateEntry:No Entry");
2934 GetModel()->InvalidateEntry( pEntry
);
2938 long SvTreeListBox::PaintEntry(SvTreeListEntry
* pEntry
,long nLine
,sal_uInt16 nTabFlags
)
2940 return PaintEntry1(pEntry
,nLine
,nTabFlags
);
2943 long SvTreeListBox::PaintEntry1(SvTreeListEntry
* pEntry
,long nLine
,sal_uInt16 nTabFlags
,
2944 sal_Bool bHasClipRegion
)
2946 DBG_CHKTHIS(SvTreeListBox
,0);
2948 Rectangle aRect
; // multi purpose
2950 sal_Bool bHorSBar
= pImp
->HasHorScrollBar();
2951 PreparePaint( pEntry
);
2953 pImp
->UpdateContextBmpWidthMax( pEntry
);
2955 if( nTreeFlags
& TREEFLAG_RECALCTABS
)
2958 short nTempEntryHeight
= GetEntryHeight();
2959 long nWidth
= pImp
->GetOutputSize().Width();
2961 // Did we turn on the scrollbar within PreparePaints? If yes, we have to set
2962 // the ClipRegion anew.
2963 if( !bHorSBar
&& pImp
->HasHorScrollBar() )
2964 SetClipRegion( Region(pImp
->GetClipRegionRect()) );
2966 Point
aEntryPos( GetMapMode().GetOrigin() );
2967 aEntryPos
.X() *= -1; // conversion document coordinates
2968 long nMaxRight
= nWidth
+ aEntryPos
.X() - 1;
2970 Color
aBackupTextColor( GetTextColor() );
2971 Font
aBackupFont( GetFont() );
2972 Color aBackupColor
= GetFillColor();
2974 bool bCurFontIsSel
= false;
2975 sal_Bool bInUse
= pEntry
->HasInUseEmphasis();
2976 // if a ClipRegion was set from outside, we don't have to reset it
2977 const WinBits nWindowStyle
= GetStyle();
2978 const sal_Bool bResetClipRegion
= !bHasClipRegion
;
2979 const sal_Bool bHideSelection
= ((nWindowStyle
& WB_HIDESELECTION
) && !HasFocus())!=0;
2980 const StyleSettings
& rSettings
= GetSettings().GetStyleSettings();
2982 Font
aHighlightFont( GetFont() );
2983 const Color
aHighlightTextColor( rSettings
.GetHighlightTextColor() );
2984 aHighlightFont
.SetColor( aHighlightTextColor
);
2986 Size
aRectSize( 0, nTempEntryHeight
);
2988 if( !bHasClipRegion
&& nWindowStyle
& WB_HSCROLL
)
2990 SetClipRegion( Region(pImp
->GetClipRegionRect()) );
2991 bHasClipRegion
= sal_True
;
2994 SvViewDataEntry
* pViewDataEntry
= GetViewDataEntry( pEntry
);
2996 sal_uInt16 nTabCount
= aTabs
.size();
2997 sal_uInt16 nItemCount
= pEntry
->ItemCount();
2998 sal_uInt16 nCurTab
= 0;
2999 sal_uInt16 nCurItem
= 0;
3001 while( nCurTab
< nTabCount
&& nCurItem
< nItemCount
)
3003 SvLBoxTab
* pTab
= aTabs
[ nCurTab
];
3004 sal_uInt16 nNextTab
= nCurTab
+ 1;
3005 SvLBoxTab
* pNextTab
= nNextTab
< nTabCount
? aTabs
[nNextTab
] : 0;
3006 SvLBoxItem
* pItem
= nCurItem
< nItemCount
? pEntry
->GetItem(nCurItem
) : 0;
3008 sal_uInt16 nFlags
= pTab
->nFlags
;
3009 Size
aSize( pItem
->GetSize( pViewDataEntry
, nCurItem
));
3010 long nTabPos
= GetTabPos( pEntry
, pTab
);
3014 nNextTabPos
= GetTabPos( pEntry
, pNextTab
);
3017 nNextTabPos
= nMaxRight
;
3018 if( nTabPos
> nMaxRight
)
3023 if( pTab
->nFlags
& SV_LBOXTAB_ADJUST_RIGHT
)
3024 // avoid cutting the right edge off the tab separation
3025 nX
= nTabPos
+ pTab
->CalcOffset(aSize
.Width(), (nNextTabPos
-SV_TAB_BORDER
-1) -nTabPos
);
3027 nX
= nTabPos
+ pTab
->CalcOffset(aSize
.Width(), nNextTabPos
-nTabPos
);
3029 if( nFlags
& nTabFlags
)
3031 if( !bHasClipRegion
&& nX
+ aSize
.Width() >= nMaxRight
)
3033 SetClipRegion( Region(pImp
->GetClipRegionRect()) );
3034 bHasClipRegion
= sal_True
;
3037 aEntryPos
.Y() = nLine
;
3039 // set background pattern/color
3041 Wallpaper aWallpaper
= GetBackground();
3043 int bSelTab
= nFlags
& SV_LBOXTAB_SHOW_SELECTION
;
3044 sal_uInt16 nItemType
= pItem
->GetType();
3046 if (pViewDataEntry
->IsHighlighted() && bSelTab
&& !pViewDataEntry
->IsCursored())
3048 Color aNewWallColor
= rSettings
.GetHighlightColor();
3049 if ( !bInUse
|| nItemType
!= SV_ITEM_ID_LBOXCONTEXTBMP
)
3051 // if the face color is bright then the deactive color is also bright
3052 // -> so you can't see any deactive selection
3053 if ( bHideSelection
&& !rSettings
.GetFaceColor().IsBright() &&
3054 aWallpaper
.GetColor().IsBright() != rSettings
.GetDeactiveColor().IsBright() )
3055 aNewWallColor
= rSettings
.GetDeactiveColor();
3056 // set font color to highlight
3057 if ( !bCurFontIsSel
)
3059 SetTextColor( aHighlightTextColor
);
3060 Control::SetFont( aHighlightFont
);
3061 bCurFontIsSel
= true;
3064 aWallpaper
.SetColor( aNewWallColor
);
3066 else // no selection
3068 if( bInUse
&& nItemType
== SV_ITEM_ID_LBOXCONTEXTBMP
)
3069 aWallpaper
.SetColor( rSettings
.GetFieldColor() );
3070 else if( bCurFontIsSel
)
3072 bCurFontIsSel
= false;
3073 SetTextColor( aBackupTextColor
);
3074 Control::SetFont( aBackupFont
);
3079 if( !(nTreeFlags
& TREEFLAG_USESEL
))
3081 // only draw the area that is used by the item
3082 aRectSize
.Width() = aSize
.Width();
3083 aRect
.SetPos( aEntryPos
);
3084 aRect
.SetSize( aRectSize
);
3088 // draw from the current to the next tab
3090 aRect
.Left() = nTabPos
;
3092 // if we're in the 0th tab, always draw from column 0 --
3093 // else we get problems with centered tabs
3095 aRect
.Top() = nLine
;
3096 aRect
.Bottom() = nLine
+ nTempEntryHeight
- 1;
3100 nRight
= GetTabPos(pEntry
,pNextTab
)-1;
3101 if( nRight
> nMaxRight
)
3103 aRect
.Right() = nRight
;
3106 aRect
.Right() = nMaxRight
;
3108 // A custom selection that starts at a tab position > 0, do not fill
3109 // the background of the 0th item, else e.g. we might not be able to
3110 // realize tab listboxes with lines.
3111 if( !(nCurTab
==0 && (nTreeFlags
& TREEFLAG_USESEL
) && nFirstSelTab
) )
3113 SetFillColor( aWallpaper
.GetColor() );
3114 // this case may occur for smaller horizontal resizes
3115 if( aRect
.Left() < aRect
.Right() )
3119 // center vertically
3120 aEntryPos
.Y() += ( nTempEntryHeight
- aSize
.Height() ) / 2;
3121 pItem
->Paint(aEntryPos
, *this, pViewDataEntry
, pEntry
);
3123 // division line between tabs
3124 if (pNextTab
&& pItem
->GetType() == SV_ITEM_ID_LBOXSTRING
&&
3125 // not at the right edge of the window!
3126 aRect
.Right() < nMaxRight
)
3128 aRect
.Left() = aRect
.Right() - SV_TAB_BORDER
;
3132 SetFillColor( aBackupColor
);
3137 if( pViewDataEntry
->IsCursored() && !HasFocus() )
3141 Color aOldLineColor
= GetLineColor();
3142 SetLineColor( Color( COL_BLACK
) );
3143 aRect
= GetFocusRect( pEntry
, nLine
);
3147 SetLineColor( aOldLineColor
);
3148 SetFillColor( aBackupColor
);
3153 SetTextColor( aBackupTextColor
);
3154 Control::SetFont( aBackupFont
);
3157 sal_uInt16 nFirstDynTabPos
;
3158 SvLBoxTab
* pFirstDynamicTab
= GetFirstDynamicTab( nFirstDynTabPos
);
3159 long nDynTabPos
= GetTabPos( pEntry
, pFirstDynamicTab
);
3160 nDynTabPos
+= pImp
->nNodeBmpTabDistance
;
3161 nDynTabPos
+= pImp
->nNodeBmpWidth
/ 2;
3162 nDynTabPos
+= 4; // 4 pixels of buffer, so the node bitmap is not too close
3165 if( (!(pEntry
->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP
)) &&
3166 (nWindowStyle
& WB_HASBUTTONS
) && pFirstDynamicTab
&&
3167 ( pEntry
->HasChildren() || pEntry
->HasChildrenOnDemand() ) )
3169 // find first tab and check if the node bitmap extends into it
3170 sal_uInt16 nNextTab
= nFirstDynTabPos
;
3171 SvLBoxTab
* pNextTab
;
3175 pNextTab
= nNextTab
< nTabCount
? aTabs
[nNextTab
] : 0;
3176 } while( pNextTab
&& pNextTab
->IsDynamic() );
3178 if( !pNextTab
|| (GetTabPos( pEntry
, pNextTab
) > nDynTabPos
) )
3180 if((nWindowStyle
& WB_HASBUTTONSATROOT
) || pModel
->GetDepth(pEntry
) > 0)
3182 Point
aPos( GetTabPos(pEntry
,pFirstDynamicTab
), nLine
);
3183 aPos
.X() += pImp
->nNodeBmpTabDistance
;
3185 const Image
* pImg
= 0;
3187 if( IsExpanded(pEntry
) )
3188 pImg
= &pImp
->GetExpandedNodeBmp( );
3191 if( (!pEntry
->HasChildren()) && pEntry
->HasChildrenOnDemand() &&
3192 (!(pEntry
->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN
)) &&
3193 pImp
->GetDontKnowNodeBmp().GetSizePixel().Width() )
3194 pImg
= &pImp
->GetDontKnowNodeBmp( );
3196 pImg
= &pImp
->GetCollapsedNodeBmp( );
3198 aPos
.Y() += (nTempEntryHeight
- pImg
->GetSizePixel().Height()) / 2;
3200 sal_uInt16 nStyle
= 0;
3202 nStyle
|= IMAGE_DRAW_DISABLE
;
3205 sal_Bool bNativeOK
= sal_False
;
3206 if ( IsNativeControlSupported( CTRL_LISTNODE
, PART_ENTIRE_CONTROL
) )
3208 ImplControlValue aControlValue
;
3209 Rectangle
aCtrlRegion( aPos
, pImg
->GetSizePixel() );
3210 ControlState nState
= 0;
3212 if ( IsEnabled() ) nState
|= CTRL_STATE_ENABLED
;
3214 if ( IsExpanded(pEntry
) )
3215 aControlValue
.setTristateVal( BUTTONVALUE_ON
);//expanded node
3218 if( (!pEntry
->HasChildren() ) &&
3219 pEntry
->HasChildrenOnDemand() &&
3220 (!(pEntry
->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN
)) &&
3221 pImp
->GetDontKnowNodeBmp().GetSizePixel().Width()
3223 aControlValue
.setTristateVal( BUTTONVALUE_DONTKNOW
); //dont know
3225 aControlValue
.setTristateVal( BUTTONVALUE_OFF
); //collapsed node
3228 bNativeOK
= DrawNativeControl( CTRL_LISTNODE
, PART_ENTIRE_CONTROL
,
3229 aCtrlRegion
, nState
, aControlValue
, OUString() );
3233 DrawImage( aPos
, *pImg
,nStyle
);
3240 if( bHasClipRegion
&& bResetClipRegion
)
3242 return 0; // nRowLen;
3245 void SvTreeListBox::PreparePaint( SvTreeListEntry
* )
3249 Rectangle
SvTreeListBox::GetFocusRect( SvTreeListEntry
* pEntry
, long nLine
)
3251 DBG_CHKTHIS(SvTreeListBox
,0);
3254 aRect
.Top() = nLine
;
3255 aSize
.Height() = GetEntryHeight();
3257 long nRealWidth
= pImp
->GetOutputSize().Width();
3258 nRealWidth
-= GetMapMode().GetOrigin().X();
3261 SvLBoxTab
* pTab
= GetFirstTab( SV_LBOXTAB_SHOW_SELECTION
, nCurTab
);
3264 nTabPos
= GetTabPos( pEntry
, pTab
);
3266 if( pTab
&& nCurTab
< aTabs
.size() - 1 )
3268 SvLBoxTab
* pNextTab
= aTabs
[ nCurTab
+ 1 ];
3269 nNextTabPos
= GetTabPos( pEntry
, pNextTab
);
3273 nNextTabPos
= nRealWidth
;
3274 if( nTabPos
> nRealWidth
)
3278 sal_Bool bUserSelection
= (sal_Bool
)( nTreeFlags
& TREEFLAG_USESEL
) != 0;
3279 if( !bUserSelection
)
3281 if( pTab
&& nCurTab
< pEntry
->ItemCount() )
3283 SvLBoxItem
* pItem
= pEntry
->GetItem( nCurTab
);
3284 aSize
.Width() = pItem
->GetSize( this, pEntry
).Width();
3285 if( !aSize
.Width() )
3287 long nX
= nTabPos
; //GetTabPos( pEntry, pTab );
3289 nX
+= pTab
->CalcOffset( aSize
.Width(), nNextTabPos
- nTabPos
);
3291 // make sure that first and last letter aren't cut off slightly
3292 aRect
.SetSize( aSize
);
3293 if( aRect
.Left() > 0 )
3300 // if SelTab != 0, we have to calculate also
3301 if( nFocusWidth
== -1 || nFirstSelTab
)
3303 sal_uInt16 nLastTab
;
3304 SvLBoxTab
* pLastTab
= GetLastTab(SV_LBOXTAB_SHOW_SELECTION
,nLastTab
);
3306 if( nLastTab
< aTabs
.size() ) // is there another one?
3307 pLastTab
= aTabs
[ nLastTab
];
3309 pLastTab
= 0; // select whole width
3310 aSize
.Width() = pLastTab
? pLastTab
->GetPos() : 0x0fffffff;
3311 nFocusWidth
= (short)aSize
.Width();
3313 nFocusWidth
= nFocusWidth
- (short)nTabPos
; //pTab->GetPos();
3317 aSize
.Width() = nFocusWidth
;
3321 aSize
.Width() += nTabPos
;
3323 aSize
.Width() += pTab
->GetPos(); // Tab0 always from the leftmost position
3326 // if selection starts with 0th tab, draw from column 0 on
3329 aRect
.Left() = nTabPos
;
3330 aSize
.Width() -= nTabPos
;
3332 aRect
.SetSize( aSize
);
3334 // adjust right edge because of clipping
3335 if( aRect
.Right() >= nRealWidth
)
3337 aRect
.Right() = nRealWidth
-1;
3338 nFocusWidth
= (short)aRect
.GetWidth();
3344 sal_IntPtr
SvTreeListBox::GetTabPos( SvTreeListEntry
* pEntry
, SvLBoxTab
* pTab
)
3346 DBG_CHKTHIS(SvTreeListBox
,0);
3347 DBG_ASSERT(pTab
,"No Tab");
3348 sal_IntPtr nPos
= pTab
->GetPos();
3349 if( pTab
->IsDynamic() )
3351 sal_uInt16 nDepth
= pModel
->GetDepth( pEntry
);
3352 nDepth
= nDepth
* (sal_uInt16
)nIndent
;
3353 nPos
+= (sal_IntPtr
)nDepth
;
3358 SvLBoxItem
* SvTreeListBox::GetItem_Impl( SvTreeListEntry
* pEntry
, long nX
,
3359 SvLBoxTab
** ppTab
, sal_uInt16 nEmptyWidth
)
3361 DBG_CHKTHIS(SvTreeListBox
,0);
3362 SvLBoxItem
* pItemClicked
= 0;
3363 sal_uInt16 nTabCount
= aTabs
.size();
3364 sal_uInt16 nItemCount
= pEntry
->ItemCount();
3365 SvLBoxTab
* pTab
= aTabs
.front();
3366 SvLBoxItem
* pItem
= pEntry
->GetItem(0);
3367 sal_uInt16 nNextItem
= 1;
3368 nX
-= GetMapMode().GetOrigin().X();
3369 long nRealWidth
= pImp
->GetOutputSize().Width();
3370 nRealWidth
-= GetMapMode().GetOrigin().X();
3374 SvLBoxTab
* pNextTab
=nNextItem
<nTabCount
? aTabs
[nNextItem
] : 0;
3375 long nStart
= GetTabPos( pEntry
, pTab
);
3379 nNextTabPos
= GetTabPos( pEntry
, pNextTab
);
3382 nNextTabPos
= nRealWidth
;
3383 if( nStart
> nRealWidth
)
3387 Size
aItemSize( pItem
->GetSize(this, pEntry
));
3388 nStart
+= pTab
->CalcOffset( aItemSize
.Width(), nNextTabPos
- nStart
);
3389 long nLen
= aItemSize
.Width();
3392 long nTabWidth
= GetTabPos( pEntry
, pNextTab
) - nStart
;
3393 if( nTabWidth
< nLen
)
3400 if( nX
>= nStart
&& nX
< (nStart
+nLen
) )
3402 pItemClicked
= pItem
;
3409 if( nNextItem
>= nItemCount
|| nNextItem
>= nTabCount
)
3411 pTab
= aTabs
[ nNextItem
];
3412 pItem
= pEntry
->GetItem( nNextItem
);
3415 return pItemClicked
;
3418 long SvTreeListBox::getPreferredDimensions(std::vector
<long> &rWidths
) const
3422 SvTreeListEntry
* pEntry
= First();
3425 sal_uInt16 nCount
= pEntry
->ItemCount();
3426 sal_uInt16 nCurPos
= 0;
3427 if (nCount
> rWidths
.size())
3428 rWidths
.resize(nCount
);
3429 while (nCurPos
< nCount
)
3431 SvLBoxItem
* pItem
= pEntry
->GetItem( nCurPos
);
3432 long nWidth
= pItem
->GetSize(this, pEntry
).Width();
3435 nWidth
+= SV_TAB_BORDER
* 2;
3436 if (nWidth
> rWidths
[nCurPos
])
3437 rWidths
[nCurPos
] = nWidth
;
3441 pEntry
= Next( pEntry
);
3442 nHeight
+= GetEntryHeight();
3447 Size
SvTreeListBox::GetOptimalSize() const
3449 std::vector
<long> aWidths
;
3450 Size
aRet(0, getPreferredDimensions(aWidths
));
3451 for (size_t i
= 0; i
< aWidths
.size(); ++i
)
3452 aRet
.Width() += aWidths
[i
];
3453 if (GetStyle() & WB_BORDER
)
3455 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
3456 aRet
.Width() += rStyleSettings
.GetBorderSize() * 2;
3457 aRet
.Height() += rStyleSettings
.GetBorderSize() * 2;
3459 long nMinWidth
= nMinWidthInChars
* approximate_char_width();
3460 aRet
.Width() = std::max(aRet
.Width(), nMinWidth
);
3464 SvLBoxItem
* SvTreeListBox::GetItem(SvTreeListEntry
* pEntry
,long nX
,SvLBoxTab
** ppTab
)
3466 return GetItem_Impl( pEntry
, nX
, ppTab
, 0 );
3469 SvLBoxItem
* SvTreeListBox::GetItem(SvTreeListEntry
* pEntry
,long nX
)
3471 DBG_CHKTHIS(SvTreeListBox
,0);
3472 SvLBoxTab
* pDummyTab
;
3473 return GetItem_Impl( pEntry
, nX
, &pDummyTab
, 0 );
3476 void SvTreeListBox::AddTab(long nTabPos
,sal_uInt16 nFlags
,void* pUserData
)
3478 DBG_CHKTHIS(SvTreeListBox
,0);
3480 SvLBoxTab
* pTab
= new SvLBoxTab( nTabPos
, nFlags
);
3481 pTab
->SetUserData( pUserData
);
3482 aTabs
.push_back( pTab
);
3483 if( nTreeFlags
& TREEFLAG_USESEL
)
3485 sal_uInt16 nPos
= aTabs
.size() - 1;
3486 if( nPos
>= nFirstSelTab
&& nPos
<= nLastSelTab
)
3487 pTab
->nFlags
|= SV_LBOXTAB_SHOW_SELECTION
;
3489 // string items usually have to be selected -- turn this off
3491 pTab
->nFlags
&= ~SV_LBOXTAB_SHOW_SELECTION
;
3497 SvLBoxTab
* SvTreeListBox::GetFirstDynamicTab( sal_uInt16
& rPos
) const
3499 DBG_CHKTHIS(SvTreeListBox
,0);
3500 sal_uInt16 nCurTab
= 0;
3501 sal_uInt16 nTabCount
= aTabs
.size();
3502 while( nCurTab
< nTabCount
)
3504 SvLBoxTab
* pTab
= aTabs
[nCurTab
];
3505 if( pTab
->nFlags
& SV_LBOXTAB_DYNAMIC
)
3515 SvLBoxTab
* SvTreeListBox::GetFirstDynamicTab() const
3518 return GetFirstDynamicTab( nDummy
);
3521 SvLBoxTab
* SvTreeListBox::GetTab( SvTreeListEntry
* pEntry
, SvLBoxItem
* pItem
) const
3523 DBG_CHKTHIS(SvTreeListBox
,0);
3524 sal_uInt16 nPos
= pEntry
->GetPos( pItem
);
3525 return aTabs
[ nPos
];
3528 void SvTreeListBox::ClearTabList()
3530 DBG_CHKTHIS(SvTreeListBox
,0);
3531 sal_uInt16 nTabCount
= aTabs
.size();
3535 SvLBoxTab
* pDelTab
= aTabs
[ nTabCount
];
3542 Size
SvTreeListBox::GetOutputSizePixel() const
3544 DBG_CHKTHIS(SvTreeListBox
,0);
3545 Size aSize
= pImp
->GetOutputSize();
3549 void SvTreeListBox::NotifyBeginScroll()
3551 DBG_CHKTHIS(SvTreeListBox
,0);
3554 void SvTreeListBox::NotifyEndScroll()
3556 DBG_CHKTHIS(SvTreeListBox
,0);
3559 void SvTreeListBox::NotifyScrolling( long )
3561 DBG_CHKTHIS(SvTreeListBox
,0);
3564 void SvTreeListBox::NotifyScrolled()
3566 DBG_CHKTHIS(SvTreeListBox
,0);
3567 aScrolledHdl
.Call( this );
3570 void SvTreeListBox::NotifyInvalidating()
3572 DBG_CHKTHIS(SvTreeListBox
,0);
3575 void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags
)
3577 DBG_CHKTHIS(SvTreeListBox
,0);
3578 if( nFocusWidth
== -1 )
3579 // to make sure that the control doesn't show the wrong focus rectangle
3581 pImp
->RecalcFocusRect();
3582 NotifyInvalidating();
3583 Control::Invalidate( nInvalidateFlags
);
3587 void SvTreeListBox::Invalidate( const Rectangle
& rRect
, sal_uInt16 nInvalidateFlags
)
3589 DBG_CHKTHIS(SvTreeListBox
,0);
3590 if( nFocusWidth
== -1 )
3591 // to make sure that the control doesn't show the wrong focus rectangle
3593 pImp
->RecalcFocusRect();
3594 NotifyInvalidating();
3595 Control::Invalidate( rRect
, nInvalidateFlags
);
3599 void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart
, sal_uInt16 nEnd
)
3601 DBG_CHKTHIS(SvTreeListBox
,0);
3604 nTreeFlags
|= TREEFLAG_USESEL
;
3611 // select all tabs that lie within the area
3612 nTreeFlags
|= TREEFLAG_RECALCTABS
;
3613 nFirstSelTab
= nStart
;
3615 pImp
->RecalcFocusRect();
3618 void SvTreeListBox::Command( const CommandEvent
& rCEvt
)
3620 DBG_CHKTHIS(SvTreeListBox
,0);
3621 // FIXME gnumake2 resync to DEV300_m84
3622 pImp
->Command( rCEvt
);
3626 void SvTreeListBox::RemoveParentKeepChildren( SvTreeListEntry
* pParent
)
3628 DBG_CHKTHIS(SvTreeListBox
,0);
3629 DBG_ASSERT(pParent
,"RemoveParentKeepChildren:No Parent");
3630 SvTreeListEntry
* pNewParent
= GetParent( pParent
);
3631 if( pParent
->HasChildren())
3633 SvTreeListEntry
* pChild
= FirstChild( pParent
);
3636 pModel
->Move( pChild
, pNewParent
, LIST_APPEND
);
3637 pChild
= FirstChild( pParent
);
3640 pModel
->Remove( pParent
);
3643 SvLBoxTab
* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask
, sal_uInt16
& rPos
)
3645 sal_uInt16 nTabCount
= aTabs
.size();
3646 for( sal_uInt16 nPos
= 0; nPos
< nTabCount
; nPos
++ )
3648 SvLBoxTab
* pTab
= aTabs
[ nPos
];
3649 if( (pTab
->nFlags
& nFlagMask
) )
3659 SvLBoxTab
* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask
, sal_uInt16
& rTabPos
)
3661 sal_uInt16 nPos
= (sal_uInt16
)aTabs
.size();
3665 SvLBoxTab
* pTab
= aTabs
[ nPos
];
3666 if( (pTab
->nFlags
& nFlagMask
) )
3676 void SvTreeListBox::RequestHelp( const HelpEvent
& rHEvt
)
3678 if( !pImp
->RequestHelp( rHEvt
) )
3679 Control::RequestHelp( rHEvt
);
3682 void SvTreeListBox::CursorMoved( SvTreeListEntry
* )
3686 IMPL_LINK( SvTreeListBox
, DefaultCompare
, SvSortData
*, pData
)
3688 const SvTreeListEntry
* pLeft
= pData
->pLeft
;
3689 const SvTreeListEntry
* pRight
= pData
->pRight
;
3690 OUString
aLeft( ((SvLBoxString
*)(pLeft
->GetFirstItem(SV_ITEM_ID_LBOXSTRING
)))->GetText());
3691 OUString
aRight( ((SvLBoxString
*)(pRight
->GetFirstItem(SV_ITEM_ID_LBOXSTRING
)))->GetText());
3692 pImp
->UpdateStringSorter();
3693 return pImp
->m_pStringSorter
->compare(aLeft
, aRight
);
3696 void SvTreeListBox::ModelNotification( sal_uInt16 nActionId
, SvTreeListEntry
* pEntry1
,
3697 SvTreeListEntry
* pEntry2
, sal_uLong nPos
)
3699 SolarMutexGuard aSolarGuard
;
3701 if( nActionId
== LISTACTION_CLEARING
)
3702 CancelTextEditing();
3704 SvListView::ModelNotification( nActionId
, pEntry1
, pEntry2
, nPos
);
3707 case LISTACTION_INSERTED
:
3709 SvTreeListEntry
* pEntry( dynamic_cast< SvTreeListEntry
* >( pEntry1
) );
3712 SAL_WARN( "svtools.contnr", "SvTreeListBox::ModelNotification: invalid entry!" );
3716 SvLBoxContextBmp
* pBmpItem
= static_cast< SvLBoxContextBmp
* >( pEntry
->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP
) );
3719 const Image
& rBitmap1( pBmpItem
->GetBitmap1() );
3720 const Image
& rBitmap2( pBmpItem
->GetBitmap2() );
3721 short nMaxWidth
= short( std::max( rBitmap1
.GetSizePixel().Width(), rBitmap2
.GetSizePixel().Width() ) );
3722 nMaxWidth
= pImp
->UpdateContextBmpWidthVector( pEntry
, nMaxWidth
);
3723 if( nMaxWidth
> nContextBmpWidthMax
)
3725 nContextBmpWidthMax
= nMaxWidth
;
3728 if (get_width_request() == -1)
3733 case LISTACTION_RESORTING
:
3734 SetUpdateMode( sal_False
);
3737 case LISTACTION_RESORTED
:
3738 // after a selection: show first entry and also keep the selection
3739 MakeVisible( (SvTreeListEntry
*)pModel
->First(), sal_True
);
3740 SetUpdateMode( sal_True
);
3743 case LISTACTION_CLEARED
:
3744 if( IsUpdateMode() )
3750 void SvTreeListBox::EndSelection()
3752 pImp
->EndSelection();
3755 void SvTreeListBox::RepaintScrollBars() const
3757 ((SvTreeListBox
*)this)->pImp
->RepaintScrollBars();
3760 ScrollBar
*SvTreeListBox::GetVScroll()
3762 return &((SvTreeListBox
*)this)->pImp
->aVerSBar
;
3765 ScrollBar
*SvTreeListBox::GetHScroll()
3767 return &((SvTreeListBox
*)this)->pImp
->aHorSBar
;
3770 void SvTreeListBox::EnableAsyncDrag( sal_Bool b
)
3772 pImp
->EnableAsyncDrag( b
);
3775 SvTreeListEntry
* SvTreeListBox::GetFirstEntryInView() const
3778 return GetEntry( aPos
);
3781 SvTreeListEntry
* SvTreeListBox::GetNextEntryInView(SvTreeListEntry
* pEntry
) const
3783 SvTreeListEntry
* pNext
= (SvTreeListEntry
*)NextVisible( pEntry
);
3786 Point
aPos( GetEntryPosition(pNext
) );
3787 const Size
& rSize
= pImp
->GetOutputSize();
3788 if( aPos
.Y() < 0 || aPos
.Y() >= rSize
.Height() )
3794 SvTreeListEntry
* SvTreeListBox::GetLastEntryInView() const
3796 SvTreeListEntry
* pEntry
= GetFirstEntryInView();
3797 SvTreeListEntry
* pNext
= 0;
3800 pNext
= (SvTreeListEntry
*)NextVisible( pEntry
);
3803 Point
aPos( GetEntryPosition(pNext
) );
3804 const Size
& rSize
= pImp
->GetOutputSize();
3805 if( aPos
.Y() < 0 || aPos
.Y() + GetEntryHeight() >= rSize
.Height() )
3816 void SvTreeListBox::ShowFocusRect( const SvTreeListEntry
* pEntry
)
3818 pImp
->ShowFocusRect( pEntry
);
3821 void SvTreeListBox::DataChanged( const DataChangedEvent
& rDCEvt
)
3823 if( (rDCEvt
.GetType()==DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
3825 nEntryHeight
= 0; // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height
3826 // forces complete recalc of heights!
3827 InitSettings( sal_True
, sal_True
, sal_True
);
3831 Control::DataChanged( rDCEvt
);
3834 void SvTreeListBox::StateChanged( StateChangedType eType
)
3836 if( eType
== STATE_CHANGE_ENABLE
)
3837 Invalidate( INVALIDATE_CHILDREN
);
3839 Control::StateChanged( eType
);
3841 if ( eType
== STATE_CHANGE_STYLE
)
3845 void SvTreeListBox::InitSettings(sal_Bool bFont
,sal_Bool bForeground
,sal_Bool bBackground
)
3847 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
3851 aFont
= rStyleSettings
.GetFieldFont();
3852 aFont
.SetColor( rStyleSettings
.GetWindowTextColor() );
3853 SetPointFont( aFont
);
3854 AdjustEntryHeightAndRecalc( aFont
);
3857 if( bForeground
|| bFont
)
3859 SetTextColor( rStyleSettings
.GetFieldTextColor() );
3864 SetBackground( rStyleSettings
.GetFieldColor() );
3866 // always try to re-create default-SvLBoxButtonData
3867 if( pCheckButtonData
&& pCheckButtonData
->HasDefaultImages() )
3868 pCheckButtonData
->SetDefaultImages( this );
3871 sal_Bool
SvTreeListBox::IsCellFocusEnabled() const
3873 return pImp
->IsCellFocusEnabled();
3876 bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos
)
3878 return pImp
->SetCurrentTabPos( _nNewPos
);
3881 sal_uInt16
SvTreeListBox::GetCurrentTabPos() const
3883 return pImp
->GetCurrentTabPos();
3886 void SvTreeListBox::InitStartEntry()
3888 if( !pImp
->pStartEntry
)
3889 pImp
->pStartEntry
= GetModel()->First();
3892 PopupMenu
* SvTreeListBox::CreateContextMenu( void )
3897 void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16
)
3899 DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" );
3902 void SvTreeListBox::EnableContextMenuHandling( void )
3904 DBG_ASSERT( pImp
, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
3906 pImp
->bContextMenuHandling
= sal_True
;
3909 void SvTreeListBox::EnableContextMenuHandling( sal_Bool b
)
3911 DBG_ASSERT( pImp
, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
3913 pImp
->bContextMenuHandling
= b
;
3916 sal_Bool
SvTreeListBox::IsContextMenuHandlingEnabled( void ) const
3918 DBG_ASSERT( pImp
, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" );
3920 return pImp
->bContextMenuHandling
;
3923 void SvTreeListBox::EnableList( bool _bEnable
)
3925 // call base class method
3926 Window::Enable( _bEnable
!= false );
3927 // then paint immediately
3928 Paint( Rectangle( Point(), GetSizePixel() ) );
3931 ::com::sun::star::uno::Reference
< XAccessible
> SvTreeListBox::CreateAccessible()
3933 Window
* pParent
= GetAccessibleParentWindow();
3934 DBG_ASSERT( pParent
, "SvTreeListBox::CreateAccessible - accessible parent not found" );
3936 ::com::sun::star::uno::Reference
< XAccessible
> xAccessible
;
3939 ::com::sun::star::uno::Reference
< XAccessible
> xAccParent
= pParent
->GetAccessible();
3940 if ( xAccParent
.is() )
3942 // need to be done here to get the vclxwindow later on in the accessbile
3943 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XWindowPeer
> xTemp(GetComponentInterface());
3944 xAccessible
= pImp
->m_aFactoryAccess
.getFactory().createAccessibleTreeListBox( *this, xAccParent
);
3950 void SvTreeListBox::FillAccessibleEntryStateSet( SvTreeListEntry
* pEntry
, ::utl::AccessibleStateSetHelper
& rStateSet
) const
3952 DBG_ASSERT( pEntry
, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" );
3954 if ( pEntry
->HasChildrenOnDemand() || pEntry
->HasChildren() )
3956 rStateSet
.AddState( AccessibleStateType::EXPANDABLE
);
3957 if ( IsExpanded( pEntry
) )
3958 rStateSet
.AddState( (sal_Int16
)AccessibleStateType::EXPANDED
);
3961 if ( GetCheckButtonState( pEntry
) == SV_BUTTON_CHECKED
)
3962 rStateSet
.AddState( AccessibleStateType::CHECKED
);
3963 if ( IsEntryVisible( pEntry
) )
3964 rStateSet
.AddState( AccessibleStateType::VISIBLE
);
3965 if ( IsSelected( pEntry
) )
3966 rStateSet
.AddState( AccessibleStateType::SELECTED
);
3969 Rectangle
SvTreeListBox::GetBoundingRect( SvTreeListEntry
* pEntry
)
3971 Point aPos
= GetEntryPosition( pEntry
);
3972 Rectangle aRect
= GetFocusRect( pEntry
, aPos
.Y() );
3976 void SvTreeListBox::EnableCellFocus()
3978 pImp
->EnableCellFocus();
3981 void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent
, void* pData
)
3983 CallEventListeners(nEvent
, pData
);
3986 void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper
& /*rStateSet*/ ) const
3990 void SvTreeListBox::set_min_width_in_chars(sal_Int32 nChars
)
3992 nMinWidthInChars
= nChars
;
3996 bool SvTreeListBox::set_property(const OString
&rKey
, const OString
&rValue
)
3998 if (rKey
== "min-width-chars")
4000 set_min_width_in_chars(rValue
.toInt32());
4003 return Control::set_property(rKey
, rValue
);
4007 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */