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

Generated by: LCOV version 1.10