1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ilstbox.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/debug.hxx>
34 #include <vcl/svdata.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/settings.hxx>
37 #include <vcl/event.hxx>
38 #include <vcl/scrbar.hxx>
39 #include <vcl/help.hxx>
40 #include <vcl/lstbox.h>
41 #include <vcl/ilstbox.hxx>
42 #include <vcl/i18nhelp.hxx>
43 #include <vcl/controllayout.hxx>
44 #include <vcl/unohelp.hxx>
45 #ifndef _COM_SUN_STAR_UTIL_XCOLLATOR_HPP_
46 #include <com/sun/star/i18n/XCollator.hpp>
49 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLE_HDL_
50 #include <com/sun/star/accessibility/XAccessible.hpp>
53 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEROLE_HPP_
54 #include <com/sun/star/accessibility/AccessibleRole.hpp>
57 #define MULTILINE_ENTRY_DRAW_FLAGS ( TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_VCENTER )
59 using namespace ::com::sun::star
;
61 // =======================================================================
63 void ImplInitFieldSettings( Window
* pWin
, BOOL bFont
, BOOL bForeground
, BOOL bBackground
)
65 const StyleSettings
& rStyleSettings
= pWin
->GetSettings().GetStyleSettings();
69 Font aFont
= rStyleSettings
.GetFieldFont();
70 if ( pWin
->IsControlFont() )
71 aFont
.Merge( pWin
->GetControlFont() );
72 pWin
->SetZoomedPointFont( aFont
);
75 if ( bFont
|| bForeground
)
77 Color aTextColor
= rStyleSettings
.GetFieldTextColor();
78 if ( pWin
->IsControlForeground() )
79 aTextColor
= pWin
->GetControlForeground();
80 pWin
->SetTextColor( aTextColor
);
85 if( pWin
->IsControlBackground() )
86 pWin
->SetBackground( pWin
->GetControlBackground() );
88 pWin
->SetBackground( rStyleSettings
.GetFieldColor() );
92 // -----------------------------------------------------------------------
94 void ImplInitDropDownButton( PushButton
* pButton
)
96 if ( pButton
->GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
97 pButton
->SetSymbol( SYMBOL_SPIN_UPDOWN
);
99 pButton
->SetSymbol( SYMBOL_SPIN_DOWN
);
101 if ( pButton
->IsNativeControlSupported(CTRL_LISTBOX
, PART_ENTIRE_CONTROL
)
102 && ! pButton
->IsNativeControlSupported(CTRL_LISTBOX
, PART_BUTTON_DOWN
) )
103 pButton
->SetBackground();
106 // =======================================================================
108 ImplEntryList::ImplEntryList( Window
* pWindow
)
111 mnLastSelected
= LISTBOX_ENTRY_NOTFOUND
;
112 mnSelectionAnchor
= LISTBOX_ENTRY_NOTFOUND
;
114 mbCallSelectionChangedHdl
= TRUE
;
120 // -----------------------------------------------------------------------
122 ImplEntryList::~ImplEntryList()
127 // -----------------------------------------------------------------------
129 void ImplEntryList::Clear()
132 for ( USHORT n
= GetEntryCount(); n
; )
134 ImplEntryType
* pImplEntry
= GetEntry( --n
);
140 // -----------------------------------------------------------------------
142 void ImplEntryList::SelectEntry( USHORT nPos
, BOOL bSelect
)
144 ImplEntryType
* pImplEntry
= GetEntry( nPos
);
146 ( pImplEntry
->mbIsSelected
!= bSelect
) &&
147 ( (pImplEntry
->mnFlags
& LISTBOX_ENTRY_FLAG_DISABLE_SELECTION
) == 0 ) )
149 pImplEntry
->mbIsSelected
= bSelect
;
150 if ( mbCallSelectionChangedHdl
)
151 maSelectionChangedHdl
.Call( (void*)sal_IntPtr(nPos
) );
155 // -----------------------------------------------------------------------
157 uno::Reference
< i18n::XCollator
> ImplGetCollator (lang::Locale
&rLocale
)
159 static uno::Reference
< i18n::XCollator
> xCollator
;
160 if ( !xCollator
.is() )
161 xCollator
= vcl::unohelper::CreateCollator();
163 xCollator
->loadDefaultCollator (rLocale
, 0);
168 USHORT
ImplEntryList::InsertEntry( USHORT nPos
, ImplEntryType
* pNewEntry
, BOOL bSort
)
170 if ( !!pNewEntry
->maImage
)
173 if ( !bSort
|| !Count() )
175 Insert( pNewEntry
, nPos
);
179 lang::Locale aLocale
= Application::GetSettings().GetLocale();
180 uno::Reference
< i18n::XCollator
> xCollator
= ImplGetCollator(aLocale
);
182 const XubString
& rStr
= pNewEntry
->maStr
;
183 ULONG nLow
, nHigh
, nMid
;
187 ImplEntryType
* pTemp
= GetEntry( (USHORT
)(nHigh
-1) );
191 // XXX even though XCollator::compareString returns a sal_Int32 the only
192 // defined values are {-1, 0, 1} which is compatible with StringCompare
193 StringCompare eComp
= xCollator
.is() ?
194 (StringCompare
)xCollator
->compareString (rStr
, pTemp
->maStr
)
197 // Schnelles Einfuegen bei sortierten Daten
198 if ( eComp
!= COMPARE_LESS
)
200 Insert( pNewEntry
, LIST_APPEND
);
205 pTemp
= (ImplEntryType
*)GetEntry( (USHORT
)nLow
);
207 eComp
= (StringCompare
)xCollator
->compareString (rStr
, pTemp
->maStr
);
208 if ( eComp
!= COMPARE_GREATER
)
210 Insert( pNewEntry
, (ULONG
)0 );
218 nMid
= (nLow
+ nHigh
) / 2;
219 pTemp
= (ImplEntryType
*)GetObject( nMid
);
221 eComp
= (StringCompare
)xCollator
->compareString (rStr
, pTemp
->maStr
);
223 if ( eComp
== COMPARE_LESS
)
227 if ( eComp
== COMPARE_GREATER
)
233 while ( nLow
<= nHigh
);
235 if ( eComp
!= COMPARE_LESS
)
238 Insert( pNewEntry
, nMid
);
242 catch (uno::RuntimeException
& )
244 // XXX this is arguable, if the exception occured because pNewEntry is
245 // garbage you wouldn't insert it. If the exception occured because the
246 // Collator implementation is garbage then give the user a chance to see
248 Insert( pNewEntry
, (ULONG
)0 );
253 return (USHORT
)GetPos( pNewEntry
);
256 // -----------------------------------------------------------------------
258 void ImplEntryList::RemoveEntry( USHORT nPos
)
260 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::Remove( nPos
);
263 if ( !!pImplEntry
->maImage
)
270 // -----------------------------------------------------------------------
272 USHORT
ImplEntryList::FindEntry( const XubString
& rString
, BOOL bSearchMRUArea
) const
274 USHORT nEntries
= GetEntryCount();
275 for ( USHORT n
= bSearchMRUArea
? 0 : GetMRUCount(); n
< nEntries
; n
++ )
277 ImplEntryType
* pImplEntry
= GetEntry( n
);
278 String
aComp( vcl::I18nHelper::filterFormattingChars( pImplEntry
->maStr
) );
279 if ( aComp
== rString
)
282 return LISTBOX_ENTRY_NOTFOUND
;
285 // -----------------------------------------------------------------------
287 USHORT
ImplEntryList::FindMatchingEntry( const XubString
& rStr
, USHORT nStart
, BOOL bForward
, BOOL bLazy
) const
289 USHORT nPos
= LISTBOX_ENTRY_NOTFOUND
;
290 USHORT nEntryCount
= GetEntryCount();
292 nStart
++; // wird sofort dekrementiert
294 const vcl::I18nHelper
& rI18nHelper
= mpWindow
->GetSettings().GetLocaleI18nHelper();
295 for ( USHORT n
= nStart
; bForward
? ( n
< nEntryCount
) : n
; )
300 ImplEntryType
* pImplEntry
= GetEntry( n
);
301 BOOL bMatch
= bLazy
? rI18nHelper
.MatchString( rStr
, pImplEntry
->maStr
) != 0 : ( rStr
.Match( pImplEntry
->maStr
) == STRING_MATCH
);
315 // -----------------------------------------------------------------------
317 USHORT
ImplEntryList::FindEntry( const void* pData
) const
319 USHORT nPos
= LISTBOX_ENTRY_NOTFOUND
;
320 for ( USHORT n
= GetEntryCount(); n
; )
322 ImplEntryType
* pImplEntry
= GetEntry( --n
);
323 if ( pImplEntry
->mpUserData
== pData
)
332 // -----------------------------------------------------------------------
334 long ImplEntryList::GetAddedHeight( USHORT i_nEndIndex
, USHORT i_nBeginIndex
, long i_nBeginHeight
) const
336 long nHeight
= i_nBeginHeight
;
337 USHORT nStart
= i_nEndIndex
> i_nBeginIndex
? i_nBeginIndex
: i_nEndIndex
;
338 USHORT nStop
= i_nEndIndex
> i_nBeginIndex
? i_nEndIndex
: i_nBeginIndex
;
339 USHORT nEntryCount
= GetEntryCount();
340 if( nStop
!= LISTBOX_ENTRY_NOTFOUND
&& nEntryCount
!= 0 )
343 if( nStop
> nEntryCount
-1 )
344 nStop
= nEntryCount
-1;
345 if( nStart
> nEntryCount
-1 )
346 nStart
= nEntryCount
-1;
348 USHORT nIndex
= nStart
;
349 while( nIndex
!= LISTBOX_ENTRY_NOTFOUND
&& nIndex
< nStop
)
351 nHeight
+= GetEntryPtr( nIndex
)-> mnHeight
;
357 return i_nEndIndex
> i_nBeginIndex
? nHeight
: -nHeight
;
360 // -----------------------------------------------------------------------
362 long ImplEntryList::GetEntryHeight( USHORT nPos
) const
364 ImplEntryType
* pImplEntry
= GetEntry( nPos
);
365 return pImplEntry
? pImplEntry
->mnHeight
: 0;
368 // -----------------------------------------------------------------------
370 XubString
ImplEntryList::GetEntryText( USHORT nPos
) const
372 XubString aEntryText
;
373 ImplEntryType
* pImplEntry
= GetEntry( nPos
);
375 aEntryText
= pImplEntry
->maStr
;
379 // -----------------------------------------------------------------------
381 BOOL
ImplEntryList::HasEntryImage( USHORT nPos
) const
384 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::GetObject( nPos
);
386 bImage
= !!pImplEntry
->maImage
;
390 // -----------------------------------------------------------------------
392 Image
ImplEntryList::GetEntryImage( USHORT nPos
) const
395 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::GetObject( nPos
);
397 aImage
= pImplEntry
->maImage
;
401 // -----------------------------------------------------------------------
403 void ImplEntryList::SetEntryData( USHORT nPos
, void* pNewData
)
405 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::GetObject( nPos
);
407 pImplEntry
->mpUserData
= pNewData
;
410 // -----------------------------------------------------------------------
412 void* ImplEntryList::GetEntryData( USHORT nPos
) const
414 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::GetObject( nPos
);
415 return pImplEntry
? pImplEntry
->mpUserData
: NULL
;
418 // -----------------------------------------------------------------------
420 void ImplEntryList::SetEntryFlags( USHORT nPos
, long nFlags
)
422 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::GetObject( nPos
);
424 pImplEntry
->mnFlags
= nFlags
;
427 // -----------------------------------------------------------------------
429 long ImplEntryList::GetEntryFlags( USHORT nPos
) const
431 ImplEntryType
* pImplEntry
= (ImplEntryType
*)List::GetObject( nPos
);
432 return pImplEntry
? pImplEntry
->mnFlags
: 0;
435 // -----------------------------------------------------------------------
437 USHORT
ImplEntryList::GetSelectEntryCount() const
439 USHORT nSelCount
= 0;
440 for ( USHORT n
= GetEntryCount(); n
; )
442 ImplEntryType
* pImplEntry
= GetEntry( --n
);
443 if ( pImplEntry
->mbIsSelected
)
449 // -----------------------------------------------------------------------
451 XubString
ImplEntryList::GetSelectEntry( USHORT nIndex
) const
453 return GetEntryText( GetSelectEntryPos( nIndex
) );
456 // -----------------------------------------------------------------------
458 USHORT
ImplEntryList::GetSelectEntryPos( USHORT nIndex
) const
460 USHORT nSelEntryPos
= LISTBOX_ENTRY_NOTFOUND
;
462 USHORT nEntryCount
= GetEntryCount();
464 for ( USHORT n
= 0; n
< nEntryCount
; n
++ )
466 ImplEntryType
* pImplEntry
= GetEntry( n
);
467 if ( pImplEntry
->mbIsSelected
)
469 if ( nSel
== nIndex
)
481 // -----------------------------------------------------------------------
483 BOOL
ImplEntryList::IsEntrySelected( const XubString
& rStr
) const
485 return IsEntryPosSelected( FindEntry( rStr
) );
488 // -----------------------------------------------------------------------
490 BOOL
ImplEntryList::IsEntryPosSelected( USHORT nIndex
) const
492 ImplEntryType
* pImplEntry
= GetEntry( nIndex
);
493 return pImplEntry
? pImplEntry
->mbIsSelected
: FALSE
;
496 // -----------------------------------------------------------------------
498 bool ImplEntryList::IsEntrySelectable( USHORT nPos
) const
500 ImplEntryType
* pImplEntry
= GetEntry( nPos
);
501 return pImplEntry
? ((pImplEntry
->mnFlags
& LISTBOX_ENTRY_FLAG_DISABLE_SELECTION
) == 0) : true;
504 // -----------------------------------------------------------------------
506 USHORT
ImplEntryList::FindFirstSelectable( USHORT nPos
, bool bForward
/* = true */ )
508 if( IsEntrySelectable( nPos
) )
513 for( nPos
= nPos
+ 1; nPos
< GetEntryCount(); nPos
++ )
515 if( IsEntrySelectable( nPos
) )
524 if( IsEntrySelectable( nPos
) )
529 return LISTBOX_ENTRY_NOTFOUND
;
532 // =======================================================================
534 ImplListBoxWindow::ImplListBoxWindow( Window
* pParent
, WinBits nWinStyle
) :
535 Control( pParent
, 0 )
537 mpEntryList
= new ImplEntryList( this );
542 mnSelectModifier
= 0;
543 mnUserDrawEntry
= LISTBOX_ENTRY_NOTFOUND
;
545 mbImgsDiffSz
= FALSE
;
546 mbTravelSelect
= FALSE
;
547 mbTrackingSelect
= FALSE
;
548 mbSelectionChanged
= FALSE
;
549 mbMouseMoveSelect
= FALSE
;
553 mbUserDrawEnabled
= FALSE
;
554 mbInUserDraw
= FALSE
;
556 mbHasFocusRect
= FALSE
;
557 mbRight
= ( nWinStyle
& WB_RIGHT
) ? TRUE
: FALSE
;
558 mbCenter
= ( nWinStyle
& WB_CENTER
) ? TRUE
: FALSE
;
559 mbSimpleMode
= ( nWinStyle
& WB_SIMPLEMODE
) ? TRUE
: FALSE
;
560 mbSort
= ( nWinStyle
& WB_SORT
) ? TRUE
: FALSE
;
562 // pb: #106948# explicit mirroring for calc
565 mnCurrentPos
= LISTBOX_ENTRY_NOTFOUND
;
566 mnTrackingSaveSelection
= LISTBOX_ENTRY_NOTFOUND
;
567 mnSeparatorPos
= LISTBOX_ENTRY_NOTFOUND
;
571 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
573 maSearchTimeout
.SetTimeout( 2500 );
574 maSearchTimeout
.SetTimeoutHdl( LINK( this, ImplListBoxWindow
, SearchStringTimeout
) );
576 ImplInitSettings( TRUE
, TRUE
, TRUE
);
580 // -----------------------------------------------------------------------
582 ImplListBoxWindow::~ImplListBoxWindow()
584 maSearchTimeout
.Stop();
588 // -----------------------------------------------------------------------
590 void ImplListBoxWindow::ImplInitSettings( BOOL bFont
, BOOL bForeground
, BOOL bBackground
)
592 ImplInitFieldSettings( this, bFont
, bForeground
, bBackground
);
595 // -----------------------------------------------------------------------
597 void ImplListBoxWindow::ImplCalcMetrics()
605 mnTextHeight
= (USHORT
)GetTextHeight();
606 mnMaxTxtHeight
= mnTextHeight
+ mnBorder
;
607 mnMaxHeight
= mnMaxTxtHeight
;
609 if ( maUserItemSize
.Height() > mnMaxHeight
)
610 mnMaxHeight
= (USHORT
) maUserItemSize
.Height();
611 if ( maUserItemSize
.Width() > mnMaxWidth
)
612 mnMaxWidth
= (USHORT
) maUserItemSize
.Width();
614 for ( USHORT n
= mpEntryList
->GetEntryCount(); n
; )
616 ImplEntryType
* pEntry
= mpEntryList
->GetMutableEntryPtr( --n
);
617 ImplUpdateEntryMetrics( *pEntry
);
620 if( mnCurrentPos
!= LISTBOX_ENTRY_NOTFOUND
)
622 Size
aSz( GetOutputSizePixel().Width(), mpEntryList
->GetEntryPtr( mnCurrentPos
)->mnHeight
);
623 maFocusRect
.SetSize( aSz
);
627 // -----------------------------------------------------------------------
629 IMPL_LINK( ImplListBoxWindow
, SearchStringTimeout
, Timer
*, EMPTYARG
)
635 // -----------------------------------------------------------------------
637 void ImplListBoxWindow::Clear()
639 mpEntryList
->Clear();
641 mnMaxHeight
= mnMaxTxtHeight
;
649 mbImgsDiffSz
= FALSE
;
650 delete mpLayoutData
, mpLayoutData
= NULL
;
652 mnCurrentPos
= LISTBOX_ENTRY_NOTFOUND
;
657 void ImplListBoxWindow::SetUserItemSize( const Size
& rSz
)
659 delete mpLayoutData
, mpLayoutData
= NULL
;
660 maUserItemSize
= rSz
;
664 // -----------------------------------------------------------------------
666 struct ImplEntryMetrics
677 // -----------------------------------------------------------------------
679 void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType
& rEntry
)
681 ImplEntryMetrics aMetrics
;
682 aMetrics
.bText
= rEntry
.maStr
.Len() ? TRUE
: FALSE
;
683 aMetrics
.bImage
= !!rEntry
.maImage
;
684 aMetrics
.nEntryWidth
= 0;
685 aMetrics
.nEntryHeight
= 0;
686 aMetrics
.nTextWidth
= 0;
687 aMetrics
.nImgWidth
= 0;
688 aMetrics
.nImgHeight
= 0;
690 if ( aMetrics
.bText
)
692 if( (rEntry
.mnFlags
& LISTBOX_ENTRY_FLAG_MULTILINE
) )
695 Size
aCurSize( PixelToLogic( GetSizePixel() ) );
696 // set the current size to a large number
697 // GetTextRect should shrink it to the actual size
698 aCurSize
.Height() = 0x7fffff;
699 Rectangle
aTextRect( Point( 0, 0 ), aCurSize
);
700 aTextRect
= GetTextRect( aTextRect
, rEntry
.maStr
, TEXT_DRAW_WORDBREAK
| TEXT_DRAW_MULTILINE
);
701 aMetrics
.nTextWidth
= aTextRect
.GetWidth();
702 if( aMetrics
.nTextWidth
> mnMaxTxtWidth
)
703 mnMaxTxtWidth
= aMetrics
.nTextWidth
;
704 aMetrics
.nEntryWidth
= mnMaxTxtWidth
;
705 aMetrics
.nEntryHeight
= aTextRect
.GetHeight() + mnBorder
;
709 // normal single line case
710 aMetrics
.nTextWidth
= (USHORT
)GetTextWidth( rEntry
.maStr
);
711 if( aMetrics
.nTextWidth
> mnMaxTxtWidth
)
712 mnMaxTxtWidth
= aMetrics
.nTextWidth
;
713 aMetrics
.nEntryWidth
= mnMaxTxtWidth
;
714 aMetrics
.nEntryHeight
= mnTextHeight
+ mnBorder
;
717 if ( aMetrics
.bImage
)
719 Size aImgSz
= rEntry
.maImage
.GetSizePixel();
720 aMetrics
.nImgWidth
= (USHORT
) CalcZoom( aImgSz
.Width() );
721 aMetrics
.nImgHeight
= (USHORT
) CalcZoom( aImgSz
.Height() );
723 if( mnMaxImgWidth
&& ( aMetrics
.nImgWidth
!= mnMaxImgWidth
) )
725 else if ( mnMaxImgHeight
&& ( aMetrics
.nImgHeight
!= mnMaxImgHeight
) )
728 if( aMetrics
.nImgWidth
> mnMaxImgWidth
)
729 mnMaxImgWidth
= aMetrics
.nImgWidth
;
730 if( aMetrics
.nImgHeight
> mnMaxImgHeight
)
731 mnMaxImgHeight
= aMetrics
.nImgHeight
;
733 mnMaxImgTxtWidth
= Max( mnMaxImgTxtWidth
, aMetrics
.nTextWidth
);
734 aMetrics
.nEntryHeight
= Max( aMetrics
.nImgHeight
, aMetrics
.nEntryHeight
);
737 if ( IsUserDrawEnabled() || aMetrics
.bImage
)
739 aMetrics
.nEntryWidth
= Max( aMetrics
.nImgWidth
, maUserItemSize
.Width() );
740 if ( aMetrics
.bText
)
741 aMetrics
.nEntryWidth
+= aMetrics
.nTextWidth
+ IMG_TXT_DISTANCE
;
742 aMetrics
.nEntryHeight
= Max( Max( mnMaxImgHeight
, maUserItemSize
.Height() ) + 2,
743 aMetrics
.nEntryHeight
);
746 if ( aMetrics
.nEntryWidth
> mnMaxWidth
)
747 mnMaxWidth
= aMetrics
.nEntryWidth
;
748 if ( aMetrics
.nEntryHeight
> mnMaxHeight
)
749 mnMaxHeight
= aMetrics
.nEntryHeight
;
751 rEntry
.mnHeight
= aMetrics
.nEntryHeight
;
754 // -----------------------------------------------------------------------
756 void ImplListBoxWindow::ImplCallSelect()
758 if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() )
760 // Insert the selected entry as MRU, if not allready first MRU
761 USHORT nSelected
= GetEntryList()->GetSelectEntryPos( 0 );
762 USHORT nMRUCount
= GetEntryList()->GetMRUCount();
763 String aSelected
= GetEntryList()->GetEntryText( nSelected
);
764 USHORT nFirstMatchingEntryPos
= GetEntryList()->FindEntry( aSelected
, TRUE
);
765 if ( nFirstMatchingEntryPos
|| !nMRUCount
)
767 BOOL bSelectNewEntry
= FALSE
;
768 if ( nFirstMatchingEntryPos
< nMRUCount
)
770 RemoveEntry( nFirstMatchingEntryPos
);
772 if ( nFirstMatchingEntryPos
== nSelected
)
773 bSelectNewEntry
= TRUE
;
775 else if ( nMRUCount
== GetEntryList()->GetMaxMRUCount() )
777 RemoveEntry( nMRUCount
- 1 );
781 delete mpLayoutData
, mpLayoutData
= NULL
;
783 ImplEntryType
* pNewEntry
= new ImplEntryType( aSelected
);
784 pNewEntry
->mbIsSelected
= bSelectNewEntry
;
785 GetEntryList()->InsertEntry( 0, pNewEntry
, FALSE
);
786 ImplUpdateEntryMetrics( *pNewEntry
);
787 GetEntryList()->SetMRUCount( ++nMRUCount
);
788 SetSeparatorPos( nMRUCount
? nMRUCount
-1 : 0 );
789 maMRUChangedHdl
.Call( NULL
);
793 maSelectHdl
.Call( NULL
);
794 mbSelectionChanged
= FALSE
;
797 // -----------------------------------------------------------------------
799 USHORT
ImplListBoxWindow::InsertEntry( USHORT nPos
, ImplEntryType
* pNewEntry
)
801 delete mpLayoutData
, mpLayoutData
= NULL
;
802 USHORT nNewPos
= mpEntryList
->InsertEntry( nPos
, pNewEntry
, mbSort
);
804 if( (GetStyle() & WB_WORDBREAK
) )
805 pNewEntry
->mnFlags
|= LISTBOX_ENTRY_FLAG_MULTILINE
;
807 ImplUpdateEntryMetrics( *pNewEntry
);
811 // -----------------------------------------------------------------------
813 void ImplListBoxWindow::RemoveEntry( USHORT nPos
)
815 delete mpLayoutData
, mpLayoutData
= NULL
;
816 mpEntryList
->RemoveEntry( nPos
);
817 if( mnCurrentPos
>= mpEntryList
->GetEntryCount() )
818 mnCurrentPos
= LISTBOX_ENTRY_NOTFOUND
;
822 // -----------------------------------------------------------------------
824 void ImplListBoxWindow::SetEntryFlags( USHORT nPos
, long nFlags
)
826 mpEntryList
->SetEntryFlags( nPos
, nFlags
);
827 ImplEntryType
* pEntry
= mpEntryList
->GetMutableEntryPtr( nPos
);
829 ImplUpdateEntryMetrics( *pEntry
);
832 // -----------------------------------------------------------------------
834 void ImplListBoxWindow::ImplShowFocusRect()
836 if ( mbHasFocusRect
)
838 ShowFocus( maFocusRect
);
839 mbHasFocusRect
= TRUE
;
842 // -----------------------------------------------------------------------
844 void ImplListBoxWindow::ImplHideFocusRect()
846 if ( mbHasFocusRect
)
849 mbHasFocusRect
= FALSE
;
854 // -----------------------------------------------------------------------
856 USHORT
ImplListBoxWindow::GetEntryPosForPoint( const Point
& rPoint
) const
860 USHORT nSelect
= mnTop
;
861 const ImplEntryType
* pEntry
= mpEntryList
->GetEntryPtr( nSelect
);
862 while( pEntry
&& rPoint
.Y() > pEntry
->mnHeight
+ nY
)
864 nY
+= pEntry
->mnHeight
;
865 pEntry
= mpEntryList
->GetEntryPtr( ++nSelect
);
868 nSelect
= LISTBOX_ENTRY_NOTFOUND
;
873 // -----------------------------------------------------------------------
875 BOOL
ImplListBoxWindow::IsVisible( USHORT i_nEntry
) const
879 if( i_nEntry
>= mnTop
)
881 if( mpEntryList
->GetAddedHeight( i_nEntry
, mnTop
) <
882 PixelToLogic( GetSizePixel() ).Height() )
891 // -----------------------------------------------------------------------
893 USHORT
ImplListBoxWindow::GetLastVisibleEntry() const
896 long nWindowHeight
= GetSizePixel().Height();
897 USHORT nCount
= mpEntryList
->GetEntryCount();
899 for( nDiff
= 0; nDiff
< nWindowHeight
&& nPos
< nCount
; nDiff
= mpEntryList
->GetAddedHeight( nPos
, mnTop
) )
902 if( nDiff
> nWindowHeight
&& nPos
> mnTop
)
911 // -----------------------------------------------------------------------
913 void ImplListBoxWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
915 mbMouseMoveSelect
= FALSE
; // Nur bis zum ersten MouseButtonDown
920 if( rMEvt
.GetClicks() == 1 )
922 USHORT nSelect
= GetEntryPosForPoint( rMEvt
.GetPosPixel() );
923 if( nSelect
!= LISTBOX_ENTRY_NOTFOUND
)
925 if ( !mbMulti
&& GetEntryList()->GetSelectEntryCount() )
926 mnTrackingSaveSelection
= GetEntryList()->GetSelectEntryPos( 0 );
928 mnTrackingSaveSelection
= LISTBOX_ENTRY_NOTFOUND
;
930 mnCurrentPos
= nSelect
;
931 mbTrackingSelect
= TRUE
;
932 SelectEntries( nSelect
, LET_MBDOWN
, rMEvt
.IsShift(), rMEvt
.IsMod1() );
933 mbTrackingSelect
= FALSE
;
937 StartTracking( STARTTRACK_SCROLLREPEAT
);
940 if( rMEvt
.GetClicks() == 2 )
942 maDoubleClickHdl
.Call( this );
945 else // if ( mbGrabFocus )
951 // -----------------------------------------------------------------------
953 void ImplListBoxWindow::MouseMove( const MouseEvent
& rMEvt
)
955 if ( rMEvt
.IsLeaveWindow() )
957 if ( mbStackMode
&& IsMouseMoveSelect() && IsReallyVisible() )
959 if ( rMEvt
.GetPosPixel().Y() < 0 )
962 mnCurrentPos
= LISTBOX_ENTRY_NOTFOUND
;
964 if ( mbStackMode
) // #87072#, #92323#
966 mbTravelSelect
= TRUE
;
967 mnSelectModifier
= rMEvt
.GetModifier();
969 mbTravelSelect
= FALSE
;
975 else if ( ( ( !mbMulti
&& IsMouseMoveSelect() ) || mbStackMode
) && mpEntryList
->GetEntryCount() )
978 Rectangle
aRect( aPoint
, GetOutputSizePixel() );
979 if( aRect
.IsInside( rMEvt
.GetPosPixel() ) )
981 if ( IsMouseMoveSelect() )
983 USHORT nSelect
= GetEntryPosForPoint( rMEvt
.GetPosPixel() );
984 if( nSelect
== LISTBOX_ENTRY_NOTFOUND
)
985 nSelect
= mpEntryList
->GetEntryCount() - 1;
986 nSelect
= Min( nSelect
, GetLastVisibleEntry() );
987 nSelect
= Min( nSelect
, (USHORT
) ( mpEntryList
->GetEntryCount() - 1 ) );
988 // Select only visible Entries with MouseMove, otherwise Tracking...
989 if ( IsVisible( nSelect
) &&
990 mpEntryList
->IsEntrySelectable( nSelect
) &&
991 ( ( nSelect
!= mnCurrentPos
) || !GetEntryList()->GetSelectEntryCount() || ( nSelect
!= GetEntryList()->GetSelectEntryPos( 0 ) ) ) )
993 mbTrackingSelect
= TRUE
;
994 if ( SelectEntries( nSelect
, LET_TRACKING
, FALSE
, FALSE
) )
996 if ( mbStackMode
) // #87072#
998 mbTravelSelect
= TRUE
;
999 mnSelectModifier
= rMEvt
.GetModifier();
1001 mbTravelSelect
= FALSE
;
1004 mbTrackingSelect
= FALSE
;
1008 // Falls der DD-Button gedrueckt wurde und jemand mit gedrueckter
1009 // Maustaste in die ListBox faehrt...
1010 if ( rMEvt
.IsLeft() && !rMEvt
.IsSynthetic() )
1012 if ( !mbMulti
&& GetEntryList()->GetSelectEntryCount() )
1013 mnTrackingSaveSelection
= GetEntryList()->GetSelectEntryPos( 0 );
1015 mnTrackingSaveSelection
= LISTBOX_ENTRY_NOTFOUND
;
1017 if ( mbStackMode
&& ( mpEntryList
->GetSelectionAnchor() == LISTBOX_ENTRY_NOTFOUND
) )
1018 mpEntryList
->SetSelectionAnchor( 0 );
1020 StartTracking( STARTTRACK_SCROLLREPEAT
);
1026 // -----------------------------------------------------------------------
1028 void ImplListBoxWindow::DeselectAll()
1030 while ( GetEntryList()->GetSelectEntryCount() )
1032 USHORT nS
= GetEntryList()->GetSelectEntryPos( 0 );
1033 SelectEntry( nS
, FALSE
);
1037 // -----------------------------------------------------------------------
1039 void ImplListBoxWindow::SelectEntry( USHORT nPos
, BOOL bSelect
)
1041 if( (mpEntryList
->IsEntryPosSelected( nPos
) != bSelect
) && mpEntryList
->IsEntrySelectable( nPos
) )
1043 ImplHideFocusRect();
1048 // Selektierten Eintrag deselektieren
1049 USHORT nDeselect
= GetEntryList()->GetSelectEntryPos( 0 );
1050 if( nDeselect
!= LISTBOX_ENTRY_NOTFOUND
)
1052 //SelectEntryPos( nDeselect, FALSE );
1053 GetEntryList()->SelectEntry( nDeselect
, FALSE
);
1054 if ( IsUpdateMode() && IsReallyVisible() )
1055 ImplPaint( nDeselect
, TRUE
);
1058 mpEntryList
->SelectEntry( nPos
, TRUE
);
1059 mnCurrentPos
= nPos
;
1060 if ( ( nPos
!= LISTBOX_ENTRY_NOTFOUND
) && IsUpdateMode() )
1063 if ( !IsVisible( nPos
) )
1065 delete mpLayoutData
, mpLayoutData
= NULL
;
1066 USHORT nVisibleEntries
= GetLastVisibleEntry()-mnTop
;
1067 if ( !nVisibleEntries
|| !IsReallyVisible() || ( nPos
< GetTopEntry() ) )
1070 SetTopEntry( nPos
);
1074 SetTopEntry( nPos
-nVisibleEntries
+1 );
1081 mpEntryList
->SelectEntry( nPos
, FALSE
);
1082 ImplPaint( nPos
, TRUE
);
1084 mbSelectionChanged
= TRUE
;
1088 // -----------------------------------------------------------------------
1090 BOOL
ImplListBoxWindow::SelectEntries( USHORT nSelect
, LB_EVENT_TYPE eLET
, BOOL bShift
, BOOL bCtrl
)
1092 BOOL bFocusChanged
= FALSE
;
1093 BOOL bSelectionChanged
= FALSE
;
1095 if( IsEnabled() && mpEntryList
->IsEntrySelectable( nSelect
) )
1097 // Hier (Single-ListBox) kann nur ein Eintrag deselektiert werden
1100 USHORT nDeselect
= mpEntryList
->GetSelectEntryPos( 0 );
1101 if( nSelect
!= nDeselect
)
1103 SelectEntry( nSelect
, TRUE
);
1104 mpEntryList
->SetLastSelected( nSelect
);
1105 bFocusChanged
= TRUE
;
1106 bSelectionChanged
= TRUE
;
1109 // MultiListBox ohne Modifier
1110 else if( mbSimpleMode
&& !bCtrl
&& !bShift
)
1112 USHORT nEntryCount
= mpEntryList
->GetEntryCount();
1113 for ( USHORT nPos
= 0; nPos
< nEntryCount
; nPos
++ )
1115 BOOL bSelect
= nPos
== nSelect
;
1116 if ( mpEntryList
->IsEntryPosSelected( nPos
) != bSelect
)
1118 SelectEntry( nPos
, bSelect
);
1119 bFocusChanged
= TRUE
;
1120 bSelectionChanged
= TRUE
;
1123 mpEntryList
->SetLastSelected( nSelect
);
1124 mpEntryList
->SetSelectionAnchor( nSelect
);
1126 // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode
1127 else if( ( !mbSimpleMode
/* && !bShift */ ) || ( (mbSimpleMode
&& ( bCtrl
|| bShift
)) || mbStackMode
) )
1129 // Space fuer Selektionswechsel
1130 if( !bShift
&& ( ( eLET
== LET_KEYSPACE
) || ( eLET
== LET_MBDOWN
) ) )
1132 BOOL bSelect
= ( mbStackMode
&& IsMouseMoveSelect() ) ? TRUE
: !mpEntryList
->IsEntryPosSelected( nSelect
);
1138 // All entries before nSelect must be selected...
1139 for ( n
= 0; n
< nSelect
; n
++ )
1140 SelectEntry( n
, TRUE
);
1144 for ( n
= nSelect
+1; n
< mpEntryList
->GetEntryCount(); n
++ )
1145 SelectEntry( n
, FALSE
);
1148 SelectEntry( nSelect
, bSelect
);
1149 mpEntryList
->SetLastSelected( nSelect
);
1150 mpEntryList
->SetSelectionAnchor( mbStackMode
? 0 : nSelect
);
1151 if ( !mpEntryList
->IsEntryPosSelected( nSelect
) )
1152 mpEntryList
->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND
);
1153 bFocusChanged
= TRUE
;
1154 bSelectionChanged
= TRUE
;
1156 else if( ( ( eLET
== LET_TRACKING
) && ( nSelect
!= mnCurrentPos
) ) ||
1157 ( (bShift
||mbStackMode
) && ( ( eLET
== LET_KEYMOVE
) || ( eLET
== LET_MBDOWN
) ) ) )
1159 mnCurrentPos
= nSelect
;
1160 bFocusChanged
= TRUE
;
1162 USHORT nAnchor
= mpEntryList
->GetSelectionAnchor();
1163 if( ( nAnchor
== LISTBOX_ENTRY_NOTFOUND
) && ( mpEntryList
->GetSelectEntryCount() || mbStackMode
) )
1165 nAnchor
= mbStackMode
? 0 : mpEntryList
->GetSelectEntryPos( mpEntryList
->GetSelectEntryCount() - 1 );
1167 if( nAnchor
!= LISTBOX_ENTRY_NOTFOUND
)
1169 // Alle Eintraege vom Anchor bis nSelect muessen selektiert sein
1170 USHORT nStart
= Min( nSelect
, nAnchor
);
1171 USHORT nEnd
= Max( nSelect
, nAnchor
);
1172 for ( USHORT n
= nStart
; n
<= nEnd
; n
++ )
1174 if ( !mpEntryList
->IsEntryPosSelected( n
) )
1176 SelectEntry( n
, TRUE
);
1177 bSelectionChanged
= TRUE
;
1181 // Ggf. muss noch was deselektiert werden...
1182 USHORT nLast
= mpEntryList
->GetLastSelected();
1183 if ( nLast
!= LISTBOX_ENTRY_NOTFOUND
)
1185 if ( ( nLast
> nSelect
) && ( nLast
> nAnchor
) )
1187 for ( USHORT n
= nSelect
+1; n
<= nLast
; n
++ )
1189 if ( mpEntryList
->IsEntryPosSelected( n
) )
1191 SelectEntry( n
, FALSE
);
1192 bSelectionChanged
= TRUE
;
1196 else if ( ( nLast
< nSelect
) && ( nLast
< nAnchor
) )
1198 for ( USHORT n
= nLast
; n
< nSelect
; n
++ )
1200 if ( mpEntryList
->IsEntryPosSelected( n
) )
1202 SelectEntry( n
, FALSE
);
1203 bSelectionChanged
= TRUE
;
1208 mpEntryList
->SetLastSelected( nSelect
);
1211 else if( eLET
!= LET_TRACKING
)
1213 ImplHideFocusRect();
1214 ImplPaint( nSelect
, TRUE
);
1215 bFocusChanged
= TRUE
;
1220 bFocusChanged
= TRUE
;
1223 if( bSelectionChanged
)
1224 mbSelectionChanged
= TRUE
;
1228 long nHeightDiff
= mpEntryList
->GetAddedHeight( nSelect
, mnTop
, 0 );
1229 maFocusRect
.SetPos( Point( 0, nHeightDiff
) );
1230 Size
aSz( maFocusRect
.GetWidth(),
1231 mpEntryList
->GetEntryHeight( nSelect
) );
1232 maFocusRect
.SetSize( aSz
);
1234 ImplShowFocusRect();
1236 delete mpLayoutData
, mpLayoutData
= NULL
;
1238 return bSelectionChanged
;
1241 // -----------------------------------------------------------------------
1243 void ImplListBoxWindow::Tracking( const TrackingEvent
& rTEvt
)
1246 Rectangle
aRect( aPoint
, GetOutputSizePixel() );
1247 BOOL bInside
= aRect
.IsInside( rTEvt
.GetMouseEvent().GetPosPixel() );
1249 if( rTEvt
.IsTrackingCanceled() || rTEvt
.IsTrackingEnded() ) // MouseButtonUp
1251 if ( bInside
&& !rTEvt
.IsTrackingCanceled() )
1253 mnSelectModifier
= rTEvt
.GetMouseEvent().GetModifier();
1258 maCancelHdl
.Call( NULL
);
1261 mbTrackingSelect
= TRUE
;
1262 SelectEntry( mnTrackingSaveSelection
, TRUE
);
1263 mbTrackingSelect
= FALSE
;
1264 if ( mnTrackingSaveSelection
!= LISTBOX_ENTRY_NOTFOUND
)
1266 long nHeightDiff
= mpEntryList
->GetAddedHeight( mnCurrentPos
, mnTop
, 0 );
1267 maFocusRect
.SetPos( Point( 0, nHeightDiff
) );
1268 Size
aSz( maFocusRect
.GetWidth(),
1269 mpEntryList
->GetEntryHeight( mnCurrentPos
) );
1270 maFocusRect
.SetSize( aSz
);
1271 ImplShowFocusRect();
1280 BOOL bTrackOrQuickClick
= mbTrack
;
1288 // Folgender Fall tritt nur auf, wenn man ganz kurz die Maustaste drueckt
1289 if( rTEvt
.IsTrackingEnded() && mbTrack
)
1291 bTrackOrQuickClick
= TRUE
;
1296 if( bTrackOrQuickClick
)
1298 MouseEvent aMEvt
= rTEvt
.GetMouseEvent();
1299 Point
aPt( aMEvt
.GetPosPixel() );
1300 BOOL bShift
= aMEvt
.IsShift();
1301 BOOL bCtrl
= aMEvt
.IsMod1();
1303 USHORT nSelect
= LISTBOX_ENTRY_NOTFOUND
;
1306 if ( mnCurrentPos
!= LISTBOX_ENTRY_NOTFOUND
)
1308 nSelect
= mnCurrentPos
? ( mnCurrentPos
- 1 ) : 0;
1309 if( nSelect
< mnTop
)
1310 SetTopEntry( mnTop
-1 );
1313 else if( aPt
.Y() > GetOutputSizePixel().Height() )
1315 if ( mnCurrentPos
!= LISTBOX_ENTRY_NOTFOUND
)
1317 nSelect
= Min( (USHORT
)(mnCurrentPos
+1), (USHORT
)(mpEntryList
->GetEntryCount()-1) );
1318 if( nSelect
>= GetLastVisibleEntry() )
1319 SetTopEntry( mnTop
+1 );
1324 nSelect
= (USHORT
) ( ( aPt
.Y() + mnBorder
) / mnMaxHeight
) + (USHORT
) mnTop
;
1325 nSelect
= Min( nSelect
, GetLastVisibleEntry() );
1326 nSelect
= Min( nSelect
, (USHORT
) ( mpEntryList
->GetEntryCount() - 1 ) );
1331 if ( ( nSelect
!= mnCurrentPos
) || !GetEntryList()->GetSelectEntryCount() )
1333 mbTrackingSelect
= TRUE
;
1334 if ( SelectEntries( nSelect
, LET_TRACKING
, bShift
, bCtrl
) )
1336 if ( mbStackMode
) // #87734# (#87072#)
1338 mbTravelSelect
= TRUE
;
1339 mnSelectModifier
= rTEvt
.GetMouseEvent().GetModifier();
1341 mbTravelSelect
= FALSE
;
1344 mbTrackingSelect
= FALSE
;
1349 if ( !mbMulti
&& GetEntryList()->GetSelectEntryCount() )
1351 mbTrackingSelect
= TRUE
;
1352 SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), FALSE
);
1353 mbTrackingSelect
= FALSE
;
1355 else if ( mbStackMode
)
1357 if ( ( rTEvt
.GetMouseEvent().GetPosPixel().X() > 0 ) && ( rTEvt
.GetMouseEvent().GetPosPixel().X() < aRect
.Right() ) )
1359 if ( ( rTEvt
.GetMouseEvent().GetPosPixel().Y() < 0 ) || ( rTEvt
.GetMouseEvent().GetPosPixel().Y() > GetOutputSizePixel().Height() ) )
1361 BOOL bSelectionChanged
= FALSE
;
1362 if ( ( rTEvt
.GetMouseEvent().GetPosPixel().Y() < 0 )
1365 if ( mpEntryList
->IsEntryPosSelected( 0 ) )
1367 SelectEntry( 0, FALSE
);
1368 bSelectionChanged
= TRUE
;
1369 nSelect
= LISTBOX_ENTRY_NOTFOUND
;
1375 mbTrackingSelect
= TRUE
;
1376 bSelectionChanged
= SelectEntries( nSelect
, LET_TRACKING
, bShift
, bCtrl
);
1377 mbTrackingSelect
= FALSE
;
1380 if ( bSelectionChanged
)
1382 mbSelectionChanged
= TRUE
;
1383 mbTravelSelect
= TRUE
;
1384 mnSelectModifier
= rTEvt
.GetMouseEvent().GetModifier();
1386 mbTravelSelect
= FALSE
;
1392 mnCurrentPos
= nSelect
;
1393 if ( mnCurrentPos
== LISTBOX_ENTRY_NOTFOUND
)
1395 ImplHideFocusRect();
1399 long nHeightDiff
= mpEntryList
->GetAddedHeight( mnCurrentPos
, mnTop
, 0 );
1400 maFocusRect
.SetPos( Point( 0, nHeightDiff
) );
1401 Size
aSz( maFocusRect
.GetWidth(), mpEntryList
->GetEntryHeight( mnCurrentPos
) );
1402 maFocusRect
.SetSize( aSz
);
1403 ImplShowFocusRect();
1410 // -----------------------------------------------------------------------
1412 void ImplListBoxWindow::KeyInput( const KeyEvent
& rKEvt
)
1414 if( !ProcessKeyInput( rKEvt
) )
1415 Control::KeyInput( rKEvt
);
1418 // -----------------------------------------------------------------------
1420 #define IMPL_SELECT_NODIRECTION 0
1421 #define IMPL_SELECT_UP 1
1422 #define IMPL_SELECT_DOWN 2
1424 BOOL
ImplListBoxWindow::ProcessKeyInput( const KeyEvent
& rKEvt
)
1426 // zu selektierender Eintrag
1427 USHORT nSelect
= LISTBOX_ENTRY_NOTFOUND
;
1428 LB_EVENT_TYPE eLET
= LET_KEYMOVE
;
1430 KeyCode aKeyCode
= rKEvt
.GetKeyCode();
1432 BOOL bShift
= aKeyCode
.IsShift();
1433 BOOL bCtrl
= aKeyCode
.IsMod1() || aKeyCode
.IsMod3();
1434 BOOL bMod2
= aKeyCode
.IsMod2();
1437 switch( aKeyCode
.GetCode() )
1443 if ( GetTopEntry() )
1444 SetTopEntry( GetTopEntry()-1 );
1448 if( mnCurrentPos
== LISTBOX_ENTRY_NOTFOUND
)
1450 nSelect
= mpEntryList
->FindFirstSelectable( 0, true );
1452 else if ( mnCurrentPos
)
1454 // search first selectable above the current position
1455 nSelect
= mpEntryList
->FindFirstSelectable( mnCurrentPos
- 1, false );
1458 if( ( nSelect
!= LISTBOX_ENTRY_NOTFOUND
) && ( nSelect
< mnTop
) )
1459 SetTopEntry( mnTop
-1 );
1463 maSearchStr
.Erase();
1471 SetTopEntry( GetTopEntry()+1 );
1475 if( mnCurrentPos
== LISTBOX_ENTRY_NOTFOUND
)
1477 nSelect
= mpEntryList
->FindFirstSelectable( 0, true );
1479 else if ( (mnCurrentPos
+1) < mpEntryList
->GetEntryCount() )
1481 // search first selectable below the current position
1482 nSelect
= mpEntryList
->FindFirstSelectable( mnCurrentPos
+ 1, true );
1485 if( ( nSelect
!= LISTBOX_ENTRY_NOTFOUND
) && ( nSelect
>= GetLastVisibleEntry() ) )
1486 SetTopEntry( mnTop
+1 );
1490 maSearchStr
.Erase();
1498 USHORT nCurVis
= GetLastVisibleEntry() - mnTop
+1;
1499 SetTopEntry( ( mnTop
> nCurVis
) ?
1500 (mnTop
-nCurVis
) : 0 );
1502 else if ( !bCtrl
&& !bMod2
)
1504 if( mnCurrentPos
== LISTBOX_ENTRY_NOTFOUND
)
1506 nSelect
= mpEntryList
->FindFirstSelectable( 0, true );
1508 else if ( mnCurrentPos
)
1510 if( mnCurrentPos
== mnTop
)
1512 USHORT nCurVis
= GetLastVisibleEntry() - mnTop
+1;
1513 SetTopEntry( ( mnTop
> nCurVis
) ? ( mnTop
-nCurVis
+1 ) : 0 );
1516 // find first selectable starting from mnTop looking foreward
1517 nSelect
= mpEntryList
->FindFirstSelectable( mnTop
, true );
1521 maSearchStr
.Erase();
1529 SetTopEntry( GetLastVisibleEntry() );
1531 else if ( !bCtrl
&& !bMod2
)
1533 if( mnCurrentPos
== LISTBOX_ENTRY_NOTFOUND
)
1535 nSelect
= mpEntryList
->FindFirstSelectable( 0, true );
1537 else if ( (mnCurrentPos
+1) < mpEntryList
->GetEntryCount() )
1539 USHORT nCount
= mpEntryList
->GetEntryCount();
1540 USHORT nCurVis
= GetLastVisibleEntry() - mnTop
;
1541 USHORT nTmp
= Min( nCurVis
, nCount
);
1543 if( mnCurrentPos
== nTmp
&& mnCurrentPos
!= nCount
- 1 )
1545 long nTmp2
= Min( (long)(nCount
-nCurVis
), (long)((long)mnTop
+(long)nCurVis
-1) );
1546 nTmp2
= Max( (long)0 , nTmp2
);
1547 nTmp
= (USHORT
)(nTmp2
+(nCurVis
-1) );
1548 SetTopEntry( (USHORT
)nTmp2
);
1550 // find first selectable starting from nTmp looking backwards
1551 nSelect
= mpEntryList
->FindFirstSelectable( nTmp
, false );
1555 maSearchStr
.Erase();
1565 else if ( !bCtrl
&& !bMod2
)
1569 nSelect
= mpEntryList
->FindFirstSelectable( mpEntryList
->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND
, true );
1576 maSearchStr
.Erase();
1584 SetTopEntry( 0xFFFF );
1586 else if ( !bCtrl
&& !bMod2
)
1588 if( mnCurrentPos
== LISTBOX_ENTRY_NOTFOUND
)
1590 nSelect
= mpEntryList
->FindFirstSelectable( 0, true );
1592 else if ( (mnCurrentPos
+1) < mpEntryList
->GetEntryCount() )
1594 USHORT nCount
= mpEntryList
->GetEntryCount();
1595 nSelect
= mpEntryList
->FindFirstSelectable( nCount
- 1, false );
1596 USHORT nCurVis
= GetLastVisibleEntry() - mnTop
+ 1;
1597 if( nCount
> nCurVis
)
1598 SetTopEntry( nCount
- nCurVis
);
1602 maSearchStr
.Erase();
1608 if ( !bCtrl
&& !bMod2
)
1610 ScrollHorz( -HORZ_SCROLL
);
1613 maSearchStr
.Erase();
1619 if ( !bCtrl
&& !bMod2
)
1621 ScrollHorz( HORZ_SCROLL
);
1624 maSearchStr
.Erase();
1630 if ( !bMod2
&& !IsReadOnly() )
1632 mnSelectModifier
= rKEvt
.GetKeyCode().GetModifier();
1634 bDone
= FALSE
; // RETURN nicht abfangen.
1636 maSearchStr
.Erase();
1642 if ( !bMod2
&& !IsReadOnly() )
1644 if( mbMulti
&& ( !mbSimpleMode
|| ( mbSimpleMode
&& bCtrl
&& !bShift
) || mbStackMode
) )
1646 nSelect
= mnCurrentPos
;
1647 eLET
= LET_KEYSPACE
;
1651 maSearchStr
.Erase();
1657 if( bCtrl
&& mbMulti
)
1660 BOOL bUpdates
= IsUpdateMode();
1661 SetUpdateMode( FALSE
);
1663 USHORT nEntryCount
= mpEntryList
->GetEntryCount();
1664 for( USHORT i
= 0; i
< nEntryCount
; i
++ )
1665 SelectEntry( i
, TRUE
);
1667 // restore update mode
1668 SetUpdateMode( bUpdates
);
1671 maSearchStr
.Erase();
1677 // fall through intentional
1680 xub_Unicode c
= rKEvt
.GetCharCode();
1682 if ( !IsReadOnly() && (c
>= 32) && (c
!= 127) && !rKEvt
.GetKeyCode().IsMod2() )
1685 XubString
aTmpSearch( maSearchStr
);
1687 nSelect
= mpEntryList
->FindMatchingEntry( aTmpSearch
, mnCurrentPos
);
1688 if ( (nSelect
== LISTBOX_ENTRY_NOTFOUND
) && (aTmpSearch
.Len() > 1) )
1690 // Wenn alles die gleichen Buchstaben, dann anderer Such-Modus
1691 BOOL bAllEqual
= TRUE
;
1692 for ( USHORT n
= aTmpSearch
.Len(); n
&& bAllEqual
; )
1693 bAllEqual
= aTmpSearch
.GetChar( --n
) == c
;
1697 nSelect
= mpEntryList
->FindMatchingEntry( aTmpSearch
, mnCurrentPos
+1 );
1700 if ( nSelect
== LISTBOX_ENTRY_NOTFOUND
)
1701 nSelect
= mpEntryList
->FindMatchingEntry( aTmpSearch
, 0 );
1703 if ( nSelect
!= LISTBOX_ENTRY_NOTFOUND
)
1705 USHORT nCurVis
= GetLastVisibleEntry() - mnTop
+ 1;
1706 if( nSelect
< mnTop
)
1707 SetTopEntry( nSelect
);
1708 else if( nSelect
>= (mnTop
+ nCurVis
) )
1709 SetTopEntry( nSelect
- nCurVis
+ 1 );
1711 if ( mpEntryList
->IsEntryPosSelected( nSelect
) )
1712 nSelect
= LISTBOX_ENTRY_NOTFOUND
;
1714 maSearchTimeout
.Start();
1717 maSearchStr
.Erase();
1723 if ( ( nSelect
!= LISTBOX_ENTRY_NOTFOUND
)
1724 && ( ( !mpEntryList
->IsEntryPosSelected( nSelect
) )
1725 || ( eLET
== LET_KEYSPACE
)
1729 DBG_ASSERT( !mpEntryList
->IsEntryPosSelected( nSelect
) || mbMulti
, "ImplListBox: Selecting same Entry" );
1730 if( nSelect
>= mpEntryList
->GetEntryCount() )
1731 nSelect
= mpEntryList
->GetEntryCount()-1;
1732 mnCurrentPos
= nSelect
;
1733 if ( SelectEntries( nSelect
, eLET
, bShift
, bCtrl
) )
1735 mbTravelSelect
= TRUE
;
1736 mnSelectModifier
= rKEvt
.GetKeyCode().GetModifier();
1738 mbTravelSelect
= FALSE
;
1745 // -----------------------------------------------------------------------
1747 void ImplListBoxWindow::ImplPaint( USHORT nPos
, BOOL bErase
, bool bLayout
)
1749 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1751 const ImplEntryType
* pEntry
= mpEntryList
->GetEntryPtr( nPos
);
1755 long nWidth
= GetOutputSizePixel().Width();
1756 long nY
= mpEntryList
->GetAddedHeight( nPos
, mnTop
);
1757 Rectangle
aRect( Point( 0, nY
), Size( nWidth
, pEntry
->mnHeight
) );
1761 if( mpEntryList
->IsEntryPosSelected( nPos
) )
1763 SetTextColor( !IsEnabled() ? rStyleSettings
.GetDisableColor() : rStyleSettings
.GetHighlightTextColor() );
1764 SetFillColor( rStyleSettings
.GetHighlightColor() );
1765 SetTextFillColor( rStyleSettings
.GetHighlightColor() );
1770 ImplInitSettings( FALSE
, TRUE
, FALSE
);
1772 SetTextColor( rStyleSettings
.GetDisableColor() );
1779 if ( IsUserDrawEnabled() )
1781 mbInUserDraw
= TRUE
;
1782 mnUserDrawEntry
= nPos
;
1783 aRect
.Left() -= mnLeft
;
1784 if ( nPos
< GetEntryList()->GetMRUCount() )
1785 nPos
= GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos
) );
1786 nPos
= sal::static_int_cast
<USHORT
>(nPos
- GetEntryList()->GetMRUCount());
1787 UserDrawEvent
aUDEvt( this, aRect
, nPos
, 0 );
1788 maUserDrawHdl
.Call( &aUDEvt
);
1789 mbInUserDraw
= FALSE
;
1793 DrawEntry( nPos
, TRUE
, TRUE
, FALSE
, bLayout
);
1797 // -----------------------------------------------------------------------
1799 void ImplListBoxWindow::DrawEntry( USHORT nPos
, BOOL bDrawImage
, BOOL bDrawText
, BOOL bDrawTextAtImagePos
, bool bLayout
)
1801 const ImplEntryType
* pEntry
= mpEntryList
->GetEntryPtr( nPos
);
1805 // Bei Aenderungen in dieser Methode ggf. auch ImplWin::DrawEntry() anpassen.
1808 nPos
= mnUserDrawEntry
; // real entry, not the matching entry from MRU
1810 long nY
= mpEntryList
->GetAddedHeight( nPos
, mnTop
);
1813 if( bDrawImage
&& mpEntryList
->HasImages() && !bLayout
)
1815 Image aImage
= mpEntryList
->GetEntryImage( nPos
);
1818 aImgSz
= aImage
.GetSizePixel();
1819 Point
aPtImg( mnBorder
- mnLeft
, nY
+ ( ( pEntry
->mnHeight
- aImgSz
.Height() ) / 2 ) );
1821 // pb: #106948# explicit mirroring for calc
1824 aPtImg
.X() = mnMaxWidth
+ mnBorder
- aImgSz
.Width() - mnLeft
;
1828 DrawImage( aPtImg
, aImage
);
1832 aImgSz
.Width() = CalcZoom( aImgSz
.Width() );
1833 aImgSz
.Height() = CalcZoom( aImgSz
.Height() );
1834 DrawImage( aPtImg
, aImgSz
, aImage
);
1841 MetricVector
* pVector
= bLayout
? &mpLayoutData
->m_aUnicodeBoundRects
: NULL
;
1842 String
* pDisplayText
= bLayout
? &mpLayoutData
->m_aDisplayText
: NULL
;
1843 XubString
aStr( mpEntryList
->GetEntryText( nPos
) );
1846 long nMaxWidth
= Max( static_cast< long >( mnMaxWidth
),
1847 GetOutputSizePixel().Width() - 2*mnBorder
);
1848 // a multiline entry should only be as wide a the window
1849 if( (pEntry
->mnFlags
& LISTBOX_ENTRY_FLAG_MULTILINE
) )
1850 nMaxWidth
= GetOutputSizePixel().Width() - 2*mnBorder
;
1852 Rectangle
aTextRect( Point( mnBorder
- mnLeft
, nY
),
1853 Size( nMaxWidth
, pEntry
->mnHeight
) );
1855 if( !bDrawTextAtImagePos
&& ( mpEntryList
->HasEntryImage(nPos
) || IsUserDrawEnabled() ) )
1857 long nImageWidth
= Max( mnMaxImgWidth
, maUserItemSize
.Width() );
1858 aTextRect
.Left() += nImageWidth
+ IMG_TXT_DISTANCE
;
1862 mpLayoutData
->m_aLineIndices
.push_back( mpLayoutData
->m_aDisplayText
.Len() );
1864 // pb: #106948# explicit mirroring for calc
1868 aTextRect
.Left() = nMaxWidth
+ mnBorder
- GetTextWidth( aStr
) - mnLeft
;
1869 if ( aImgSz
.Width() > 0 )
1870 aTextRect
.Left() -= ( aImgSz
.Width() + IMG_TXT_DISTANCE
);
1873 USHORT nDrawStyle
= ImplGetTextStyle();
1874 if( (pEntry
->mnFlags
& LISTBOX_ENTRY_FLAG_MULTILINE
) )
1875 nDrawStyle
|= MULTILINE_ENTRY_DRAW_FLAGS
;
1877 DrawText( aTextRect
, aStr
, nDrawStyle
, pVector
, pDisplayText
);
1883 if ( ( mnSeparatorPos
!= LISTBOX_ENTRY_NOTFOUND
) &&
1884 ( ( nPos
== mnSeparatorPos
) || ( nPos
== mnSeparatorPos
+1 ) ) )
1886 Color
aOldLineColor( GetLineColor() );
1887 SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY
) ? COL_LIGHTGRAY
: COL_GRAY
);
1888 Point
aStartPos( 0, nY
);
1889 if ( nPos
== mnSeparatorPos
)
1890 aStartPos
.Y() += pEntry
->mnHeight
-1;
1891 Point
aEndPos( aStartPos
);
1892 aEndPos
.X() = GetOutputSizePixel().Width();
1893 DrawLine( aStartPos
, aEndPos
);
1894 SetLineColor( aOldLineColor
);
1899 // -----------------------------------------------------------------------
1901 void ImplListBoxWindow::FillLayoutData() const
1903 mpLayoutData
= new vcl::ControlLayoutData();
1904 const_cast<ImplListBoxWindow
*>(this)->
1905 ImplDoPaint( Rectangle( Point( 0, 0 ), GetOutputSize() ), true );
1908 // -----------------------------------------------------------------------
1910 void ImplListBoxWindow::ImplDoPaint( const Rectangle
& rRect
, bool bLayout
)
1912 USHORT nCount
= mpEntryList
->GetEntryCount();
1914 BOOL bShowFocusRect
= mbHasFocusRect
;
1915 if ( mbHasFocusRect
&& ! bLayout
)
1916 ImplHideFocusRect();
1918 long nY
= 0; // + mnBorder;
1919 long nHeight
= GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
1921 for( USHORT i
= (USHORT
)mnTop
; i
< nCount
&& nY
< nHeight
+ mnMaxHeight
; i
++ )
1923 const ImplEntryType
* pEntry
= mpEntryList
->GetEntryPtr( i
);
1924 if( nY
+ pEntry
->mnHeight
>= rRect
.Top() &&
1925 nY
<= rRect
.Bottom() + mnMaxHeight
)
1927 ImplPaint( i
, FALSE
, bLayout
);
1929 nY
+= pEntry
->mnHeight
;
1932 long nHeightDiff
= mpEntryList
->GetAddedHeight( mnCurrentPos
, mnTop
, 0 );
1933 maFocusRect
.SetPos( Point( 0, nHeightDiff
) );
1934 Size
aSz( maFocusRect
.GetWidth(), mpEntryList
->GetEntryHeight( mnCurrentPos
) );
1935 maFocusRect
.SetSize( aSz
);
1936 if( HasFocus() && bShowFocusRect
&& !bLayout
)
1937 ImplShowFocusRect();
1940 // -----------------------------------------------------------------------
1942 void ImplListBoxWindow::Paint( const Rectangle
& rRect
)
1944 ImplDoPaint( rRect
);
1947 // -----------------------------------------------------------------------
1949 USHORT
ImplListBoxWindow::GetDisplayLineCount() const
1951 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE
1953 USHORT nCount
= mpEntryList
->GetEntryCount();
1954 long nHeight
= GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
1955 USHORT nEntries
= static_cast< USHORT
>( ( nHeight
+ mnMaxHeight
- 1 ) / mnMaxHeight
);
1956 if( nEntries
> nCount
-mnTop
)
1957 nEntries
= nCount
-mnTop
;
1962 // -----------------------------------------------------------------------
1964 void ImplListBoxWindow::Resize()
1968 BOOL bShowFocusRect
= mbHasFocusRect
;
1969 if ( bShowFocusRect
)
1970 ImplHideFocusRect();
1972 if( mnCurrentPos
!= LISTBOX_ENTRY_NOTFOUND
)
1974 Size
aSz( GetOutputSizePixel().Width(), mpEntryList
->GetEntryHeight( mnCurrentPos
) );
1975 maFocusRect
.SetSize( aSz
);
1978 if ( bShowFocusRect
)
1979 ImplShowFocusRect();
1981 delete mpLayoutData
, mpLayoutData
= NULL
;
1984 // -----------------------------------------------------------------------
1986 void ImplListBoxWindow::GetFocus()
1988 USHORT nPos
= mnCurrentPos
;
1989 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
1991 long nHeightDiff
= mpEntryList
->GetAddedHeight( nPos
, mnTop
, 0 );
1992 maFocusRect
.SetPos( Point( 0, nHeightDiff
) );
1993 Size
aSz( maFocusRect
.GetWidth(), mpEntryList
->GetEntryHeight( nPos
) );
1994 maFocusRect
.SetSize( aSz
);
1995 ImplShowFocusRect();
1996 Control::GetFocus();
1999 // -----------------------------------------------------------------------
2001 void ImplListBoxWindow::LoseFocus()
2003 ImplHideFocusRect();
2004 Control::LoseFocus();
2007 // -----------------------------------------------------------------------
2010 void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt )
2012 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
2013 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), String() );
2015 Window::RequestHelp( rHEvt );
2019 // -----------------------------------------------------------------------
2021 void ImplListBoxWindow::SetTopEntry( USHORT nTop
)
2023 if( mpEntryList
->GetEntryCount() == 0 )
2026 long nWHeight
= PixelToLogic( GetSizePixel() ).Height();
2028 USHORT nLastEntry
= mpEntryList
->GetEntryCount()-1;
2029 if( nTop
> nLastEntry
)
2031 const ImplEntryType
* pLast
= mpEntryList
->GetEntryPtr( nLastEntry
);
2032 while( nTop
> 0 && mpEntryList
->GetAddedHeight( nLastEntry
, nTop
-1 ) + pLast
->mnHeight
<= nWHeight
)
2035 if ( nTop
!= mnTop
)
2037 delete mpLayoutData
, mpLayoutData
= NULL
;
2038 long nDiff
= mpEntryList
->GetAddedHeight( mnTop
, nTop
, 0 );
2040 ImplHideFocusRect();
2044 maFocusRect
.Top() += nDiff
;
2045 maFocusRect
.Bottom() += nDiff
;
2047 ImplShowFocusRect();
2048 maScrollHdl
.Call( this );
2052 // -----------------------------------------------------------------------
2054 void ImplListBoxWindow::SetLeftIndent( long n
)
2056 ScrollHorz( n
- mnLeft
);
2059 // -----------------------------------------------------------------------
2061 void ImplListBoxWindow::ScrollHorz( long n
)
2066 long nWidth
= GetOutputSizePixel().Width();
2067 if( ( mnMaxWidth
- mnLeft
+ n
) > nWidth
)
2075 nDiff
= - ( ( mnLeft
> nAbs
) ? nAbs
: mnLeft
);
2081 delete mpLayoutData
, mpLayoutData
= NULL
;
2082 mnLeft
= sal::static_int_cast
<USHORT
>(mnLeft
+ nDiff
);
2084 ImplHideFocusRect();
2085 Scroll( -nDiff
, 0 );
2088 ImplShowFocusRect();
2089 maScrollHdl
.Call( this );
2093 // -----------------------------------------------------------------------
2095 Size
ImplListBoxWindow::CalcSize( USHORT nMaxLines
) const
2097 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE
2100 // USHORT nL = Min( nMaxLines, mpEntryList->GetEntryCount() );
2101 aSz
.Height() = nMaxLines
* mnMaxHeight
;
2102 aSz
.Width() = mnMaxWidth
+ 2*mnBorder
;
2106 // -----------------------------------------------------------------------
2108 Rectangle
ImplListBoxWindow::GetBoundingRectangle( USHORT nItem
) const
2110 const ImplEntryType
* pEntry
= mpEntryList
->GetEntryPtr( nItem
);
2111 Size
aSz( GetSizePixel().Width(), pEntry
? pEntry
->mnHeight
: GetEntryHeight() );
2112 long nY
= mpEntryList
->GetAddedHeight( nItem
, GetTopEntry() ) - mpEntryList
->GetAddedHeight( GetTopEntry() );
2113 Rectangle
aRect( Point( 0, nY
), aSz
);
2118 // -----------------------------------------------------------------------
2120 void ImplListBoxWindow::StateChanged( StateChangedType nType
)
2122 Control::StateChanged( nType
);
2124 if ( nType
== STATE_CHANGE_ZOOM
)
2126 ImplInitSettings( TRUE
, FALSE
, FALSE
);
2130 else if ( nType
== STATE_CHANGE_UPDATEMODE
)
2132 if ( IsUpdateMode() && IsReallyVisible() )
2135 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
2137 ImplInitSettings( TRUE
, FALSE
, FALSE
);
2141 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
2143 ImplInitSettings( FALSE
, TRUE
, FALSE
);
2146 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
2148 ImplInitSettings( FALSE
, FALSE
, TRUE
);
2151 delete mpLayoutData
, mpLayoutData
= NULL
;
2154 // -----------------------------------------------------------------------
2156 void ImplListBoxWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
2158 Control::DataChanged( rDCEvt
);
2160 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
2161 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
2162 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
2163 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
2165 delete mpLayoutData
, mpLayoutData
= NULL
;
2166 ImplInitSettings( TRUE
, TRUE
, TRUE
);
2172 // -----------------------------------------------------------------------
2174 USHORT
ImplListBoxWindow::ImplGetTextStyle() const
2176 USHORT nTextStyle
= TEXT_DRAW_VCENTER
;
2178 if ( mpEntryList
->HasImages() )
2179 nTextStyle
|= TEXT_DRAW_LEFT
;
2180 else if ( mbCenter
)
2181 nTextStyle
|= TEXT_DRAW_CENTER
;
2183 nTextStyle
|= TEXT_DRAW_RIGHT
;
2185 nTextStyle
|= TEXT_DRAW_LEFT
;
2190 // =======================================================================
2192 ImplListBox::ImplListBox( Window
* pParent
, WinBits nWinStyle
) :
2193 Control( pParent
, nWinStyle
),
2194 maLBWindow( this, nWinStyle
&(~WB_BORDER
) )
2196 // for native widget rendering we must be able to detect this window type
2197 SetType( WINDOW_LISTBOXWINDOW
);
2199 mpVScrollBar
= new ScrollBar( this, WB_VSCROLL
| WB_DRAG
);
2200 mpHScrollBar
= new ScrollBar( this, WB_HSCROLL
| WB_DRAG
);
2201 mpScrollBarBox
= new ScrollBarBox( this );
2203 Link
aLink( LINK( this, ImplListBox
, ScrollBarHdl
) );
2204 mpVScrollBar
->SetScrollHdl( aLink
);
2205 mpHScrollBar
->SetScrollHdl( aLink
);
2209 mbAutoHScroll
= ( nWinStyle
& WB_AUTOHSCROLL
) ? TRUE
: FALSE
;
2211 maLBWindow
.SetScrollHdl( LINK( this, ImplListBox
, LBWindowScrolled
) );
2212 maLBWindow
.SetMRUChangedHdl( LINK( this, ImplListBox
, MRUChanged
) );
2216 // -----------------------------------------------------------------------
2218 ImplListBox::~ImplListBox()
2220 delete mpHScrollBar
;
2221 delete mpVScrollBar
;
2222 delete mpScrollBarBox
;
2225 // -----------------------------------------------------------------------
2227 void ImplListBox::Clear()
2230 if ( GetEntryList()->GetMRUCount() )
2232 maLBWindow
.GetEntryList()->SetMRUCount( 0 );
2233 maLBWindow
.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND
);
2235 mpVScrollBar
->SetThumbPos( 0 );
2236 mpHScrollBar
->SetThumbPos( 0 );
2237 StateChanged( STATE_CHANGE_DATA
);
2240 // -----------------------------------------------------------------------
2242 USHORT
ImplListBox::InsertEntry( USHORT nPos
, const XubString
& rStr
)
2244 ImplEntryType
* pNewEntry
= new ImplEntryType( rStr
);
2245 USHORT nNewPos
= maLBWindow
.InsertEntry( nPos
, pNewEntry
);
2246 StateChanged( STATE_CHANGE_DATA
);
2250 // -----------------------------------------------------------------------
2252 USHORT
ImplListBox::InsertEntry( USHORT nPos
, const Image
& rImage
)
2254 ImplEntryType
* pNewEntry
= new ImplEntryType( rImage
);
2255 USHORT nNewPos
= maLBWindow
.InsertEntry( nPos
, pNewEntry
);
2256 StateChanged( STATE_CHANGE_DATA
);
2260 // -----------------------------------------------------------------------
2262 USHORT
ImplListBox::InsertEntry( USHORT nPos
, const XubString
& rStr
, const Image
& rImage
)
2264 ImplEntryType
* pNewEntry
= new ImplEntryType( rStr
, rImage
);
2265 USHORT nNewPos
= maLBWindow
.InsertEntry( nPos
, pNewEntry
);
2266 StateChanged( STATE_CHANGE_DATA
);
2270 // -----------------------------------------------------------------------
2272 void ImplListBox::RemoveEntry( USHORT nPos
)
2274 maLBWindow
.RemoveEntry( nPos
);
2275 StateChanged( STATE_CHANGE_DATA
);
2278 // -----------------------------------------------------------------------
2280 void ImplListBox::SetEntryFlags( USHORT nPos
, long nFlags
)
2282 maLBWindow
.SetEntryFlags( nPos
, nFlags
);
2285 // -----------------------------------------------------------------------
2287 long ImplListBox::GetEntryFlags( USHORT nPos
) const
2289 return maLBWindow
.GetEntryList()->GetEntryFlags( nPos
);
2292 // -----------------------------------------------------------------------
2294 void ImplListBox::SelectEntry( USHORT nPos
, BOOL bSelect
)
2296 maLBWindow
.SelectEntry( nPos
, bSelect
);
2299 // -----------------------------------------------------------------------
2301 void ImplListBox::SetNoSelection()
2303 maLBWindow
.DeselectAll();
2306 // -----------------------------------------------------------------------
2308 void ImplListBox::GetFocus()
2310 maLBWindow
.GrabFocus();
2313 // -----------------------------------------------------------------------
2315 Window
* ImplListBox::GetPreferredKeyInputWindow()
2320 // -----------------------------------------------------------------------
2322 void ImplListBox::Resize()
2325 ImplResizeControls();
2326 ImplCheckScrollBars();
2330 // -----------------------------------------------------------------------
2332 IMPL_LINK( ImplListBox
, MRUChanged
, void*, EMPTYARG
)
2334 StateChanged( STATE_CHANGE_DATA
);
2338 // -----------------------------------------------------------------------
2340 IMPL_LINK( ImplListBox
, LBWindowScrolled
, void*, EMPTYARG
)
2342 mpVScrollBar
->SetThumbPos( GetTopEntry() );
2343 mpHScrollBar
->SetThumbPos( GetLeftIndent() );
2345 maScrollHdl
.Call( this );
2350 // -----------------------------------------------------------------------
2352 IMPL_LINK( ImplListBox
, ScrollBarHdl
, ScrollBar
*, pSB
)
2354 USHORT nPos
= (USHORT
) pSB
->GetThumbPos();
2355 if( pSB
== mpVScrollBar
)
2356 SetTopEntry( nPos
);
2357 else if( pSB
== mpHScrollBar
)
2358 SetLeftIndent( nPos
);
2363 // -----------------------------------------------------------------------
2365 void ImplListBox::ImplCheckScrollBars()
2367 BOOL bArrange
= FALSE
;
2369 Size aOutSz
= GetOutputSizePixel();
2370 USHORT nEntries
= GetEntryList()->GetEntryCount();
2371 USHORT nMaxVisEntries
= (USHORT
) (aOutSz
.Height() / GetEntryHeight());
2374 if( nEntries
> nMaxVisEntries
)
2380 // Ueberpruefung des rausgescrollten Bereichs
2381 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft...
2394 long nWidth
= (USHORT
) aOutSz
.Width();
2396 nWidth
-= mpVScrollBar
->GetSizePixel().Width();
2398 long nMaxWidth
= GetMaxEntryWidth();
2399 if( nWidth
< nMaxWidth
)
2405 if ( !mbVScroll
) // ggf. brauchen wir jetzt doch einen
2407 nMaxVisEntries
= (USHORT
) ( ( aOutSz
.Height() - mpHScrollBar
->GetSizePixel().Height() ) / GetEntryHeight() );
2408 if( nEntries
> nMaxVisEntries
)
2413 // Ueberpruefung des rausgescrollten Bereichs
2414 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft...
2418 // Ueberpruefung des rausgescrollten Bereichs
2419 USHORT nMaxLI
= (USHORT
) (nMaxWidth
- nWidth
);
2420 if ( nMaxLI
< GetLeftIndent() )
2421 SetLeftIndent( nMaxLI
);
2433 ImplResizeControls();
2435 ImplInitScrollBars();
2438 // -----------------------------------------------------------------------
2440 void ImplListBox::ImplInitScrollBars()
2442 Size aOutSz
= maLBWindow
.GetOutputSizePixel();
2446 USHORT nEntries
= GetEntryList()->GetEntryCount();
2447 USHORT nVisEntries
= (USHORT
) (aOutSz
.Height() / GetEntryHeight());
2448 mpVScrollBar
->SetRangeMax( nEntries
);
2449 mpVScrollBar
->SetVisibleSize( nVisEntries
);
2450 mpVScrollBar
->SetPageSize( nVisEntries
- 1 );
2455 mpHScrollBar
->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL
);
2456 mpHScrollBar
->SetVisibleSize( (USHORT
)aOutSz
.Width() );
2457 mpHScrollBar
->SetLineSize( HORZ_SCROLL
);
2458 mpHScrollBar
->SetPageSize( aOutSz
.Width() - HORZ_SCROLL
);
2462 // -----------------------------------------------------------------------
2464 void ImplListBox::ImplResizeControls()
2466 // Hier werden die Controls nur angeordnet, ob die Scrollbars
2467 // sichtbar sein sollen wird bereits in ImplCheckScrollBars ermittelt.
2469 Size aOutSz
= GetOutputSizePixel();
2470 long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
2471 nSBWidth
= CalcZoom( nSBWidth
);
2473 Size
aInnerSz( aOutSz
);
2475 aInnerSz
.Width() -= nSBWidth
;
2477 aInnerSz
.Height() -= nSBWidth
;
2479 // pb: #106948# explicit mirroring for calc
2480 // Scrollbar on left or right side?
2481 BOOL bMirroring
= maLBWindow
.IsMirroring();
2482 Point
aWinPos( bMirroring
&& mbVScroll
? nSBWidth
: 0, 0 );
2483 maLBWindow
.SetPosSizePixel( aWinPos
, aInnerSz
);
2486 if( mbVScroll
&& mbHScroll
)
2488 Point
aBoxPos( bMirroring
? 0 : aInnerSz
.Width(), aInnerSz
.Height() );
2489 mpScrollBarBox
->SetPosSizePixel( aBoxPos
, Size( nSBWidth
, nSBWidth
) );
2490 mpScrollBarBox
->Show();
2494 mpScrollBarBox
->Hide();
2500 // Scrollbar on left or right side?
2501 Point
aVPos( bMirroring
? 0 : aOutSz
.Width() - nSBWidth
, 0 );
2502 mpVScrollBar
->SetPosSizePixel( aVPos
, Size( nSBWidth
, aInnerSz
.Height() ) );
2503 mpVScrollBar
->Show();
2507 mpVScrollBar
->Hide();
2508 // #107254# Don't reset top entry after resize, but check for max top entry
2509 SetTopEntry( GetTopEntry() );
2515 Point
aHPos( ( bMirroring
&& mbVScroll
) ? nSBWidth
: 0, aOutSz
.Height() - nSBWidth
);
2516 mpHScrollBar
->SetPosSizePixel( aHPos
, Size( aInnerSz
.Width(), nSBWidth
) );
2517 mpHScrollBar
->Show();
2521 mpHScrollBar
->Hide();
2526 // -----------------------------------------------------------------------
2528 void ImplListBox::StateChanged( StateChangedType nType
)
2530 if ( nType
== STATE_CHANGE_INITSHOW
)
2532 ImplCheckScrollBars();
2534 else if ( ( nType
== STATE_CHANGE_UPDATEMODE
) || ( nType
== STATE_CHANGE_DATA
) )
2536 BOOL bUpdate
= IsUpdateMode();
2537 maLBWindow
.SetUpdateMode( bUpdate
);
2538 // mpHScrollBar->SetUpdateMode( bUpdate );
2539 // mpVScrollBar->SetUpdateMode( bUpdate );
2540 if ( bUpdate
&& IsReallyVisible() )
2541 ImplCheckScrollBars();
2543 else if( nType
== STATE_CHANGE_ENABLE
)
2545 mpHScrollBar
->Enable( IsEnabled() );
2546 mpVScrollBar
->Enable( IsEnabled() );
2547 mpScrollBarBox
->Enable( IsEnabled() );
2550 else if ( nType
== STATE_CHANGE_ZOOM
)
2552 maLBWindow
.SetZoom( GetZoom() );
2555 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
2557 maLBWindow
.SetControlFont( GetControlFont() );
2559 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
2561 maLBWindow
.SetControlForeground( GetControlForeground() );
2563 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
2565 maLBWindow
.SetControlBackground( GetControlBackground() );
2567 else if( nType
== STATE_CHANGE_MIRRORING
)
2569 maLBWindow
.EnableRTL( IsRTLEnabled() );
2570 mpHScrollBar
->EnableRTL( IsRTLEnabled() );
2571 mpVScrollBar
->EnableRTL( IsRTLEnabled() );
2572 ImplResizeControls();
2575 Control::StateChanged( nType
);
2578 // -----------------------------------------------------------------------
2580 void ImplListBox::DataChanged( const DataChangedEvent
& rDCEvt
)
2582 // if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2583 // (rDCEvt.GetFlags() & SETTINGS_STYLE) )
2585 // maLBWindow.SetSettings( GetSettings() );
2589 Control::DataChanged( rDCEvt
);
2592 // -----------------------------------------------------------------------
2594 long ImplListBox::Notify( NotifyEvent
& rNEvt
)
2597 if ( rNEvt
.GetType() == EVENT_COMMAND
)
2599 const CommandEvent
& rCEvt
= *rNEvt
.GetCommandEvent();
2600 if ( rCEvt
.GetCommand() == COMMAND_WHEEL
)
2602 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
2603 if( !pData
->GetModifier() && ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
) )
2605 nDone
= HandleScrollCommand( rCEvt
, mpHScrollBar
, mpVScrollBar
);
2610 return nDone
? nDone
: Window::Notify( rNEvt
);
2613 // -----------------------------------------------------------------------
2615 const Wallpaper
& ImplListBox::GetDisplayBackground() const
2617 return maLBWindow
.GetDisplayBackground();
2620 // -----------------------------------------------------------------------
2622 BOOL
ImplListBox::HandleWheelAsCursorTravel( const CommandEvent
& rCEvt
)
2625 if ( rCEvt
.GetCommand() == COMMAND_WHEEL
)
2627 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
2628 if( !pData
->GetModifier() && ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
) )
2630 USHORT nKey
= ( pData
->GetDelta() < 0 ) ? KEY_DOWN
: KEY_UP
;
2631 KeyEvent
aKeyEvent( 0, KeyCode( nKey
) );
2632 bDone
= ProcessKeyInput( aKeyEvent
);
2638 // -----------------------------------------------------------------------
2640 void ImplListBox::SetMRUEntries( const XubString
& rEntries
, xub_Unicode cSep
)
2642 BOOL bChanges
= GetEntryList()->GetMRUCount() ? TRUE
: FALSE
;
2644 // Remove old MRU entries
2645 for ( USHORT n
= GetEntryList()->GetMRUCount();n
; )
2646 maLBWindow
.RemoveEntry( --n
);
2648 USHORT nMRUCount
= 0;
2649 USHORT nEntries
= rEntries
.GetTokenCount( cSep
);
2650 for ( USHORT nEntry
= 0; nEntry
< nEntries
; nEntry
++ )
2652 XubString aEntry
= rEntries
.GetToken( nEntry
, cSep
);
2653 // Accept only existing entries
2654 if ( GetEntryList()->FindEntry( aEntry
) != LISTBOX_ENTRY_NOTFOUND
)
2656 ImplEntryType
* pNewEntry
= new ImplEntryType( aEntry
);
2657 maLBWindow
.GetEntryList()->InsertEntry( nMRUCount
++, pNewEntry
, FALSE
);
2664 maLBWindow
.GetEntryList()->SetMRUCount( nMRUCount
);
2665 SetSeparatorPos( nMRUCount
? nMRUCount
-1 : 0 );
2666 StateChanged( STATE_CHANGE_DATA
);
2670 // -----------------------------------------------------------------------
2672 XubString
ImplListBox::GetMRUEntries( xub_Unicode cSep
) const
2675 for ( USHORT n
= 0; n
< GetEntryList()->GetMRUCount(); n
++ )
2677 aEntries
+= GetEntryList()->GetEntryText( n
);
2678 if( n
< ( GetEntryList()->GetMRUCount() - 1 ) )
2684 // =======================================================================
2686 ImplWin::ImplWin( Window
* pParent
, WinBits nWinStyle
) :
2687 Control ( pParent
, nWinStyle
)
2689 if ( IsNativeControlSupported(CTRL_LISTBOX
, PART_ENTIRE_CONTROL
)
2690 && ! IsNativeControlSupported(CTRL_LISTBOX
, PART_BUTTON_DOWN
) )
2693 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
2695 mbInUserDraw
= FALSE
;
2696 mbUserDrawEnabled
= FALSE
;
2697 mnItemPos
= LISTBOX_ENTRY_NOTFOUND
;
2700 // -----------------------------------------------------------------------
2702 BOOL
ImplWin::SetModeImage( const Image
& rImage
, BmpColorMode eMode
)
2704 if( eMode
== BMP_COLOR_NORMAL
)
2706 else if( eMode
== BMP_COLOR_HIGHCONTRAST
)
2713 // -----------------------------------------------------------------------
2715 const Image
& ImplWin::GetModeImage( BmpColorMode eMode
) const
2717 if( eMode
== BMP_COLOR_HIGHCONTRAST
)
2723 // -----------------------------------------------------------------------
2725 void ImplWin::MBDown()
2728 maMBDownHdl
.Call( this );
2731 // -----------------------------------------------------------------------
2733 void ImplWin::MouseButtonDown( const MouseEvent
& )
2737 // Control::MouseButtonDown( rMEvt );
2742 // -----------------------------------------------------------------------
2744 void ImplWin::FillLayoutData() const
2746 mpLayoutData
= new vcl::ControlLayoutData();
2747 const_cast<ImplWin
*>(this)->ImplDraw( true );
2750 // -----------------------------------------------------------------------
2752 long ImplWin::PreNotify( NotifyEvent
& rNEvt
)
2755 const MouseEvent
* pMouseEvt
= NULL
;
2757 if( (rNEvt
.GetType() == EVENT_MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != NULL
)
2759 if( pMouseEvt
->IsEnterWindow() || pMouseEvt
->IsLeaveWindow() )
2761 // trigger redraw as mouse over state has changed
2762 if ( IsNativeControlSupported(CTRL_LISTBOX
, PART_ENTIRE_CONTROL
)
2763 && ! IsNativeControlSupported(CTRL_LISTBOX
, PART_BUTTON_DOWN
) )
2765 GetParent()->GetWindow( WINDOW_BORDER
)->Invalidate( INVALIDATE_NOERASE
);
2766 GetParent()->GetWindow( WINDOW_BORDER
)->Update();
2771 return nDone
? nDone
: Control::PreNotify(rNEvt
);
2774 // -----------------------------------------------------------------------
2776 void ImplWin::ImplDraw( bool bLayout
)
2778 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
2780 BOOL bNativeOK
= FALSE
;
2784 ControlState nState
= CTRL_STATE_ENABLED
;
2785 if ( IsNativeControlSupported(CTRL_LISTBOX
, PART_ENTIRE_CONTROL
)
2786 && IsNativeControlSupported(CTRL_LISTBOX
, HAS_BACKGROUND_TEXTURE
) )
2788 // Repaint the (focused) area similarly to
2789 // ImplSmallBorderWindowView::DrawWindow() in
2790 // vcl/source/window/brdwin.cxx
2791 Window
*pWin
= GetParent();
2793 ImplControlValue aControlValue
;
2794 if ( !pWin
->IsEnabled() )
2795 nState
&= ~CTRL_STATE_ENABLED
;
2796 if ( pWin
->HasFocus() )
2797 nState
|= CTRL_STATE_FOCUSED
;
2799 // The listbox is painted over the entire control including the
2800 // border, but ImplWin does not contain the border => correction
2802 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
2803 pWin
->GetBorder( nLeft
, nTop
, nRight
, nBottom
);
2804 Point
aPoint( -nLeft
, -nTop
);
2805 Region
aCtrlRegion( Rectangle( aPoint
- GetPosPixel(), pWin
->GetSizePixel() ) );
2807 BOOL bMouseOver
= FALSE
;
2810 Window
*pChild
= GetParent()->GetWindow( WINDOW_FIRSTCHILD
);
2811 while( pChild
&& (bMouseOver
= pChild
->IsMouseOver()) == FALSE
)
2812 pChild
= pChild
->GetWindow( WINDOW_NEXT
);
2816 nState
|= CTRL_STATE_ROLLOVER
;
2818 // if parent has no border, then nobody has drawn the background
2819 // since no border window exists. so draw it here.
2820 WinBits nParentStyle
= pWin
->GetStyle();
2821 if( ! (nParentStyle
& WB_BORDER
) || (nParentStyle
& WB_NOBORDER
) )
2823 Rectangle
aParentRect( Point( 0, 0 ), pWin
->GetSizePixel() );
2824 Region
aParentReg( aParentRect
);
2825 pWin
->DrawNativeControl( CTRL_LISTBOX
, PART_ENTIRE_CONTROL
, aParentReg
,
2826 nState
, aControlValue
, rtl::OUString() );
2829 bNativeOK
= DrawNativeControl( CTRL_LISTBOX
, PART_ENTIRE_CONTROL
, aCtrlRegion
, nState
,
2830 aControlValue
, rtl::OUString() );
2837 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
2838 SetFillColor( rStyleSettings
.GetHighlightColor() );
2839 DrawRect( maFocusRect
);
2844 if( bNativeOK
&& (nState
& CTRL_STATE_ROLLOVER
) )
2845 aColor
= rStyleSettings
.GetFieldRolloverTextColor();
2847 aColor
= rStyleSettings
.GetFieldTextColor();
2848 if( IsControlForeground() )
2849 aColor
= GetControlForeground();
2850 SetTextColor( aColor
);
2852 Erase( maFocusRect
);
2857 SetTextColor( rStyleSettings
.GetDisableColor() );
2859 Erase( maFocusRect
);
2863 if ( IsUserDrawEnabled() )
2865 mbInUserDraw
= TRUE
;
2866 UserDrawEvent
aUDEvt( this, maFocusRect
, mnItemPos
, 0 );
2867 maUserDrawHdl
.Call( &aUDEvt
);
2868 mbInUserDraw
= FALSE
;
2872 DrawEntry( TRUE
, TRUE
, FALSE
, bLayout
);
2876 // -----------------------------------------------------------------------
2878 void ImplWin::Paint( const Rectangle
& )
2883 // -----------------------------------------------------------------------
2885 void ImplWin::DrawEntry( BOOL bDrawImage
, BOOL bDrawText
, BOOL bDrawTextAtImagePos
, bool bLayout
)
2888 Size aOutSz
= GetOutputSizePixel();
2890 BOOL bImage
= !!maImage
;
2891 if( bDrawImage
&& bImage
&& !bLayout
)
2894 Size aImgSz
= maImage
.GetSizePixel();
2895 Point
aPtImg( nBorder
, ( ( aOutSz
.Height() - aImgSz
.Height() ) / 2 ) );
2897 // check for HC mode
2898 Image
*pImage
= &maImage
;
2902 if( GetSettings().GetStyleSettings().GetHighContrastMode() )
2903 pImage
= &maImageHC
;
2908 DrawImage( aPtImg
, *pImage
, nStyle
);
2912 aImgSz
.Width() = CalcZoom( aImgSz
.Width() );
2913 aImgSz
.Height() = CalcZoom( aImgSz
.Height() );
2914 DrawImage( aPtImg
, aImgSz
, *pImage
, nStyle
);
2918 if( bDrawText
&& maString
.Len() )
2920 USHORT nTextStyle
= TEXT_DRAW_VCENTER
;
2922 if ( bDrawImage
&& bImage
&& !bLayout
)
2923 nTextStyle
|= TEXT_DRAW_LEFT
;
2924 else if ( GetStyle() & WB_CENTER
)
2925 nTextStyle
|= TEXT_DRAW_CENTER
;
2926 else if ( GetStyle() & WB_RIGHT
)
2927 nTextStyle
|= TEXT_DRAW_RIGHT
;
2929 nTextStyle
|= TEXT_DRAW_LEFT
;
2931 Rectangle
aTextRect( Point( nBorder
, 0 ), Size( aOutSz
.Width()-2*nBorder
, aOutSz
.Height() ) );
2933 if ( !bDrawTextAtImagePos
&& ( bImage
|| IsUserDrawEnabled() ) )
2935 long nMaxWidth
= Max( maImage
.GetSizePixel().Width(), maUserItemSize
.Width() );
2936 aTextRect
.Left() += nMaxWidth
+ IMG_TXT_DISTANCE
;
2939 MetricVector
* pVector
= bLayout
? &mpLayoutData
->m_aUnicodeBoundRects
: NULL
;
2940 String
* pDisplayText
= bLayout
? &mpLayoutData
->m_aDisplayText
: NULL
;
2941 DrawText( aTextRect
, maString
, nTextStyle
, pVector
, pDisplayText
);
2944 if( HasFocus() && !bLayout
)
2945 ShowFocus( maFocusRect
);
2948 // -----------------------------------------------------------------------
2950 void ImplWin::Resize()
2953 maFocusRect
.SetSize( GetOutputSizePixel() );
2957 // -----------------------------------------------------------------------
2959 void ImplWin::GetFocus()
2961 ShowFocus( maFocusRect
);
2962 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2963 IsNativeWidgetEnabled() &&
2964 IsNativeControlSupported( CTRL_LISTBOX
, PART_ENTIRE_CONTROL
) )
2966 Window
* pWin
= GetParent()->GetWindow( WINDOW_BORDER
);
2973 Control::GetFocus();
2976 // -----------------------------------------------------------------------
2978 void ImplWin::LoseFocus()
2981 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2982 IsNativeWidgetEnabled() &&
2983 IsNativeControlSupported( CTRL_LISTBOX
, PART_ENTIRE_CONTROL
) )
2985 Window
* pWin
= GetParent()->GetWindow( WINDOW_BORDER
);
2992 Control::LoseFocus();
2995 // =======================================================================
2997 ImplBtn::ImplBtn( Window
* pParent
, WinBits nWinStyle
) :
2998 PushButton( pParent
, nWinStyle
),
3003 // -----------------------------------------------------------------------
3005 void ImplBtn::MBDown()
3008 maMBDownHdl
.Call( this );
3011 // -----------------------------------------------------------------------
3013 void ImplBtn::MouseButtonDown( const MouseEvent
& )
3015 //PushButton::MouseButtonDown( rMEvt );
3023 // =======================================================================
3025 ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window
* pParent
) :
3026 FloatingWindow( pParent
, WB_BORDER
| WB_SYSTEMWINDOW
| WB_NOSHADOW
) // no drop shadow for list boxes
3030 mbAutoWidth
= FALSE
;
3032 mnPopupModeStartSaveSelection
= LISTBOX_ENTRY_NOTFOUND
;
3034 EnableSaveBackground();
3036 Window
* pBorderWindow
= ImplGetBorderWindow();
3039 SetAccessibleRole(accessibility::AccessibleRole::PANEL
);
3040 pBorderWindow
->SetAccessibleRole(accessibility::AccessibleRole::WINDOW
);
3044 SetAccessibleRole(accessibility::AccessibleRole::WINDOW
);
3049 // -----------------------------------------------------------------------
3051 long ImplListBoxFloatingWindow::PreNotify( NotifyEvent
& rNEvt
)
3053 if( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
3055 if( !GetParent()->HasChildPathFocus( TRUE
) )
3059 return FloatingWindow::PreNotify( rNEvt
);
3062 // -----------------------------------------------------------------------
3064 void ImplListBoxFloatingWindow::SetPosSizePixel( long nX
, long nY
, long nWidth
, long nHeight
, USHORT nFlags
)
3066 FloatingWindow::SetPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
3068 // Fix #60890# ( MBA ): um auch im aufgeklappten Zustand der Listbox die Gr"o\se einfach zu einen
3069 // Aufruf von Resize() "andern zu k"onnen, wird die Position hier ggf. angepa\t
3070 if ( IsReallyVisible() && ( nFlags
& WINDOW_POSSIZE_HEIGHT
) )
3072 Point aPos
= GetParent()->GetPosPixel();
3073 aPos
= GetParent()->GetParent()->OutputToScreenPixel( aPos
);
3075 if ( nFlags
& WINDOW_POSSIZE_X
)
3078 if ( nFlags
& WINDOW_POSSIZE_Y
)
3082 SetPosPixel( ImplCalcPos( this, Rectangle( aPos
, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN
, nIndex
) );
3085 // if( !IsReallyVisible() )
3087 // Die ImplListBox erhaelt kein Resize, weil nicht sichtbar.
3088 // Die Fenster muessen aber ein Resize() erhalten, damit die
3089 // Anzahl der sichtbaren Eintraege fuer PgUp/PgDown stimmt.
3090 // Die Anzahl kann auch nicht von List/Combobox berechnet werden,
3091 // weil hierfuer auch die ggf. vorhandene vertikale Scrollbar
3092 // beruecksichtigt werden muss.
3093 mpImplLB
->SetSizePixel( GetOutputSizePixel() );
3094 ((Window
*)mpImplLB
)->Resize();
3095 ((Window
*)mpImplLB
->GetMainWindow())->Resize();
3099 // -----------------------------------------------------------------------
3101 void ImplListBoxFloatingWindow::Resize()
3103 mpImplLB
->GetMainWindow()->ImplClearLayoutData();
3104 FloatingWindow::Resize();
3107 // -----------------------------------------------------------------------
3109 Size
ImplListBoxFloatingWindow::CalcFloatSize()
3111 Size
aFloatSz( maPrefSz
);
3113 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
3114 GetBorder( nLeft
, nTop
, nRight
, nBottom
);
3116 USHORT nLines
= mpImplLB
->GetEntryList()->GetEntryCount();
3117 if ( mnDDLineCount
&& ( nLines
> mnDDLineCount
) )
3118 nLines
= mnDDLineCount
;
3120 Size aSz
= mpImplLB
->CalcSize( nLines
);
3121 long nMaxHeight
= aSz
.Height() + nTop
+ nBottom
;
3123 if ( mnDDLineCount
)
3124 aFloatSz
.Height() = nMaxHeight
;
3128 // AutoSize erstmal nur fuer die Breite...
3130 aFloatSz
.Width() = aSz
.Width() + nLeft
+ nRight
;
3131 aFloatSz
.Width() += nRight
; // etwas mehr Platz sieht besser aus...
3133 if ( ( aFloatSz
.Height() < nMaxHeight
) || ( mnDDLineCount
&& ( mnDDLineCount
< mpImplLB
->GetEntryList()->GetEntryCount() ) ) )
3135 // dann wird noch der vertikale Scrollbar benoetigt
3136 long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
3137 aFloatSz
.Width() += nSBWidth
;
3141 if ( aFloatSz
.Height() > nMaxHeight
)
3142 aFloatSz
.Height() = nMaxHeight
;
3144 // Minimale Hoehe, falls Hoehe nicht auf Float-Hoehe eingestellt wurde.
3145 // Der Parent vom FloatWin muss die DropDown-Combo/Listbox sein.
3146 Size aParentSz
= GetParent()->GetSizePixel();
3147 if( !mnDDLineCount
&& ( aFloatSz
.Height() < aParentSz
.Height() ) )
3148 aFloatSz
.Height() = aParentSz
.Height();
3150 // Nicht schmaler als der Parent werden...
3151 if( aFloatSz
.Width() < aParentSz
.Width() )
3152 aFloatSz
.Width() = aParentSz
.Width();
3154 // Hoehe auf Entries alignen...
3155 long nInnerHeight
= aFloatSz
.Height() - nTop
- nBottom
;
3156 long nEntryHeight
= mpImplLB
->GetEntryHeight();
3157 if ( nInnerHeight
% nEntryHeight
)
3159 nInnerHeight
/= nEntryHeight
;
3161 nInnerHeight
*= nEntryHeight
;
3162 aFloatSz
.Height() = nInnerHeight
+ nTop
+ nBottom
;
3168 // -----------------------------------------------------------------------
3170 void ImplListBoxFloatingWindow::StartFloat( BOOL bStartTracking
)
3172 if( !IsInPopupMode() )
3174 Size aFloatSz
= CalcFloatSize();
3176 SetSizePixel( aFloatSz
);
3177 mpImplLB
->SetSizePixel( GetOutputSizePixel() );
3179 USHORT nPos
= mpImplLB
->GetEntryList()->GetSelectEntryPos( 0 );
3180 mnPopupModeStartSaveSelection
= nPos
;
3182 Size aSz
= GetParent()->GetSizePixel();
3183 Point aPos
= GetParent()->GetPosPixel();
3184 aPos
= GetParent()->GetParent()->OutputToScreenPixel( aPos
);
3185 // FIXME: this ugly hack is for Mac/Aqua
3186 // should be replaced by a real mechanism to place the float rectangle
3187 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
3188 GetParent()->IsNativeWidgetEnabled() )
3190 sal_Int32 nLeft
= 4, nTop
= 4, nRight
= 4, nBottom
= 4;
3193 aSz
.Width() -= nLeft
+ nRight
;
3194 aSz
.Height() -= nTop
+ nBottom
;
3196 Rectangle
aRect( aPos
, aSz
);
3198 // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI
3199 // where the document is unmirrored
3200 // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror
3201 if( GetParent()->GetParent()->ImplIsAntiparallel() )
3202 GetParent()->GetParent()->ImplReMirror( aRect
);
3204 StartPopupMode( aRect
, FLOATWIN_POPUPMODE_DOWN
);
3206 if( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
3207 mpImplLB
->SetTopEntry( nPos
);
3209 if( bStartTracking
)
3210 mpImplLB
->GetMainWindow()->EnableMouseMoveSelect( TRUE
);
3212 if ( mpImplLB
->GetMainWindow()->IsGrabFocusAllowed() )
3213 mpImplLB
->GetMainWindow()->GrabFocus();
3215 mpImplLB
->GetMainWindow()->ImplClearLayoutData();