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 .
20 #include <vcl/svapp.hxx>
21 #include <vcl/salnativewidgets.hxx>
22 #include <vcl/help.hxx>
26 #include <svtools/treelistbox.hxx>
27 #include <svtools/svlbitm.hxx>
28 #include <svimpbox.hxx>
29 #include <rtl/instance.hxx>
30 #include <svtools/svtresid.hxx>
31 #include <tools/wintypes.hxx>
32 #include <svtools/svtools.hrc>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/string.hxx>
36 #include "svtools/treelistentry.hxx"
37 #include "svtools/viewdataentry.hxx"
39 #define NODE_BMP_TABDIST_NOTVALID -2000000
40 #define FIRST_ENTRY_TAB 1
42 // #i27063# (pl), #i32300# (pb) never access VCL after DeInitVCL - also no destructors
43 Image
* SvImpLBox::s_pDefCollapsed
= NULL
;
44 Image
* SvImpLBox::s_pDefExpanded
= NULL
;
45 sal_Int32
SvImpLBox::s_nImageRefCount
= 0;
47 SvImpLBox::SvImpLBox( SvTreeListBox
* pLBView
, SvTreeList
* pLBTree
, WinBits nWinStyle
) :
49 aVerSBar( pLBView
, WB_DRAG
| WB_VSCROLL
),
50 aHorSBar( pLBView
, WB_DRAG
| WB_HSCROLL
),
51 aScrBarBox( pLBView
),
53 aSelEng( pLBView
, (FunctionSet
*)0 ),
54 aFctSet( this, &aSelEng
, pLBView
),
55 nExtendedWinBits( 0 ),
56 bAreChildrenTransient( true ),
59 osl_atomic_increment(&s_nImageRefCount
);
62 aSelEng
.SetFunctionSet( (FunctionSet
*)&aFctSet
);
63 aSelEng
.ExpandSelectionOnMouseMove( false );
64 SetStyle( nWinStyle
);
65 SetSelectionMode( SINGLE_SELECTION
);
68 aVerSBar
.SetScrollHdl( LINK( this, SvImpLBox
, ScrollUpDownHdl
) );
69 aHorSBar
.SetScrollHdl( LINK( this, SvImpLBox
, ScrollLeftRightHdl
) );
70 aHorSBar
.SetEndScrollHdl( LINK( this, SvImpLBox
, EndScrollHdl
) );
71 aVerSBar
.SetEndScrollHdl( LINK( this, SvImpLBox
, EndScrollHdl
) );
72 aVerSBar
.SetRange( Range(0,0) );
74 aHorSBar
.SetRange( Range(0,0) );
75 aHorSBar
.SetPageSize( 24 ); // pixels
76 aHorSBar
.SetLineSize( 8 ); // pixels
78 nHorSBarHeight
= (short)aHorSBar
.GetSizePixel().Height();
79 nVerSBarWidth
= (short)aVerSBar
.GetSizePixel().Width();
84 nVisibleCount
= 0; // number of rows of data in control
85 nNodeBmpTabDistance
= NODE_BMP_TABDIST_NOTVALID
;
89 bAsyncBeginDrag
= false;
90 aAsyncBeginDragTimer
.SetTimeout( 0 );
91 aAsyncBeginDragTimer
.SetTimeoutHdl( LINK(this,SvImpLBox
,BeginDragHdl
));
92 // button animation in listbox
98 nCurTabPos
= FIRST_ENTRY_TAB
;
100 aEditTimer
.SetTimeout( 800 );
101 aEditTimer
.SetTimeoutHdl( LINK(this,SvImpLBox
,EditTimerCall
) );
105 nCurUserEvent
= 0xffffffff;
108 bInVScrollHdl
= false;
111 bSubLstOpRet
= bSubLstOpLR
= bContextMenuHandling
= bIsCellFocusEnabled
= false;
114 SvImpLBox::~SvImpLBox()
119 delete m_pStringSorter
;
120 if ( osl_atomic_decrement(&s_nImageRefCount
) == 0 )
122 DELETEZ(s_pDefCollapsed
);
123 DELETEZ(s_pDefExpanded
);
127 void SvImpLBox::UpdateStringSorter()
129 const ::com::sun::star::lang::Locale
& rNewLocale
= Application::GetSettings().GetLanguageTag().getLocale();
131 if( m_pStringSorter
)
133 // different Locale from the older one, drop it and force recreate
134 const ::com::sun::star::lang::Locale
&aLocale
= m_pStringSorter
->getLocale();
135 if( aLocale
.Language
!= rNewLocale
.Language
||
136 aLocale
.Country
!= rNewLocale
.Country
||
137 aLocale
.Variant
!= rNewLocale
.Variant
)
139 delete m_pStringSorter
;
140 m_pStringSorter
= NULL
;
144 if( !m_pStringSorter
)
146 m_pStringSorter
= new comphelper::string::NaturalStringSorter(
147 ::comphelper::getProcessComponentContext(),
152 // #97680# ----------------------
153 short SvImpLBox::UpdateContextBmpWidthVector( SvTreeListEntry
* pEntry
, short nWidth
)
155 DBG_ASSERT( pView
->pModel
, "View and Model aren't valid!" );
157 sal_uInt16 nDepth
= pView
->pModel
->GetDepth( pEntry
);
158 // initialize vector if necessary
159 std::vector
< short >::size_type nSize
= aContextBmpWidthVector
.size();
160 while ( nDepth
> nSize
)
162 aContextBmpWidthVector
.resize( nSize
+ 1 );
163 aContextBmpWidthVector
.at( nSize
) = nWidth
;
166 if( aContextBmpWidthVector
.size() == nDepth
)
168 aContextBmpWidthVector
.resize( nDepth
+ 1 );
169 aContextBmpWidthVector
.at( nDepth
) = 0;
171 short nContextBmpWidth
= aContextBmpWidthVector
[ nDepth
];
172 if( nContextBmpWidth
< nWidth
)
174 aContextBmpWidthVector
.at( nDepth
) = nWidth
;
178 return nContextBmpWidth
;
181 void SvImpLBox::UpdateContextBmpWidthVectorFromMovedEntry( SvTreeListEntry
* pEntry
)
183 DBG_ASSERT( pEntry
, "Moved Entry is invalid!" );
185 SvLBoxContextBmp
* pBmpItem
= static_cast< SvLBoxContextBmp
* >( pEntry
->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP
) );
186 short nExpWidth
= (short)pBmpItem
->GetBitmap1().GetSizePixel().Width();
187 short nColWidth
= (short)pBmpItem
->GetBitmap2().GetSizePixel().Width();
188 short nMax
= std::max(nExpWidth
, nColWidth
);
189 UpdateContextBmpWidthVector( pEntry
, nMax
);
191 if( pEntry
->HasChildren() ) // recursive call, whether expanded or not
193 SvTreeListEntry
* pChild
= pView
->FirstChild( pEntry
);
194 DBG_ASSERT( pChild
, "The first child is invalid!" );
197 UpdateContextBmpWidthVectorFromMovedEntry( pChild
);
198 pChild
= pView
->Next( pChild
);
203 void SvImpLBox::UpdateContextBmpWidthMax( SvTreeListEntry
* pEntry
)
205 sal_uInt16 nDepth
= pView
->pModel
->GetDepth( pEntry
);
206 if( aContextBmpWidthVector
.size() < 1 )
208 short nWidth
= aContextBmpWidthVector
[ nDepth
];
209 if( nWidth
!= pView
->nContextBmpWidthMax
) {
210 pView
->nContextBmpWidthMax
= nWidth
;
211 nFlags
|= F_IGNORE_CHANGED_TABS
;
213 nFlags
&= ~F_IGNORE_CHANGED_TABS
;
217 void SvImpLBox::CalcCellFocusRect( SvTreeListEntry
* pEntry
, Rectangle
& rRect
)
219 if ( pEntry
&& bIsCellFocusEnabled
)
221 if ( nCurTabPos
> FIRST_ENTRY_TAB
)
223 SvLBoxItem
* pItem
= pCursor
->GetItem( nCurTabPos
);
224 rRect
.Left() = pView
->GetTab( pCursor
, pItem
)->GetPos();
226 if (pCursor
->ItemCount() > static_cast<size_t>(nCurTabPos
+1))
228 SvLBoxItem
* pNextItem
= pCursor
->GetItem( nCurTabPos
+ 1 );
229 long nRight
= pView
->GetTab( pCursor
, pNextItem
)->GetPos() - 1;
230 if ( nRight
< rRect
.Right() )
231 rRect
.Right() = nRight
;
236 void SvImpLBox::SetStyle( WinBits i_nWinStyle
)
238 m_nStyle
= i_nWinStyle
;
239 if ( ( m_nStyle
& WB_SIMPLEMODE
) && ( aSelEng
.GetSelectionMode() == MULTIPLE_SELECTION
) )
240 aSelEng
.AddAlways( true );
243 void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits
)
245 nExtendedWinBits
= _nBits
;
248 // don't touch the model any more
249 void SvImpLBox::Clear()
262 // don't touch the cursor any more
265 if( pView
->HasFocus() )
270 aVerSBar
.SetThumbPos( 0 );
271 Range
aRange( 0, 0 );
272 aVerSBar
.SetRange( aRange
);
273 aOutputSize
= pView
->Control::GetOutputSizePixel();
274 nFlags
&= ~(F_VER_SBARSIZE_WITH_HBAR
| F_HOR_SBARSIZE_WITH_VBAR
);
276 aHorSBar
.SetThumbPos( 0 );
277 MapMode
aMapMode( pView
->GetMapMode());
278 aMapMode
.SetOrigin( Point(0,0) );
279 pView
->Control::SetMapMode( aMapMode
);
280 aHorSBar
.SetRange( aRange
);
281 aHorSBar
.SetSizePixel(Size(aOutputSize
.Width(),nHorSBarHeight
));
282 pView
->SetClipRegion();
283 if( GetUpdateMode() )
284 pView
->Invalidate( GetVisibleArea() );
286 if( !aHorSBar
.IsVisible() && !aVerSBar
.IsVisible() )
289 aContextBmpWidthVector
.clear();
292 // *********************************************************************
293 // Paint, navigate, scroll
294 // *********************************************************************
296 IMPL_LINK_NOARG_INLINE_START(SvImpLBox
, EndScrollHdl
)
298 if( nFlags
& F_ENDSCROLL_SET_VIS_SIZE
)
300 aVerSBar
.SetVisibleSize( nNextVerVisSize
);
301 nFlags
&= ~F_ENDSCROLL_SET_VIS_SIZE
;
306 IMPL_LINK_NOARG_INLINE_END(SvImpLBox
, EndScrollHdl
)
309 // handler for vertical scrollbar
311 IMPL_LINK( SvImpLBox
, ScrollUpDownHdl
, ScrollBar
*, pScrollBar
)
313 DBG_ASSERT(!bInVScrollHdl
,"Scroll handler out-paces itself!");
314 long nDelta
= pScrollBar
->GetDelta();
318 nFlags
&= (~F_FILLING
);
320 bInVScrollHdl
= true;
322 if( pView
->IsEditingActive() )
324 pView
->EndEditing( true ); // Cancel
334 PageDown( (sal_uInt16
) nDelta
);
342 PageUp( (sal_uInt16
) nDelta
);
344 bInVScrollHdl
= false;
349 void SvImpLBox::CursorDown()
354 SvTreeListEntry
* pNextFirstToDraw
= pView
->NextVisible(pStartEntry
);
355 if( pNextFirstToDraw
)
357 nFlags
&= (~F_FILLING
);
358 pView
->NotifyScrolling( -1 );
361 pStartEntry
= pNextFirstToDraw
;
362 Rectangle
aArea( GetVisibleArea() );
363 pView
->Scroll( 0, -(pView
->GetEntryHeight()), aArea
, SCROLL_NOCHILDREN
);
366 pView
->NotifyScrolled();
370 void SvImpLBox::CursorUp()
375 SvTreeListEntry
* pPrevFirstToDraw
= pView
->PrevVisible(pStartEntry
);
376 if( pPrevFirstToDraw
)
378 nFlags
&= (~F_FILLING
);
379 long nEntryHeight
= pView
->GetEntryHeight();
380 pView
->NotifyScrolling( 1 );
383 pStartEntry
= pPrevFirstToDraw
;
384 Rectangle
aArea( GetVisibleArea() );
385 aArea
.Bottom() -= nEntryHeight
;
386 pView
->Scroll( 0, nEntryHeight
, aArea
, SCROLL_NOCHILDREN
);
389 pView
->NotifyScrolled();
393 void SvImpLBox::PageDown( sal_uInt16 nDelta
)
395 sal_uInt16 nRealDelta
= nDelta
;
403 SvTreeListEntry
* pNext
= pView
->NextVisible(pStartEntry
, nRealDelta
);
404 if( (sal_uLong
)pNext
== (sal_uLong
)pStartEntry
)
409 nFlags
&= (~F_FILLING
);
413 if( nRealDelta
>= nVisibleCount
)
415 pView
->Invalidate( GetVisibleArea() );
420 long nScroll
= nRealDelta
* (-1);
421 pView
->NotifyScrolling( nScroll
);
422 Rectangle
aArea( GetVisibleArea() );
423 nScroll
= pView
->GetEntryHeight()*nRealDelta
;
426 pView
->Scroll( 0, nScroll
, aArea
, SCROLL_NOCHILDREN
);
428 pView
->NotifyScrolled();
434 void SvImpLBox::PageUp( sal_uInt16 nDelta
)
436 sal_uInt16 nRealDelta
= nDelta
;
443 SvTreeListEntry
* pPrev
= pView
->PrevVisible(pStartEntry
, nRealDelta
);
444 if( (sal_uLong
)pPrev
== (sal_uLong
)pStartEntry
)
447 nFlags
&= (~F_FILLING
);
452 if( nRealDelta
>= nVisibleCount
)
454 pView
->Invalidate( GetVisibleArea() );
459 long nEntryHeight
= pView
->GetEntryHeight();
460 pView
->NotifyScrolling( (long)nRealDelta
);
461 Rectangle
aArea( GetVisibleArea() );
463 pView
->Scroll( 0, nEntryHeight
*nRealDelta
, aArea
, SCROLL_NOCHILDREN
);
465 pView
->NotifyScrolled();
471 void SvImpLBox::KeyUp( bool bPageUp
, bool bNotifyScroll
)
473 if( !aVerSBar
.IsVisible() )
478 nDelta
= aVerSBar
.GetPageSize();
482 long nThumbPos
= aVerSBar
.GetThumbPos();
484 if( nThumbPos
< nDelta
)
490 nFlags
&= (~F_FILLING
);
494 aVerSBar
.SetThumbPos( nThumbPos
- nDelta
);
496 PageUp( (short)nDelta
);
505 void SvImpLBox::KeyDown( bool bPageDown
, bool bNotifyScroll
)
507 if( !aVerSBar
.IsVisible() )
512 nDelta
= aVerSBar
.GetPageSize();
516 long nThumbPos
= aVerSBar
.GetThumbPos();
517 long nVisibleSize
= aVerSBar
.GetVisibleSize();
518 long nRange
= aVerSBar
.GetRange().Len();
520 long nTmp
= nThumbPos
+nVisibleSize
;
521 while( (nDelta
> 0) && (nTmp
+nDelta
) >= nRange
)
527 nFlags
&= (~F_FILLING
);
531 aVerSBar
.SetThumbPos( nThumbPos
+nDelta
);
533 PageDown( (short)nDelta
);
543 void SvImpLBox::InvalidateEntriesFrom( long nY
) const
545 if( !(nFlags
& F_IN_PAINT
))
547 Rectangle
aRect( GetVisibleArea() );
549 pView
->Invalidate( aRect
);
553 void SvImpLBox::InvalidateEntry( long nY
) const
555 if( !(nFlags
& F_IN_PAINT
))
557 Rectangle
aRect( GetVisibleArea() );
558 long nMaxBottom
= aRect
.Bottom();
560 aRect
.Bottom() = nY
; aRect
.Bottom() += pView
->GetEntryHeight();
561 if( aRect
.Top() > nMaxBottom
)
563 if( aRect
.Bottom() > nMaxBottom
)
564 aRect
.Bottom() = nMaxBottom
;
565 pView
->Invalidate( aRect
);
569 void SvImpLBox::InvalidateEntry( SvTreeListEntry
* pEntry
)
571 if( GetUpdateMode() )
573 long nPrev
= nMostRight
;
574 SetMostRight( pEntry
);
575 if( nPrev
< nMostRight
)
578 if( !(nFlags
& F_IN_PAINT
))
580 bool bHasFocusRect
= false;
581 if( pEntry
==pCursor
&& pView
->HasFocus() )
583 bHasFocusRect
= true;
586 InvalidateEntry( GetEntryLine( pEntry
) );
593 void SvImpLBox::RecalcFocusRect()
595 if( pView
->HasFocus() && pCursor
)
598 long nY
= GetEntryLine( pCursor
);
599 Rectangle aRect
= pView
->GetFocusRect( pCursor
, nY
);
600 CalcCellFocusRect( pCursor
, aRect
);
601 Region
aOldClip( pView
->GetClipRegion());
602 Region
aClipRegion( GetClipRegionRect() );
603 pView
->SetClipRegion( aClipRegion
);
604 pView
->ShowFocus( aRect
);
605 pView
->SetClipRegion( aOldClip
);
610 // Sets cursor. When using SingleSelection, the selection is adjusted.
613 void SvImpLBox::SetCursor( SvTreeListEntry
* pEntry
, bool bForceNoSelect
)
615 SvViewDataEntry
* pViewDataNewCur
= 0;
617 pViewDataNewCur
= pView
->GetViewDataEntry(pEntry
);
620 pViewDataNewCur
->HasFocus() &&
621 pViewDataNewCur
->IsSelected())
626 // if this cursor is not selectable, find first visible that is and use it
627 while( pEntry
&& pViewDataNewCur
&& !pViewDataNewCur
->IsSelectable() )
629 pEntry
= pView
->NextVisible(pEntry
);
630 pViewDataNewCur
= pEntry
? pView
->GetViewDataEntry(pEntry
) : 0;
633 SvTreeListEntry
* pOldCursor
= pCursor
;
634 if( pCursor
&& pEntry
!= pCursor
)
636 pView
->SetEntryFocus( pCursor
, false );
638 pView
->Select( pCursor
, false );
644 pViewDataNewCur
->SetFocus( true );
645 if(!bForceNoSelect
&& bSimpleTravel
&& !(nFlags
& F_DESEL_ALL
) && GetUpdateMode())
647 pView
->Select( pCursor
, true );
649 // multiple selection: select in cursor move if we're not in
650 // Add mode (Ctrl-F8)
651 else if( GetUpdateMode() &&
652 pView
->GetSelectionMode() == MULTIPLE_SELECTION
&&
653 !(nFlags
& F_DESEL_ALL
) && !aSelEng
.IsAddMode() &&
656 pView
->Select( pCursor
, true );
665 DBG_ASSERT(aSelEng
.GetSelectionMode() != SINGLE_SELECTION
,"Mode?");
666 SetAnchorSelection( pOldCursor
, pCursor
);
669 nFlags
&= (~F_DESEL_ALL
);
671 pView
->OnCurrentEntryChanged();
674 void SvImpLBox::ShowCursor( bool bShow
)
676 if( !bShow
|| !pCursor
|| !pView
->HasFocus() )
678 Region
aOldClip( pView
->GetClipRegion());
679 Region
aClipRegion( GetClipRegionRect() );
680 pView
->SetClipRegion( aClipRegion
);
682 pView
->SetClipRegion( aOldClip
);
686 long nY
= GetEntryLine( pCursor
);
687 Rectangle aRect
= pView
->GetFocusRect( pCursor
, nY
);
688 CalcCellFocusRect( pCursor
, aRect
);
689 Region
aOldClip( pView
->GetClipRegion());
690 Region
aClipRegion( GetClipRegionRect() );
691 pView
->SetClipRegion( aClipRegion
);
692 pView
->ShowFocus( aRect
);
693 pView
->SetClipRegion( aOldClip
);
699 void SvImpLBox::UpdateAll(
700 bool bInvalidateCompleteView
, bool bUpdateVerScrollBar
)
702 if( bUpdateVerScrollBar
)
704 aVerSBar
.SetRange( Range(0, pView
->GetVisibleCount()-1 ) );
708 if( bSimpleTravel
&& pCursor
&& pView
->HasFocus() )
709 pView
->Select( pCursor
, true );
711 if( bInvalidateCompleteView
)
714 pView
->Invalidate( GetVisibleArea() );
717 IMPL_LINK_INLINE_START( SvImpLBox
, ScrollLeftRightHdl
, ScrollBar
*, pScrollBar
)
719 long nDelta
= pScrollBar
->GetDelta();
722 if( pView
->IsEditingActive() )
724 pView
->EndEditing( true ); // Cancel
727 pView
->nFocusWidth
= -1;
728 KeyLeftRight( nDelta
);
732 IMPL_LINK_INLINE_END( SvImpLBox
, ScrollLeftRightHdl
, ScrollBar
*, pScrollBar
)
734 void SvImpLBox::KeyLeftRight( long nDelta
)
736 if( !(nFlags
& F_IN_RESIZE
) )
739 nFlags
&= (~F_FILLING
);
740 pView
->NotifyScrolling( 0 ); // 0 == horizontal scrolling
743 // neuen Origin berechnen
744 long nPos
= aHorSBar
.GetThumbPos();
745 Point
aOrigin( -nPos
, 0 );
747 MapMode
aMapMode( pView
->GetMapMode() );
748 aMapMode
.SetOrigin( aOrigin
);
749 pView
->SetMapMode( aMapMode
);
751 if( !(nFlags
& F_IN_RESIZE
) )
753 Rectangle
aRect( GetVisibleArea() );
754 pView
->Scroll( -nDelta
, 0, aRect
, SCROLL_NOCHILDREN
);
760 pView
->NotifyScrolled();
764 // returns the last entry if position is just past the last entry
765 SvTreeListEntry
* SvImpLBox::GetClickedEntry( const Point
& rPoint
) const
767 DBG_ASSERT( pView
->GetModel(), "SvImpLBox::GetClickedEntry: how can this ever happen? Please tell me (frank.schoenheit@sun.com) how to reproduce!" );
768 if ( !pView
->GetModel() )
769 // this is quite impossible. Nevertheless, stack traces from the crash reporter
770 // suggest it isn't. Okay, make it safe, and wait for somebody to reproduce it
772 // #122359# / 2005-05-23 / frank.schoenheit@sun.com
774 if( pView
->GetEntryCount() == 0 || !pStartEntry
|| !pView
->GetEntryHeight())
777 sal_uInt16 nClickedEntry
= (sal_uInt16
)(rPoint
.Y() / pView
->GetEntryHeight() );
778 sal_uInt16 nTemp
= nClickedEntry
;
779 SvTreeListEntry
* pEntry
= pView
->NextVisible(pStartEntry
, nTemp
);
784 // checks if the entry was hit "the right way"
785 // (Focusrect+ ContextBitmap bei TreeListBox)
787 bool SvImpLBox::EntryReallyHit(SvTreeListEntry
* pEntry
, const Point
& rPosPixel
, long nLine
)
790 // we are not too exact when it comes to "special" entries
791 // (with CheckButtons etc.)
792 if( pEntry
->ItemCount() >= 3 )
795 Rectangle
aRect( pView
->GetFocusRect( pEntry
, nLine
));
796 aRect
.Right() = GetOutputSize().Width() - pView
->GetMapMode().GetOrigin().X();
798 SvLBoxContextBmp
* pBmp
= (SvLBoxContextBmp
*)(pEntry
->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP
));
799 aRect
.Left() -= pBmp
->GetSize(pView
,pEntry
).Width();
800 aRect
.Left() -= 4; // a little tolerance
802 Point
aPos( rPosPixel
);
803 aPos
-= pView
->GetMapMode().GetOrigin();
804 if( aRect
.IsInside( aPos
) )
812 // returns 0 if position is just past the last entry
813 SvTreeListEntry
* SvImpLBox::GetEntry( const Point
& rPoint
) const
815 if( (pView
->GetEntryCount() == 0) || !pStartEntry
||
816 (rPoint
.Y() > aOutputSize
.Height())
817 || !pView
->GetEntryHeight())
820 sal_uInt16 nClickedEntry
= (sal_uInt16
)(rPoint
.Y() / pView
->GetEntryHeight() );
821 sal_uInt16 nTemp
= nClickedEntry
;
822 SvTreeListEntry
* pEntry
= pView
->NextVisible(pStartEntry
, nTemp
);
823 if( nTemp
!= nClickedEntry
)
829 SvTreeListEntry
* SvImpLBox::MakePointVisible(const Point
& rPoint
, bool bNotifyScroll
)
833 long nY
= rPoint
.Y();
834 SvTreeListEntry
* pEntry
= 0;
835 long nMax
= aOutputSize
.Height();
836 if( nY
< 0 || nY
>= nMax
) // aOutputSize.Height() )
839 pEntry
= pView
->PrevVisible(pCursor
);
841 pEntry
= pView
->NextVisible(pCursor
);
843 if( pEntry
&& pEntry
!= pCursor
)
844 pView
->SetEntryFocus( pCursor
, false );
847 KeyUp( false, bNotifyScroll
);
849 KeyDown( false, bNotifyScroll
);
853 pEntry
= GetClickedEntry( rPoint
);
856 sal_uInt16 nSteps
= 0xFFFF;
857 // TODO: LastVisible is not yet implemented!
858 pEntry
= pView
->NextVisible(pStartEntry
, nSteps
);
862 if( pEntry
!= pCursor
&&
863 aSelEng
.GetSelectionMode() == SINGLE_SELECTION
865 pView
->Select( pCursor
, false );
871 Rectangle
SvImpLBox::GetClipRegionRect() const
873 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
874 aOrigin
.X() *= -1; // conversion document coordinates
875 Rectangle
aClipRect( aOrigin
, aOutputSize
);
876 aClipRect
.Bottom()++;
881 void SvImpLBox::Paint( const Rectangle
& rRect
)
883 if( !pView
->GetVisibleCount() )
886 nFlags
|= F_IN_PAINT
;
888 if( nFlags
& F_FILLING
)
890 SvTreeListEntry
* pFirst
= pView
->First();
891 if( pFirst
!= pStartEntry
)
894 pStartEntry
= pView
->First();
895 aVerSBar
.SetThumbPos( 0 );
898 nCurUserEvent
= Application::PostUserEvent(LINK(this,SvImpLBox
,MyUserEvent
),(void*)1);
905 pStartEntry
= pView
->First();
908 if( nNodeBmpTabDistance
== NODE_BMP_TABDIST_NOTVALID
)
909 SetNodeBmpTabDistance();
911 long nRectHeight
= rRect
.GetHeight();
912 long nEntryHeight
= pView
->GetEntryHeight();
914 // calculate area for the entries we want to draw
915 sal_uInt16 nStartLine
= (sal_uInt16
)( rRect
.Top() / nEntryHeight
);
916 sal_uInt16 nCount
= (sal_uInt16
)( nRectHeight
/ nEntryHeight
);
917 nCount
+= 2; // don't miss a row
919 long nY
= nStartLine
* nEntryHeight
;
920 SvTreeListEntry
* pEntry
= pStartEntry
;
921 while( nStartLine
&& pEntry
)
923 pEntry
= pView
->NextVisible(pEntry
);
927 Region
aClipRegion( GetClipRegionRect() );
929 // first draw the lines, then clip them!
930 pView
->SetClipRegion();
931 if( m_nStyle
& ( WB_HASLINES
| WB_HASLINESATROOT
) )
934 pView
->SetClipRegion( aClipRegion
);
936 for( sal_uInt16 n
=0; n
< nCount
&& pEntry
; n
++ )
939 pView
->PaintEntry1( pEntry
, nY
, 0xffff, true );
941 pEntry
= pView
->NextVisible(pEntry
);
944 if ( !pCursor
&& ( ( nExtendedWinBits
& EWB_NO_AUTO_CURENTRY
) == 0 ) )
946 // do not select if multiselection or explicit set
947 bool bNotSelect
= ( aSelEng
.GetSelectionMode() == MULTIPLE_SELECTION
)
948 || ( ( m_nStyle
& WB_NOINITIALSELECTION
) == WB_NOINITIALSELECTION
);
949 SetCursor( pStartEntry
, bNotSelect
);
952 nFlags
&= (~F_DESEL_ALL
);
953 pView
->SetClipRegion();
954 if( !(nFlags
& F_PAINTED
) )
959 nFlags
&= (~F_IN_PAINT
);
962 void SvImpLBox::MakeVisible( SvTreeListEntry
* pEntry
, bool bMoveToTop
)
967 bool bInView
= IsEntryInView( pEntry
);
969 if( bInView
&& (!bMoveToTop
|| pStartEntry
== pEntry
) )
970 return; // is already visible
972 if( pStartEntry
|| (m_nStyle
& WB_FORCE_MAKEVISIBLE
) )
973 nFlags
&= (~F_FILLING
);
976 if( !pView
->IsEntryVisible(pEntry
) ) // Parent(s) collapsed?
978 SvTreeListEntry
* pParent
= pView
->GetParent( pEntry
);
981 if( !pView
->IsExpanded( pParent
) )
986 pView
->Expand( pParent
);
987 DBG_ASSERT(bRet
,"Not expanded!");
989 pParent
= pView
->GetParent( pParent
);
991 // do the parent's children fit into the view or do we have to scroll?
992 if( IsEntryInView( pEntry
) && !bMoveToTop
)
993 return; // no need to scroll
997 pStartEntry
= pEntry
;
1000 aVerSBar
.SetThumbPos( (long)(pView
->GetVisiblePos( pStartEntry
)) );
1002 pView
->Invalidate();
1005 void SvImpLBox::ScrollToAbsPos( long nPos
)
1007 if( pView
->GetVisibleCount() == 0 )
1009 long nLastEntryPos
= pView
->GetAbsPos( pView
->Last() );
1013 else if( nPos
> nLastEntryPos
)
1014 nPos
= nLastEntryPos
;
1016 SvTreeListEntry
* pEntry
= (SvTreeListEntry
*)pView
->GetEntryAtAbsPos( nPos
);
1017 if( !pEntry
|| pEntry
== pStartEntry
)
1020 if( pStartEntry
|| (m_nStyle
& WB_FORCE_MAKEVISIBLE
) )
1021 nFlags
&= (~F_FILLING
);
1023 if( pView
->IsEntryVisible(pEntry
) )
1025 pStartEntry
= pEntry
;
1026 ShowCursor( false );
1027 aVerSBar
.SetThumbPos( nPos
);
1029 if (GetUpdateMode())
1030 pView
->Invalidate();
1034 void SvImpLBox::DrawNet()
1036 if( pView
->GetVisibleCount() < 2 && !pStartEntry
->HasChildrenOnDemand() &&
1037 !pStartEntry
->HasChildren() )
1040 // for platforms that don't have nets, DrawNativeControl does nothing and returns true
1041 // so that SvImpLBox::DrawNet() doesn't draw anything either
1042 if(pView
->IsNativeControlSupported( CTRL_LISTNET
, PART_ENTIRE_CONTROL
)) {
1043 ImplControlValue aControlValue
;
1044 Point
aTemp(0,0); // temporary needed for g++ 3.3.5
1045 Rectangle
aCtrlRegion( aTemp
, Size( 0, 0 ) );
1046 ControlState nState
= CTRL_STATE_ENABLED
;
1047 if( pView
->DrawNativeControl( CTRL_LISTNET
, PART_ENTIRE_CONTROL
,
1048 aCtrlRegion
, nState
, aControlValue
, OUString() ) )
1055 long nEntryHeight
= pView
->GetEntryHeight();
1056 long nEntryHeightDIV2
= nEntryHeight
/ 2;
1057 if( nEntryHeightDIV2
&& !(nEntryHeight
& 0x0001))
1060 SvTreeListEntry
* pChild
;
1061 SvTreeListEntry
* pEntry
= pStartEntry
;
1063 SvLBoxTab
* pFirstDynamicTab
= pView
->GetFirstDynamicTab();
1064 while( pTree
->GetDepth( pEntry
) > 0 )
1065 pEntry
= pView
->GetParent( pEntry
);
1066 sal_uInt16 nOffs
= (sal_uInt16
)(pView
->GetVisiblePos( pStartEntry
) -
1067 pView
->GetVisiblePos( pEntry
));
1069 nY
-= ( nOffs
* nEntryHeight
);
1071 DBG_ASSERT(pFirstDynamicTab
,"No Tree!");
1073 Color aOldLineColor
= pView
->GetLineColor();
1074 const StyleSettings
& rStyleSettings
= pView
->GetSettings().GetStyleSettings();
1075 Color aCol
= rStyleSettings
.GetFaceColor();
1077 if( aCol
.IsRGBEqual( pView
->GetBackground().GetColor()) )
1078 aCol
= rStyleSettings
.GetShadowColor();
1079 pView
->SetLineColor( aCol
);
1081 sal_uInt16 nDistance
;
1082 sal_uLong nMax
= nVisibleCount
+ nOffs
+ 1;
1084 const Image
& rExpandedNodeBitmap
= GetExpandedNodeBmp();
1086 for( sal_uLong n
=0; n
< nMax
&& pEntry
; n
++ )
1088 if( pView
->IsExpanded(pEntry
) )
1090 aPos1
.X() = pView
->GetTabPos(pEntry
, pFirstDynamicTab
);
1091 // if it is not a context bitmap, go a little to the right below the
1092 // first text (node bitmap, too)
1093 if( !pView
->nContextBmpWidthMax
)
1094 aPos1
.X() += rExpandedNodeBitmap
.GetSizePixel().Width() / 2;
1097 aPos1
.Y() += nEntryHeightDIV2
;
1099 pChild
= pView
->FirstChild( pEntry
);
1100 DBG_ASSERT(pChild
,"Child?");
1101 pChild
= pTree
->LastSibling( pChild
);
1102 nDistance
= (sal_uInt16
)(pView
->GetVisiblePos(pChild
) -
1103 pView
->GetVisiblePos(pEntry
));
1105 aPos2
.Y() += nDistance
* nEntryHeight
;
1106 pView
->DrawLine( aPos1
, aPos2
);
1108 // visible in control?
1109 if( n
>= nOffs
&& ((m_nStyle
& WB_HASLINESATROOT
) || !pTree
->IsAtRootDepth(pEntry
)))
1111 // can we recycle aPos1?
1112 if( !pView
->IsExpanded(pEntry
) )
1115 aPos1
.X() = pView
->GetTabPos(pEntry
, pFirstDynamicTab
);
1116 // if it is not a context bitmap, go a little to the right below
1117 // the first text (node bitmap, too)
1118 if( !pView
->nContextBmpWidthMax
)
1119 aPos1
.X() += rExpandedNodeBitmap
.GetSizePixel().Width() / 2;
1121 aPos1
.Y() += nEntryHeightDIV2
;
1122 aPos2
.X() = aPos1
.X();
1124 aPos2
.Y() = aPos1
.Y();
1125 aPos2
.X() -= pView
->GetIndent();
1126 pView
->DrawLine( aPos1
, aPos2
);
1129 pEntry
= pView
->NextVisible(pEntry
);
1131 if( m_nStyle
& WB_HASLINESATROOT
)
1133 pEntry
= pView
->First();
1134 aPos1
.X() = pView
->GetTabPos( pEntry
, pFirstDynamicTab
);
1135 // if it is not a context bitmap, go a little to the right below the
1136 // first text (node bitmap, too)
1137 if( !pView
->nContextBmpWidthMax
)
1138 aPos1
.X() += rExpandedNodeBitmap
.GetSizePixel().Width() / 2;
1139 aPos1
.X() -= pView
->GetIndent();
1140 aPos1
.Y() = GetEntryLine( pEntry
);
1141 aPos1
.Y() += nEntryHeightDIV2
;
1142 pChild
= pTree
->LastSibling( pEntry
);
1143 aPos2
.X() = aPos1
.X();
1144 aPos2
.Y() = GetEntryLine( pChild
);
1145 aPos2
.Y() += nEntryHeightDIV2
;
1146 pView
->DrawLine( aPos1
, aPos2
);
1148 pView
->SetLineColor( aOldLineColor
);
1151 void SvImpLBox::PositionScrollBars( Size
& rSize
, sal_uInt16 nMask
)
1155 Size
aVerSize( nVerSBarWidth
, rSize
.Height() );
1156 Size
aHorSize( rSize
.Width(), nHorSBarHeight
);
1158 if( nMask
& 0x0001 )
1159 aHorSize
.Width() -= nVerSBarWidth
;
1160 if( nMask
& 0x0002 )
1161 aVerSize
.Height() -= nHorSBarHeight
;
1163 aVerSize
.Height() += 2 * nOverlap
;
1164 Point
aVerPos( rSize
.Width() - aVerSize
.Width() + nOverlap
, -nOverlap
);
1165 aVerSBar
.SetPosSizePixel( aVerPos
, aVerSize
);
1167 aHorSize
.Width() += 2 * nOverlap
;
1168 Point
aHorPos( -nOverlap
, rSize
.Height() - aHorSize
.Height() + nOverlap
);
1170 aHorSBar
.SetPosSizePixel( aHorPos
, aHorSize
);
1172 if( nMask
& 0x0001 )
1173 rSize
.Width() = aVerPos
.X();
1174 if( nMask
& 0x0002 )
1175 rSize
.Height() = aHorPos
.Y();
1177 if( (nMask
& (0x0001|0x0002)) == (0x0001|0x0002) )
1183 // nResult: Bit0 == VerSBar Bit1 == HorSBar
1184 sal_uInt16
SvImpLBox::AdjustScrollBars( Size
& rSize
)
1186 long nEntryHeight
= pView
->GetEntryHeight();
1190 sal_uInt16 nResult
= 0;
1192 Size
aOSize( pView
->Control::GetOutputSizePixel() );
1194 const WinBits nWindowStyle
= pView
->GetStyle();
1195 bool bVerSBar
= ( nWindowStyle
& WB_VSCROLL
) != 0;
1196 bool bHorBar
= false;
1197 long nMaxRight
= aOSize
.Width(); //GetOutputSize().Width();
1198 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
1200 nMaxRight
+= aOrigin
.X() - 1;
1201 long nVis
= nMostRight
- aOrigin
.X();
1202 if( (nWindowStyle
& WB_HSCROLL
) &&
1203 (nVis
< nMostRight
|| nMaxRight
< nMostRight
) )
1208 // number of entries that are not collapsed
1209 sal_uLong nTotalCount
= pView
->GetVisibleCount();
1211 // number of entries visible within the view
1212 nVisibleCount
= aOSize
.Height() / nEntryHeight
;
1214 // do we need a vertical scrollbar?
1215 if( bVerSBar
|| nTotalCount
> nVisibleCount
)
1218 nFlags
|= F_HOR_SBARSIZE_WITH_VBAR
;
1219 nMaxRight
-= nVerSBarWidth
;
1222 if( (nWindowStyle
& WB_HSCROLL
) &&
1223 (nVis
< nMostRight
|| nMaxRight
< nMostRight
) )
1228 // do we need a horizontal scrollbar?
1232 // the number of entries visible within the view has to be recalculated
1233 // because the horizontal scrollbar is now visible.
1234 nVisibleCount
= (aOSize
.Height() - nHorSBarHeight
) / nEntryHeight
;
1235 // we might actually need a vertical scrollbar now
1236 if( !(nResult
& 0x0001) &&
1237 ((nTotalCount
> nVisibleCount
) || bVerSBar
) )
1240 nFlags
|= F_VER_SBARSIZE_WITH_HBAR
;
1244 PositionScrollBars( aOSize
, nResult
);
1246 // adapt Range, VisibleRange etc.
1248 // refresh output size, in case we have to scroll
1250 aRect
.SetSize( aOSize
);
1251 aSelEng
.SetVisibleArea( aRect
);
1253 // vertical scrollbar
1254 long nTemp
= (long)nVisibleCount
;
1256 if( nTemp
!= aVerSBar
.GetVisibleSize() )
1258 if( !bInVScrollHdl
)
1260 aVerSBar
.SetPageSize( nTemp
- 1 );
1261 aVerSBar
.SetVisibleSize( nTemp
);
1265 nFlags
|= F_ENDSCROLL_SET_VIS_SIZE
;
1266 nNextVerVisSize
= nTemp
;
1270 // horizontal scrollbar
1271 nTemp
= aHorSBar
.GetThumbPos();
1272 aHorSBar
.SetVisibleSize( aOSize
.Width() );
1273 long nNewThumbPos
= aHorSBar
.GetThumbPos();
1274 Range
aRange( aHorSBar
.GetRange() );
1275 if( aRange
.Max() < nMostRight
+25 )
1277 aRange
.Max() = nMostRight
+25;
1278 aHorSBar
.SetRange( aRange
);
1281 if( nTemp
!= nNewThumbPos
)
1283 nTemp
= nNewThumbPos
- nTemp
;
1284 if( pView
->IsEditingActive() )
1286 pView
->EndEditing( true ); // Cancel
1289 pView
->nFocusWidth
= -1;
1290 KeyLeftRight( nTemp
);
1293 if( nResult
& 0x0001 )
1298 if( nResult
& 0x0002 )
1308 void SvImpLBox::InitScrollBarBox()
1310 aScrBarBox
.SetSizePixel( Size(nVerSBarWidth
, nHorSBarHeight
) );
1311 Size
aSize( pView
->Control::GetOutputSizePixel() );
1312 aScrBarBox
.SetPosPixel( Point(aSize
.Width()-nVerSBarWidth
, aSize
.Height()-nHorSBarHeight
));
1315 void SvImpLBox::Resize()
1317 aOutputSize
= pView
->Control::GetOutputSizePixel();
1318 if( aOutputSize
.Width() <= 0 || aOutputSize
.Height() <= 0 )
1320 nFlags
|= F_IN_RESIZE
;
1323 if( pView
->GetEntryHeight())
1325 AdjustScrollBars( aOutputSize
);
1328 // HACK, as in floating and docked windows the scrollbars might not be drawn
1329 // correctly/not be drawn at all after resizing!
1330 if( aHorSBar
.IsVisible())
1331 aHorSBar
.Invalidate();
1332 if( aVerSBar
.IsVisible())
1333 aVerSBar
.Invalidate();
1334 nFlags
&= (~(F_IN_RESIZE
| F_PAINTED
));
1337 void SvImpLBox::FillView()
1341 sal_uInt16 nVisibleViewCount
= (sal_uInt16
)(pView
->GetVisibleCount());
1342 sal_uInt16 nTempThumb
= (sal_uInt16
)aVerSBar
.GetThumbPos();
1343 if( nTempThumb
>= nVisibleViewCount
)
1344 nTempThumb
= nVisibleViewCount
- 1;
1345 pStartEntry
= pView
->GetEntryAtVisPos(nTempThumb
);
1349 sal_uInt16 nLast
= (sal_uInt16
)(pView
->GetVisiblePos(pView
->LastVisible()));
1350 sal_uInt16 nThumb
= (sal_uInt16
)(pView
->GetVisiblePos( pStartEntry
));
1351 sal_uInt16 nCurDispEntries
= nLast
-nThumb
+1;
1352 if( nCurDispEntries
< nVisibleCount
)
1354 ShowCursor( false );
1355 // fill window by moving the thumb up incrementally
1356 bool bFound
= false;
1357 SvTreeListEntry
* pTemp
= pStartEntry
;
1358 while( nCurDispEntries
< nVisibleCount
&& pTemp
)
1360 pTemp
= pView
->PrevVisible(pStartEntry
);
1364 pStartEntry
= pTemp
;
1371 aVerSBar
.SetThumbPos( nThumb
);
1372 ShowCursor( true ); // recalculate focus rectangle
1373 pView
->Invalidate();
1382 void SvImpLBox::ShowVerSBar()
1384 bool bVerBar
= ( pView
->GetStyle() & WB_VSCROLL
) != 0;
1387 nVis
= pView
->GetVisibleCount();
1388 if( bVerBar
|| (nVisibleCount
&& nVis
> (sal_uLong
)(nVisibleCount
-1)) )
1390 if( !aVerSBar
.IsVisible() )
1392 pView
->nFocusWidth
= -1;
1393 AdjustScrollBars( aOutputSize
);
1394 if( GetUpdateMode() )
1400 if( aVerSBar
.IsVisible() )
1402 pView
->nFocusWidth
= -1;
1403 AdjustScrollBars( aOutputSize
);
1407 long nMaxRight
= GetOutputSize().Width();
1408 Point
aPos( pView
->GetMapMode().GetOrigin() );
1409 aPos
.X() *= -1; // convert document coordinates
1410 nMaxRight
= nMaxRight
+ aPos
.X() - 1;
1411 if( nMaxRight
< nMostRight
)
1413 if( !aHorSBar
.IsVisible() )
1415 pView
->nFocusWidth
= -1;
1416 AdjustScrollBars( aOutputSize
);
1417 if( GetUpdateMode() )
1422 Range
aRange( aHorSBar
.GetRange() );
1423 if( aRange
.Max() < nMostRight
+25 )
1425 aRange
.Max() = nMostRight
+25;
1426 aHorSBar
.SetRange( aRange
);
1430 pView
->nFocusWidth
= -1;
1431 AdjustScrollBars( aOutputSize
);
1437 if( aHorSBar
.IsVisible() )
1439 pView
->nFocusWidth
= -1;
1440 AdjustScrollBars( aOutputSize
);
1446 void SvImpLBox::SyncVerThumb()
1450 long nEntryPos
= pView
->GetVisiblePos( pStartEntry
);
1451 aVerSBar
.SetThumbPos( nEntryPos
);
1454 aVerSBar
.SetThumbPos( 0 );
1457 bool SvImpLBox::IsEntryInView( SvTreeListEntry
* pEntry
) const
1460 if( !pView
->IsEntryVisible(pEntry
) )
1462 long nY
= GetEntryLine( pEntry
);
1465 long nMax
= nVisibleCount
* pView
->GetEntryHeight();
1472 long SvImpLBox::GetEntryLine( SvTreeListEntry
* pEntry
) const
1475 return -1; // invisible position
1477 long nFirstVisPos
= pView
->GetVisiblePos( pStartEntry
);
1478 long nEntryVisPos
= pView
->GetVisiblePos( pEntry
);
1479 nFirstVisPos
= nEntryVisPos
- nFirstVisPos
;
1480 nFirstVisPos
*= pView
->GetEntryHeight();
1481 return nFirstVisPos
;
1484 void SvImpLBox::SetEntryHeight( short /* nHeight */ )
1486 SetNodeBmpYOffset( GetExpandedNodeBmp() );
1487 SetNodeBmpYOffset( GetCollapsedNodeBmp() );
1488 if(!pView
->HasViewData()) // are we within the Clear?
1490 Size aSize
= pView
->Control::GetOutputSizePixel();
1491 AdjustScrollBars( aSize
);
1496 if( GetUpdateMode() )
1497 pView
->Invalidate();
1503 // ***********************************************************************
1504 // Callback Functions
1505 // ***********************************************************************
1507 void SvImpLBox::EntryExpanded( SvTreeListEntry
* pEntry
)
1509 // SelAllDestrAnch( false, true ); //DeselectAll();
1510 if( GetUpdateMode() )
1512 ShowCursor( false );
1513 long nY
= GetEntryLine( pEntry
);
1514 if( IsLineVisible(nY
) )
1516 InvalidateEntriesFrom( nY
);
1517 FindMostRight( pEntry
, 0 );
1519 aVerSBar
.SetRange( Range(0, pView
->GetVisibleCount()-1 ) );
1520 // if we expanded before the thumb, the thumb's position has to be
1528 void SvImpLBox::EntryCollapsed( SvTreeListEntry
* pEntry
)
1530 if( !pView
->IsEntryVisible( pEntry
) )
1533 ShowCursor( false );
1535 if( !pMostRightEntry
|| pTree
->IsChild( pEntry
,pMostRightEntry
) )
1542 long nOldThumbPos
= aVerSBar
.GetThumbPos();
1543 sal_uLong nVisList
= pView
->GetVisibleCount();
1544 aVerSBar
.SetRange( Range(0, nVisList
-1) );
1545 long nNewThumbPos
= aVerSBar
.GetThumbPos();
1546 if( nNewThumbPos
!= nOldThumbPos
)
1548 pStartEntry
= pView
->First();
1549 sal_uInt16 nDistance
= (sal_uInt16
)nNewThumbPos
;
1551 pStartEntry
= pView
->NextVisible(pStartEntry
, nDistance
);
1552 if( GetUpdateMode() )
1553 pView
->Invalidate();
1559 // has the cursor been collapsed?
1560 if( pTree
->IsChild( pEntry
, pCursor
) )
1561 SetCursor( pEntry
);
1562 if( GetUpdateMode() )
1565 if( GetUpdateMode() && pCursor
)
1566 pView
->Select( pCursor
, true );
1569 void SvImpLBox::CollapsingEntry( SvTreeListEntry
* pEntry
)
1571 if( !pView
->IsEntryVisible( pEntry
) || !pStartEntry
)
1574 SelAllDestrAnch( false, true ); // deselect all
1576 // is the collapsed cursor visible?
1577 long nY
= GetEntryLine( pEntry
);
1578 if( IsLineVisible(nY
) )
1580 if( GetUpdateMode() )
1581 InvalidateEntriesFrom( nY
);
1585 if( pTree
->IsChild(pEntry
, pStartEntry
) )
1587 pStartEntry
= pEntry
;
1588 if( GetUpdateMode() )
1589 pView
->Invalidate();
1595 void SvImpLBox::SetNodeBmpYOffset( const Image
& rBmp
)
1598 nYoffsNodeBmp
= pView
->GetHeightOffset( rBmp
, aSize
);
1599 nNodeBmpWidth
= aSize
.Width();
1602 void SvImpLBox::SetNodeBmpTabDistance()
1604 nNodeBmpTabDistance
= -pView
->GetIndent();
1605 if( pView
->nContextBmpWidthMax
)
1607 // only if the first dynamic tab is centered (we currently assume that)
1608 Size aSize
= GetExpandedNodeBmp().GetSizePixel();
1609 nNodeBmpTabDistance
-= aSize
.Width() / 2;
1614 // corrects the cursor when using SingleSelection
1616 void SvImpLBox::EntrySelected( SvTreeListEntry
* pEntry
, bool bSelect
)
1618 if( nFlags
& F_IGNORE_SELECT
)
1621 nFlags
&= (~F_DESEL_ALL
);
1623 aSelEng
.GetSelectionMode() == SINGLE_SELECTION
&&
1626 SetCursor( pEntry
);
1627 DBG_ASSERT(pView
->GetSelectionCount()==1,"selection count?");
1630 if( GetUpdateMode() && pView
->IsEntryVisible(pEntry
) )
1632 long nY
= GetEntryLine( pEntry
);
1633 if( IsLineVisible( nY
) )
1635 ShowCursor( false );
1636 pView
->PaintEntry1( pEntry
, nY
, 0xffff ); // because of ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1643 void SvImpLBox::RemovingEntry( SvTreeListEntry
* pEntry
)
1647 if( !pView
->IsEntryVisible( pEntry
) )
1649 // if parent is collapsed => bye!
1650 nFlags
|= F_REMOVED_ENTRY_INVISIBLE
;
1654 if( pEntry
== pMostRightEntry
|| (
1655 pEntry
->HasChildren() && pView
->IsExpanded(pEntry
) &&
1656 pTree
->IsChild(pEntry
, pMostRightEntry
)))
1658 nFlags
|= F_REMOVED_RECALC_MOST_RIGHT
;
1661 SvTreeListEntry
* pOldStartEntry
= pStartEntry
;
1663 SvTreeListEntry
* pParent
= pView
->GetModel()->GetParent(pEntry
);
1665 if (pParent
&& pView
->GetModel()->GetChildList(pParent
).size() == 1)
1667 DBG_ASSERT( pView
->IsExpanded( pParent
), "Parent not expanded");
1668 pParent
->SetFlags( pParent
->GetFlags() | SV_ENTRYFLAG_NO_NODEBMP
);
1669 InvalidateEntry( pParent
);
1672 if( pCursor
&& pTree
->IsChild( pEntry
, pCursor
) )
1674 if( pStartEntry
&& pTree
->IsChild(pEntry
,pStartEntry
) )
1675 pStartEntry
= pEntry
;
1677 SvTreeListEntry
* pTemp
;
1678 if( pCursor
&& pCursor
== pEntry
)
1681 pView
->Select( pCursor
, false );
1682 ShowCursor( false ); // focus rectangle gone
1683 // NextSibling, because we also delete the children of the cursor
1684 pTemp
= pView
->NextSibling( pCursor
);
1686 pTemp
= pView
->PrevVisible(pCursor
);
1688 SetCursor( pTemp
, true );
1690 if( pStartEntry
&& pStartEntry
== pEntry
)
1692 pTemp
= pView
->NextSibling( pStartEntry
);
1694 pTemp
= pView
->PrevVisible(pStartEntry
);
1695 pStartEntry
= pTemp
;
1697 if( GetUpdateMode())
1699 // if it is the last one, we have to invalidate it, so the lines are
1700 // drawn correctly (in this case they're deleted)
1701 if( pStartEntry
&& (pStartEntry
!= pOldStartEntry
|| pEntry
== (SvTreeListEntry
*)pView
->GetModel()->Last()) )
1703 aVerSBar
.SetThumbPos( pView
->GetVisiblePos( pStartEntry
));
1704 pView
->Invalidate( GetVisibleArea() );
1707 InvalidateEntriesFrom( GetEntryLine( pEntry
) );
1711 void SvImpLBox::EntryRemoved()
1713 if( nFlags
& F_REMOVED_ENTRY_INVISIBLE
)
1715 nFlags
&= (~F_REMOVED_ENTRY_INVISIBLE
);
1719 pStartEntry
= pTree
->First();
1721 SetCursor( pStartEntry
, true );
1723 if( pCursor
&& (bSimpleTravel
|| !pView
->GetSelectionCount() ))
1724 pView
->Select( pCursor
, true );
1726 if( GetUpdateMode())
1728 if( nFlags
& F_REMOVED_RECALC_MOST_RIGHT
)
1730 aVerSBar
.SetRange( Range(0, pView
->GetVisibleCount()-1 ) );
1733 // if something above the thumb was deleted
1734 aVerSBar
.SetThumbPos( pView
->GetVisiblePos( pStartEntry
) );
1737 if( pCursor
&& pView
->HasFocus() && !pView
->IsSelected(pCursor
) )
1739 if( pView
->GetSelectionCount() )
1741 // is a neighboring entry selected?
1742 SvTreeListEntry
* pNextCursor
= (SvTreeListEntry
*)pView
->PrevVisible( pCursor
);
1743 if( !pNextCursor
|| !pView
->IsSelected( pNextCursor
))
1744 pNextCursor
= (SvTreeListEntry
*)pView
->NextVisible( pCursor
);
1745 if( !pNextCursor
|| !pView
->IsSelected( pNextCursor
))
1746 // no neighbor selected: use first selected
1747 pNextCursor
= pView
->FirstSelected();
1748 SetCursor( pNextCursor
);
1749 MakeVisible( pCursor
);
1752 pView
->Select( pCursor
, true );
1756 nFlags
&= (~F_REMOVED_RECALC_MOST_RIGHT
);
1760 void SvImpLBox::MovingEntry( SvTreeListEntry
* pEntry
)
1762 int bDeselAll
= nFlags
& F_DESEL_ALL
;
1763 SelAllDestrAnch( false, true ); // DeselectAll();
1765 nFlags
&= (~F_DESEL_ALL
);
1767 if( pEntry
== pCursor
)
1768 ShowCursor( false );
1769 if( IsEntryInView( pEntry
) )
1770 pView
->Invalidate();
1771 if( pEntry
== pStartEntry
)
1773 SvTreeListEntry
* pNew
= 0;
1774 if( !pEntry
->HasChildren() )
1776 pNew
= pView
->NextVisible(pStartEntry
);
1778 pNew
= pView
->PrevVisible(pStartEntry
);
1782 pNew
= pTree
->NextSibling( pEntry
);
1784 pNew
= pTree
->PrevSibling( pEntry
);
1790 void SvImpLBox::EntryMoved( SvTreeListEntry
* pEntry
)
1792 UpdateContextBmpWidthVectorFromMovedEntry( pEntry
);
1795 // this might happen if the only entry in the view is moved to its very same position
1797 pStartEntry
= pView
->First();
1799 aVerSBar
.SetRange( Range(0, pView
->GetVisibleCount()-1));
1800 sal_uInt16 nFirstPos
= (sal_uInt16
)pTree
->GetAbsPos( pStartEntry
);
1801 sal_uInt16 nNewPos
= (sal_uInt16
)pTree
->GetAbsPos( pEntry
);
1803 if( nNewPos
< nFirstPos
) // HACK!
1804 pStartEntry
= pEntry
;
1806 if( pEntry
== pCursor
)
1808 if( pView
->IsEntryVisible( pCursor
) )
1812 SvTreeListEntry
* pParent
= pEntry
;
1814 pParent
= pTree
->GetParent( pParent
);
1816 while( !pView
->IsEntryVisible( pParent
) );
1817 SetCursor( pParent
);
1820 if( IsEntryInView( pEntry
) )
1821 pView
->Invalidate();
1826 void SvImpLBox::EntryInserted( SvTreeListEntry
* pEntry
)
1828 if( GetUpdateMode() )
1830 SvTreeListEntry
* pParent
= (SvTreeListEntry
*)pTree
->GetParent(pEntry
);
1831 if (pParent
&& pTree
->GetChildList(pParent
).size() == 1)
1833 pTree
->InvalidateEntry( pParent
);
1835 if( !pView
->IsEntryVisible( pEntry
) )
1837 int bDeselAll
= nFlags
& F_DESEL_ALL
;
1839 SelAllDestrAnch( false, true );
1842 // nFlags &= (~F_DESEL_ALL);
1843 // ShowCursor( false ); // if cursor is moved lower
1844 long nY
= GetEntryLine( pEntry
);
1845 bool bEntryVisible
= IsLineVisible( nY
);
1848 ShowCursor( false ); // if cursor is moved lower
1849 nY
-= pView
->GetEntryHeight(); // because of lines
1850 InvalidateEntriesFrom( nY
);
1852 else if( pStartEntry
&& nY
< GetEntryLine(pStartEntry
) )
1854 // Check if the view is filled completely. If not, then adjust
1855 // pStartEntry and the Cursor (automatic scrolling).
1856 sal_uInt16 nLast
= (sal_uInt16
)(pView
->GetVisiblePos(pView
->LastVisible()));
1857 sal_uInt16 nThumb
= (sal_uInt16
)(pView
->GetVisiblePos( pStartEntry
));
1858 sal_uInt16 nCurDispEntries
= nLast
-nThumb
+1;
1859 if( nCurDispEntries
< nVisibleCount
)
1861 // set at the next paint event
1864 pView
->Invalidate();
1867 else if( !pStartEntry
)
1868 pView
->Invalidate();
1870 SetMostRight( pEntry
);
1871 aVerSBar
.SetRange( Range(0, pView
->GetVisibleCount()-1));
1872 SyncVerThumb(); // if something was inserted before the thumb
1875 if( pStartEntry
!= pView
->First() && (nFlags
& F_FILLING
) )
1882 // ********************************************************************
1884 // ********************************************************************
1887 // ****** Control the control animation
1889 bool SvImpLBox::ButtonDownCheckCtrl(
1890 const MouseEvent
& rMEvt
, SvTreeListEntry
* pEntry
, long nY
)
1892 SvLBoxItem
* pItem
= pView
->GetItem(pEntry
,rMEvt
.GetPosPixel().X(),&pActiveTab
);
1893 if (pItem
&& pItem
->GetType() == SV_ITEM_ID_LBOXBUTTON
)
1895 pActiveButton
= (SvLBoxButton
*)pItem
;
1896 pActiveEntry
= pEntry
;
1897 if( pCursor
== pActiveEntry
)
1899 pView
->CaptureMouse();
1900 pActiveButton
->SetStateHilighted( true );
1901 pView
->PaintEntry1( pActiveEntry
, nY
,
1902 SV_LBOXTAB_PUSHABLE
| SV_LBOXTAB_ADJUST_CENTER
|
1903 SV_LBOXTAB_ADJUST_RIGHT
);
1911 bool SvImpLBox::MouseMoveCheckCtrl(const MouseEvent
& rMEvt
, SvTreeListEntry
* pEntry
)
1916 long nMouseX
= rMEvt
.GetPosPixel().X();
1917 if( pEntry
== pActiveEntry
&&
1918 pView
->GetItem(pActiveEntry
, nMouseX
) == pActiveButton
)
1920 if( !pActiveButton
->IsStateHilighted() )
1922 pActiveButton
->SetStateHilighted(true );
1923 nY
= GetEntryLine( pActiveEntry
);
1924 pView
->PaintEntry1( pActiveEntry
, nY
,
1925 SV_LBOXTAB_PUSHABLE
| SV_LBOXTAB_ADJUST_CENTER
|
1926 SV_LBOXTAB_ADJUST_RIGHT
);
1931 if( pActiveButton
->IsStateHilighted() )
1933 pActiveButton
->SetStateHilighted(false );
1934 nY
= GetEntryLine( pActiveEntry
);
1935 pView
->PaintEntry1( pActiveEntry
, nY
, SV_LBOXTAB_PUSHABLE
);
1943 bool SvImpLBox::ButtonUpCheckCtrl( const MouseEvent
& rMEvt
)
1947 pView
->ReleaseMouse();
1948 SvTreeListEntry
* pEntry
= GetClickedEntry( rMEvt
.GetPosPixel() );
1949 long nY
= GetEntryLine( pActiveEntry
);
1950 pActiveButton
->SetStateHilighted( false );
1951 long nMouseX
= rMEvt
.GetPosPixel().X();
1952 if( pEntry
== pActiveEntry
&&
1953 pView
->GetItem( pActiveEntry
, nMouseX
) == pActiveButton
)
1954 pActiveButton
->ClickHdl( pView
, pActiveEntry
);
1955 pView
->PaintEntry1( pActiveEntry
, nY
,
1956 SV_LBOXTAB_PUSHABLE
| SV_LBOXTAB_ADJUST_CENTER
|
1957 SV_LBOXTAB_ADJUST_RIGHT
);
1958 if( pCursor
== pActiveEntry
)
1968 // ******* Control plus/minus button for expanding/collapsing
1970 // false == no expand/collapse button hit
1971 bool SvImpLBox::IsNodeButton( const Point
& rPosPixel
, SvTreeListEntry
* pEntry
) const
1973 if( !pEntry
->HasChildren() && !pEntry
->HasChildrenOnDemand() )
1976 SvLBoxTab
* pFirstDynamicTab
= pView
->GetFirstDynamicTab();
1977 if( !pFirstDynamicTab
)
1980 long nMouseX
= rPosPixel
.X();
1981 // convert to document coordinates
1982 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
1983 nMouseX
-= aOrigin
.X();
1985 long nX
= pView
->GetTabPos( pEntry
, pFirstDynamicTab
);
1986 nX
+= nNodeBmpTabDistance
;
1989 nX
+= nNodeBmpWidth
;
1995 // false == hit no node button
1996 bool SvImpLBox::ButtonDownCheckExpand( const MouseEvent
& rMEvt
, SvTreeListEntry
* pEntry
, long /* nY */ )
2000 if ( pView
->IsEditingActive() && pEntry
== pView
->pEdEntry
)
2001 // inplace editing -> nothing to do
2003 else if ( IsNodeButton( rMEvt
.GetPosPixel(), pEntry
) )
2005 if ( pView
->IsExpanded( pEntry
) )
2007 pView
->EndEditing( true );
2008 pView
->Collapse( pEntry
);
2012 // you can expand an entry, which is in editing
2013 pView
->Expand( pEntry
);
2021 void SvImpLBox::MouseButtonDown( const MouseEvent
& rMEvt
)
2023 if ( !rMEvt
.IsLeft() && !rMEvt
.IsRight())
2027 Point
aPos( rMEvt
.GetPosPixel());
2029 if( aPos
.X() > aOutputSize
.Width() || aPos
.Y() > aOutputSize
.Height() )
2032 SvTreeListEntry
* pEntry
= GetEntry( aPos
);
2033 if ( pEntry
!= pCursor
)
2034 // new entry selected -> reset current tab position to first tab
2035 nCurTabPos
= FIRST_ENTRY_TAB
;
2036 nFlags
&= (~F_FILLING
);
2038 // the entry can still be invalid!
2039 if( !pEntry
|| !pView
->GetViewData( pEntry
))
2042 long nY
= GetEntryLine( pEntry
);
2044 if( ButtonDownCheckExpand( rMEvt
, pEntry
, nY
) )
2047 if( !EntryReallyHit(pEntry
,aPos
,nY
))
2050 SvLBoxItem
* pXItem
= pView
->GetItem( pEntry
, aPos
.X() );
2053 SvLBoxTab
* pXTab
= pView
->GetTab( pEntry
, pXItem
);
2054 if ( !rMEvt
.IsMod1() && !rMEvt
.IsMod2() && rMEvt
.IsLeft() && pXTab
->IsEditable()
2055 && pEntry
== pView
->FirstSelected() && NULL
== pView
->NextSelected( pEntry
) )
2056 // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
2057 nFlags
|= F_START_EDITTIMER
;
2058 if ( !pView
->IsSelected( pEntry
) )
2059 nFlags
&= ~F_START_EDITTIMER
;
2063 if( (rMEvt
.GetClicks() % 2) == 0 )
2065 nFlags
&= (~F_START_EDITTIMER
);
2066 pView
->pHdlEntry
= pEntry
;
2067 if( pView
->DoubleClickHdl() )
2069 // if the entry was deleted within the handler
2070 pEntry
= GetClickedEntry( aPos
);
2073 if( pEntry
!= pView
->pHdlEntry
)
2075 // select anew & bye
2076 if( !bSimpleTravel
&& !aSelEng
.IsAlwaysAdding())
2077 SelAllDestrAnch( false, true ); // DeselectAll();
2078 SetCursor( pEntry
);
2082 if( pEntry
->HasChildren() || pEntry
->HasChildrenOnDemand() )
2084 if( pView
->IsExpanded(pEntry
) )
2085 pView
->Collapse( pEntry
);
2087 pView
->Expand( pEntry
);
2088 if( pEntry
== pCursor
) // only if Entryitem was clicked
2089 // (Nodebutton is not an Entryitem!)
2090 pView
->Select( pCursor
, true );
2097 // CheckButton? (TreeListBox: Check + Info)
2098 if( ButtonDownCheckCtrl(rMEvt
, pEntry
, nY
) == true)
2102 if ( aSelEng
.GetSelectionMode() != NO_SELECTION
)
2103 aSelEng
.SelMouseButtonDown( rMEvt
);
2106 void SvImpLBox::MouseButtonUp( const MouseEvent
& rMEvt
)
2108 if ( !ButtonUpCheckCtrl( rMEvt
) && ( aSelEng
.GetSelectionMode() != NO_SELECTION
) )
2109 aSelEng
.SelMouseButtonUp( rMEvt
);
2111 if( nFlags
& F_START_EDITTIMER
)
2113 nFlags
&= (~F_START_EDITTIMER
);
2114 aEditClickPos
= rMEvt
.GetPosPixel();
2121 void SvImpLBox::MouseMove( const MouseEvent
& rMEvt
)
2123 SvTreeListEntry
* pEntry
= GetClickedEntry( rMEvt
.GetPosPixel() );
2124 if ( !MouseMoveCheckCtrl( rMEvt
, pEntry
) && ( aSelEng
.GetSelectionMode() != NO_SELECTION
) )
2125 aSelEng
.SelMouseMove( rMEvt
);
2129 bool SvImpLBox::KeyInput( const KeyEvent
& rKEvt
)
2132 const KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
2134 if( rKeyCode
.IsMod2() )
2135 return false; // don't evaluate Alt key
2137 nFlags
&= (~F_FILLING
);
2140 pCursor
= pStartEntry
;
2144 bool bKeyUsed
= true;
2146 sal_uInt16 nDelta
= (sal_uInt16
)aVerSBar
.GetPageSize();
2147 sal_uInt16 aCode
= rKeyCode
.GetCode();
2149 bool bShift
= rKeyCode
.IsShift();
2150 bool bMod1
= rKeyCode
.IsMod1();
2152 SvTreeListEntry
* pNewCursor
;
2154 const WinBits nWindowStyle
= pView
->GetStyle();
2158 if( !IsEntryInView( pCursor
) )
2159 MakeVisible( pCursor
);
2161 pNewCursor
= pCursor
;
2164 pNewCursor
= pView
->PrevVisible(pNewCursor
);
2165 } while( pNewCursor
&& !IsSelectable(pNewCursor
) );
2168 // new entry selected -> reset current tab position to first tab
2169 nCurTabPos
= FIRST_ENTRY_TAB
;
2170 // if there is no next entry, take the current one
2171 // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2173 if ( !pNewCursor
&& pCursor
)
2174 pNewCursor
= pCursor
;
2178 aSelEng
.CursorPosChanging( bShift
, bMod1
);
2179 SetCursor( pNewCursor
, bMod1
); // no selection, when Ctrl is on
2180 if( !IsEntryInView( pNewCursor
) )
2186 if( !IsEntryInView( pCursor
) )
2187 MakeVisible( pCursor
);
2189 pNewCursor
= pCursor
;
2192 pNewCursor
= pView
->NextVisible(pNewCursor
);
2193 } while( pNewCursor
&& !IsSelectable(pNewCursor
) );
2196 // new entry selected -> reset current tab position to first tab
2197 nCurTabPos
= FIRST_ENTRY_TAB
;
2199 // if there is no next entry, take the current one
2200 // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2202 // 06.09.20001 - 83416 - frank.schoenheit@sun.com
2203 if ( !pNewCursor
&& pCursor
)
2204 pNewCursor
= pCursor
;
2208 aSelEng
.CursorPosChanging( bShift
, bMod1
);
2209 if( IsEntryInView( pNewCursor
) )
2210 SetCursor( pNewCursor
, bMod1
); // no selection, when Ctrl is on
2214 pView
->Select( pCursor
, false );
2216 SetCursor( pNewCursor
, bMod1
); // no selection, when Ctrl is on
2220 KeyDown( false ); // because scrollbar range might still
2226 if( bSubLstOpLR
&& IsNowExpandable() )
2227 pView
->Expand( pCursor
);
2228 else if ( bIsCellFocusEnabled
&& pCursor
)
2230 if ( nCurTabPos
< ( pView
->TabCount() - 1 /*!2*/ ) )
2234 CallEventListeners( VCLEVENT_LISTBOX_SELECT
, pCursor
);
2237 else if( nWindowStyle
& WB_HSCROLL
)
2239 long nThumb
= aHorSBar
.GetThumbPos();
2240 nThumb
+= aHorSBar
.GetLineSize();
2241 long nOldThumb
= aHorSBar
.GetThumbPos();
2242 aHorSBar
.SetThumbPos( nThumb
);
2244 nThumb
-= aHorSBar
.GetThumbPos();
2248 KeyLeftRight( nThumb
);
2259 if ( bIsCellFocusEnabled
)
2261 if ( nCurTabPos
> FIRST_ENTRY_TAB
)
2265 CallEventListeners( VCLEVENT_LISTBOX_SELECT
, pCursor
);
2268 else if ( nWindowStyle
& WB_HSCROLL
)
2270 long nThumb
= aHorSBar
.GetThumbPos();
2271 nThumb
-= aHorSBar
.GetLineSize();
2272 long nOldThumb
= aHorSBar
.GetThumbPos();
2273 aHorSBar
.SetThumbPos( nThumb
);
2275 nThumb
-= aHorSBar
.GetThumbPos();
2278 KeyLeftRight( -nThumb
);
2281 else if( bSubLstOpLR
)
2283 if( IsExpandable() && pView
->IsExpanded( pCursor
) )
2284 pView
->Collapse( pCursor
);
2287 pNewCursor
= pView
->GetParent( pCursor
);
2289 SetCursor( pNewCursor
);
2293 else if( bSubLstOpLR
&& IsExpandable() )
2294 pView
->Collapse( pCursor
);
2303 pNewCursor
= pView
->PrevVisible(pCursor
, nDelta
);
2305 while( nDelta
&& pNewCursor
&& !IsSelectable(pNewCursor
) )
2307 pNewCursor
= pView
->NextVisible(pNewCursor
);
2313 DBG_ASSERT(pNewCursor
&&(sal_uLong
)pNewCursor
!=(sal_uLong
)pCursor
,"Cursor?");
2314 aSelEng
.CursorPosChanging( bShift
, bMod1
);
2315 if( IsEntryInView( pNewCursor
) )
2316 SetCursor( pNewCursor
);
2319 SetCursor( pNewCursor
);
2331 pNewCursor
= pView
->NextVisible(pCursor
, nDelta
);
2333 while( nDelta
&& pNewCursor
&& !IsSelectable(pNewCursor
) )
2335 pNewCursor
= pView
->PrevVisible(pNewCursor
);
2341 DBG_ASSERT(pNewCursor
&&(sal_uLong
)pNewCursor
!=(sal_uLong
)pCursor
,"Cursor?");
2342 aSelEng
.CursorPosChanging( bShift
, bMod1
);
2343 if( IsEntryInView( pNewCursor
) )
2344 SetCursor( pNewCursor
);
2347 SetCursor( pNewCursor
);
2352 KeyDown( false ); // see also: KEY_DOWN
2359 if ( pView
->GetSelectionMode() != NO_SELECTION
)
2363 if ( pView
->GetSelectionMode() == MULTIPLE_SELECTION
&& !bShift
)
2365 pView
->Select( pCursor
, !pView
->IsSelected( pCursor
) );
2367 else if ( !bShift
/*&& !bMod1*/ )
2369 if ( aSelEng
.IsAddMode() )
2372 pView
->Select( pCursor
, !pView
->IsSelected( pCursor
) );
2374 else if ( !pView
->IsSelected( pCursor
) )
2376 SelAllDestrAnch( false );
2377 pView
->Select( pCursor
, true );
2390 if( bSubLstOpRet
&& IsExpandable() )
2392 if( pView
->IsExpanded( pCursor
) )
2393 pView
->Collapse( pCursor
);
2395 pView
->Expand( pCursor
);
2402 if( !bShift
&& !bMod1
)
2404 aEditClickPos
= Point( -1, -1 );
2412 if( bShift
&& pView
->GetSelectionMode()==MULTIPLE_SELECTION
&&
2413 !(m_nStyle
& WB_SIMPLEMODE
))
2415 if( aSelEng
.IsAlwaysAdding() )
2416 aSelEng
.AddAlways( false );
2418 aSelEng
.AddAlways( true );
2427 if( !pView
->IsExpanded(pCursor
))
2428 pView
->Expand( pCursor
);
2431 sal_uInt16 nRefDepth
= pTree
->GetDepth( pCursor
);
2432 SvTreeListEntry
* pCur
= pTree
->Next( pCursor
);
2433 while( pCur
&& pTree
->GetDepth(pCur
) > nRefDepth
)
2435 if( pCur
->HasChildren() && !pView
->IsExpanded(pCur
))
2436 pView
->Expand( pCur
);
2437 pCur
= pTree
->Next( pCur
);
2447 SelAllDestrAnch( true );
2455 if( pView
->IsExpanded(pCursor
))
2456 pView
->Collapse( pCursor
);
2459 // collapse all parents until we get to the root
2460 SvTreeListEntry
* pParentToCollapse
= (SvTreeListEntry
*)pTree
->GetRootLevelParent(pCursor
);
2461 if( pParentToCollapse
)
2463 sal_uInt16 nRefDepth
;
2464 // special case explorer: if the root only has a single
2465 // entry, don't collapse the root entry
2466 if (pTree
->GetChildList(0).size() < 2)
2469 pParentToCollapse
= pCursor
;
2470 while( pTree
->GetParent(pParentToCollapse
) &&
2471 pTree
->GetDepth( pTree
->GetParent(pParentToCollapse
)) > 0)
2473 pParentToCollapse
= pTree
->GetParent(pParentToCollapse
);
2479 if( pView
->IsExpanded(pParentToCollapse
) )
2480 pView
->Collapse( pParentToCollapse
);
2481 SvTreeListEntry
* pCur
= pTree
->Next( pParentToCollapse
);
2482 while( pCur
&& pTree
->GetDepth(pCur
) > nRefDepth
)
2484 if( pCur
->HasChildren() && pView
->IsExpanded(pCur
) )
2485 pView
->Collapse( pCur
);
2486 pCur
= pTree
->Next( pCur
);
2497 SelAllDestrAnch( true );
2504 SelAllDestrAnch( false );
2510 pNewCursor
= pView
->GetModel()->First();
2512 while( pNewCursor
&& !IsSelectable(pNewCursor
) )
2514 pNewCursor
= pView
->NextVisible(pNewCursor
);
2517 if( pNewCursor
&& pNewCursor
!= pCursor
)
2519 // SelAllDestrAnch( false );
2520 aSelEng
.CursorPosChanging( bShift
, bMod1
);
2521 SetCursor( pNewCursor
);
2522 if( !IsEntryInView( pNewCursor
) )
2523 MakeVisible( pNewCursor
);
2530 pNewCursor
= pView
->GetModel()->Last();
2532 while( pNewCursor
&& !IsSelectable(pNewCursor
) )
2534 pNewCursor
= pView
->PrevVisible(pNewCursor
);
2537 if( pNewCursor
&& pNewCursor
!= pCursor
)
2539 // SelAllDestrAnch( false );
2540 aSelEng
.CursorPosChanging( bShift
, bMod1
);
2541 SetCursor( pNewCursor
);
2542 if( !IsEntryInView( pNewCursor
) )
2543 MakeVisible( pNewCursor
);
2553 // must not be handled because this quits dialogs and does other magic things...
2554 // if there are other single keys which should not be handled, they can be added here
2559 // is there any reason why we should eat the events here? The only place where this is called
2560 // is from SvTreeListBox::KeyInput. If we set bKeyUsed to true here, then the key input
2561 // is just silenced. However, we want SvLBox::KeyInput to get a chance, to do the QuickSelection
2563 // (The old code here which intentionally set bKeyUsed to TRUE said this was because of "quick search"
2564 // handling, but actually there was no quick search handling anymore. We just re-implemented it.)
2565 // #i31275# / 2009-06-16 / frank.schoenheit@sun.com
2572 void SvImpLBox::GetFocus()
2576 pView
->SetEntryFocus( pCursor
, true );
2578 // auskommentiert wg. deselectall
2579 // if( bSimpleTravel && !pView->IsSelected(pCursor) )
2580 // pView->Select( pCursor, true );
2582 if( m_nStyle
& WB_HIDESELECTION
)
2584 SvTreeListEntry
* pEntry
= pView
->FirstSelected();
2587 InvalidateEntry( pEntry
);
2588 pEntry
= pView
->NextSelected( pEntry
);
2593 void SvImpLBox::LoseFocus()
2597 pView
->SetEntryFocus( pCursor
,false );
2598 ShowCursor( false );
2600 if( m_nStyle
& WB_HIDESELECTION
)
2602 SvTreeListEntry
* pEntry
= pView
->FirstSelected();
2605 InvalidateEntry( pEntry
);
2606 pEntry
= pView
->NextSelected( pEntry
);
2612 // ********************************************************************
2614 // ********************************************************************
2616 void SvImpLBox::SelectEntry( SvTreeListEntry
* pEntry
, bool bSelect
)
2618 pView
->Select( pEntry
, bSelect
);
2621 ImpLBSelEng::ImpLBSelEng( SvImpLBox
* pImpl
, SelectionEngine
* pSEng
,
2629 ImpLBSelEng::~ImpLBSelEng()
2633 void ImpLBSelEng::BeginDrag()
2638 void ImpLBSelEng::CreateAnchor()
2640 pImp
->pAnchor
= pImp
->pCursor
;
2643 void ImpLBSelEng::DestroyAnchor()
2648 sal_Bool
ImpLBSelEng::SetCursorAtPoint(const Point
& rPoint
, sal_Bool bDontSelectAtCursor
)
2650 SvTreeListEntry
* pNewCursor
= pImp
->MakePointVisible( rPoint
);
2651 if( pNewCursor
!= pImp
->pCursor
)
2652 pImp
->BeginScroll();
2656 // at SimpleTravel, the SetCursor is selected and the select handler is
2658 //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
2659 // pImp->SelectEntry( pNewCursor, true );
2660 pImp
->SetCursor( pNewCursor
, bDontSelectAtCursor
);
2666 sal_Bool
ImpLBSelEng::IsSelectionAtPoint( const Point
& rPoint
)
2668 SvTreeListEntry
* pEntry
= pImp
->MakePointVisible( rPoint
);
2670 return pView
->IsSelected(pEntry
);
2674 void ImpLBSelEng::DeselectAtPoint( const Point
& rPoint
)
2676 SvTreeListEntry
* pEntry
= pImp
->MakePointVisible( rPoint
);
2679 pImp
->SelectEntry( pEntry
, false );
2682 void ImpLBSelEng::DeselectAll()
2684 pImp
->SelAllDestrAnch( false, false ); // don't reset SelectionEngine!
2685 pImp
->nFlags
&= (~F_DESEL_ALL
);
2688 // ***********************************************************************
2690 // ***********************************************************************
2692 void SvImpLBox::SetAnchorSelection(SvTreeListEntry
* pOldCursor
,SvTreeListEntry
* pNewCursor
)
2694 SvTreeListEntry
* pEntry
;
2695 sal_uLong nAnchorVisPos
= pView
->GetVisiblePos( pAnchor
);
2696 sal_uLong nOldVisPos
= pView
->GetVisiblePos( pOldCursor
);
2697 sal_uLong nNewVisPos
= pView
->GetVisiblePos( pNewCursor
);
2699 if( nOldVisPos
> nAnchorVisPos
||
2700 ( nAnchorVisPos
==nOldVisPos
&& nNewVisPos
> nAnchorVisPos
) )
2702 if( nNewVisPos
> nOldVisPos
)
2704 pEntry
= pOldCursor
;
2705 while( pEntry
&& pEntry
!= pNewCursor
)
2707 pView
->Select( pEntry
, true );
2708 pEntry
= pView
->NextVisible(pEntry
);
2711 pView
->Select( pEntry
, true );
2715 if( nNewVisPos
< nAnchorVisPos
)
2718 while( pEntry
&& pEntry
!= pOldCursor
)
2720 pView
->Select( pEntry
, false );
2721 pEntry
= pView
->NextVisible(pEntry
);
2724 pView
->Select( pEntry
, false );
2726 pEntry
= pNewCursor
;
2727 while( pEntry
&& pEntry
!= pAnchor
)
2729 pView
->Select( pEntry
, true );
2730 pEntry
= pView
->NextVisible(pEntry
);
2733 pView
->Select( pEntry
, true );
2737 if( nNewVisPos
< nOldVisPos
)
2739 pEntry
= pNewCursor
;
2740 pEntry
= pView
->NextVisible(pEntry
);
2741 while( pEntry
&& pEntry
!= pOldCursor
)
2743 pView
->Select( pEntry
, false );
2744 pEntry
= pView
->NextVisible(pEntry
);
2747 pView
->Select( pEntry
, false );
2753 if( nNewVisPos
< nOldVisPos
) // enlarge selection
2755 pEntry
= pNewCursor
;
2756 while( pEntry
&& pEntry
!= pOldCursor
)
2758 pView
->Select( pEntry
, true );
2759 pEntry
= pView
->NextVisible(pEntry
);
2762 pView
->Select( pEntry
, true );
2766 if( nNewVisPos
> nAnchorVisPos
)
2768 pEntry
= pOldCursor
;
2769 while( pEntry
&& pEntry
!= pAnchor
)
2771 pView
->Select( pEntry
, false );
2772 pEntry
= pView
->NextVisible(pEntry
);
2775 pView
->Select( pEntry
, false );
2777 while( pEntry
&& pEntry
!= pNewCursor
)
2779 pView
->Select( pEntry
, true );
2780 pEntry
= pView
->NextVisible(pEntry
);
2783 pView
->Select( pEntry
, true );
2787 if( nNewVisPos
> nOldVisPos
)
2789 pEntry
= pOldCursor
;
2790 while( pEntry
&& pEntry
!= pNewCursor
)
2792 pView
->Select( pEntry
, false );
2793 pEntry
= pView
->NextVisible(pEntry
);
2800 void SvImpLBox::SelAllDestrAnch(
2801 bool bSelect
, bool bDestroyAnchor
, bool bSingleSelToo
)
2803 SvTreeListEntry
* pEntry
;
2804 nFlags
&= (~F_DESEL_ALL
);
2805 if( bSelect
&& bSimpleTravel
)
2807 if( pCursor
&& !pView
->IsSelected( pCursor
))
2809 pView
->Select( pCursor
, true );
2813 if( !bSelect
&& pView
->GetSelectionCount() == 0 )
2815 if( bSimpleTravel
&& ( !GetUpdateMode() || !pCursor
) )
2816 nFlags
|= F_DESEL_ALL
;
2819 if( bSelect
&& pView
->GetSelectionCount() == pView
->GetEntryCount())
2821 if( !bSingleSelToo
&& bSimpleTravel
)
2824 if( !bSelect
&& pView
->GetSelectionCount()==1 && pCursor
&&
2825 pView
->IsSelected( pCursor
))
2827 pView
->Select( pCursor
, false );
2828 if( bDestroyAnchor
)
2829 DestroyAnchor(); // delete anchor & reset SelectionEngine
2831 pAnchor
= 0; // always delete internal anchor
2835 if( bSimpleTravel
&& !pCursor
&& !GetUpdateMode() )
2836 nFlags
|= F_DESEL_ALL
;
2838 ShowCursor( false );
2839 bool bUpdate
= GetUpdateMode();
2841 nFlags
|= F_IGNORE_SELECT
; // EntryInserted should not do anything
2842 pEntry
= pTree
->First();
2845 if( pView
->Select( pEntry
, bSelect
) )
2847 if( bUpdate
&& pView
->IsEntryVisible(pEntry
) )
2849 long nY
= GetEntryLine( pEntry
);
2850 if( IsLineVisible( nY
) )
2851 pView
->PaintEntry1( pEntry
, nY
, 0xffff ); // because of ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
2854 pEntry
= pTree
->Next( pEntry
);
2856 nFlags
&= ~F_IGNORE_SELECT
;
2858 if( bDestroyAnchor
)
2859 DestroyAnchor(); // delete anchor & reset SelectionEngine
2861 pAnchor
= 0; // always delete internal anchor
2865 void SvImpLBox::SetSelectionMode( SelectionMode eSelMode
)
2867 aSelEng
.SetSelectionMode( eSelMode
);
2868 if( eSelMode
== SINGLE_SELECTION
)
2869 bSimpleTravel
= true;
2871 bSimpleTravel
= false;
2872 if( (m_nStyle
& WB_SIMPLEMODE
) && (eSelMode
== MULTIPLE_SELECTION
) )
2873 aSelEng
.AddAlways( true );
2876 // ***********************************************************************
2878 // ***********************************************************************
2880 void SvImpLBox::SetDragDropMode( DragDropMode eDDMode
)
2882 if( eDDMode
&& eDDMode
!= SV_DRAGDROP_APP_DROP
)
2884 aSelEng
.ExpandSelectionOnMouseMove( false );
2885 aSelEng
.EnableDrag( true );
2889 aSelEng
.ExpandSelectionOnMouseMove( true );
2890 aSelEng
.EnableDrag( false );
2894 void SvImpLBox::BeginDrag()
2896 nFlags
&= (~F_FILLING
);
2897 if( !bAsyncBeginDrag
)
2900 pView
->StartDrag( 0, aSelEng
.GetMousePosPixel() );
2905 aAsyncBeginDragPos
= aSelEng
.GetMousePosPixel();
2906 aAsyncBeginDragTimer
.Start();
2910 IMPL_LINK_NOARG(SvImpLBox
, BeginDragHdl
)
2912 pView
->StartDrag( 0, aAsyncBeginDragPos
);
2916 void SvImpLBox::PaintDDCursor( SvTreeListEntry
* pInsertionPos
)
2921 nY
= GetEntryLine( pInsertionPos
);
2922 nY
+= pView
->GetEntryHeight();
2926 RasterOp eOldOp
= pView
->GetRasterOp();
2927 pView
->SetRasterOp( ROP_INVERT
);
2928 Color aOldLineColor
= pView
->GetLineColor();
2929 pView
->SetLineColor( Color( COL_BLACK
) );
2930 pView
->DrawLine( Point( 0, nY
), Point( aOutputSize
.Width(), nY
) );
2931 pView
->SetLineColor( aOldLineColor
);
2932 pView
->SetRasterOp( eOldOp
);
2935 // Delete all submenus of a PopupMenu, recursively
2936 static void lcl_DeleteSubPopups(PopupMenu
* pPopup
)
2938 for(sal_uInt16 i
= 0; i
< pPopup
->GetItemCount(); i
++)
2940 PopupMenu
* pSubPopup
= pPopup
->GetPopupMenu( pPopup
->GetItemId( i
));
2943 lcl_DeleteSubPopups(pSubPopup
);
2949 void SvImpLBox::Command( const CommandEvent
& rCEvt
)
2951 sal_uInt16 nCommand
= rCEvt
.GetCommand();
2953 if( nCommand
== COMMAND_CONTEXTMENU
)
2956 // scroll mouse event?
2957 if( ( ( nCommand
== COMMAND_WHEEL
) || ( nCommand
== COMMAND_STARTAUTOSCROLL
) || ( nCommand
== COMMAND_AUTOSCROLL
) )
2958 && pView
->HandleScrollCommand( rCEvt
, &aHorSBar
, &aVerSBar
) )
2961 if( bContextMenuHandling
&& nCommand
== COMMAND_CONTEXTMENU
)
2964 bool bClickedIsFreePlace
= false;
2965 std::stack
<SvTreeListEntry
*> aSelRestore
;
2967 if( rCEvt
.IsMouseEvent() )
2968 { // change selection, if mouse position doesn't fit to selection
2970 aPopupPos
= rCEvt
.GetMousePosPixel();
2972 SvTreeListEntry
* pClickedEntry
= GetEntry( aPopupPos
);
2974 { // mouse in non empty area
2975 bool bClickedIsSelected
= false;
2977 // collect the currently selected entries
2978 SvTreeListEntry
* pSelected
= pView
->FirstSelected();
2981 bClickedIsSelected
|= ( pClickedEntry
== pSelected
);
2982 pSelected
= pView
->NextSelected( pSelected
);
2985 // if the entry which the user clicked at is not selected
2986 if( !bClickedIsSelected
)
2987 { // deselect all other and select the clicked one
2988 pView
->SelectAll( false );
2989 pView
->SetCursor( pClickedEntry
);
2992 else if( aSelEng
.GetSelectionMode() == SINGLE_SELECTION
)
2994 bClickedIsFreePlace
= true;
2995 sal_Int32 nSelectedEntries
= pView
->GetSelectionCount();
2996 SvTreeListEntry
* pSelected
= pView
->FirstSelected();
2997 for(sal_uInt16 nSel
= 0; nSel
< nSelectedEntries
; nSel
++ )
2999 aSelRestore
.push(pSelected
);
3000 pSelected
= pView
->NextSelected( pSelected
);
3002 pView
->SelectAll( false );
3006 pView
->SelectAll( false );
3012 { // key event (or at least no mouse event)
3013 sal_Int32 nSelectionCount
= pView
->GetSelectionCount();
3015 if( nSelectionCount
)
3016 { // now always take first visible as base for positioning the menu
3017 SvTreeListEntry
* pSelected
= pView
->FirstSelected();
3020 if( IsEntryInView( pSelected
) )
3023 pSelected
= pView
->NextSelected( pSelected
);
3028 // no one was visible
3029 pSelected
= pView
->FirstSelected();
3030 pView
->MakeVisible( pSelected
);
3033 aPopupPos
= pView
->GetFocusRect( pSelected
, pView
->GetEntryPosition( pSelected
).Y() ).Center();
3036 aPopupPos
= Point( 0, 0 );
3039 PopupMenu
* pPopup
= pView
->CreateContextMenu();
3043 // do action for selected entry in popup menu
3044 sal_uInt16 nMenuAction
= pPopup
->Execute( pView
, aPopupPos
);
3046 pView
->ExcecuteContextMenuAction( nMenuAction
);
3047 lcl_DeleteSubPopups(pPopup
);
3051 if( bClickedIsFreePlace
)
3053 while(!aSelRestore
.empty())
3055 SvTreeListEntry
* pEntry
= aSelRestore
.top();
3056 //#i19717# the entry is maybe already deleted
3057 bool bFound
= false;
3058 for(sal_uLong nEntry
= 0; nEntry
< pView
->GetEntryCount(); nEntry
++)
3059 if(pEntry
== pView
->GetEntry(nEntry
))
3065 SetCurEntry( pEntry
);
3073 const Point
& rPos
= rCEvt
.GetMousePosPixel();
3074 if( rPos
.X() < aOutputSize
.Width() && rPos
.Y() < aOutputSize
.Height() )
3075 aSelEng
.Command( rCEvt
);
3080 void SvImpLBox::BeginScroll()
3082 if( !(nFlags
& F_IN_SCROLLING
))
3084 pView
->NotifyBeginScroll();
3085 nFlags
|= F_IN_SCROLLING
;
3089 void SvImpLBox::EndScroll()
3091 if( nFlags
& F_IN_SCROLLING
)
3093 pView
->NotifyEndScroll();
3094 nFlags
&= (~F_IN_SCROLLING
);
3099 Rectangle
SvImpLBox::GetVisibleArea() const
3101 Point
aPos( pView
->GetMapMode().GetOrigin() );
3103 Rectangle
aRect( aPos
, aOutputSize
);
3107 void SvImpLBox::Invalidate()
3109 pView
->SetClipRegion();
3112 void SvImpLBox::SetCurEntry( SvTreeListEntry
* pEntry
)
3114 if ( ( aSelEng
.GetSelectionMode() != SINGLE_SELECTION
)
3115 && ( aSelEng
.GetSelectionMode() != NO_SELECTION
)
3117 SelAllDestrAnch( false, true, false );
3119 MakeVisible( pEntry
);
3120 SetCursor( pEntry
);
3121 if ( pEntry
&& ( aSelEng
.GetSelectionMode() != NO_SELECTION
) )
3122 pView
->Select( pEntry
, true );
3125 IMPL_LINK_NOARG(SvImpLBox
, EditTimerCall
)
3127 if( pView
->IsInplaceEditingEnabled() )
3129 bool bIsMouseTriggered
= aEditClickPos
.X() >= 0;
3130 if ( bIsMouseTriggered
)
3132 Point aCurrentMousePos
= pView
->GetPointerPosPixel();
3133 if ( ( abs( aCurrentMousePos
.X() - aEditClickPos
.X() ) > 5 )
3134 || ( abs( aCurrentMousePos
.Y() - aEditClickPos
.Y() ) > 5 )
3141 SvTreeListEntry
* pEntry
= GetCurEntry();
3144 ShowCursor( false );
3145 pView
->ImplEditEntry( pEntry
);
3152 bool SvImpLBox::RequestHelp( const HelpEvent
& rHEvt
)
3154 if( rHEvt
.GetMode() & HELPMODE_QUICK
)
3156 Point
aPos( pView
->ScreenToOutputPixel( rHEvt
.GetMousePosPixel() ));
3157 if( !GetVisibleArea().IsInside( aPos
))
3160 SvTreeListEntry
* pEntry
= GetEntry( aPos
);
3163 // recalculate text rectangle
3165 SvLBoxString
* pItem
= (SvLBoxString
*)(pView
->GetItem( pEntry
, aPos
.X(), &pTab
));
3166 if (!pItem
|| pItem
->GetType() != SV_ITEM_ID_LBOXSTRING
)
3169 aPos
= GetEntryPosition( pEntry
);
3170 aPos
.X() = pView
->GetTabPos( pEntry
, pTab
); //pTab->GetPos();
3171 Size
aSize( pItem
->GetSize( pView
, pEntry
) );
3172 SvLBoxTab
* pNextTab
= NextTab( pTab
);
3173 bool bItemClipped
= false;
3174 // is the item cut off by its right neighbor?
3175 if( pNextTab
&& pView
->GetTabPos(pEntry
,pNextTab
) < aPos
.X()+aSize
.Width() )
3177 aSize
.Width() = pNextTab
->GetPos() - pTab
->GetPos();
3178 bItemClipped
= true;
3180 Rectangle
aItemRect( aPos
, aSize
);
3182 Rectangle
aViewRect( GetVisibleArea() );
3184 if( bItemClipped
|| !aViewRect
.IsInside( aItemRect
) )
3186 // clip the right edge of the item at the edge of the view
3187 //if( aItemRect.Right() > aViewRect.Right() )
3188 // aItemRect.Right() = aViewRect.Right();
3190 Point aPt
= pView
->OutputToScreenPixel( aItemRect
.TopLeft() );
3191 aItemRect
.Left() = aPt
.X();
3192 aItemRect
.Top() = aPt
.Y();
3193 aPt
= pView
->OutputToScreenPixel( aItemRect
.BottomRight() );
3194 aItemRect
.Right() = aPt
.X();
3195 aItemRect
.Bottom() = aPt
.Y();
3197 Help::ShowQuickHelp( pView
, aItemRect
,
3198 pItem
->GetText(), QUICKHELP_LEFT
| QUICKHELP_VCENTER
);
3206 SvLBoxTab
* SvImpLBox::NextTab( SvLBoxTab
* pTab
)
3208 sal_uInt16 nTabCount
= pView
->TabCount();
3209 if( nTabCount
<= 1 )
3211 for( sal_uInt16 nTab
=0; nTab
< (nTabCount
-1); nTab
++)
3213 if( pView
->aTabs
[nTab
]==pTab
)
3214 return (SvLBoxTab
*)(pView
->aTabs
[nTab
+1]);
3219 void SvImpLBox::EndSelection()
3222 nFlags
&= ~F_START_EDITTIMER
;
3225 void SvImpLBox::RepaintScrollBars()
3229 void SvImpLBox::SetUpdateMode( bool bMode
)
3231 if( bUpdateMode
!= bMode
)
3233 bUpdateMode
= bMode
;
3239 bool SvImpLBox::SetMostRight( SvTreeListEntry
* pEntry
)
3241 if( pView
->nTreeFlags
& TREEFLAG_RECALCTABS
)
3243 nFlags
|= F_IGNORE_CHANGED_TABS
;
3245 nFlags
&= ~F_IGNORE_CHANGED_TABS
;
3248 sal_uInt16 nLastTab
= pView
->aTabs
.size() - 1;
3249 sal_uInt16 nLastItem
= pEntry
->ItemCount() - 1;
3250 if( !pView
->aTabs
.empty() && nLastItem
!= USHRT_MAX
)
3252 if( nLastItem
< nLastTab
)
3253 nLastTab
= nLastItem
;
3255 SvLBoxTab
* pTab
= pView
->aTabs
[ nLastTab
];
3256 SvLBoxItem
* pItem
= pEntry
->GetItem( nLastTab
);
3258 long nTabPos
= pView
->GetTabPos( pEntry
, pTab
);
3260 long nMaxRight
= GetOutputSize().Width();
3261 Point
aPos( pView
->GetMapMode().GetOrigin() );
3262 aPos
.X() *= -1; // conversion document coordinates
3263 nMaxRight
= nMaxRight
+ aPos
.X() - 1;
3265 long nNextTab
= nTabPos
< nMaxRight
? nMaxRight
: nMaxRight
+ 50;
3266 long nTabWidth
= nNextTab
- nTabPos
+ 1;
3267 long nItemSize
= pItem
->GetSize(pView
,pEntry
).Width();
3268 long nOffset
= pTab
->CalcOffset( nItemSize
, nTabWidth
);
3270 long nRight
= nTabPos
+ nOffset
+ nItemSize
;
3271 if( nRight
> nMostRight
)
3273 nMostRight
= nRight
;
3274 pMostRightEntry
= pEntry
;
3281 void SvImpLBox::FindMostRight( SvTreeListEntry
* pEntryToIgnore
)
3284 pMostRightEntry
= 0;
3285 if( !pView
->GetModel() )
3288 SvTreeListEntry
* pEntry
= (SvTreeListEntry
*)pView
->FirstVisible();
3291 if( pEntry
!= pEntryToIgnore
)
3292 SetMostRight( pEntry
);
3293 pEntry
= (SvTreeListEntry
*)pView
->NextVisible( pEntry
);
3297 void SvImpLBox::FindMostRight( SvTreeListEntry
* pParent
, SvTreeListEntry
* pEntryToIgnore
)
3300 FindMostRight( pEntryToIgnore
);
3302 FindMostRight_Impl( pParent
, pEntryToIgnore
);
3305 void SvImpLBox::FindMostRight_Impl( SvTreeListEntry
* pParent
, SvTreeListEntry
* pEntryToIgnore
)
3307 SvTreeListEntries
& rList
= pTree
->GetChildList( pParent
);
3309 size_t nCount
= rList
.size();
3310 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
3312 SvTreeListEntry
* pChild
= &rList
[nCur
];
3313 if( pChild
!= pEntryToIgnore
)
3315 SetMostRight( pChild
);
3316 if( pChild
->HasChildren() && pView
->IsExpanded( pChild
))
3317 FindMostRight_Impl( pChild
, pEntryToIgnore
);
3322 void SvImpLBox::NotifyTabsChanged()
3324 if( GetUpdateMode() && !(nFlags
& F_IGNORE_CHANGED_TABS
) &&
3325 nCurUserEvent
== 0xffffffff )
3327 nCurUserEvent
= Application::PostUserEvent(LINK(this,SvImpLBox
,MyUserEvent
),(void*)0);
3331 bool SvImpLBox::IsExpandable() const
3333 return pCursor
->HasChildren() || pCursor
->HasChildrenOnDemand();
3336 bool SvImpLBox::IsNowExpandable() const
3338 return IsExpandable() && !pView
->IsExpanded( pCursor
);
3341 IMPL_LINK(SvImpLBox
,MyUserEvent
,void*, pArg
)
3343 nCurUserEvent
= 0xffffffff;
3346 pView
->Invalidate();
3353 pView
->Invalidate( GetVisibleArea() );
3359 void SvImpLBox::StopUserEvent()
3361 if( nCurUserEvent
!= 0xffffffff )
3363 Application::RemoveUserEvent( nCurUserEvent
);
3364 nCurUserEvent
= 0xffffffff;
3368 void SvImpLBox::ShowFocusRect( const SvTreeListEntry
* pEntry
)
3372 long nY
= GetEntryLine( (SvTreeListEntry
*)pEntry
);
3373 Rectangle aRect
= pView
->GetFocusRect( (SvTreeListEntry
*)pEntry
, nY
);
3374 Region
aOldClip( pView
->GetClipRegion());
3375 Region
aClipRegion( GetClipRegionRect() );
3376 pView
->SetClipRegion( aClipRegion
);
3377 pView
->ShowFocus( aRect
);
3378 pView
->SetClipRegion( aOldClip
);
3387 // -----------------------------------------------------------------------
3388 void SvImpLBox::implInitDefaultNodeImages()
3390 if ( s_pDefCollapsed
)
3391 // assume that all or nothing is initialized
3394 s_pDefCollapsed
= new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED
) );
3395 s_pDefExpanded
= new Image( SvtResId( RID_IMG_TREENODE_EXPANDED
) );
3398 // -----------------------------------------------------------------------
3399 const Image
& SvImpLBox::GetDefaultExpandedNodeImage( )
3401 implInitDefaultNodeImages();
3402 return *s_pDefExpanded
;
3405 // -----------------------------------------------------------------------
3406 const Image
& SvImpLBox::GetDefaultCollapsedNodeImage( )
3408 implInitDefaultNodeImages();
3409 return *s_pDefCollapsed
;
3412 // -----------------------------------------------------------------------
3413 void SvImpLBox::CallEventListeners( sal_uLong nEvent
, void* pData
)
3416 pView
->CallImplEventListeners( nEvent
, pData
);
3419 // -----------------------------------------------------------------------
3421 bool SvImpLBox::SetCurrentTabPos( sal_uInt16 _nNewPos
)
3425 if ( pView
&& _nNewPos
< ( pView
->TabCount() - 2 ) )
3427 nCurTabPos
= _nNewPos
;
3435 // -----------------------------------------------------------------------
3437 bool SvImpLBox::IsSelectable( const SvTreeListEntry
* pEntry
)
3441 SvViewDataEntry
* pViewDataNewCur
= pView
->GetViewDataEntry(const_cast<SvTreeListEntry
*>(pEntry
));
3442 return (pViewDataNewCur
== 0) || pViewDataNewCur
->IsSelectable();
3450 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */