LCOV - code coverage report
Current view: top level - vcl/source/control - ilstbox.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 904 1759 51.4 %
Date: 2015-06-13 12:38:46 Functions: 88 134 65.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <tools/debug.hxx>
      21             : 
      22             : #include <vcl/svapp.hxx>
      23             : #include <vcl/settings.hxx>
      24             : #include <vcl/event.hxx>
      25             : #include <vcl/scrbar.hxx>
      26             : #include <vcl/help.hxx>
      27             : #include <vcl/lstbox.h>
      28             : #include <vcl/unohelp.hxx>
      29             : #include <vcl/i18nhelp.hxx>
      30             : 
      31             : #include <ilstbox.hxx>
      32             : #include <controldata.hxx>
      33             : #include <svdata.hxx>
      34             : #include <window.h>
      35             : 
      36             : #include <com/sun/star/i18n/XCollator.hpp>
      37             : #include <com/sun/star/accessibility/XAccessible.hpp>
      38             : #include <com/sun/star/accessibility/AccessibleRole.hpp>
      39             : 
      40             : #include <rtl/instance.hxx>
      41             : #include <comphelper/string.hxx>
      42             : #include <comphelper/processfactory.hxx>
      43             : 
      44             : #include <limits>
      45             : 
      46             : #define MULTILINE_ENTRY_DRAW_FLAGS ( DrawTextFlags::WordBreak | DrawTextFlags::MultiLine | DrawTextFlags::VCenter )
      47             : 
      48             : using namespace ::com::sun::star;
      49             : 
      50        3793 : void ImplInitDropDownButton( PushButton* pButton )
      51             : {
      52        3793 :     if ( pButton->GetSettings().GetStyleSettings().GetOptions() & StyleSettingsOptions::SpinUpDown )
      53           0 :         pButton->SetSymbol( SymbolType::SPIN_UPDOWN );
      54             :     else
      55        3793 :         pButton->SetSymbol( SymbolType::SPIN_DOWN );
      56             : 
      57        7586 :     if ( pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
      58        3793 :             && ! pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
      59           0 :         pButton->SetBackground();
      60        3793 : }
      61             : 
      62        3312 : ImplEntryList::ImplEntryList( vcl::Window* pWindow )
      63             : {
      64        3312 :     mpWindow = pWindow;
      65        3312 :     mnLastSelected = LISTBOX_ENTRY_NOTFOUND;
      66        3312 :     mnSelectionAnchor = LISTBOX_ENTRY_NOTFOUND;
      67        3312 :     mnImages = 0;
      68        3312 :     mbCallSelectionChangedHdl = true;
      69             : 
      70        3312 :     mnMRUCount = 0;
      71        3312 :     mnMaxMRUCount = 0;
      72        3312 : }
      73             : 
      74        6620 : ImplEntryList::~ImplEntryList()
      75             : {
      76        3310 :     Clear();
      77        3310 : }
      78             : 
      79       12952 : void ImplEntryList::Clear()
      80             : {
      81       12952 :     mnImages = 0;
      82       12952 :     maEntries.clear();
      83       12952 : }
      84             : 
      85        2659 : void ImplEntryList::SelectEntry( sal_Int32 nPos, bool bSelect )
      86             : {
      87        2659 :     if (0 <= nPos && static_cast<size_t>(nPos) < maEntries.size())
      88             :     {
      89        2659 :         boost::ptr_vector<ImplEntryType>::iterator iter = maEntries.begin()+nPos;
      90             : 
      91       10636 :         if ( ( iter->mbIsSelected != bSelect ) &&
      92       10636 :            ( (iter->mnFlags & ListBoxEntryFlags::DisableSelection) == ListBoxEntryFlags::NONE  ) )
      93             :         {
      94        2659 :             iter->mbIsSelected = bSelect;
      95        2659 :             if ( mbCallSelectionChangedHdl )
      96         254 :                 maSelectionChangedHdl.Call( reinterpret_cast<void*>(nPos) );
      97             :         }
      98             :     }
      99        2659 : }
     100             : 
     101             : namespace
     102             : {
     103             :     struct theSorter
     104             :         : public rtl::StaticWithInit< comphelper::string::NaturalStringSorter, theSorter >
     105             :     {
     106           7 :         comphelper::string::NaturalStringSorter operator () ()
     107             :         {
     108             :             return comphelper::string::NaturalStringSorter(
     109             :                 ::comphelper::getProcessComponentContext(),
     110           7 :                 Application::GetSettings().GetLanguageTag().getLocale());
     111             :         }
     112             :     };
     113             : }
     114             : 
     115      172810 : sal_Int32 ImplEntryList::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort )
     116             : {
     117      172810 :     if (nPos < 0 || LISTBOX_MAX_ENTRIES <= maEntries.size())
     118           0 :         return LISTBOX_ERROR;
     119             : 
     120      172810 :     if ( !!pNewEntry->maImage )
     121          51 :         mnImages++;
     122             : 
     123      172810 :     sal_Int32 insPos = 0;
     124             : 
     125      172810 :     if ( !bSort || maEntries.empty())
     126             :     {
     127      172470 :         if (0 <= nPos && static_cast<size_t>(nPos) < maEntries.size())
     128             :         {
     129        5815 :             insPos = nPos;
     130        5815 :             maEntries.insert( maEntries.begin() + nPos, pNewEntry );
     131             :         }
     132             :         else
     133             :         {
     134      166655 :             insPos = maEntries.size();
     135      166655 :             maEntries.push_back(pNewEntry);
     136             :         }
     137             :     }
     138             :     else
     139             :     {
     140         340 :         const comphelper::string::NaturalStringSorter &rSorter = theSorter::get();
     141             : 
     142         340 :         const OUString& rStr = pNewEntry->maStr;
     143             :         sal_uLong nLow, nHigh, nMid;
     144             : 
     145         340 :         nHigh = maEntries.size();
     146             : 
     147         340 :         ImplEntryType* pTemp = GetEntry( (sal_Int32)(nHigh-1) );
     148             : 
     149             :         try
     150             :         {
     151         340 :             sal_Int32 nComp = rSorter.compare(rStr, pTemp->maStr);
     152             : 
     153             :             // fast insert for sorted data
     154         340 :             if ( nComp >= 0 )
     155             :             {
     156         305 :                 insPos = maEntries.size();
     157         305 :                 maEntries.push_back(pNewEntry);
     158             :             }
     159             :             else
     160             :             {
     161          35 :                 nLow  = mnMRUCount;
     162          35 :                 pTemp = GetEntry( (sal_Int32)nLow );
     163             : 
     164          35 :                 nComp = rSorter.compare(rStr, pTemp->maStr);
     165          35 :                 if ( nComp <= 0 )
     166             :                 {
     167           0 :                     insPos = 0;
     168           0 :                     maEntries.insert(maEntries.begin(),pNewEntry);
     169             :                 }
     170             :                 else
     171             :                 {
     172             :                     // binary search
     173          35 :                     nHigh--;
     174          87 :                     do
     175             :                     {
     176          87 :                         nMid = (nLow + nHigh) / 2;
     177          87 :                         pTemp = GetEntry( nMid );
     178             : 
     179          87 :                         nComp = rSorter.compare(rStr, pTemp->maStr);
     180             : 
     181          87 :                         if ( nComp < 0 )
     182          52 :                             nHigh = nMid-1;
     183             :                         else
     184             :                         {
     185          35 :                             if ( nComp > 0 )
     186          35 :                                 nLow = nMid + 1;
     187             :                             else
     188           0 :                                 break;
     189             :                         }
     190             :                     }
     191             :                     while ( nLow <= nHigh );
     192             : 
     193          35 :                     if ( nComp >= 0 )
     194          13 :                         nMid++;
     195             : 
     196          35 :                     insPos = nMid;
     197          35 :                     maEntries.insert(maEntries.begin()+nMid,pNewEntry);
     198             :                 }
     199             :             }
     200             :         }
     201           0 :         catch (uno::RuntimeException& )
     202             :         {
     203             :             // XXX this is arguable, if the exception occurred because pNewEntry is
     204             :             // garbage you wouldn't insert it. If the exception occurred because the
     205             :             // Collator implementation is garbage then give the user a chance to see
     206             :             // his stuff
     207           0 :             insPos = 0;
     208           0 :             maEntries.insert(maEntries.begin(),pNewEntry);
     209             :         }
     210             : 
     211             :     }
     212             : 
     213      172810 :     return insPos;
     214             : }
     215             : 
     216           0 : void ImplEntryList::RemoveEntry( sal_Int32 nPos )
     217             : {
     218           0 :     if (0 <= nPos && static_cast<size_t>(nPos) < maEntries.size())
     219             :     {
     220           0 :         boost::ptr_vector<ImplEntryType>::iterator iter = maEntries.begin()+ nPos;
     221             : 
     222           0 :         if ( !!iter->maImage )
     223           0 :             mnImages--;
     224             : 
     225           0 :         maEntries.erase(iter);
     226             :     }
     227           0 : }
     228             : 
     229       13795 : sal_Int32 ImplEntryList::FindEntry( const OUString& rString, bool bSearchMRUArea ) const
     230             : {
     231       13795 :     sal_Int32 nEntries = maEntries.size();
     232      115726 :     for ( sal_Int32 n = bSearchMRUArea ? 0 : GetMRUCount(); n < nEntries; n++ )
     233             :     {
     234      104351 :         OUString aComp( vcl::I18nHelper::filterFormattingChars( maEntries[n].maStr ) );
     235      104351 :         if ( aComp == rString )
     236        2420 :             return n;
     237      101931 :     }
     238       11375 :     return LISTBOX_ENTRY_NOTFOUND;
     239             : }
     240             : 
     241       11375 : sal_Int32 ImplEntryList::FindMatchingEntry( const OUString& rStr, sal_Int32 nStart, bool bForward, bool bLazy ) const
     242             : {
     243       11375 :     sal_Int32  nPos = LISTBOX_ENTRY_NOTFOUND;
     244       11375 :     sal_Int32  nEntryCount = GetEntryCount();
     245       11375 :     if ( !bForward )
     246           0 :         nStart++;   // decrements right away
     247             : 
     248       11375 :     const vcl::I18nHelper& rI18nHelper = mpWindow->GetSettings().GetLocaleI18nHelper();
     249       38203 :     for ( sal_Int32 n = nStart; bForward ? n < nEntryCount : n != 0; )
     250             :     {
     251       17466 :         if ( !bForward )
     252           0 :             n--;
     253             : 
     254       17466 :         ImplEntryType* pImplEntry = GetEntry( n );
     255             :         bool bMatch;
     256       17466 :         if ( bLazy  )
     257             :         {
     258       17466 :             bMatch = rI18nHelper.MatchString( rStr, pImplEntry->maStr );
     259             :         }
     260             :         else
     261             :         {
     262           0 :             bMatch = rStr.isEmpty() || (pImplEntry->maStr.startsWith(rStr));
     263             :         }
     264       17466 :         if ( bMatch )
     265             :         {
     266        2013 :             nPos = n;
     267        2013 :             break;
     268             :         }
     269             : 
     270       15453 :         if ( bForward )
     271       15453 :             n++;
     272             :     }
     273             : 
     274       11375 :     return nPos;
     275             : }
     276             : 
     277           0 : sal_Int32 ImplEntryList::FindEntry( const void* pData ) const
     278             : {
     279           0 :     sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
     280           0 :     for ( sal_Int32 n = GetEntryCount(); n; )
     281             :     {
     282           0 :         ImplEntryType* pImplEntry = GetEntry( --n );
     283           0 :         if ( pImplEntry->mpUserData == pData )
     284             :         {
     285           0 :             nPos = n;
     286           0 :             break;
     287             :         }
     288             :     }
     289           0 :     return nPos;
     290             : }
     291             : 
     292       34073 : long ImplEntryList::GetAddedHeight( sal_Int32 i_nEndIndex, sal_Int32 i_nBeginIndex, long i_nBeginHeight ) const
     293             : {
     294       34073 :     long nHeight = i_nBeginHeight;
     295       34073 :     sal_Int32 nStart = i_nEndIndex > i_nBeginIndex ? i_nBeginIndex : i_nEndIndex;
     296       34073 :     sal_Int32 nStop  = i_nEndIndex > i_nBeginIndex ? i_nEndIndex : i_nBeginIndex;
     297       34073 :     sal_Int32 nEntryCount = GetEntryCount();
     298       34073 :     if( 0 <= nStop && nStop != LISTBOX_ENTRY_NOTFOUND && nEntryCount != 0 )
     299             :     {
     300             :         // sanity check
     301       33761 :         if( nStop > nEntryCount-1 )
     302           0 :             nStop = nEntryCount-1;
     303       33761 :         if (nStart < 0)
     304           0 :             nStart = 0;
     305       33761 :         else if( nStart > nEntryCount-1 )
     306           0 :             nStart = nEntryCount-1;
     307             : 
     308       33761 :         sal_Int32 nIndex = nStart;
     309      576313 :         while( nIndex != LISTBOX_ENTRY_NOTFOUND && nIndex < nStop )
     310             :         {
     311      508791 :             long nPosHeight = GetEntryPtr( nIndex )->mnHeight;
     312      508791 :             if (nHeight > ::std::numeric_limits<long>::max() - nPosHeight)
     313             :             {
     314             :                 SAL_WARN( "vcl", "ImplEntryList::GetAddedHeight: truncated");
     315           0 :                 break;
     316             :             }
     317      508791 :             nHeight += nPosHeight;
     318      508791 :             nIndex++;
     319       33761 :         }
     320             :     }
     321             :     else
     322         312 :         nHeight = 0;
     323       34073 :     return i_nEndIndex > i_nBeginIndex ? nHeight : -nHeight;
     324             : }
     325             : 
     326        6980 : long ImplEntryList::GetEntryHeight( sal_Int32 nPos ) const
     327             : {
     328        6980 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     329        6980 :     return pImplEntry ? pImplEntry->mnHeight : 0;
     330             : }
     331             : 
     332       87920 : OUString ImplEntryList::GetEntryText( sal_Int32 nPos ) const
     333             : {
     334       87920 :     OUString aEntryText;
     335       87920 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     336       87920 :     if ( pImplEntry )
     337       87918 :         aEntryText = pImplEntry->maStr;
     338       87920 :     return aEntryText;
     339             : }
     340             : 
     341         441 : bool ImplEntryList::HasEntryImage( sal_Int32 nPos ) const
     342             : {
     343         441 :     bool bImage = false;
     344         441 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     345         441 :     if ( pImplEntry )
     346         441 :         bImage = !!pImplEntry->maImage;
     347         441 :     return bImage;
     348             : }
     349             : 
     350           3 : Image ImplEntryList::GetEntryImage( sal_Int32 nPos ) const
     351             : {
     352           3 :     Image aImage;
     353           3 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     354           3 :     if ( pImplEntry )
     355           3 :         aImage = pImplEntry->maImage;
     356           3 :     return aImage;
     357             : }
     358             : 
     359       29580 : void ImplEntryList::SetEntryData( sal_Int32 nPos, void* pNewData )
     360             : {
     361       29580 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     362       29580 :     if ( pImplEntry )
     363       29580 :         pImplEntry->mpUserData = pNewData;
     364       29580 : }
     365             : 
     366           0 : void* ImplEntryList::GetEntryData( sal_Int32 nPos ) const
     367             : {
     368           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     369           0 :     return pImplEntry ? pImplEntry->mpUserData : NULL;
     370             : }
     371             : 
     372           0 : void ImplEntryList::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
     373             : {
     374           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     375           0 :     if ( pImplEntry )
     376           0 :         pImplEntry->mnFlags = nFlags;
     377           0 : }
     378             : 
     379           0 : ListBoxEntryFlags ImplEntryList::GetEntryFlags( sal_Int32 nPos ) const
     380             : {
     381           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     382           0 :     return pImplEntry ? pImplEntry->mnFlags : ListBoxEntryFlags::NONE;
     383             : }
     384             : 
     385        6015 : sal_Int32 ImplEntryList::GetSelectEntryCount() const
     386             : {
     387        6015 :     sal_Int32 nSelCount = 0;
     388      297739 :     for ( sal_Int32 n = GetEntryCount(); n; )
     389             :     {
     390      285709 :         ImplEntryType* pImplEntry = GetEntry( --n );
     391      285709 :         if ( pImplEntry->mbIsSelected )
     392        4277 :             nSelCount++;
     393             :     }
     394        6015 :     return nSelCount;
     395             : }
     396             : 
     397           0 : OUString ImplEntryList::GetSelectEntry( sal_Int32 nIndex ) const
     398             : {
     399           0 :     return GetEntryText( GetSelectEntryPos( nIndex ) );
     400             : }
     401             : 
     402       19845 : sal_Int32 ImplEntryList::GetSelectEntryPos( sal_Int32 nIndex ) const
     403             : {
     404       19845 :     sal_Int32 nSelEntryPos = LISTBOX_ENTRY_NOTFOUND;
     405       19845 :     sal_Int32 nSel = 0;
     406       19845 :     sal_Int32 nEntryCount = GetEntryCount();
     407             : 
     408      334703 :     for ( sal_Int32 n = 0; n < nEntryCount; n++ )
     409             :     {
     410      321887 :         ImplEntryType* pImplEntry = GetEntry( n );
     411      321887 :         if ( pImplEntry->mbIsSelected )
     412             :         {
     413        7029 :             if ( nSel == nIndex )
     414             :             {
     415        7029 :                 nSelEntryPos = n;
     416        7029 :                 break;
     417             :             }
     418           0 :             nSel++;
     419             :         }
     420             :     }
     421             : 
     422       19845 :     return nSelEntryPos;
     423             : }
     424             : 
     425        8786 : bool ImplEntryList::IsEntryPosSelected( sal_Int32 nIndex ) const
     426             : {
     427        8786 :     ImplEntryType* pImplEntry = GetEntry( nIndex );
     428        8786 :     return pImplEntry && pImplEntry->mbIsSelected;
     429             : }
     430             : 
     431        2657 : bool ImplEntryList::IsEntrySelectable( sal_Int32 nPos ) const
     432             : {
     433        2657 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     434        2657 :     return pImplEntry == nullptr || ((pImplEntry->mnFlags & ListBoxEntryFlags::DisableSelection) == ListBoxEntryFlags::NONE);
     435             : }
     436             : 
     437           0 : sal_Int32 ImplEntryList::FindFirstSelectable( sal_Int32 nPos, bool bForward /* = true */ )
     438             : {
     439           0 :     if( IsEntrySelectable( nPos ) )
     440           0 :         return nPos;
     441             : 
     442           0 :     if( bForward )
     443             :     {
     444           0 :         for( nPos = nPos + 1; nPos < GetEntryCount(); nPos++ )
     445             :         {
     446           0 :             if( IsEntrySelectable( nPos ) )
     447           0 :                 return nPos;
     448             :         }
     449             :     }
     450             :     else
     451             :     {
     452           0 :         while( nPos )
     453             :         {
     454           0 :             nPos--;
     455           0 :             if( IsEntrySelectable( nPos ) )
     456           0 :                 return nPos;
     457             :         }
     458             :     }
     459             : 
     460           0 :     return LISTBOX_ENTRY_NOTFOUND;
     461             : }
     462             : 
     463        3312 : ImplListBoxWindow::ImplListBoxWindow( vcl::Window* pParent, WinBits nWinStyle ) :
     464             :     Control( pParent, 0 ),
     465        3312 :     maQuickSelectionEngine( *this )
     466             : {
     467        3312 :     mpEntryList         = new ImplEntryList( this );
     468             : 
     469        3312 :     mnTop               = 0;
     470        3312 :     mnLeft              = 0;
     471        3312 :     mnBorder            = 1;
     472        3312 :     mnSelectModifier    = 0;
     473        3312 :     mnUserDrawEntry     = LISTBOX_ENTRY_NOTFOUND;
     474        3312 :     mbTrack             = false;
     475        3312 :     mbImgsDiffSz        = false;
     476        3312 :     mbTravelSelect      = false;
     477        3312 :     mbTrackingSelect    = false;
     478        3312 :     mbSelectionChanged  = false;
     479        3312 :     mbMouseMoveSelect   = false;
     480        3312 :     mbMulti             = false;
     481        3312 :     mbStackMode         = false;
     482        3312 :     mbGrabFocus         = false;
     483        3312 :     mbUserDrawEnabled   = false;
     484        3312 :     mbInUserDraw        = false;
     485        3312 :     mbReadOnly          = false;
     486        3312 :     mbHasFocusRect      = false;
     487        3312 :     mbRight             = ( nWinStyle & WB_RIGHT );
     488        3312 :     mbCenter            = ( nWinStyle & WB_CENTER );
     489        3312 :     mbSimpleMode        = ( nWinStyle & WB_SIMPLEMODE );
     490        3312 :     mbSort              = ( nWinStyle & WB_SORT );
     491        3312 :     mbEdgeBlending      = false;
     492             : 
     493             :     // pb: #106948# explicit mirroring for calc
     494        3312 :     mbMirroring         = false;
     495             : 
     496        3312 :     mnCurrentPos            = LISTBOX_ENTRY_NOTFOUND;
     497        3312 :     mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
     498        3312 :     mnSeparatorPos          = LISTBOX_ENTRY_NOTFOUND;
     499        3312 :     meProminentType         = ProminentEntry::TOP;
     500             : 
     501        3312 :     SetLineColor();
     502        3312 :     SetTextFillColor();
     503        3312 :     SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
     504             : 
     505        3312 :     ApplySettings(*this);
     506        3312 :     ImplCalcMetrics();
     507        3312 : }
     508             : 
     509        9930 : ImplListBoxWindow::~ImplListBoxWindow()
     510             : {
     511        3310 :     disposeOnce();
     512        6620 : }
     513             : 
     514        3310 : void ImplListBoxWindow::dispose()
     515             : {
     516        3310 :     delete mpEntryList;
     517        3310 :     Control::dispose();
     518        3310 : }
     519             : 
     520        4413 : void ImplListBoxWindow::ApplySettings(vcl::RenderContext& rRenderContext)
     521             : {
     522        4413 :     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
     523             : 
     524        4413 :     vcl::Font aFont = rStyleSettings.GetFieldFont();
     525        4413 :     if (IsControlFont())
     526         815 :         aFont.Merge(GetControlFont());
     527        4413 :     SetZoomedPointFont(rRenderContext, aFont);
     528             : 
     529        4413 :     Color aTextColor = rStyleSettings.GetFieldTextColor();
     530        4413 :     if (IsControlForeground())
     531          17 :         aTextColor = GetControlForeground();
     532        4413 :     rRenderContext.SetTextColor(aTextColor);
     533             : 
     534        4413 :     if (IsControlBackground())
     535          25 :         rRenderContext.SetBackground(GetControlBackground());
     536             :     else
     537        4388 :         rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
     538        4413 : }
     539             : 
     540       11150 : void ImplListBoxWindow::ImplCalcMetrics()
     541             : {
     542       11150 :     mnMaxWidth      = 0;
     543       11150 :     mnMaxTxtWidth   = 0;
     544       11150 :     mnMaxImgWidth   = 0;
     545       11150 :     mnMaxImgTxtWidth= 0;
     546       11150 :     mnMaxImgHeight  = 0;
     547             : 
     548       11150 :     mnTextHeight = (sal_uInt16)GetTextHeight();
     549       11150 :     mnMaxTxtHeight = mnTextHeight + mnBorder;
     550       11150 :     mnMaxHeight = mnMaxTxtHeight;
     551             : 
     552       11150 :     if ( maUserItemSize.Height() > mnMaxHeight )
     553        6187 :         mnMaxHeight = (sal_uInt16) maUserItemSize.Height();
     554       11150 :     if ( maUserItemSize.Width() > mnMaxWidth )
     555        5402 :         mnMaxWidth= (sal_uInt16) maUserItemSize.Width();
     556             : 
     557      155333 :     for ( sal_Int32 n = mpEntryList->GetEntryCount(); n; )
     558             :     {
     559      133033 :         ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( --n );
     560      133033 :         ImplUpdateEntryMetrics( *pEntry );
     561             :     }
     562             : 
     563       11150 :     if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND )
     564             :     {
     565           2 :         Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryPtr( mnCurrentPos )->mnHeight );
     566           2 :         maFocusRect.SetSize( aSz );
     567             :     }
     568       11150 : }
     569             : 
     570        9642 : void ImplListBoxWindow::Clear()
     571             : {
     572        9642 :     mpEntryList->Clear();
     573             : 
     574        9642 :     mnMaxHeight     = mnMaxTxtHeight;
     575        9642 :     mnMaxWidth      = 0;
     576        9642 :     mnMaxTxtWidth   = 0;
     577        9642 :     mnMaxImgTxtWidth= 0;
     578        9642 :     mnMaxImgWidth   = 0;
     579        9642 :     mnMaxImgHeight  = 0;
     580        9642 :     mnTop           = 0;
     581        9642 :     mnLeft          = 0;
     582        9642 :     mbImgsDiffSz    = false;
     583        9642 :     ImplClearLayoutData();
     584             : 
     585        9642 :     mnCurrentPos = LISTBOX_ENTRY_NOTFOUND;
     586        9642 :     maQuickSelectionEngine.Reset();
     587             : 
     588        9642 :     Invalidate();
     589        9642 : }
     590             : 
     591        7218 : void ImplListBoxWindow::SetUserItemSize( const Size& rSz )
     592             : {
     593        7218 :     ImplClearLayoutData();
     594        7218 :     maUserItemSize = rSz;
     595        7218 :     ImplCalcMetrics();
     596        7218 : }
     597             : 
     598             : struct ImplEntryMetrics
     599             : {
     600             :     bool    bText;
     601             :     bool    bImage;
     602             :     long    nEntryWidth;
     603             :     long    nEntryHeight;
     604             :     long    nTextWidth;
     605             :     long    nImgWidth;
     606             :     long    nImgHeight;
     607             : };
     608             : 
     609           0 : void ImplListBoxWindow::EnableQuickSelection( const bool& b )
     610             : {
     611           0 :     maQuickSelectionEngine.SetEnabled( b );
     612           0 : }
     613             : 
     614      305843 : void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType& rEntry )
     615             : {
     616             :     ImplEntryMetrics aMetrics;
     617      305843 :     aMetrics.bText = !rEntry.maStr.isEmpty();
     618      305843 :     aMetrics.bImage = !!rEntry.maImage;
     619      305843 :     aMetrics.nEntryWidth = 0;
     620      305843 :     aMetrics.nEntryHeight = 0;
     621      305843 :     aMetrics.nTextWidth = 0;
     622      305843 :     aMetrics.nImgWidth = 0;
     623      305843 :     aMetrics.nImgHeight = 0;
     624             : 
     625      305843 :     if ( aMetrics.bText )
     626             :     {
     627      305843 :         if( (rEntry.mnFlags & ListBoxEntryFlags::MultiLine) )
     628             :         {
     629             :             // multiline case
     630           0 :             Size aCurSize( PixelToLogic( GetSizePixel() ) );
     631             :             // set the current size to a large number
     632             :             // GetTextRect should shrink it to the actual size
     633           0 :             aCurSize.Height() = 0x7fffff;
     634           0 :             Rectangle aTextRect( Point( 0, 0 ), aCurSize );
     635           0 :             aTextRect = GetTextRect( aTextRect, rEntry.maStr, DrawTextFlags::WordBreak | DrawTextFlags::MultiLine );
     636           0 :             aMetrics.nTextWidth = aTextRect.GetWidth();
     637           0 :             if( aMetrics.nTextWidth > mnMaxTxtWidth )
     638           0 :                 mnMaxTxtWidth = aMetrics.nTextWidth;
     639           0 :             aMetrics.nEntryWidth = mnMaxTxtWidth;
     640           0 :             aMetrics.nEntryHeight = aTextRect.GetHeight() + mnBorder;
     641             :         }
     642             :         else
     643             :         {
     644             :             // normal single line case
     645      305843 :             aMetrics.nTextWidth = (sal_uInt16)GetTextWidth( rEntry.maStr );
     646      305843 :             if( aMetrics.nTextWidth > mnMaxTxtWidth )
     647       43747 :                 mnMaxTxtWidth = aMetrics.nTextWidth;
     648      305843 :             aMetrics.nEntryWidth = mnMaxTxtWidth;
     649      305843 :             aMetrics.nEntryHeight = mnTextHeight + mnBorder;
     650             :         }
     651             :     }
     652      305843 :     if ( aMetrics.bImage )
     653             :     {
     654          51 :         Size aImgSz = rEntry.maImage.GetSizePixel();
     655          51 :         aMetrics.nImgWidth  = (sal_uInt16) CalcZoom( aImgSz.Width() );
     656          51 :         aMetrics.nImgHeight = (sal_uInt16) CalcZoom( aImgSz.Height() );
     657             : 
     658          51 :         if( mnMaxImgWidth && ( aMetrics.nImgWidth != mnMaxImgWidth ) )
     659           0 :             mbImgsDiffSz = true;
     660          51 :         else if ( mnMaxImgHeight && ( aMetrics.nImgHeight != mnMaxImgHeight ) )
     661           0 :             mbImgsDiffSz = true;
     662             : 
     663          51 :         if( aMetrics.nImgWidth > mnMaxImgWidth )
     664           3 :             mnMaxImgWidth = aMetrics.nImgWidth;
     665          51 :         if( aMetrics.nImgHeight > mnMaxImgHeight )
     666           3 :             mnMaxImgHeight = aMetrics.nImgHeight;
     667             : 
     668          51 :         mnMaxImgTxtWidth = std::max( mnMaxImgTxtWidth, aMetrics.nTextWidth );
     669          51 :         aMetrics.nEntryHeight = std::max( aMetrics.nImgHeight, aMetrics.nEntryHeight );
     670             : 
     671             :     }
     672      305843 :     if ( IsUserDrawEnabled() || aMetrics.bImage )
     673             :     {
     674      263093 :         aMetrics.nEntryWidth = std::max( aMetrics.nImgWidth, maUserItemSize.Width() );
     675      263093 :         if ( aMetrics.bText )
     676      263093 :             aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE;
     677      263093 :         aMetrics.nEntryHeight = std::max( std::max( mnMaxImgHeight, maUserItemSize.Height() ) + 2,
     678      263093 :                                      aMetrics.nEntryHeight );
     679             :     }
     680             : 
     681      305843 :     if ( !aMetrics.bText && !aMetrics.bImage && !IsUserDrawEnabled() )
     682             :     {
     683             :         // entries which have no (aka an empty) text, and no image,
     684             :         // and are not user-drawn, should be shown nonetheless
     685           0 :         aMetrics.nEntryHeight = mnTextHeight + mnBorder;
     686             :     }
     687             : 
     688      305843 :     if ( aMetrics.nEntryWidth > mnMaxWidth )
     689       43751 :         mnMaxWidth = aMetrics.nEntryWidth;
     690      305843 :     if ( aMetrics.nEntryHeight > mnMaxHeight )
     691       10389 :         mnMaxHeight = aMetrics.nEntryHeight;
     692             : 
     693      305843 :     rEntry.mnHeight = aMetrics.nEntryHeight;
     694      305843 : }
     695             : 
     696           0 : void ImplListBoxWindow::ImplCallSelect()
     697             : {
     698           0 :     if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() )
     699             :     {
     700             :         // Insert the selected entry as MRU, if not already first MRU
     701           0 :         sal_Int32 nSelected = GetEntryList()->GetSelectEntryPos( 0 );
     702           0 :         sal_Int32 nMRUCount = GetEntryList()->GetMRUCount();
     703           0 :         OUString aSelected = GetEntryList()->GetEntryText( nSelected );
     704           0 :         sal_Int32 nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected, true );
     705           0 :         if ( nFirstMatchingEntryPos || !nMRUCount )
     706             :         {
     707           0 :             bool bSelectNewEntry = false;
     708           0 :             if ( nFirstMatchingEntryPos < nMRUCount )
     709             :             {
     710           0 :                 RemoveEntry( nFirstMatchingEntryPos );
     711           0 :                 nMRUCount--;
     712           0 :                 if ( nFirstMatchingEntryPos == nSelected )
     713           0 :                     bSelectNewEntry = true;
     714             :             }
     715           0 :             else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() )
     716             :             {
     717           0 :                 RemoveEntry( nMRUCount - 1 );
     718           0 :                 nMRUCount--;
     719             :             }
     720             : 
     721           0 :             ImplClearLayoutData();
     722             : 
     723           0 :             ImplEntryType* pNewEntry = new ImplEntryType( aSelected );
     724           0 :             pNewEntry->mbIsSelected = bSelectNewEntry;
     725           0 :             GetEntryList()->InsertEntry( 0, pNewEntry, false );
     726           0 :             ImplUpdateEntryMetrics( *pNewEntry );
     727           0 :             GetEntryList()->SetMRUCount( ++nMRUCount );
     728           0 :             SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
     729           0 :             maMRUChangedHdl.Call( NULL );
     730           0 :         }
     731             :     }
     732             : 
     733           0 :     maSelectHdl.Call( NULL );
     734           0 :     mbSelectionChanged = false;
     735           0 : }
     736             : 
     737      172810 : sal_Int32 ImplListBoxWindow::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry )
     738             : {
     739      172810 :     if (nPos < 0 || LISTBOX_MAX_ENTRIES <= mpEntryList->GetEntryCount())
     740           0 :         return LISTBOX_ERROR;
     741             : 
     742      172810 :     ImplClearLayoutData();
     743      172810 :     sal_Int32 nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort );
     744             : 
     745      172810 :     if( (GetStyle() & WB_WORDBREAK) )
     746           0 :         pNewEntry->mnFlags |= ListBoxEntryFlags::MultiLine;
     747             : 
     748      172810 :     ImplUpdateEntryMetrics( *pNewEntry );
     749      172810 :     return nNewPos;
     750             : }
     751             : 
     752           0 : void ImplListBoxWindow::RemoveEntry( sal_Int32 nPos )
     753             : {
     754           0 :     ImplClearLayoutData();
     755           0 :     mpEntryList->RemoveEntry( nPos );
     756           0 :     if( mnCurrentPos >= mpEntryList->GetEntryCount() )
     757           0 :         mnCurrentPos = LISTBOX_ENTRY_NOTFOUND;
     758           0 :     ImplCalcMetrics();
     759           0 : }
     760             : 
     761           0 : void ImplListBoxWindow::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
     762             : {
     763           0 :     mpEntryList->SetEntryFlags( nPos, nFlags );
     764           0 :     ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( nPos );
     765           0 :     if( pEntry )
     766           0 :         ImplUpdateEntryMetrics( *pEntry );
     767           0 : }
     768             : 
     769           0 : void ImplListBoxWindow::ImplShowFocusRect()
     770             : {
     771           0 :     if ( mbHasFocusRect )
     772           0 :         HideFocus();
     773           0 :     ShowFocus( maFocusRect );
     774           0 :     mbHasFocusRect = true;
     775           0 : }
     776             : 
     777        6547 : void ImplListBoxWindow::ImplHideFocusRect()
     778             : {
     779        6547 :     if ( mbHasFocusRect )
     780             :     {
     781           0 :         HideFocus();
     782           0 :         mbHasFocusRect = false;
     783             :     }
     784        6547 : }
     785             : 
     786           0 : sal_Int32 ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const
     787             : {
     788           0 :     long nY = mnBorder;
     789             : 
     790           0 :     sal_Int32 nSelect = mnTop;
     791           0 :     const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nSelect );
     792           0 :     while( pEntry && rPoint.Y() > pEntry->mnHeight + nY )
     793             :     {
     794           0 :         nY += pEntry->mnHeight;
     795           0 :         pEntry = mpEntryList->GetEntryPtr( ++nSelect );
     796             :     }
     797           0 :     if( pEntry == NULL )
     798           0 :         nSelect = LISTBOX_ENTRY_NOTFOUND;
     799             : 
     800           0 :     return nSelect;
     801             : }
     802             : 
     803        9692 : bool ImplListBoxWindow::IsVisible( sal_Int32 i_nEntry ) const
     804             : {
     805        9692 :     bool bRet = false;
     806             : 
     807        9692 :     if( i_nEntry >= mnTop )
     808             :     {
     809       26133 :         if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) <
     810       17422 :             PixelToLogic( GetSizePixel() ).Height() )
     811             :         {
     812        3221 :             bRet = true;
     813             :         }
     814             :     }
     815             : 
     816        9692 :     return bRet;
     817             : }
     818             : 
     819        1203 : sal_Int32 ImplListBoxWindow::GetLastVisibleEntry() const
     820             : {
     821        1203 :     sal_Int32 nPos = mnTop;
     822        1203 :     long nWindowHeight = GetSizePixel().Height();
     823        1203 :     sal_Int32 nCount = mpEntryList->GetEntryCount();
     824             :     long nDiff;
     825        1204 :     for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) )
     826           1 :         nPos++;
     827             : 
     828        1203 :     if( nDiff > nWindowHeight && nPos > mnTop )
     829           0 :         nPos--;
     830             : 
     831        1203 :     if( nPos >= nCount )
     832           0 :         nPos = nCount-1;
     833             : 
     834        1203 :     return nPos;
     835             : }
     836             : 
     837           0 : void ImplListBoxWindow::MouseButtonDown( const MouseEvent& rMEvt )
     838             : {
     839           0 :     mbMouseMoveSelect = false;  // only till the first MouseButtonDown
     840           0 :     maQuickSelectionEngine.Reset();
     841             : 
     842           0 :     if ( !IsReadOnly() )
     843             :     {
     844           0 :         if( rMEvt.GetClicks() == 1 )
     845             :         {
     846           0 :             sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
     847           0 :             if( nSelect != LISTBOX_ENTRY_NOTFOUND )
     848             :             {
     849           0 :                 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() )
     850           0 :                     mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 );
     851             :                 else
     852           0 :                     mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
     853             : 
     854           0 :                 mnCurrentPos = nSelect;
     855           0 :                 mbTrackingSelect = true;
     856           0 :                 bool bCurPosChange = (mnCurrentPos != nSelect);
     857           0 :                 (void)SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ,bCurPosChange);
     858           0 :                 mbTrackingSelect = false;
     859           0 :                 if ( mbGrabFocus )
     860           0 :                     GrabFocus();
     861             : 
     862           0 :                 StartTracking( StartTrackingFlags::ScrollRepeat );
     863             :             }
     864             :         }
     865           0 :         if( rMEvt.GetClicks() == 2 )
     866             :         {
     867           0 :             maDoubleClickHdl.Call( this );
     868             :         }
     869             :     }
     870             :     else // if ( mbGrabFocus )
     871             :     {
     872           0 :         GrabFocus();
     873             :     }
     874           0 : }
     875             : 
     876           0 : void ImplListBoxWindow::MouseMove( const MouseEvent& rMEvt )
     877             : {
     878           0 :     if ( rMEvt.IsLeaveWindow() )
     879             :     {
     880           0 :         if ( mbStackMode && IsMouseMoveSelect() && IsReallyVisible() )
     881             :         {
     882           0 :             if ( rMEvt.GetPosPixel().Y() < 0 )
     883             :             {
     884           0 :                 DeselectAll();
     885           0 :                 mnCurrentPos = LISTBOX_ENTRY_NOTFOUND;
     886           0 :                 SetTopEntry( 0 );
     887           0 :                 if ( mbStackMode ) // #87072#, #92323#
     888             :                 {
     889           0 :                     mbTravelSelect = true;
     890           0 :                     mnSelectModifier = rMEvt.GetModifier();
     891           0 :                     ImplCallSelect();
     892           0 :                     mbTravelSelect = false;
     893             :                 }
     894             : 
     895             :             }
     896             :         }
     897             :     }
     898           0 :     else if ( ( ( !mbMulti && IsMouseMoveSelect() ) || mbStackMode ) && mpEntryList->GetEntryCount() )
     899             :     {
     900           0 :         Point aPoint;
     901           0 :         Rectangle aRect( aPoint, GetOutputSizePixel() );
     902           0 :         if( aRect.IsInside( rMEvt.GetPosPixel() ) )
     903             :         {
     904           0 :             if ( IsMouseMoveSelect() )
     905             :             {
     906           0 :                 sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
     907           0 :                 if( nSelect == LISTBOX_ENTRY_NOTFOUND )
     908           0 :                     nSelect = mpEntryList->GetEntryCount() - 1;
     909           0 :                 nSelect = std::min( nSelect, GetLastVisibleEntry() );
     910           0 :                 nSelect = std::min( nSelect, (sal_Int32) ( mpEntryList->GetEntryCount() - 1 ) );
     911             :                 // Select only visible Entries with MouseMove, otherwise Tracking...
     912           0 :                 if ( IsVisible( nSelect ) &&
     913           0 :                     mpEntryList->IsEntrySelectable( nSelect ) &&
     914           0 :                     ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() || ( nSelect != GetEntryList()->GetSelectEntryPos( 0 ) ) ) )
     915             :                 {
     916           0 :                     mbTrackingSelect = true;
     917           0 :                     if ( SelectEntries( nSelect, LET_TRACKING, false, false ) )
     918             :                     {
     919           0 :                         if ( mbStackMode ) // #87072#
     920             :                         {
     921           0 :                             mbTravelSelect = true;
     922           0 :                             mnSelectModifier = rMEvt.GetModifier();
     923           0 :                             ImplCallSelect();
     924           0 :                             mbTravelSelect = false;
     925             :                         }
     926             :                         // When list box selection change by mouse move, notity
     927             :                         // VCLEVENT_LISTBOX_SELECT vcl event.
     928             :                         else
     929             :                         {
     930           0 :                             maListItemSelectHdl.Call(NULL);
     931             :                         }
     932             :                     }
     933           0 :                     mbTrackingSelect = false;
     934             :                 }
     935             :             }
     936             : 
     937             :             // if the DD button was pressed and someone moved into the ListBox
     938             :             // with the mouse button pressed...
     939           0 :             if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() )
     940             :             {
     941           0 :                 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() )
     942           0 :                     mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 );
     943             :                 else
     944           0 :                     mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
     945             : 
     946           0 :                 if ( mbStackMode && ( mpEntryList->GetSelectionAnchor() == LISTBOX_ENTRY_NOTFOUND ) )
     947           0 :                     mpEntryList->SetSelectionAnchor( 0 );
     948             : 
     949           0 :                 StartTracking( StartTrackingFlags::ScrollRepeat );
     950             :             }
     951             :         }
     952             :     }
     953           0 : }
     954             : 
     955          45 : void ImplListBoxWindow::DeselectAll()
     956             : {
     957         101 :     while ( GetEntryList()->GetSelectEntryCount() )
     958             :     {
     959          11 :         sal_Int32 nS = GetEntryList()->GetSelectEntryPos( 0 );
     960          11 :         SelectEntry( nS, false );
     961             :     }
     962          45 : }
     963             : 
     964        7775 : void ImplListBoxWindow::SelectEntry( sal_Int32 nPos, bool bSelect )
     965             : {
     966        7775 :     if( (mpEntryList->IsEntryPosSelected( nPos ) != bSelect) && mpEntryList->IsEntrySelectable( nPos ) )
     967             :     {
     968        2657 :         ImplHideFocusRect();
     969        2657 :         if( bSelect )
     970             :         {
     971        2639 :             if( !mbMulti )
     972             :             {
     973             :                 // deselect the selected entry
     974        2639 :                 sal_Int32 nDeselect = GetEntryList()->GetSelectEntryPos( 0 );
     975        2639 :                 if( nDeselect != LISTBOX_ENTRY_NOTFOUND )
     976             :                 {
     977             :                     //SelectEntryPos( nDeselect, false );
     978           2 :                     GetEntryList()->SelectEntry( nDeselect, false );
     979           2 :                     if (IsUpdateMode() && IsReallyVisible())
     980           0 :                         Invalidate();
     981             :                 }
     982             :             }
     983        2639 :             mpEntryList->SelectEntry( nPos, true );
     984        2639 :             mnCurrentPos = nPos;
     985        2639 :             if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() )
     986             :             {
     987        2631 :                 Invalidate();
     988        2631 :                 if ( !IsVisible( nPos ) )
     989             :                 {
     990        1203 :                     ImplClearLayoutData();
     991        1203 :                     sal_Int32 nVisibleEntries = GetLastVisibleEntry()-mnTop;
     992        1203 :                     if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) )
     993             :                     {
     994        1203 :                         Resize();
     995        1203 :                         ShowProminentEntry( nPos );
     996             :                     }
     997             :                     else
     998             :                     {
     999           0 :                         ShowProminentEntry( nPos );
    1000             :                     }
    1001             :                 }
    1002             :             }
    1003             :         }
    1004             :         else
    1005             :         {
    1006          18 :             mpEntryList->SelectEntry( nPos, false );
    1007          18 :             Invalidate();
    1008             :         }
    1009        2657 :         mbSelectionChanged = true;
    1010             :     }
    1011        7775 : }
    1012             : 
    1013           0 : bool ImplListBoxWindow::SelectEntries( sal_Int32 nSelect, LB_EVENT_TYPE eLET, bool bShift, bool bCtrl, bool bSelectPosChange /*=FALSE*/ )
    1014             : {
    1015           0 :     bool bSelectionChanged = false;
    1016             : 
    1017           0 :     if( IsEnabled() && mpEntryList->IsEntrySelectable( nSelect ) )
    1018             :     {
    1019           0 :         bool bFocusChanged = false;
    1020             : 
    1021             :         // here (Single-ListBox) only one entry can be deselected
    1022           0 :         if( !mbMulti )
    1023             :         {
    1024           0 :             sal_Int32 nDeselect = mpEntryList->GetSelectEntryPos( 0 );
    1025           0 :             if( nSelect != nDeselect )
    1026             :             {
    1027           0 :                 SelectEntry( nSelect, true );
    1028           0 :                 mpEntryList->SetLastSelected( nSelect );
    1029           0 :                 bFocusChanged = true;
    1030           0 :                 bSelectionChanged = true;
    1031             :             }
    1032             :         }
    1033             :         // MultiListBox without Modifier
    1034           0 :         else if( mbSimpleMode && !bCtrl && !bShift )
    1035             :         {
    1036           0 :             sal_Int32 nEntryCount = mpEntryList->GetEntryCount();
    1037           0 :             for ( sal_Int32 nPos = 0; nPos < nEntryCount; nPos++ )
    1038             :             {
    1039           0 :                 bool bSelect = nPos == nSelect;
    1040           0 :                 if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect )
    1041             :                 {
    1042           0 :                     SelectEntry( nPos, bSelect );
    1043           0 :                     bFocusChanged = true;
    1044           0 :                     bSelectionChanged = true;
    1045             :                 }
    1046             :             }
    1047           0 :             mpEntryList->SetLastSelected( nSelect );
    1048           0 :             mpEntryList->SetSelectionAnchor( nSelect );
    1049             :         }
    1050             :         // MultiListBox only with CTRL/SHIFT or not in SimpleMode
    1051           0 :         else if( ( !mbSimpleMode /* && !bShift */ ) || ( (mbSimpleMode && ( bCtrl || bShift )) || mbStackMode ) )
    1052             :         {
    1053             :             // Space for selection change
    1054           0 :             if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) )
    1055             :             {
    1056           0 :                 bool bSelect = ( mbStackMode && IsMouseMoveSelect() ) || !mpEntryList->IsEntryPosSelected( nSelect );
    1057           0 :                 if ( mbStackMode )
    1058             :                 {
    1059             :                     sal_Int32 n;
    1060           0 :                     if ( bSelect )
    1061             :                     {
    1062             :                         // All entries before nSelect must be selected...
    1063           0 :                         for ( n = 0; n < nSelect; n++ )
    1064           0 :                             SelectEntry( n, true );
    1065             :                     }
    1066           0 :                     if ( !bSelect )
    1067             :                     {
    1068           0 :                         for ( n = nSelect+1; n < mpEntryList->GetEntryCount(); n++ )
    1069           0 :                             SelectEntry( n, false );
    1070             :                     }
    1071             :                 }
    1072           0 :                 SelectEntry( nSelect, bSelect );
    1073           0 :                 mpEntryList->SetLastSelected( nSelect );
    1074           0 :                 mpEntryList->SetSelectionAnchor( mbStackMode ? 0 : nSelect );
    1075           0 :                 if ( !mpEntryList->IsEntryPosSelected( nSelect ) )
    1076           0 :                     mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND );
    1077           0 :                 bFocusChanged = true;
    1078           0 :                 bSelectionChanged = true;
    1079             :             }
    1080           0 :             else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) ||
    1081           0 :                      ( (bShift||mbStackMode) && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) )
    1082             :             {
    1083           0 :                 mnCurrentPos = nSelect;
    1084           0 :                 bFocusChanged = true;
    1085             : 
    1086           0 :                 sal_Int32 nAnchor = mpEntryList->GetSelectionAnchor();
    1087           0 :                 if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && ( mpEntryList->GetSelectEntryCount() || mbStackMode ) )
    1088             :                 {
    1089           0 :                     nAnchor = mbStackMode ? 0 : mpEntryList->GetSelectEntryPos( mpEntryList->GetSelectEntryCount() - 1 );
    1090             :                 }
    1091           0 :                 if( nAnchor != LISTBOX_ENTRY_NOTFOUND )
    1092             :                 {
    1093             :                     // All entries from achor to nSelect have to be selected
    1094           0 :                     sal_Int32 nStart = std::min( nSelect, nAnchor );
    1095           0 :                     sal_Int32 nEnd = std::max( nSelect, nAnchor );
    1096           0 :                     for ( sal_Int32 n = nStart; n <= nEnd; n++ )
    1097             :                     {
    1098           0 :                         if ( !mpEntryList->IsEntryPosSelected( n ) )
    1099             :                         {
    1100           0 :                             SelectEntry( n, true );
    1101           0 :                             bSelectionChanged = true;
    1102             :                         }
    1103             :                     }
    1104             : 
    1105             :                     // if appropriate some more has to be deselected...
    1106           0 :                     sal_Int32 nLast = mpEntryList->GetLastSelected();
    1107           0 :                     if ( nLast != LISTBOX_ENTRY_NOTFOUND )
    1108             :                     {
    1109           0 :                         if ( ( nLast > nSelect ) && ( nLast > nAnchor ) )
    1110             :                         {
    1111           0 :                             for ( sal_Int32 n = nSelect+1; n <= nLast; n++ )
    1112             :                             {
    1113           0 :                                 if ( mpEntryList->IsEntryPosSelected( n ) )
    1114             :                                 {
    1115           0 :                                     SelectEntry( n, false );
    1116           0 :                                     bSelectionChanged = true;
    1117             :                                 }
    1118           0 :                             }
    1119             :                         }
    1120           0 :                         else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) )
    1121             :                         {
    1122           0 :                             for ( sal_Int32 n = nLast; n < nSelect; n++ )
    1123             :                             {
    1124           0 :                                 if ( mpEntryList->IsEntryPosSelected( n ) )
    1125             :                                 {
    1126           0 :                                     SelectEntry( n, false );
    1127           0 :                                     bSelectionChanged = true;
    1128             :                                 }
    1129             :                             }
    1130             :                         }
    1131             :                     }
    1132           0 :                     mpEntryList->SetLastSelected( nSelect );
    1133           0 :                 }
    1134             :             }
    1135           0 :             else if( eLET != LET_TRACKING )
    1136             :             {
    1137           0 :                 ImplHideFocusRect();
    1138           0 :                 Invalidate();
    1139           0 :                 bFocusChanged = true;
    1140           0 :             }
    1141             :         }
    1142           0 :         else if( bShift )
    1143             :         {
    1144           0 :             bFocusChanged = true;
    1145             :         }
    1146             : 
    1147           0 :         if( bSelectionChanged )
    1148           0 :             mbSelectionChanged = true;
    1149             : 
    1150           0 :         if( bFocusChanged )
    1151             :         {
    1152           0 :             long nHeightDiff = mpEntryList->GetAddedHeight( nSelect, mnTop, 0 );
    1153           0 :             maFocusRect.SetPos( Point( 0, nHeightDiff ) );
    1154             :             Size aSz( maFocusRect.GetWidth(),
    1155           0 :                       mpEntryList->GetEntryHeight( nSelect ) );
    1156           0 :             maFocusRect.SetSize( aSz );
    1157           0 :             if( HasFocus() )
    1158           0 :                 ImplShowFocusRect();
    1159           0 :             if (bSelectPosChange)
    1160             :             {
    1161           0 :                 maFocusHdl.Call(reinterpret_cast<void*>(nSelect));
    1162             :             }
    1163             :         }
    1164           0 :         ImplClearLayoutData();
    1165             :     }
    1166           0 :     return bSelectionChanged;
    1167             : }
    1168             : 
    1169           0 : void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt )
    1170             : {
    1171           0 :     Point aPoint;
    1172           0 :     Rectangle aRect( aPoint, GetOutputSizePixel() );
    1173           0 :     bool bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() );
    1174             : 
    1175           0 :     if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp
    1176             :     {
    1177           0 :         if ( bInside && !rTEvt.IsTrackingCanceled() )
    1178             :         {
    1179           0 :             mnSelectModifier = rTEvt.GetMouseEvent().GetModifier();
    1180           0 :             ImplCallSelect();
    1181             :         }
    1182             :         else
    1183             :         {
    1184           0 :             maCancelHdl.Call( NULL );
    1185           0 :             if ( !mbMulti )
    1186             :             {
    1187           0 :                 mbTrackingSelect = true;
    1188           0 :                 SelectEntry( mnTrackingSaveSelection, true );
    1189           0 :                 mbTrackingSelect = false;
    1190           0 :                 if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND )
    1191             :                 {
    1192           0 :                     long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 );
    1193           0 :                     maFocusRect.SetPos( Point( 0, nHeightDiff ) );
    1194             :                     Size aSz( maFocusRect.GetWidth(),
    1195           0 :                               mpEntryList->GetEntryHeight( mnCurrentPos ) );
    1196           0 :                     maFocusRect.SetSize( aSz );
    1197           0 :                     ImplShowFocusRect();
    1198             :                 }
    1199             :             }
    1200             :         }
    1201             : 
    1202           0 :         mbTrack = false;
    1203             :     }
    1204             :     else
    1205             :     {
    1206           0 :         bool bTrackOrQuickClick = mbTrack;
    1207           0 :         if( !mbTrack )
    1208             :         {
    1209           0 :             if ( bInside )
    1210             :             {
    1211           0 :                 mbTrack = true;
    1212             :             }
    1213             : 
    1214             :             // this case only happens, if the mouse button is pressed very briefly
    1215           0 :             if( rTEvt.IsTrackingEnded() && mbTrack )
    1216             :             {
    1217           0 :                 bTrackOrQuickClick = true;
    1218           0 :                 mbTrack = false;
    1219             :             }
    1220             :         }
    1221             : 
    1222           0 :         if( bTrackOrQuickClick )
    1223             :         {
    1224           0 :             MouseEvent aMEvt = rTEvt.GetMouseEvent();
    1225           0 :             Point aPt( aMEvt.GetPosPixel() );
    1226           0 :             bool bShift = aMEvt.IsShift();
    1227           0 :             bool bCtrl  = aMEvt.IsMod1();
    1228             : 
    1229           0 :             sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
    1230           0 :             if( aPt.Y() < 0 )
    1231             :             {
    1232           0 :                 if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND )
    1233             :                 {
    1234           0 :                     nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0;
    1235           0 :                     if( nSelect < mnTop )
    1236           0 :                         SetTopEntry( mnTop-1 );
    1237             :                 }
    1238             :             }
    1239           0 :             else if( aPt.Y() > GetOutputSizePixel().Height() )
    1240             :             {
    1241           0 :                 if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND )
    1242             :                 {
    1243           0 :                     nSelect = std::min(  (sal_Int32)(mnCurrentPos+1), (sal_Int32)(mpEntryList->GetEntryCount()-1) );
    1244           0 :                     if( nSelect >= GetLastVisibleEntry() )
    1245           0 :                         SetTopEntry( mnTop+1 );
    1246             :                 }
    1247             :             }
    1248             :             else
    1249             :             {
    1250           0 :                 nSelect = (sal_Int32) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (sal_Int32) mnTop;
    1251           0 :                 nSelect = std::min( nSelect, GetLastVisibleEntry() );
    1252           0 :                 nSelect = std::min( nSelect, (sal_Int32) ( mpEntryList->GetEntryCount() - 1 ) );
    1253             :             }
    1254             : 
    1255           0 :             if ( bInside )
    1256             :             {
    1257           0 :                 if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() )
    1258             :                 {
    1259           0 :                     mbTrackingSelect = true;
    1260           0 :                     if ( SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ) )
    1261             :                     {
    1262           0 :                         if ( mbStackMode ) // #87734# (#87072#)
    1263             :                         {
    1264           0 :                             mbTravelSelect = true;
    1265           0 :                             mnSelectModifier = rTEvt.GetMouseEvent().GetModifier();
    1266           0 :                             ImplCallSelect();
    1267           0 :                             mbTravelSelect = false;
    1268             :                         }
    1269             :                     }
    1270           0 :                     mbTrackingSelect = false;
    1271             :                 }
    1272             :             }
    1273             :             else
    1274             :             {
    1275           0 :                 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() )
    1276             :                 {
    1277           0 :                     mbTrackingSelect = true;
    1278           0 :                     SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), false );
    1279           0 :                     mbTrackingSelect = false;
    1280             :                 }
    1281           0 :                 else if ( mbStackMode )
    1282             :                 {
    1283           0 :                     if ( ( rTEvt.GetMouseEvent().GetPosPixel().X() > 0 )  && ( rTEvt.GetMouseEvent().GetPosPixel().X() < aRect.Right() ) )
    1284             :                     {
    1285           0 :                         if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) || ( rTEvt.GetMouseEvent().GetPosPixel().Y() > GetOutputSizePixel().Height() ) )
    1286             :                         {
    1287           0 :                             bool bSelectionChanged = false;
    1288           0 :                             if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 )
    1289           0 :                                    && !mnCurrentPos )
    1290             :                             {
    1291           0 :                                 if ( mpEntryList->IsEntryPosSelected( 0 ) )
    1292             :                                 {
    1293           0 :                                     SelectEntry( 0, false );
    1294           0 :                                     bSelectionChanged = true;
    1295           0 :                                     nSelect = LISTBOX_ENTRY_NOTFOUND;
    1296             : 
    1297             :                                 }
    1298             :                             }
    1299             :                             else
    1300             :                             {
    1301           0 :                                 mbTrackingSelect = true;
    1302           0 :                                 bSelectionChanged = SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl );
    1303           0 :                                 mbTrackingSelect = false;
    1304             :                             }
    1305             : 
    1306           0 :                             if ( bSelectionChanged )
    1307             :                             {
    1308           0 :                                 mbSelectionChanged = true;
    1309           0 :                                 mbTravelSelect = true;
    1310           0 :                                 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier();
    1311           0 :                                 ImplCallSelect();
    1312           0 :                                 mbTravelSelect = false;
    1313             :                             }
    1314             :                         }
    1315             :                     }
    1316             :                 }
    1317             :             }
    1318           0 :             mnCurrentPos = nSelect;
    1319           0 :             if ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
    1320             :             {
    1321           0 :                 ImplHideFocusRect();
    1322             :             }
    1323             :             else
    1324             :             {
    1325           0 :                 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 );
    1326           0 :                 maFocusRect.SetPos( Point( 0, nHeightDiff ) );
    1327           0 :                 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
    1328           0 :                 maFocusRect.SetSize( aSz );
    1329           0 :                 ImplShowFocusRect();
    1330             :             }
    1331             :         }
    1332             :     }
    1333           0 : }
    1334             : 
    1335           0 : void ImplListBoxWindow::KeyInput( const KeyEvent& rKEvt )
    1336             : {
    1337           0 :     if( !ProcessKeyInput( rKEvt ) )
    1338           0 :         Control::KeyInput( rKEvt );
    1339           0 : }
    1340             : 
    1341           0 : bool ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt )
    1342             : {
    1343             :     // entry to be selected
    1344           0 :     sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
    1345           0 :     LB_EVENT_TYPE eLET = LET_KEYMOVE;
    1346             : 
    1347           0 :     vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
    1348             : 
    1349           0 :     bool bShift = aKeyCode.IsShift();
    1350           0 :     bool bCtrl  = aKeyCode.IsMod1() || aKeyCode.IsMod3();
    1351           0 :     bool bMod2 = aKeyCode.IsMod2();
    1352           0 :     bool bDone = false;
    1353           0 :     bool bHandleKey = false;
    1354             : 
    1355           0 :     switch( aKeyCode.GetCode() )
    1356             :     {
    1357             :         case KEY_UP:
    1358             :         {
    1359           0 :             if ( IsReadOnly() )
    1360             :             {
    1361           0 :                 if ( GetTopEntry() )
    1362           0 :                     SetTopEntry( GetTopEntry()-1 );
    1363             :             }
    1364           0 :             else if ( !bMod2 )
    1365             :             {
    1366           0 :                 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
    1367             :                 {
    1368           0 :                     nSelect = mpEntryList->FindFirstSelectable( 0, true );
    1369             :                 }
    1370           0 :                 else if ( mnCurrentPos )
    1371             :                 {
    1372             :                     // search first selectable above the current position
    1373           0 :                     nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos - 1, false );
    1374             :                 }
    1375             : 
    1376           0 :                 if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) )
    1377           0 :                     SetTopEntry( mnTop-1 );
    1378             : 
    1379           0 :                 bDone = true;
    1380             :             }
    1381           0 :             maQuickSelectionEngine.Reset();
    1382             :         }
    1383           0 :         break;
    1384             : 
    1385             :         case KEY_DOWN:
    1386             :         {
    1387           0 :             if ( IsReadOnly() )
    1388             :             {
    1389           0 :                 SetTopEntry( GetTopEntry()+1 );
    1390             :             }
    1391           0 :             else if ( !bMod2 )
    1392             :             {
    1393           0 :                 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
    1394             :                 {
    1395           0 :                     nSelect = mpEntryList->FindFirstSelectable( 0, true );
    1396             :                 }
    1397           0 :                 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
    1398             :                 {
    1399             :                     // search first selectable below the current position
    1400           0 :                     nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1, true );
    1401             :                 }
    1402             : 
    1403           0 :                 if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) )
    1404           0 :                     SetTopEntry( mnTop+1 );
    1405             : 
    1406           0 :                 bDone = true;
    1407             :             }
    1408           0 :             maQuickSelectionEngine.Reset();
    1409             :         }
    1410           0 :         break;
    1411             : 
    1412             :         case KEY_PAGEUP:
    1413             :         {
    1414           0 :             if ( IsReadOnly() )
    1415             :             {
    1416           0 :                 sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
    1417           0 :                 SetTopEntry( ( mnTop > nCurVis ) ?
    1418           0 :                                 (mnTop-nCurVis) : 0 );
    1419             :             }
    1420           0 :             else if ( !bCtrl && !bMod2 )
    1421             :             {
    1422           0 :                 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
    1423             :                 {
    1424           0 :                     nSelect = mpEntryList->FindFirstSelectable( 0, true );
    1425             :                 }
    1426           0 :                 else if ( mnCurrentPos )
    1427             :                 {
    1428           0 :                     if( mnCurrentPos == mnTop )
    1429             :                     {
    1430           0 :                         sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
    1431           0 :                         SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 );
    1432             :                     }
    1433             : 
    1434             :                     // find first selectable starting from mnTop looking forward
    1435           0 :                     nSelect = mpEntryList->FindFirstSelectable( mnTop, true );
    1436             :                 }
    1437           0 :                 bDone = true;
    1438             :             }
    1439           0 :             maQuickSelectionEngine.Reset();
    1440             :         }
    1441           0 :         break;
    1442             : 
    1443             :         case KEY_PAGEDOWN:
    1444             :         {
    1445           0 :             if ( IsReadOnly() )
    1446             :             {
    1447           0 :                 SetTopEntry( GetLastVisibleEntry() );
    1448             :             }
    1449           0 :             else if ( !bCtrl && !bMod2 )
    1450             :             {
    1451           0 :                 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
    1452             :                 {
    1453           0 :                     nSelect = mpEntryList->FindFirstSelectable( 0, true );
    1454             :                 }
    1455           0 :                 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
    1456             :                 {
    1457           0 :                     sal_Int32 nCount = mpEntryList->GetEntryCount();
    1458           0 :                     sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop;
    1459           0 :                     sal_Int32 nTmp = std::min( nCurVis, nCount );
    1460           0 :                     nTmp += mnTop - 1;
    1461           0 :                     if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 )
    1462             :                     {
    1463           0 :                         long nTmp2 = std::min( (long)(nCount-nCurVis), (long)((long)mnTop+(long)nCurVis-1) );
    1464           0 :                         nTmp2 = std::max( (long)0 , nTmp2 );
    1465           0 :                         nTmp = (sal_Int32)(nTmp2+(nCurVis-1) );
    1466           0 :                         SetTopEntry( (sal_Int32)nTmp2 );
    1467             :                     }
    1468             :                     // find first selectable starting from nTmp looking backwards
    1469           0 :                     nSelect = mpEntryList->FindFirstSelectable( nTmp, false );
    1470             :                 }
    1471           0 :                 bDone = true;
    1472             :             }
    1473           0 :             maQuickSelectionEngine.Reset();
    1474             :         }
    1475           0 :         break;
    1476             : 
    1477             :         case KEY_HOME:
    1478             :         {
    1479           0 :             if ( IsReadOnly() )
    1480             :             {
    1481           0 :                 SetTopEntry( 0 );
    1482             :             }
    1483           0 :             else if ( !bCtrl && !bMod2 )
    1484             :             {
    1485           0 :                 if ( mnCurrentPos )
    1486             :                 {
    1487           0 :                     nSelect = mpEntryList->FindFirstSelectable( mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND, true );
    1488           0 :                     if( mnTop != 0 )
    1489           0 :                         SetTopEntry( 0 );
    1490             : 
    1491           0 :                     bDone = true;
    1492             :                 }
    1493             :             }
    1494           0 :             maQuickSelectionEngine.Reset();
    1495             :         }
    1496           0 :         break;
    1497             : 
    1498             :         case KEY_END:
    1499             :         {
    1500           0 :             if ( IsReadOnly() )
    1501             :             {
    1502           0 :                 SetTopEntry( 0xFFFF );
    1503             :             }
    1504           0 :             else if ( !bCtrl && !bMod2 )
    1505             :             {
    1506           0 :                 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
    1507             :                 {
    1508           0 :                     nSelect = mpEntryList->FindFirstSelectable( 0, true );
    1509             :                 }
    1510           0 :                 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
    1511             :                 {
    1512           0 :                     sal_Int32 nCount = mpEntryList->GetEntryCount();
    1513           0 :                     nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false );
    1514           0 :                     sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop + 1;
    1515           0 :                     if( nCount > nCurVis )
    1516           0 :                         SetTopEntry( nCount - nCurVis );
    1517             :                 }
    1518           0 :                 bDone = true;
    1519             :             }
    1520           0 :             maQuickSelectionEngine.Reset();
    1521             :         }
    1522           0 :         break;
    1523             : 
    1524             :         case KEY_LEFT:
    1525             :         {
    1526           0 :             if ( !bCtrl && !bMod2 )
    1527             :             {
    1528           0 :                 ScrollHorz( -HORZ_SCROLL );
    1529           0 :                 bDone = true;
    1530             :             }
    1531           0 :             maQuickSelectionEngine.Reset();
    1532             :         }
    1533           0 :         break;
    1534             : 
    1535             :         case KEY_RIGHT:
    1536             :         {
    1537           0 :             if ( !bCtrl && !bMod2 )
    1538             :             {
    1539           0 :                 ScrollHorz( HORZ_SCROLL );
    1540           0 :                 bDone = true;
    1541             :             }
    1542           0 :             maQuickSelectionEngine.Reset();
    1543             :         }
    1544           0 :         break;
    1545             : 
    1546             :         case KEY_RETURN:
    1547             :         {
    1548           0 :             if ( !bMod2 && !IsReadOnly() )
    1549             :             {
    1550           0 :                 mnSelectModifier = rKEvt.GetKeyCode().GetModifier();
    1551           0 :                 ImplCallSelect();
    1552           0 :                 bDone = false;  // do not catch RETURN
    1553             :             }
    1554           0 :             maQuickSelectionEngine.Reset();
    1555             :         }
    1556           0 :         break;
    1557             : 
    1558             :         case KEY_SPACE:
    1559             :         {
    1560           0 :             if ( !bMod2 && !IsReadOnly() )
    1561             :             {
    1562           0 :                 if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) || mbStackMode ) )
    1563             :                 {
    1564           0 :                     nSelect = mnCurrentPos;
    1565           0 :                     eLET = LET_KEYSPACE;
    1566             :                 }
    1567           0 :                 bDone = true;
    1568             :             }
    1569           0 :             bHandleKey = true;
    1570             :         }
    1571           0 :         break;
    1572             : 
    1573             :         case KEY_A:
    1574             :         {
    1575           0 :             if( bCtrl && mbMulti )
    1576             :             {
    1577             :                 // paint only once
    1578           0 :                 bool bUpdates = IsUpdateMode();
    1579           0 :                 SetUpdateMode( false );
    1580             : 
    1581           0 :                 sal_Int32 nEntryCount = mpEntryList->GetEntryCount();
    1582           0 :                 for( sal_Int32 i = 0; i < nEntryCount; i++ )
    1583           0 :                     SelectEntry( i, true );
    1584             : 
    1585             :                 // restore update mode
    1586           0 :                 SetUpdateMode( bUpdates );
    1587           0 :                 Invalidate();
    1588             : 
    1589           0 :                 maQuickSelectionEngine.Reset();
    1590             : 
    1591           0 :                 bDone = true;
    1592             :             }
    1593             :             else
    1594             :             {
    1595           0 :                 bHandleKey = true;
    1596             :             }
    1597             :         }
    1598           0 :         break;
    1599             : 
    1600             :         default:
    1601           0 :             bHandleKey = true;
    1602           0 :             break;
    1603             :     }
    1604           0 :     if (bHandleKey && !IsReadOnly())
    1605             :     {
    1606           0 :         bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt );
    1607             :     }
    1608             : 
    1609           0 :     if  (   ( nSelect != LISTBOX_ENTRY_NOTFOUND )
    1610           0 :         &&  (   ( !mpEntryList->IsEntryPosSelected( nSelect ) )
    1611           0 :             ||  ( eLET == LET_KEYSPACE )
    1612             :             )
    1613             :         )
    1614             :     {
    1615             :         DBG_ASSERT( !mpEntryList->IsEntryPosSelected( nSelect ) || mbMulti, "ImplListBox: Selecting same Entry" );
    1616           0 :         if( nSelect >= mpEntryList->GetEntryCount() )
    1617           0 :             nSelect = mpEntryList->GetEntryCount()-1;
    1618           0 :         bool bCurPosChange = (mnCurrentPos != nSelect);
    1619           0 :         mnCurrentPos = nSelect;
    1620           0 :         if(SelectEntries( nSelect, eLET, bShift, bCtrl, bCurPosChange))
    1621             :         {
    1622           0 :             mbTravelSelect = true;
    1623           0 :             mnSelectModifier = rKEvt.GetKeyCode().GetModifier();
    1624           0 :             ImplCallSelect();
    1625           0 :             mbTravelSelect = false;
    1626             :         }
    1627             :     }
    1628             : 
    1629           0 :     return bDone;
    1630             : }
    1631             : 
    1632             : namespace
    1633             : {
    1634           0 :     static vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_Int32 _nPos, OUString& _out_entryText )
    1635             :     {
    1636             :         OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" );
    1637           0 :         sal_Int32 nEntryCount( _rList.GetEntryCount() );
    1638           0 :         if ( _nPos >= nEntryCount )
    1639           0 :             _nPos = 0;
    1640           0 :         _out_entryText = _rList.GetEntryText( _nPos );
    1641             : 
    1642             :         // vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based
    1643             :         // => normalize
    1644           0 :         return reinterpret_cast< vcl::StringEntryIdentifier >( _nPos + 1 );
    1645             :     }
    1646             : 
    1647           0 :     static sal_Int32 lcl_getEntryPos( vcl::StringEntryIdentifier _entry )
    1648             :     {
    1649             :         // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL
    1650           0 :         return static_cast< sal_Int32 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1;
    1651             :     }
    1652             : }
    1653             : 
    1654           0 : vcl::StringEntryIdentifier ImplListBoxWindow::CurrentEntry( OUString& _out_entryText ) const
    1655             : {
    1656           0 :     return lcl_getEntry( *GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos, _out_entryText );
    1657             : }
    1658             : 
    1659           0 : vcl::StringEntryIdentifier ImplListBoxWindow::NextEntry( vcl::StringEntryIdentifier _currentEntry, OUString& _out_entryText ) const
    1660             : {
    1661           0 :     sal_Int32 nNextPos = lcl_getEntryPos( _currentEntry ) + 1;
    1662           0 :     return lcl_getEntry( *GetEntryList(), nNextPos, _out_entryText );
    1663             : }
    1664             : 
    1665           0 : void ImplListBoxWindow::SelectEntry( vcl::StringEntryIdentifier _entry )
    1666             : {
    1667           0 :     sal_Int32 nSelect = lcl_getEntryPos( _entry );
    1668           0 :     if ( mpEntryList->IsEntryPosSelected( nSelect ) )
    1669             :     {
    1670             :         // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted
    1671             :         // to select the given entry by typing its starting letters. No need to act.
    1672           0 :         return;
    1673             :     }
    1674             : 
    1675             :     // normalize
    1676             :     OSL_ENSURE( nSelect < mpEntryList->GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" );
    1677           0 :     if( nSelect >= mpEntryList->GetEntryCount() )
    1678           0 :         nSelect = mpEntryList->GetEntryCount()-1;
    1679             : 
    1680             :     // make visible
    1681           0 :     ShowProminentEntry( nSelect );
    1682             : 
    1683             :     // actually select
    1684           0 :     mnCurrentPos = nSelect;
    1685           0 :     if ( SelectEntries( nSelect, LET_KEYMOVE, false, false ) )
    1686             :     {
    1687           0 :         mbTravelSelect = true;
    1688           0 :         mnSelectModifier = 0;
    1689           0 :         ImplCallSelect();
    1690           0 :         mbTravelSelect = false;
    1691             :     }
    1692             : }
    1693             : 
    1694         467 : void ImplListBoxWindow::ImplPaint(vcl::RenderContext& rRenderContext, sal_Int32 nPos, bool bErase, bool bLayout)
    1695             : {
    1696         467 :     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
    1697             : 
    1698         467 :     const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos );
    1699         467 :     if (!pEntry)
    1700         467 :         return;
    1701             : 
    1702         467 :     long nWidth = rRenderContext.GetOutputSizePixel().Width();
    1703         467 :     long nY = mpEntryList->GetAddedHeight(nPos, mnTop);
    1704         467 :     Rectangle aRect(Point(0, nY), Size(nWidth, pEntry->mnHeight));
    1705             : 
    1706         467 :     if (!bLayout)
    1707             :     {
    1708         467 :         if (mpEntryList->IsEntryPosSelected(nPos))
    1709             :         {
    1710           7 :             rRenderContext.SetTextColor(!IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor());
    1711           7 :             rRenderContext.SetFillColor(rStyleSettings.GetHighlightColor());
    1712           7 :             rRenderContext.SetTextFillColor(rStyleSettings.GetHighlightColor());
    1713           7 :             rRenderContext.DrawRect(aRect);
    1714             :         }
    1715             :         else
    1716             :         {
    1717         460 :             ApplySettings(*this);
    1718         460 :             if (!IsEnabled())
    1719         195 :                 rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
    1720         460 :             rRenderContext.SetTextFillColor();
    1721         460 :             if (bErase)
    1722           0 :                 rRenderContext.Erase(aRect);
    1723             :         }
    1724             :     }
    1725             : 
    1726         467 :     if (IsUserDrawEnabled())
    1727             :     {
    1728          26 :         mbInUserDraw = true;
    1729          26 :         mnUserDrawEntry = nPos;
    1730          26 :         aRect.Left() -= mnLeft;
    1731          26 :         if (nPos < GetEntryList()->GetMRUCount())
    1732           0 :             nPos = GetEntryList()->FindEntry(GetEntryList()->GetEntryText(nPos));
    1733          26 :         nPos = nPos - GetEntryList()->GetMRUCount();
    1734          26 :         sal_Int32 nCurr = mnCurrentPos;
    1735          26 :         if (mnCurrentPos < GetEntryList()->GetMRUCount())
    1736           0 :             nCurr = GetEntryList()->FindEntry(GetEntryList()->GetEntryText(nCurr));
    1737          26 :         nCurr = sal::static_int_cast<sal_Int32>(nCurr - GetEntryList()->GetMRUCount());
    1738             : 
    1739          26 :         UserDrawEvent aUDEvt(&rRenderContext, aRect, nPos, nCurr);
    1740          26 :         userDrawSignal(&aUDEvt);
    1741          26 :         mbInUserDraw = false;
    1742             :     }
    1743             :     else
    1744             :     {
    1745         441 :         DrawEntry(rRenderContext, nPos, true, true, false, bLayout);
    1746             :     }
    1747             : }
    1748             : 
    1749         467 : void ImplListBoxWindow::DrawEntry(vcl::RenderContext& rRenderContext, sal_Int32 nPos, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos, bool bLayout)
    1750             : {
    1751         467 :     const ImplEntryType* pEntry = mpEntryList->GetEntryPtr(nPos);
    1752         467 :     if (!pEntry)
    1753         467 :         return;
    1754             : 
    1755             :     // when changing this function don't forget to adjust ImplWin::DrawEntry()
    1756             : 
    1757         467 :     if (mbInUserDraw)
    1758          26 :         nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU
    1759             : 
    1760         467 :     long nY = mpEntryList->GetAddedHeight(nPos, mnTop);
    1761         467 :     Size aImgSz;
    1762             : 
    1763         467 :     if (bDrawImage && mpEntryList->HasImages() && !bLayout)
    1764             :     {
    1765           0 :         Image aImage = mpEntryList->GetEntryImage(nPos);
    1766           0 :         if (!!aImage)
    1767             :         {
    1768           0 :             aImgSz = aImage.GetSizePixel();
    1769           0 :             Point aPtImg(mnBorder - mnLeft, nY + ((pEntry->mnHeight - aImgSz.Height()) / 2));
    1770             : 
    1771             :             // pb: #106948# explicit mirroring for calc
    1772           0 :             if (mbMirroring)
    1773             :                 // right aligned
    1774           0 :                 aPtImg.X() = mnMaxWidth + mnBorder - aImgSz.Width() - mnLeft;
    1775             : 
    1776           0 :             if (!IsZoom())
    1777             :             {
    1778           0 :                 rRenderContext.DrawImage(aPtImg, aImage);
    1779             :             }
    1780             :             else
    1781             :             {
    1782           0 :                 aImgSz.Width() = CalcZoom(aImgSz.Width());
    1783           0 :                 aImgSz.Height() = CalcZoom(aImgSz.Height());
    1784           0 :                 rRenderContext.DrawImage(aPtImg, aImgSz, aImage);
    1785             :             }
    1786             : 
    1787           0 :             const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    1788           0 :             const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
    1789             : 
    1790           0 :             if (nEdgeBlendingPercent && aImgSz.Width() && aImgSz.Height())
    1791             :             {
    1792           0 :                 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
    1793           0 :                 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
    1794           0 :                 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
    1795           0 :                 const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
    1796             : 
    1797           0 :                 if (!aBlendFrame.IsEmpty())
    1798             :                 {
    1799           0 :                     rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
    1800           0 :                 }
    1801             :             }
    1802           0 :         }
    1803             :     }
    1804             : 
    1805         467 :     if (bDrawText)
    1806             :     {
    1807         441 :         MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
    1808         441 :         OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
    1809         441 :         OUString aStr(mpEntryList->GetEntryText(nPos));
    1810         441 :         if (!aStr.isEmpty())
    1811             :         {
    1812         441 :             long nMaxWidth = std::max(static_cast< long >(mnMaxWidth), rRenderContext.GetOutputSizePixel().Width() - 2 * mnBorder);
    1813             :             // a multiline entry should only be as wide a the window
    1814         441 :             if ((pEntry->mnFlags & ListBoxEntryFlags::MultiLine))
    1815           0 :                 nMaxWidth = rRenderContext.GetOutputSizePixel().Width() - 2 * mnBorder;
    1816             : 
    1817             :             Rectangle aTextRect(Point(mnBorder - mnLeft, nY),
    1818         441 :                                 Size(nMaxWidth, pEntry->mnHeight));
    1819             : 
    1820         441 :             if (!bDrawTextAtImagePos && (mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled()))
    1821             :             {
    1822           0 :                 long nImageWidth = std::max(mnMaxImgWidth, maUserItemSize.Width());
    1823           0 :                 aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE;
    1824             :             }
    1825             : 
    1826         441 :             if (bLayout)
    1827           0 :                 mpControlData->mpLayoutData->m_aLineIndices.push_back(mpControlData->mpLayoutData->m_aDisplayText.getLength());
    1828             : 
    1829             :             // pb: #106948# explicit mirroring for calc
    1830         441 :             if (mbMirroring)
    1831             :             {
    1832             :                 // right aligned
    1833           0 :                 aTextRect.Left() = nMaxWidth + mnBorder - rRenderContext.GetTextWidth(aStr) - mnLeft;
    1834           0 :                 if (aImgSz.Width() > 0)
    1835           0 :                     aTextRect.Left() -= (aImgSz.Width() + IMG_TXT_DISTANCE);
    1836             :             }
    1837             : 
    1838         441 :             DrawTextFlags nDrawStyle = ImplGetTextStyle();
    1839         441 :             if ((pEntry->mnFlags & ListBoxEntryFlags::MultiLine))
    1840           0 :                 nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS;
    1841         441 :             if ((pEntry->mnFlags & ListBoxEntryFlags::DrawDisabled))
    1842           0 :                 nDrawStyle |= DrawTextFlags::Disable;
    1843             : 
    1844         441 :             rRenderContext.DrawText(aTextRect, aStr, nDrawStyle, pVector, pDisplayText);
    1845         441 :         }
    1846             :     }
    1847             : 
    1848         467 :     if (!bLayout)
    1849             :     {
    1850         493 :         if ((mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND) &&
    1851          48 :             ((nPos == mnSeparatorPos) || (nPos == mnSeparatorPos + 1)))
    1852             :         {
    1853           8 :             Color aOldLineColor(rRenderContext.GetLineColor());
    1854           8 :             rRenderContext.SetLineColor((GetBackground().GetColor() != COL_LIGHTGRAY) ? COL_LIGHTGRAY : COL_GRAY);
    1855           8 :             Point aStartPos(0, nY);
    1856           8 :             if (nPos == mnSeparatorPos)
    1857           4 :                 aStartPos.Y() += pEntry->mnHeight - 1;
    1858           8 :             Point aEndPos(aStartPos);
    1859           8 :             aEndPos.X() = GetOutputSizePixel().Width();
    1860           8 :             rRenderContext.DrawLine(aStartPos, aEndPos);
    1861           8 :             rRenderContext.SetLineColor(aOldLineColor);
    1862             :         }
    1863             :     }
    1864             : }
    1865             : 
    1866           0 : void ImplListBoxWindow::FillLayoutData() const
    1867             : {
    1868           0 :     mpControlData->mpLayoutData = new vcl::ControlLayoutData();
    1869           0 :     const_cast<ImplListBoxWindow*>(this)->Invalidate(Rectangle(Point(0, 0), GetOutputSize()));
    1870           0 : }
    1871             : 
    1872         319 : void ImplListBoxWindow::ImplDoPaint(vcl::RenderContext& rRenderContext, const Rectangle& rRect, bool bLayout)
    1873             : {
    1874         319 :     sal_Int32 nCount = mpEntryList->GetEntryCount();
    1875             : 
    1876         319 :     bool bShowFocusRect = mbHasFocusRect;
    1877         319 :     if (mbHasFocusRect && !bLayout)
    1878           0 :         ImplHideFocusRect();
    1879             : 
    1880         319 :     long nY = 0; // + mnBorder;
    1881         319 :     long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
    1882             : 
    1883         800 :     for (sal_Int32 i = (sal_Int32)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++)
    1884             :     {
    1885         481 :         const ImplEntryType* pEntry = mpEntryList->GetEntryPtr(i);
    1886         962 :         if (nY + pEntry->mnHeight >= rRect.Top() &&
    1887         481 :             nY <= rRect.Bottom() + mnMaxHeight)
    1888             :         {
    1889         467 :             ImplPaint(rRenderContext, i, false, bLayout);
    1890             :         }
    1891         481 :         nY += pEntry->mnHeight;
    1892             :     }
    1893             : 
    1894         319 :     long nHeightDiff = mpEntryList->GetAddedHeight(mnCurrentPos, mnTop, 0);
    1895         319 :     maFocusRect.SetPos(Point(0, nHeightDiff));
    1896         319 :     Size aSz(maFocusRect.GetWidth(), mpEntryList->GetEntryHeight(mnCurrentPos));
    1897         319 :     maFocusRect.SetSize(aSz);
    1898         319 :     if (HasFocus() && bShowFocusRect && !bLayout)
    1899           0 :         ImplShowFocusRect();
    1900         319 : }
    1901             : 
    1902         319 : void ImplListBoxWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
    1903             : {
    1904         319 :     ImplDoPaint(rRenderContext, rRect);
    1905         319 : }
    1906             : 
    1907         166 : sal_uInt16 ImplListBoxWindow::GetDisplayLineCount() const
    1908             : {
    1909             :     // FIXME: ListBoxEntryFlags::MultiLine
    1910             : 
    1911         166 :     sal_Int32 nCount = mpEntryList->GetEntryCount();
    1912         166 :     long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
    1913         166 :     sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight );
    1914         166 :     if( nEntries > nCount-mnTop )
    1915           0 :         nEntries = nCount-mnTop;
    1916             : 
    1917         166 :     return nEntries;
    1918             : }
    1919             : 
    1920       15939 : void ImplListBoxWindow::Resize()
    1921             : {
    1922       15939 :     Control::Resize();
    1923             : 
    1924       15939 :     bool bShowFocusRect = mbHasFocusRect;
    1925       15939 :     if ( bShowFocusRect )
    1926           0 :         ImplHideFocusRect();
    1927             : 
    1928       15939 :     if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND )
    1929             :     {
    1930        6661 :         Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
    1931        6661 :         maFocusRect.SetSize( aSz );
    1932             :     }
    1933             : 
    1934       15939 :     if ( bShowFocusRect )
    1935           0 :         ImplShowFocusRect();
    1936             : 
    1937       15939 :     ImplClearLayoutData();
    1938       15939 : }
    1939             : 
    1940           0 : void ImplListBoxWindow::GetFocus()
    1941             : {
    1942           0 :     sal_Int32 nPos = mnCurrentPos;
    1943           0 :     if ( nPos == LISTBOX_ENTRY_NOTFOUND )
    1944           0 :         nPos = 0;
    1945           0 :     long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop, 0 );
    1946           0 :     maFocusRect.SetPos( Point( 0, nHeightDiff ) );
    1947           0 :     Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) );
    1948           0 :     maFocusRect.SetSize( aSz );
    1949           0 :     ImplShowFocusRect();
    1950           0 :     Control::GetFocus();
    1951           0 : }
    1952             : 
    1953           0 : void ImplListBoxWindow::LoseFocus()
    1954             : {
    1955           0 :     ImplHideFocusRect();
    1956           0 :     Control::LoseFocus();
    1957           0 : }
    1958             : 
    1959       31554 : void ImplListBoxWindow::SetTopEntry( sal_Int32 nTop )
    1960             : {
    1961       31554 :     if( mpEntryList->GetEntryCount() == 0 )
    1962       45352 :         return;
    1963             : 
    1964       17756 :     long nWHeight = PixelToLogic( GetSizePixel() ).Height();
    1965             : 
    1966       17756 :     sal_Int32 nLastEntry = mpEntryList->GetEntryCount()-1;
    1967       17756 :     if( nTop > nLastEntry )
    1968           0 :         nTop = nLastEntry;
    1969       17756 :     const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry );
    1970       35569 :     while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->mnHeight <= nWHeight )
    1971          57 :         nTop--;
    1972             : 
    1973       17756 :     if ( nTop != mnTop )
    1974             :     {
    1975        3890 :         ImplClearLayoutData();
    1976        3890 :         long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 );
    1977        3890 :         Update();
    1978        3890 :         ImplHideFocusRect();
    1979        3890 :         mnTop = nTop;
    1980        3890 :         Scroll( 0, nDiff );
    1981        3890 :         Update();
    1982        3890 :         if( HasFocus() )
    1983           0 :             ImplShowFocusRect();
    1984        3890 :         maScrollHdl.Call( this );
    1985             :     }
    1986             : }
    1987             : 
    1988        9957 : void ImplListBoxWindow::ShowProminentEntry( sal_Int32 nEntryPos )
    1989             : {
    1990        9957 :     if( meProminentType == ProminentEntry::MIDDLE )
    1991             :     {
    1992        4915 :         sal_Int32 nPos = nEntryPos;
    1993        4915 :         long nWHeight = PixelToLogic( GetSizePixel() ).Height();
    1994       15734 :         while( nEntryPos > 0 && mpEntryList->GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 )
    1995        5904 :             nEntryPos--;
    1996             :     }
    1997        9957 :     SetTopEntry( nEntryPos );
    1998        9957 : }
    1999             : 
    2000       28274 : void ImplListBoxWindow::SetLeftIndent( long n )
    2001             : {
    2002       28274 :     ScrollHorz( n - mnLeft );
    2003       28274 : }
    2004             : 
    2005       28274 : void ImplListBoxWindow::ScrollHorz( long n )
    2006             : {
    2007       28274 :     long nDiff = 0;
    2008       28274 :     if ( n > 0 )
    2009             :     {
    2010           0 :         long nWidth = GetOutputSizePixel().Width();
    2011           0 :         if( ( mnMaxWidth - mnLeft + n ) > nWidth )
    2012           0 :             nDiff = n;
    2013             :     }
    2014       28274 :     else if ( n < 0 )
    2015             :     {
    2016           0 :         if( mnLeft )
    2017             :         {
    2018           0 :             long nAbs = -n;
    2019           0 :             nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft );
    2020             :         }
    2021             :     }
    2022             : 
    2023       28274 :     if ( nDiff )
    2024             :     {
    2025           0 :         ImplClearLayoutData();
    2026           0 :         mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff);
    2027           0 :         Update();
    2028           0 :         ImplHideFocusRect();
    2029           0 :         Scroll( -nDiff, 0 );
    2030           0 :         Update();
    2031           0 :         if( HasFocus() )
    2032           0 :             ImplShowFocusRect();
    2033           0 :         maScrollHdl.Call( this );
    2034             :     }
    2035       28274 : }
    2036             : 
    2037        6351 : Size ImplListBoxWindow::CalcSize(sal_Int32 nMaxLines) const
    2038             : {
    2039             :     // FIXME: ListBoxEntryFlags::MultiLine
    2040             : 
    2041        6351 :     Size aSz;
    2042        6351 :     aSz.Height() =  nMaxLines * mnMaxHeight;
    2043        6351 :     aSz.Width() = mnMaxWidth + 2*mnBorder;
    2044        6351 :     return aSz;
    2045             : }
    2046             : 
    2047           0 : Rectangle ImplListBoxWindow::GetBoundingRectangle( sal_Int32 nItem ) const
    2048             : {
    2049           0 :     const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem );
    2050           0 :     Size aSz( GetSizePixel().Width(), pEntry ? pEntry->mnHeight : GetEntryHeight() );
    2051           0 :     long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) + GetEntryList()->GetMRUCount()*GetEntryHeight();
    2052           0 :     Rectangle aRect( Point( 0, nY ), aSz );
    2053           0 :     return aRect;
    2054             : }
    2055             : 
    2056      204385 : void ImplListBoxWindow::StateChanged( StateChangedType nType )
    2057             : {
    2058      204385 :     Control::StateChanged( nType );
    2059             : 
    2060      204385 :     if ( nType == StateChangedType::Zoom )
    2061             :     {
    2062           3 :         ApplySettings(*this);
    2063           3 :         ImplCalcMetrics();
    2064           3 :         Invalidate();
    2065             :     }
    2066      204382 :     else if ( nType == StateChangedType::UpdateMode )
    2067             :     {
    2068      200482 :         if ( IsUpdateMode() && IsReallyVisible() )
    2069          10 :             Invalidate();
    2070             :     }
    2071        3900 :     else if ( nType == StateChangedType::ControlFont )
    2072             :     {
    2073         319 :         ApplySettings(*this);
    2074         319 :         ImplCalcMetrics();
    2075         319 :         Invalidate();
    2076             :     }
    2077        3581 :     else if ( nType == StateChangedType::ControlForeground )
    2078             :     {
    2079           4 :         ApplySettings(*this);
    2080           4 :         Invalidate();
    2081             :     }
    2082        3577 :     else if ( nType == StateChangedType::ControlBackground )
    2083             :     {
    2084           4 :         ApplySettings(*this);
    2085           4 :         Invalidate();
    2086             :     }
    2087        3573 :     else if( nType == StateChangedType::Enable )
    2088             :     {
    2089         139 :         Invalidate();
    2090             :     }
    2091             : 
    2092      204385 :     ImplClearLayoutData();
    2093      204385 : }
    2094             : 
    2095         298 : void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt )
    2096             : {
    2097         298 :     Control::DataChanged( rDCEvt );
    2098             : 
    2099        1192 :     if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
    2100        1192 :          (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
    2101         894 :          ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
    2102        1192 :           (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
    2103             :     {
    2104         298 :         ImplClearLayoutData();
    2105         298 :         ApplySettings(*this);
    2106         298 :         ImplCalcMetrics();
    2107         298 :         Invalidate();
    2108             :     }
    2109         298 : }
    2110             : 
    2111         441 : DrawTextFlags ImplListBoxWindow::ImplGetTextStyle() const
    2112             : {
    2113         441 :     DrawTextFlags nTextStyle = DrawTextFlags::VCenter;
    2114             : 
    2115         441 :     if (mpEntryList->HasImages())
    2116           0 :         nTextStyle |= DrawTextFlags::Left;
    2117         441 :     else if (mbCenter)
    2118          63 :         nTextStyle |= DrawTextFlags::Center;
    2119         378 :     else if (mbRight)
    2120           0 :         nTextStyle |= DrawTextFlags::Right;
    2121             :     else
    2122         378 :         nTextStyle |= DrawTextFlags::Left;
    2123             : 
    2124         441 :     return nTextStyle;
    2125             : }
    2126             : 
    2127        3312 : ImplListBox::ImplListBox( vcl::Window* pParent, WinBits nWinStyle ) :
    2128             :     Control( pParent, nWinStyle ),
    2129        3312 :     maLBWindow(VclPtr<ImplListBoxWindow>::Create( this, nWinStyle&(~WB_BORDER) ))
    2130             : {
    2131        3312 :     maLBWindow->userDrawSignal.connect( userDrawSignal );
    2132             : 
    2133             :     // for native widget rendering we must be able to detect this window type
    2134        3312 :     SetType( WINDOW_LISTBOXWINDOW );
    2135             : 
    2136        3312 :     mpVScrollBar    = VclPtr<ScrollBar>::Create( this, WB_VSCROLL | WB_DRAG );
    2137        3312 :     mpHScrollBar    = VclPtr<ScrollBar>::Create( this, WB_HSCROLL | WB_DRAG );
    2138        3312 :     mpScrollBarBox  = VclPtr<ScrollBarBox>::Create( this );
    2139             : 
    2140        3312 :     Link<> aLink( LINK( this, ImplListBox, ScrollBarHdl ) );
    2141        3312 :     mpVScrollBar->SetScrollHdl( aLink );
    2142        3312 :     mpHScrollBar->SetScrollHdl( aLink );
    2143             : 
    2144        3312 :     mbVScroll       = false;
    2145        3312 :     mbHScroll       = false;
    2146        3312 :     mbAutoHScroll   = ( nWinStyle & WB_AUTOHSCROLL );
    2147        3312 :     mbEdgeBlending  = false;
    2148             : 
    2149        3312 :     maLBWindow->SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) );
    2150        3312 :     maLBWindow->SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) );
    2151        3312 :     maLBWindow->SetEdgeBlending(GetEdgeBlending());
    2152        3312 :     maLBWindow->Show();
    2153        3312 : }
    2154             : 
    2155        9930 : ImplListBox::~ImplListBox()
    2156             : {
    2157        3310 :     disposeOnce();
    2158        6620 : }
    2159             : 
    2160        3310 : void ImplListBox::dispose()
    2161             : {
    2162        3310 :     mpHScrollBar.disposeAndClear();
    2163        3310 :     mpVScrollBar.disposeAndClear();
    2164        3310 :     mpScrollBarBox.disposeAndClear();
    2165        3310 :     maLBWindow.disposeAndClear();
    2166        3310 :     Control::dispose();
    2167        3310 : }
    2168             : 
    2169        9642 : void ImplListBox::Clear()
    2170             : {
    2171        9642 :     maLBWindow->Clear();
    2172        9642 :     if ( GetEntryList()->GetMRUCount() )
    2173             :     {
    2174           0 :         maLBWindow->GetEntryList()->SetMRUCount( 0 );
    2175           0 :         maLBWindow->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
    2176             :     }
    2177        9642 :     mpVScrollBar->SetThumbPos( 0 );
    2178        9642 :     mpHScrollBar->SetThumbPos( 0 );
    2179        9642 :     CompatStateChanged( StateChangedType::Data );
    2180        9642 : }
    2181             : 
    2182      172610 : sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr )
    2183             : {
    2184      172610 :     ImplEntryType* pNewEntry = new ImplEntryType( rStr );
    2185      172610 :     sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
    2186      172610 :     if (nNewPos == LISTBOX_ERROR)
    2187             :     {
    2188           0 :         delete pNewEntry;
    2189           0 :         return nNewPos;
    2190             :     }
    2191      172610 :     CompatStateChanged( StateChangedType::Data );
    2192      172610 :     return nNewPos;
    2193             : }
    2194             : 
    2195         200 : sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr, const Image& rImage )
    2196             : {
    2197         200 :     ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage );
    2198         200 :     sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
    2199         200 :     if (nNewPos == LISTBOX_ERROR)
    2200             :     {
    2201           0 :         delete pNewEntry;
    2202           0 :         return nNewPos;
    2203             :     }
    2204         200 :     CompatStateChanged( StateChangedType::Data );
    2205         200 :     return nNewPos;
    2206             : }
    2207             : 
    2208           0 : void ImplListBox::RemoveEntry( sal_Int32 nPos )
    2209             : {
    2210           0 :     maLBWindow->RemoveEntry( nPos );
    2211           0 :     CompatStateChanged( StateChangedType::Data );
    2212           0 : }
    2213             : 
    2214           0 : void ImplListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
    2215             : {
    2216           0 :     maLBWindow->SetEntryFlags( nPos, nFlags );
    2217           0 : }
    2218             : 
    2219        7764 : void ImplListBox::SelectEntry( sal_Int32 nPos, bool bSelect )
    2220             : {
    2221        7764 :     maLBWindow->SelectEntry( nPos, bSelect );
    2222        7764 : }
    2223             : 
    2224          45 : void ImplListBox::SetNoSelection()
    2225             : {
    2226          45 :     maLBWindow->DeselectAll();
    2227          45 : }
    2228             : 
    2229           0 : void ImplListBox::GetFocus()
    2230             : {
    2231           0 :     if (maLBWindow)
    2232           0 :         maLBWindow->GrabFocus();
    2233             :     else
    2234           0 :         Control::GetFocus();
    2235           0 : }
    2236             : 
    2237           0 : vcl::Window* ImplListBox::GetPreferredKeyInputWindow()
    2238             : {
    2239           0 :     return maLBWindow.get();
    2240             : }
    2241             : 
    2242       14013 : void ImplListBox::Resize()
    2243             : {
    2244       14013 :     Control::Resize();
    2245       14013 :     ImplResizeControls();
    2246       14013 :     ImplCheckScrollBars();
    2247       14013 : }
    2248             : 
    2249           0 : IMPL_LINK_NOARG(ImplListBox, MRUChanged)
    2250             : {
    2251           0 :     CompatStateChanged( StateChangedType::Data );
    2252           0 :     return 1;
    2253             : }
    2254             : 
    2255        7780 : IMPL_LINK_NOARG(ImplListBox, LBWindowScrolled)
    2256             : {
    2257        3890 :     long nSet = GetTopEntry();
    2258        3890 :     if( nSet > mpVScrollBar->GetRangeMax() )
    2259           0 :         mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() );
    2260        3890 :     mpVScrollBar->SetThumbPos( GetTopEntry() );
    2261             : 
    2262        3890 :     mpHScrollBar->SetThumbPos( GetLeftIndent() );
    2263             : 
    2264        3890 :     maScrollHdl.Call( this );
    2265             : 
    2266        3890 :     return 1;
    2267             : }
    2268             : 
    2269           0 : IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB )
    2270             : {
    2271           0 :     sal_uInt16 nPos = (sal_uInt16) pSB->GetThumbPos();
    2272           0 :     if( pSB == mpVScrollBar )
    2273           0 :         SetTopEntry( nPos );
    2274           0 :     else if( pSB == mpHScrollBar )
    2275           0 :         SetLeftIndent( nPos );
    2276             : 
    2277           0 :     return 1;
    2278             : }
    2279             : 
    2280       14031 : void ImplListBox::ImplCheckScrollBars()
    2281             : {
    2282       14031 :     bool bArrange = false;
    2283             : 
    2284       14031 :     Size aOutSz = GetOutputSizePixel();
    2285       14031 :     sal_Int32 nEntries = GetEntryList()->GetEntryCount();
    2286       14031 :     sal_uInt16 nMaxVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight());
    2287             : 
    2288             :     // vertical ScrollBar
    2289       14031 :     if( nEntries > nMaxVisEntries )
    2290             :     {
    2291        4644 :         if( !mbVScroll )
    2292        1483 :             bArrange = true;
    2293        4644 :         mbVScroll = true;
    2294             : 
    2295             :         // check of the scrolled-out region
    2296        8126 :         if( GetEntryList()->GetSelectEntryCount() == 1 &&
    2297        3482 :             GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND )
    2298        3482 :             ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) );
    2299             :         else
    2300        1162 :             SetTopEntry( GetTopEntry() );   // MaxTop is being checked...
    2301             :     }
    2302             :     else
    2303             :     {
    2304        9387 :         if( mbVScroll )
    2305           2 :             bArrange = true;
    2306        9387 :         mbVScroll = false;
    2307        9387 :         SetTopEntry( 0 );
    2308             :     }
    2309             : 
    2310             :     // horizontal ScrollBar
    2311       14031 :     if( mbAutoHScroll )
    2312             :     {
    2313       12662 :         long nWidth = (sal_uInt16) aOutSz.Width();
    2314       12662 :         if ( mbVScroll )
    2315        4644 :             nWidth -= mpVScrollBar->GetSizePixel().Width();
    2316             : 
    2317       12662 :         long nMaxWidth = GetMaxEntryWidth();
    2318       12662 :         if( nWidth < nMaxWidth )
    2319             :         {
    2320           0 :             if( !mbHScroll )
    2321           0 :                 bArrange = true;
    2322           0 :             mbHScroll = true;
    2323             : 
    2324           0 :             if ( !mbVScroll )   // maybe we do need one now
    2325             :             {
    2326           0 :                 nMaxVisEntries = (sal_uInt16) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() );
    2327           0 :                 if( nEntries > nMaxVisEntries )
    2328             :                 {
    2329           0 :                     bArrange = true;
    2330           0 :                     mbVScroll = true;
    2331             : 
    2332             :                     // check of the scrolled-out region
    2333           0 :                     if( GetEntryList()->GetSelectEntryCount() == 1 &&
    2334           0 :                         GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND )
    2335           0 :                         ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) );
    2336             :                     else
    2337           0 :                         SetTopEntry( GetTopEntry() );   // MaxTop is being checked...
    2338             :                 }
    2339             :             }
    2340             : 
    2341             :             // check of the scrolled-out region
    2342           0 :             sal_uInt16 nMaxLI = (sal_uInt16) (nMaxWidth - nWidth);
    2343           0 :             if ( nMaxLI < GetLeftIndent() )
    2344           0 :                 SetLeftIndent( nMaxLI );
    2345             :         }
    2346             :         else
    2347             :         {
    2348       12662 :             if( mbHScroll )
    2349           0 :                 bArrange = true;
    2350       12662 :             mbHScroll = false;
    2351       12662 :             SetLeftIndent( 0 );
    2352             :         }
    2353             :     }
    2354             : 
    2355       14031 :     if( bArrange )
    2356        1485 :         ImplResizeControls();
    2357             : 
    2358       14031 :     ImplInitScrollBars();
    2359       14031 : }
    2360             : 
    2361       14031 : void ImplListBox::ImplInitScrollBars()
    2362             : {
    2363       14031 :     Size aOutSz = maLBWindow->GetOutputSizePixel();
    2364             : 
    2365       14031 :     if ( mbVScroll )
    2366             :     {
    2367        4644 :         sal_Int32 nEntries = GetEntryList()->GetEntryCount();
    2368        4644 :         sal_uInt16 nVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight());
    2369        4644 :         mpVScrollBar->SetRangeMax( nEntries );
    2370        4644 :         mpVScrollBar->SetVisibleSize( nVisEntries );
    2371        4644 :         mpVScrollBar->SetPageSize( nVisEntries - 1 );
    2372             :     }
    2373             : 
    2374       14031 :     if ( mbHScroll )
    2375             :     {
    2376           0 :         mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL );
    2377           0 :         mpHScrollBar->SetVisibleSize( (sal_uInt16)aOutSz.Width() );
    2378           0 :         mpHScrollBar->SetLineSize( HORZ_SCROLL );
    2379           0 :         mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL );
    2380             :     }
    2381       14031 : }
    2382             : 
    2383       15612 : void ImplListBox::ImplResizeControls()
    2384             : {
    2385             :     // Here we only position the Controls; if the Scrollbars are to be
    2386             :     // visible is already determined in ImplCheckScrollBars
    2387             : 
    2388       15612 :     Size aOutSz = GetOutputSizePixel();
    2389       15612 :     long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
    2390       15612 :     nSBWidth = CalcZoom( nSBWidth );
    2391             : 
    2392       15612 :     Size aInnerSz( aOutSz );
    2393       15612 :     if ( mbVScroll )
    2394        4648 :         aInnerSz.Width() -= nSBWidth;
    2395       15612 :     if ( mbHScroll )
    2396           0 :         aInnerSz.Height() -= nSBWidth;
    2397             : 
    2398             :     // pb: #106948# explicit mirroring for calc
    2399             :     // Scrollbar on left or right side?
    2400       15612 :     bool bMirroring = maLBWindow->IsMirroring();
    2401       15612 :     Point aWinPos( bMirroring && mbVScroll ? nSBWidth : 0, 0 );
    2402       15612 :     maLBWindow->SetPosSizePixel( aWinPos, aInnerSz );
    2403             : 
    2404             :     // ScrollBarBox
    2405       15612 :     if( mbVScroll && mbHScroll )
    2406             :     {
    2407           0 :         Point aBoxPos( bMirroring ? 0 : aInnerSz.Width(), aInnerSz.Height() );
    2408           0 :         mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) );
    2409           0 :         mpScrollBarBox->Show();
    2410             :     }
    2411             :     else
    2412             :     {
    2413       15612 :         mpScrollBarBox->Hide();
    2414             :     }
    2415             : 
    2416             :     // vertical ScrollBar
    2417       15612 :     if( mbVScroll )
    2418             :     {
    2419             :         // Scrollbar on left or right side?
    2420        4648 :         Point aVPos( bMirroring ? 0 : aOutSz.Width() - nSBWidth, 0 );
    2421        4648 :         mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) );
    2422        4648 :         mpVScrollBar->Show();
    2423             :     }
    2424             :     else
    2425             :     {
    2426       10964 :         mpVScrollBar->Hide();
    2427             :         // #107254# Don't reset top entry after resize, but check for max top entry
    2428       10964 :         SetTopEntry( GetTopEntry() );
    2429             :     }
    2430             : 
    2431             :     // horizontal ScrollBar
    2432       15612 :     if( mbHScroll )
    2433             :     {
    2434           0 :         Point aHPos( ( bMirroring && mbVScroll ) ? nSBWidth : 0, aOutSz.Height() - nSBWidth );
    2435           0 :         mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) );
    2436           0 :         mpHScrollBar->Show();
    2437             :     }
    2438             :     else
    2439             :     {
    2440       15612 :         mpHScrollBar->Hide();
    2441       15612 :         SetLeftIndent( 0 );
    2442             :     }
    2443       15612 : }
    2444             : 
    2445      204385 : void ImplListBox::StateChanged( StateChangedType nType )
    2446             : {
    2447      204385 :     if ( nType == StateChangedType::InitShow )
    2448             :     {
    2449           8 :         ImplCheckScrollBars();
    2450             :     }
    2451      204377 :     else if ( ( nType == StateChangedType::UpdateMode ) || ( nType == StateChangedType::Data ) )
    2452             :     {
    2453      200482 :         bool bUpdate = IsUpdateMode();
    2454      200482 :         maLBWindow->SetUpdateMode( bUpdate );
    2455      200482 :         if ( bUpdate && IsReallyVisible() )
    2456          10 :             ImplCheckScrollBars();
    2457             :     }
    2458        3895 :     else if( nType == StateChangedType::Enable )
    2459             :     {
    2460         139 :         mpHScrollBar->Enable( IsEnabled() );
    2461         139 :         mpVScrollBar->Enable( IsEnabled() );
    2462         139 :         mpScrollBarBox->Enable( IsEnabled() );
    2463         139 :         maLBWindow->Enable( IsEnabled() );
    2464             : 
    2465         139 :         Invalidate();
    2466             :     }
    2467        3756 :     else if ( nType == StateChangedType::Zoom )
    2468             :     {
    2469           3 :         maLBWindow->SetZoom( GetZoom() );
    2470           3 :         Resize();
    2471             :     }
    2472        3753 :     else if ( nType == StateChangedType::ControlFont )
    2473             :     {
    2474         319 :         maLBWindow->SetControlFont( GetControlFont() );
    2475             :     }
    2476        3434 :     else if ( nType == StateChangedType::ControlForeground )
    2477             :     {
    2478           4 :         maLBWindow->SetControlForeground( GetControlForeground() );
    2479             :     }
    2480        3430 :     else if ( nType == StateChangedType::ControlBackground )
    2481             :     {
    2482           4 :         maLBWindow->SetControlBackground( GetControlBackground() );
    2483             :     }
    2484        3426 :     else if( nType == StateChangedType::Mirroring )
    2485             :     {
    2486         114 :         maLBWindow->EnableRTL( IsRTLEnabled() );
    2487         114 :         mpHScrollBar->EnableRTL( IsRTLEnabled() );
    2488         114 :         mpVScrollBar->EnableRTL( IsRTLEnabled() );
    2489         114 :         ImplResizeControls();
    2490             :     }
    2491             : 
    2492      204385 :     Control::StateChanged( nType );
    2493      204385 : }
    2494             : 
    2495         298 : void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt )
    2496             : {
    2497         298 :         Control::DataChanged( rDCEvt );
    2498         298 : }
    2499             : 
    2500       13356 : bool ImplListBox::Notify( NotifyEvent& rNEvt )
    2501             : {
    2502       13356 :     bool nDone = false;
    2503       13356 :     if ( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
    2504             :     {
    2505           0 :         const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
    2506           0 :         if ( rCEvt.GetCommand() == CommandEventId::Wheel )
    2507             :         {
    2508           0 :             const CommandWheelData* pData = rCEvt.GetWheelData();
    2509           0 :             if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
    2510             :             {
    2511           0 :                 nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
    2512             :             }
    2513             :         }
    2514             :     }
    2515             : 
    2516       13356 :     return nDone || Window::Notify( rNEvt );
    2517             : }
    2518             : 
    2519           0 : const Wallpaper& ImplListBox::GetDisplayBackground() const
    2520             : {
    2521           0 :     return maLBWindow->GetDisplayBackground();
    2522             : }
    2523             : 
    2524           0 : bool ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt )
    2525             : {
    2526           0 :     bool bDone = false;
    2527           0 :     if ( rCEvt.GetCommand() == CommandEventId::Wheel )
    2528             :     {
    2529           0 :         const CommandWheelData* pData = rCEvt.GetWheelData();
    2530           0 :         if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
    2531             :         {
    2532           0 :             sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP;
    2533           0 :             KeyEvent aKeyEvent( 0, vcl::KeyCode( nKey ) );
    2534           0 :             bDone = ProcessKeyInput( aKeyEvent );
    2535             :         }
    2536             :     }
    2537           0 :     return bDone;
    2538             : }
    2539             : 
    2540           0 : void ImplListBox::SetMRUEntries( const OUString& rEntries, sal_Unicode cSep )
    2541             : {
    2542           0 :     bool bChanges = GetEntryList()->GetMRUCount() != 0;
    2543             : 
    2544             :     // Remove old MRU entries
    2545           0 :     for ( sal_Int32 n = GetEntryList()->GetMRUCount();n; )
    2546           0 :         maLBWindow->RemoveEntry( --n );
    2547             : 
    2548           0 :     sal_Int32 nMRUCount = 0;
    2549           0 :     sal_Int32 nIndex = 0;
    2550           0 :     do
    2551             :     {
    2552           0 :         OUString aEntry = rEntries.getToken( 0, cSep, nIndex );
    2553             :         // Accept only existing entries
    2554           0 :         if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND )
    2555             :         {
    2556           0 :             ImplEntryType* pNewEntry = new ImplEntryType( aEntry );
    2557           0 :             maLBWindow->GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, false );
    2558           0 :             bChanges = true;
    2559           0 :         }
    2560             :     }
    2561           0 :     while ( nIndex >= 0 );
    2562             : 
    2563           0 :     if ( bChanges )
    2564             :     {
    2565           0 :         maLBWindow->GetEntryList()->SetMRUCount( nMRUCount );
    2566           0 :         SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
    2567           0 :         CompatStateChanged( StateChangedType::Data );
    2568             :     }
    2569           0 : }
    2570             : 
    2571        1962 : OUString ImplListBox::GetMRUEntries( sal_Unicode cSep ) const
    2572             : {
    2573        1962 :     OUStringBuffer aEntries;
    2574        1962 :     for ( sal_Int32 n = 0; n < GetEntryList()->GetMRUCount(); n++ )
    2575             :     {
    2576           0 :         aEntries.append(GetEntryList()->GetEntryText( n ));
    2577           0 :         if( n < ( GetEntryList()->GetMRUCount() - 1 ) )
    2578           0 :             aEntries.append(cSep);
    2579             :     }
    2580        1962 :     return aEntries.makeStringAndClear();
    2581             : }
    2582             : 
    2583         374 : void ImplListBox::SetEdgeBlending(bool bNew)
    2584             : {
    2585         374 :     if(mbEdgeBlending != bNew)
    2586             :     {
    2587          51 :         mbEdgeBlending = bNew;
    2588          51 :         maLBWindow->SetEdgeBlending(GetEdgeBlending());
    2589             :     }
    2590         374 : }
    2591             : 
    2592         309 : ImplWin::ImplWin( vcl::Window* pParent, WinBits nWinStyle ) :
    2593         309 :     Control ( pParent, nWinStyle )
    2594             : {
    2595         618 :     if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
    2596         309 :             && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
    2597           0 :         SetBackground();
    2598             :     else
    2599         309 :         SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
    2600             : 
    2601         309 :     ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
    2602             : 
    2603         309 :     mbInUserDraw = false;
    2604         309 :     mbUserDrawEnabled = false;
    2605         309 :     mbEdgeBlending = false;
    2606         309 :     mnItemPos = LISTBOX_ENTRY_NOTFOUND;
    2607         309 : }
    2608             : 
    2609           0 : void ImplWin::MBDown()
    2610             : {
    2611           0 :     if( IsEnabled() )
    2612           0 :         buttonDownSignal( this );
    2613           0 : }
    2614             : 
    2615           0 : void ImplWin::MouseButtonDown( const MouseEvent& )
    2616             : {
    2617           0 :     if( IsEnabled() )
    2618             :     {
    2619           0 :         MBDown();
    2620             :     }
    2621           0 : }
    2622             : 
    2623           0 : void ImplWin::FillLayoutData() const
    2624             : {
    2625           0 :     mpControlData->mpLayoutData = new vcl::ControlLayoutData();
    2626           0 :     ImplWin* pThis = const_cast<ImplWin*>(this);
    2627           0 :     pThis->ImplDraw(*pThis, true);
    2628           0 : }
    2629             : 
    2630           1 : bool ImplWin::PreNotify( NotifyEvent& rNEvt )
    2631             : {
    2632           1 :     const MouseEvent* pMouseEvt = NULL;
    2633             : 
    2634           1 :     if( (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
    2635             :     {
    2636           0 :         if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() )
    2637             :         {
    2638             :             // trigger redraw as mouse over state has changed
    2639           0 :             if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
    2640           0 :             && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
    2641             :             {
    2642           0 :                 GetParent()->GetWindow( GetWindowType::Border )->Invalidate( InvalidateFlags::NoErase );
    2643           0 :                 GetParent()->GetWindow( GetWindowType::Border )->Update();
    2644             :             }
    2645             :         }
    2646             :     }
    2647             : 
    2648           1 :     return Control::PreNotify(rNEvt);
    2649             : }
    2650             : 
    2651        1056 : void ImplWin::ImplDraw(vcl::RenderContext& rRenderContext, bool bLayout)
    2652             : {
    2653        1056 :     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
    2654             : 
    2655        1056 :     if (!bLayout)
    2656             :     {
    2657        1056 :         bool bNativeOK = false;
    2658             : 
    2659        1056 :         ControlState nState = ControlState::ENABLED;
    2660        2112 :         if (rRenderContext.IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
    2661        1056 :             && rRenderContext.IsNativeControlSupported(CTRL_LISTBOX, HAS_BACKGROUND_TEXTURE) )
    2662             :         {
    2663             :             // Repaint the (focused) area similarly to
    2664             :             // ImplSmallBorderWindowView::DrawWindow() in
    2665             :             // vcl/source/window/brdwin.cxx
    2666           0 :             vcl::Window *pWin = GetParent();
    2667             : 
    2668           0 :             ImplControlValue aControlValue;
    2669           0 :             if ( !pWin->IsEnabled() )
    2670           0 :                 nState &= ~ControlState::ENABLED;
    2671           0 :             if ( pWin->HasFocus() )
    2672           0 :                 nState |= ControlState::FOCUSED;
    2673             : 
    2674             :             // The listbox is painted over the entire control including the
    2675             :             // border, but ImplWin does not contain the border => correction
    2676             :             // needed.
    2677             :             sal_Int32 nLeft, nTop, nRight, nBottom;
    2678           0 :             pWin->GetBorder( nLeft, nTop, nRight, nBottom );
    2679           0 :             Point aPoint( -nLeft, -nTop );
    2680           0 :             Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() );
    2681             : 
    2682           0 :             bool bMouseOver = false;
    2683           0 :             if( GetParent() )
    2684             :             {
    2685           0 :                 vcl::Window *pChild = GetParent()->GetWindow( GetWindowType::FirstChild );
    2686           0 :                 while( pChild && !(bMouseOver = pChild->IsMouseOver()) )
    2687           0 :                     pChild = pChild->GetWindow( GetWindowType::Next );
    2688             :             }
    2689             : 
    2690           0 :             if( bMouseOver )
    2691           0 :                 nState |= ControlState::ROLLOVER;
    2692             : 
    2693             :             // if parent has no border, then nobody has drawn the background
    2694             :             // since no border window exists. so draw it here.
    2695           0 :             WinBits nParentStyle = pWin->GetStyle();
    2696           0 :             if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) )
    2697             :             {
    2698           0 :                 Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() );
    2699             :                 pWin->DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aParentRect,
    2700           0 :                                          nState, aControlValue, OUString() );
    2701             :             }
    2702             : 
    2703             :             bNativeOK = rRenderContext.DrawNativeControl(CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
    2704           0 :                                                          nState, aControlValue, OUString());
    2705             :         }
    2706             : 
    2707        1056 :         if (IsEnabled())
    2708             :         {
    2709         871 :             if (HasFocus() && !ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
    2710             :             {
    2711           2 :                 rRenderContext.SetTextColor( rStyleSettings.GetHighlightTextColor() );
    2712           2 :                 rRenderContext.SetFillColor( rStyleSettings.GetHighlightColor() );
    2713           2 :                 rRenderContext.DrawRect( maFocusRect );
    2714             :             }
    2715             :             else
    2716             :             {
    2717         869 :                 Color aColor;
    2718         869 :                 if( ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea )
    2719             :                 {
    2720           0 :                     if( bNativeOK && (nState & ControlState::ROLLOVER) )
    2721           0 :                         aColor = rStyleSettings.GetButtonRolloverTextColor();
    2722             :                     else
    2723           0 :                         aColor = rStyleSettings.GetButtonTextColor();
    2724             :                 }
    2725             :                 else
    2726             :                 {
    2727         869 :                     if( bNativeOK && (nState & ControlState::ROLLOVER) )
    2728           0 :                         aColor = rStyleSettings.GetFieldRolloverTextColor();
    2729             :                     else
    2730         869 :                         aColor = rStyleSettings.GetFieldTextColor();
    2731             :                 }
    2732         869 :                 if (IsControlForeground())
    2733           0 :                     aColor = GetControlForeground();
    2734         869 :                 rRenderContext.SetTextColor(aColor);
    2735         869 :                 if (!bNativeOK)
    2736         869 :                     rRenderContext.Erase(maFocusRect);
    2737             :             }
    2738             :         }
    2739             :         else // Disabled
    2740             :         {
    2741         185 :             rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
    2742         185 :             if (!bNativeOK)
    2743         185 :                 rRenderContext.Erase(maFocusRect);
    2744             :         }
    2745             :     }
    2746             : 
    2747        1056 :     if ( IsUserDrawEnabled() )
    2748             :     {
    2749           1 :         mbInUserDraw = true;
    2750           1 :         UserDrawEvent aUDEvt(&rRenderContext, maFocusRect, mnItemPos, 0);
    2751           1 :         userDrawSignal( &aUDEvt );
    2752           1 :         mbInUserDraw = false;
    2753             :     }
    2754             :     else
    2755             :     {
    2756        1055 :         DrawEntry(rRenderContext, true, true, false, bLayout);
    2757             :     }
    2758        1056 : }
    2759             : 
    2760        1084 : void ImplWin::ApplySettings(vcl::RenderContext& rRenderContext)
    2761             : {
    2762        1084 :     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
    2763             : 
    2764        1084 :     vcl::Font aFont = rStyleSettings.GetFieldFont();
    2765        1084 :     if (IsControlFont())
    2766         152 :         aFont.Merge(GetControlFont());
    2767        1084 :     SetZoomedPointFont(rRenderContext, aFont);
    2768             : 
    2769        1084 :     Color aTextColor = rStyleSettings.GetFieldTextColor();
    2770        1084 :     if (IsControlForeground())
    2771           0 :         aTextColor = GetControlForeground();
    2772        1084 :     rRenderContext.SetTextColor(aTextColor);
    2773             : 
    2774        1084 :     if (IsControlBackground())
    2775           0 :         rRenderContext.SetBackground(GetControlBackground());
    2776             :     else
    2777        1084 :         rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
    2778        1084 : }
    2779             : 
    2780        1056 : void ImplWin::Paint( vcl::RenderContext& rRenderContext, const Rectangle& )
    2781             : {
    2782        1056 :     ImplDraw(rRenderContext);
    2783        1056 : }
    2784             : 
    2785        1056 : void ImplWin::DrawEntry(vcl::RenderContext& rRenderContext, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos, bool bLayout)
    2786             : {
    2787        1056 :     long nBorder = 1;
    2788        1056 :     Size aOutSz = rRenderContext.GetOutputSizePixel();
    2789             : 
    2790        1056 :     bool bImage = !!maImage;
    2791        1056 :     if (bDrawImage && bImage && !bLayout)
    2792             :     {
    2793           0 :         DrawImageFlags nStyle = DrawImageFlags::NONE;
    2794           0 :         Size aImgSz = maImage.GetSizePixel();
    2795           0 :         Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) );
    2796           0 :         const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    2797             : 
    2798             :         // check for HC mode
    2799           0 :         Image *pImage = &maImage;
    2800             : 
    2801           0 :         if ( !IsZoom() )
    2802             :         {
    2803           0 :             rRenderContext.DrawImage( aPtImg, *pImage, nStyle );
    2804             :         }
    2805             :         else
    2806             :         {
    2807           0 :             aImgSz.Width() = CalcZoom( aImgSz.Width() );
    2808           0 :             aImgSz.Height() = CalcZoom( aImgSz.Height() );
    2809           0 :             rRenderContext.DrawImage( aPtImg, aImgSz, *pImage, nStyle );
    2810             :         }
    2811             : 
    2812           0 :         const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
    2813             : 
    2814           0 :         if(nEdgeBlendingPercent)
    2815             :         {
    2816           0 :             const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
    2817           0 :             const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
    2818           0 :             const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
    2819           0 :             const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
    2820             : 
    2821           0 :             if(!aBlendFrame.IsEmpty())
    2822             :             {
    2823           0 :                 rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
    2824           0 :             }
    2825             :         }
    2826             :     }
    2827             : 
    2828        1056 :     if( bDrawText && !maString.isEmpty() )
    2829             :     {
    2830          41 :         DrawTextFlags nTextStyle = DrawTextFlags::VCenter;
    2831             : 
    2832          41 :         if ( bDrawImage && bImage && !bLayout )
    2833           0 :             nTextStyle |= DrawTextFlags::Left;
    2834          41 :         else if ( GetStyle() & WB_CENTER )
    2835           0 :             nTextStyle |= DrawTextFlags::Center;
    2836          41 :         else if ( GetStyle() & WB_RIGHT )
    2837           0 :             nTextStyle |= DrawTextFlags::Right;
    2838             :         else
    2839          41 :             nTextStyle |= DrawTextFlags::Left;
    2840             : 
    2841          41 :         Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) );
    2842             : 
    2843          41 :         if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) )
    2844             :         {
    2845           0 :             long nMaxWidth = std::max( maImage.GetSizePixel().Width(), maUserItemSize.Width() );
    2846           0 :             aTextRect.Left() += nMaxWidth + IMG_TXT_DISTANCE;
    2847             :         }
    2848             : 
    2849          41 :         MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
    2850          41 :         OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
    2851          41 :         rRenderContext.DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText );
    2852             :     }
    2853             : 
    2854        1056 :     if( HasFocus() && !bLayout )
    2855           2 :         ShowFocus( maFocusRect );
    2856        1056 : }
    2857             : 
    2858         956 : void ImplWin::Resize()
    2859             : {
    2860         956 :     Control::Resize();
    2861         956 :     maFocusRect.SetSize( GetOutputSizePixel() );
    2862         956 :     Invalidate();
    2863         956 : }
    2864             : 
    2865           1 : void ImplWin::GetFocus()
    2866             : {
    2867           1 :     ShowFocus( maFocusRect );
    2868           2 :     if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
    2869           1 :         IsNativeWidgetEnabled() &&
    2870           0 :         IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
    2871             :     {
    2872           0 :         vcl::Window* pWin = GetParent()->GetWindow( GetWindowType::Border );
    2873           0 :         if( ! pWin )
    2874           0 :             pWin = GetParent();
    2875           0 :         pWin->Invalidate();
    2876             :     }
    2877             :     else
    2878           1 :         Invalidate();
    2879           1 :     Control::GetFocus();
    2880           1 : }
    2881             : 
    2882           0 : void ImplWin::LoseFocus()
    2883             : {
    2884           0 :     HideFocus();
    2885           0 :     if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
    2886           0 :         IsNativeWidgetEnabled() &&
    2887           0 :         IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
    2888             :     {
    2889           0 :         vcl::Window* pWin = GetParent()->GetWindow( GetWindowType::Border );
    2890           0 :         if( ! pWin )
    2891           0 :             pWin = GetParent();
    2892           0 :         pWin->Invalidate();
    2893             :     }
    2894             :     else
    2895           0 :         Invalidate();
    2896           0 :     Control::LoseFocus();
    2897           0 : }
    2898             : 
    2899           3 : void ImplWin::ShowFocus(const Rectangle& rRect)
    2900             : {
    2901           3 :     if (IsNativeControlSupported(CTRL_LISTBOX, PART_FOCUS))
    2902             :     {
    2903           0 :         ImplControlValue aControlValue;
    2904             : 
    2905           0 :         vcl::Window *pWin = GetParent();
    2906           0 :         Rectangle aParentRect(Point(0, 0), pWin->GetSizePixel());
    2907             :         pWin->DrawNativeControl(CTRL_LISTBOX, PART_FOCUS, aParentRect,
    2908           0 :                                 ControlState::FOCUSED, aControlValue, OUString());
    2909             :     }
    2910           3 :     Control::ShowFocus(rRect);
    2911           3 : }
    2912             : 
    2913        3282 : ImplBtn::ImplBtn( vcl::Window* pParent, WinBits nWinStyle ) :
    2914             :     PushButton(  pParent, nWinStyle ),
    2915        3282 :     mbDown  ( false )
    2916             : {
    2917        3282 : }
    2918             : 
    2919           0 : void ImplBtn::MBDown()
    2920             : {
    2921           0 :     if( IsEnabled() )
    2922           0 :        buttonDownSignal( this );
    2923           0 : }
    2924             : 
    2925           0 : void ImplBtn::MouseButtonDown( const MouseEvent& )
    2926             : {
    2927             :     //PushButton::MouseButtonDown( rMEvt );
    2928           0 :     if( IsEnabled() )
    2929             :     {
    2930           0 :         MBDown();
    2931           0 :         mbDown = true;
    2932             :     }
    2933           0 : }
    2934             : 
    2935        3282 : ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( vcl::Window* pParent ) :
    2936        3282 :     FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW )    // no drop shadow for list boxes
    2937             : {
    2938        3282 :     mpImplLB = NULL;
    2939        3282 :     mnDDLineCount = 0;
    2940        3282 :     mbAutoWidth = false;
    2941             : 
    2942        3282 :     mnPopupModeStartSaveSelection = LISTBOX_ENTRY_NOTFOUND;
    2943             : 
    2944        3282 :     EnableSaveBackground();
    2945             : 
    2946        3282 :     vcl::Window * pBorderWindow = ImplGetBorderWindow();
    2947        3282 :     if( pBorderWindow )
    2948             :     {
    2949        3282 :         SetAccessibleRole(accessibility::AccessibleRole::PANEL);
    2950        3282 :         pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
    2951             :     }
    2952             :     else
    2953             :     {
    2954           0 :         SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
    2955             :     }
    2956             : 
    2957        3282 : }
    2958             : 
    2959        9840 : ImplListBoxFloatingWindow::~ImplListBoxFloatingWindow()
    2960             : {
    2961        3280 :     disposeOnce();
    2962        6560 : }
    2963             : 
    2964        3280 : void ImplListBoxFloatingWindow::dispose()
    2965             : {
    2966        3280 :     mpImplLB.clear();
    2967        3280 :     FloatingWindow::dispose();
    2968        3280 : }
    2969             : 
    2970             : 
    2971           0 : bool ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt )
    2972             : {
    2973           0 :     if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    2974             :     {
    2975           0 :         if( !GetParent()->HasChildPathFocus( true ) )
    2976           0 :             EndPopupMode();
    2977             :     }
    2978             : 
    2979           0 :     return FloatingWindow::PreNotify( rNEvt );
    2980             : }
    2981             : 
    2982        6069 : void ImplListBoxFloatingWindow::setPosSizePixel( long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags )
    2983             : {
    2984        6069 :     FloatingWindow::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
    2985             : 
    2986             :     // Fix #60890# ( MBA ): to be able to resize the Listbox even in its open state
    2987             :     // after a call to Resize(), we adjust its position if necessary
    2988        6069 :     if ( IsReallyVisible() && ( nFlags & PosSizeFlags::Height ) )
    2989             :     {
    2990           0 :         Point aPos = GetParent()->GetPosPixel();
    2991           0 :         aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
    2992             : 
    2993           0 :         if ( nFlags & PosSizeFlags::X )
    2994           0 :             aPos.X() = nX;
    2995             : 
    2996           0 :         if ( nFlags & PosSizeFlags::Y )
    2997           0 :             aPos.Y() = nY;
    2998             : 
    2999             :         sal_uInt16 nIndex;
    3000           0 :         SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FloatWinPopupFlags::Down, nIndex ) );
    3001             :     }
    3002             : 
    3003             : //  if( !IsReallyVisible() )
    3004             :     {
    3005             :         // The ImplListBox does not get a Resize() as not visible.
    3006             :         // But the windows must get a Resize(), so that the number of
    3007             :         // visible entries is correct for PgUp/PgDown.
    3008             :         // The number also cannot be calculated by List/Combobox, as for
    3009             :         // this the presence of the vertical Scrollbar has to be known.
    3010        6069 :         mpImplLB->SetSizePixel( GetOutputSizePixel() );
    3011        6069 :         static_cast<vcl::Window*>(mpImplLB)->Resize();
    3012        6069 :         static_cast<vcl::Window*>(mpImplLB->GetMainWindow())->Resize();
    3013             :     }
    3014        6069 : }
    3015             : 
    3016           2 : void ImplListBoxFloatingWindow::Resize()
    3017             : {
    3018           2 :     mpImplLB->GetMainWindow()->ImplClearLayoutData();
    3019           2 :     FloatingWindow::Resize();
    3020           2 : }
    3021             : 
    3022        6065 : Size ImplListBoxFloatingWindow::CalcFloatSize()
    3023             : {
    3024        6065 :     Size aFloatSz( maPrefSz );
    3025             : 
    3026             :     sal_Int32 nLeft, nTop, nRight, nBottom;
    3027        6065 :     GetBorder( nLeft, nTop, nRight, nBottom );
    3028             : 
    3029        6065 :     sal_Int32 nLines = mpImplLB->GetEntryList()->GetEntryCount();
    3030        6065 :     if ( mnDDLineCount && ( nLines > mnDDLineCount ) )
    3031           3 :         nLines = mnDDLineCount;
    3032             : 
    3033        6065 :     Size aSz = mpImplLB->CalcSize( nLines );
    3034        6065 :     long nMaxHeight = aSz.Height() + nTop + nBottom;
    3035             : 
    3036        6065 :     if ( mnDDLineCount )
    3037        1709 :         aFloatSz.Height() = nMaxHeight;
    3038             : 
    3039        6065 :     if( mbAutoWidth )
    3040             :     {
    3041             :         // AutoSize first only for width...
    3042             : 
    3043        6065 :         aFloatSz.Width() = aSz.Width() + nLeft + nRight;
    3044        6065 :         aFloatSz.Width() += nRight; // adding some space looks better...
    3045             : 
    3046        6065 :         if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) )
    3047             :         {
    3048             :             // then we also need the vertical Scrollbar
    3049        3036 :             long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
    3050        3036 :             aFloatSz.Width() += nSBWidth;
    3051             :         }
    3052             : 
    3053        6065 :         long nDesktopWidth = GetDesktopRectPixel().getWidth();
    3054        6065 :         if (aFloatSz.Width() > nDesktopWidth)
    3055             :             // Don't exceed the desktop width.
    3056           0 :             aFloatSz.Width() = nDesktopWidth;
    3057             :     }
    3058             : 
    3059        6065 :     if ( aFloatSz.Height() > nMaxHeight )
    3060        1323 :         aFloatSz.Height() = nMaxHeight;
    3061             : 
    3062             :     // Minimal height, in case height is not set to Float height.
    3063             :     // The parent of FloatWin must be DropDown-Combo/Listbox.
    3064        6065 :     Size aParentSz = GetParent()->GetSizePixel();
    3065        6065 :     if( (!mnDDLineCount || !nLines) && ( aFloatSz.Height() < aParentSz.Height() ) )
    3066        1429 :         aFloatSz.Height() = aParentSz.Height();
    3067             : 
    3068             :     // do not get narrower than the parent...
    3069        6065 :     if( aFloatSz.Width() < aParentSz.Width() )
    3070        2684 :         aFloatSz.Width() = aParentSz.Width();
    3071             : 
    3072             :     // align height to entries...
    3073        6065 :     long nInnerHeight = aFloatSz.Height() - nTop - nBottom;
    3074        6065 :     long nEntryHeight = mpImplLB->GetEntryHeight();
    3075        6065 :     if ( nInnerHeight % nEntryHeight )
    3076             :     {
    3077        4436 :         nInnerHeight /= nEntryHeight;
    3078        4436 :         nInnerHeight++;
    3079        4436 :         nInnerHeight *= nEntryHeight;
    3080        4436 :         aFloatSz.Height() = nInnerHeight + nTop + nBottom;
    3081             :     }
    3082             : 
    3083        6065 :     if (aFloatSz.Width() < aSz.Width())
    3084             :     {
    3085             :         // The max width of list box entries exceeds the window width.
    3086             :         // Account for the scroll bar height.
    3087           0 :         long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
    3088           0 :         aFloatSz.Height() += nSBWidth;
    3089             :     }
    3090             : 
    3091        6065 :     return aFloatSz;
    3092             : }
    3093             : 
    3094           4 : void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
    3095             : {
    3096           4 :     if( !IsInPopupMode() )
    3097             :     {
    3098           4 :         Size aFloatSz = CalcFloatSize();
    3099             : 
    3100           4 :         SetSizePixel( aFloatSz );
    3101           4 :         mpImplLB->SetSizePixel( GetOutputSizePixel() );
    3102             : 
    3103           4 :         sal_Int32 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 );
    3104           4 :         mnPopupModeStartSaveSelection = nPos;
    3105             : 
    3106           4 :         Size aSz = GetParent()->GetSizePixel();
    3107           4 :         Point aPos = GetParent()->GetPosPixel();
    3108           4 :         aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
    3109             :         // FIXME: this ugly hack is for Mac/Aqua
    3110             :         // should be replaced by a real mechanism to place the float rectangle
    3111           4 :         if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
    3112           0 :             GetParent()->IsNativeWidgetEnabled() )
    3113             :         {
    3114           0 :             sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4;
    3115           0 :             aPos.X() += nLeft;
    3116           0 :             aPos.Y() += nTop;
    3117           0 :             aSz.Width() -= nLeft + nRight;
    3118           0 :             aSz.Height() -= nTop + nBottom;
    3119             :         }
    3120           4 :         Rectangle aRect( aPos, aSz );
    3121             : 
    3122             :         // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI
    3123             :         // where the document is unmirrored
    3124             :         // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror
    3125           4 :         vcl::Window *pGrandparent = GetParent()->GetParent();
    3126           4 :         const OutputDevice *pGrandparentOutDev = pGrandparent->GetOutDev();
    3127             : 
    3128           4 :         if( pGrandparent->ImplIsAntiparallel() )
    3129           0 :             pGrandparentOutDev->ReMirror( aRect );
    3130             : 
    3131             :         // mouse-button right: close the List-Box-Float-win and don't stop the handling fdo#84795
    3132           4 :         StartPopupMode( aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::AllMouseButtonClose );
    3133             : 
    3134           4 :         if( nPos != LISTBOX_ENTRY_NOTFOUND )
    3135           4 :             mpImplLB->ShowProminentEntry( nPos );
    3136             : 
    3137           4 :         if( bStartTracking )
    3138           4 :             mpImplLB->GetMainWindow()->EnableMouseMoveSelect( true );
    3139             : 
    3140           4 :         if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() )
    3141           0 :             mpImplLB->GetMainWindow()->GrabFocus();
    3142             : 
    3143           4 :         mpImplLB->GetMainWindow()->ImplClearLayoutData();
    3144             :     }
    3145         805 : }
    3146             : 
    3147             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11