LCOV - code coverage report
Current view: top level - vcl/source/control - ilstbox.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1719 0.0 %
Date: 2014-04-14 Functions: 0 126 0.0 %
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           0 : void ImplInitFieldSettings( Window* pWin, bool bFont, bool bForeground, bool bBackground )
      50             : {
      51           0 :     const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
      52             : 
      53           0 :     if ( bFont )
      54             :     {
      55           0 :         Font aFont = rStyleSettings.GetFieldFont();
      56           0 :         if ( pWin->IsControlFont() )
      57           0 :             aFont.Merge( pWin->GetControlFont() );
      58           0 :         pWin->SetZoomedPointFont( aFont );
      59             :     }
      60             : 
      61           0 :     if ( bFont || bForeground )
      62             :     {
      63           0 :         Color aTextColor = rStyleSettings.GetFieldTextColor();
      64           0 :         if ( pWin->IsControlForeground() )
      65           0 :             aTextColor = pWin->GetControlForeground();
      66           0 :         pWin->SetTextColor( aTextColor );
      67             :     }
      68             : 
      69           0 :     if ( bBackground )
      70             :     {
      71           0 :         if( pWin->IsControlBackground() )
      72           0 :             pWin->SetBackground( pWin->GetControlBackground() );
      73             :         else
      74           0 :             pWin->SetBackground( rStyleSettings.GetFieldColor() );
      75             :     }
      76           0 : }
      77             : 
      78           0 : void ImplInitDropDownButton( PushButton* pButton )
      79             : {
      80           0 :     if ( pButton->GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN )
      81           0 :         pButton->SetSymbol( SYMBOL_SPIN_UPDOWN );
      82             :     else
      83           0 :         pButton->SetSymbol( SYMBOL_SPIN_DOWN );
      84             : 
      85           0 :     if ( pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
      86           0 :             && ! pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
      87           0 :         pButton->SetBackground();
      88           0 : }
      89             : 
      90           0 : ImplEntryList::ImplEntryList( Window* pWindow )
      91             : {
      92           0 :     mpWindow = pWindow;
      93           0 :     mnLastSelected = LISTBOX_ENTRY_NOTFOUND;
      94           0 :     mnSelectionAnchor = LISTBOX_ENTRY_NOTFOUND;
      95           0 :     mnImages = 0;
      96           0 :     mbCallSelectionChangedHdl = true;
      97             : 
      98           0 :     mnMRUCount = 0;
      99           0 :     mnMaxMRUCount = 0;
     100           0 : }
     101             : 
     102           0 : ImplEntryList::~ImplEntryList()
     103             : {
     104           0 :     Clear();
     105           0 : }
     106             : 
     107           0 : void ImplEntryList::Clear()
     108             : {
     109           0 :     mnImages = 0;
     110           0 :     maEntries.clear();
     111           0 : }
     112             : 
     113           0 : void ImplEntryList::SelectEntry( sal_Int32 nPos, bool bSelect )
     114             : {
     115           0 :     if (0 <= nPos && static_cast<size_t>(nPos) < maEntries.size())
     116             :     {
     117           0 :         boost::ptr_vector<ImplEntryType>::iterator iter = maEntries.begin()+nPos;
     118             : 
     119           0 :         if ( ( iter->mbIsSelected != bSelect ) &&
     120           0 :            ( (iter->mnFlags & LISTBOX_ENTRY_FLAG_DISABLE_SELECTION) == 0  ) )
     121             :         {
     122           0 :             iter->mbIsSelected = bSelect;
     123           0 :             if ( mbCallSelectionChangedHdl )
     124           0 :                 maSelectionChangedHdl.Call( (void*)sal_IntPtr(nPos) );
     125             :         }
     126             :     }
     127           0 : }
     128             : 
     129             : namespace
     130             : {
     131             :     struct theSorter
     132             :         : public rtl::StaticWithInit< comphelper::string::NaturalStringSorter, theSorter >
     133             :     {
     134           0 :         comphelper::string::NaturalStringSorter operator () ()
     135             :         {
     136             :             return comphelper::string::NaturalStringSorter(
     137             :                 ::comphelper::getProcessComponentContext(),
     138           0 :                 Application::GetSettings().GetLanguageTag().getLocale());
     139             :         }
     140             :     };
     141             : }
     142             : 
     143           0 : sal_Int32 ImplEntryList::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort )
     144             : {
     145           0 :     if (nPos < 0 || LISTBOX_MAX_ENTRIES <= maEntries.size())
     146           0 :         return LISTBOX_ERROR;
     147             : 
     148           0 :     if ( !!pNewEntry->maImage )
     149           0 :         mnImages++;
     150             : 
     151           0 :     sal_Int32 insPos = 0;
     152             : 
     153           0 :     if ( !bSort || maEntries.empty())
     154             :     {
     155           0 :         if (0 <= nPos && static_cast<size_t>(nPos) < maEntries.size())
     156             :         {
     157           0 :             insPos = nPos;
     158           0 :             maEntries.insert( maEntries.begin() + nPos, pNewEntry );
     159             :         }
     160             :         else
     161             :         {
     162           0 :             insPos = maEntries.size();
     163           0 :             maEntries.push_back(pNewEntry);
     164             :         }
     165             :     }
     166             :     else
     167             :     {
     168           0 :         const comphelper::string::NaturalStringSorter &rSorter = theSorter::get();
     169             : 
     170           0 :         const OUString& rStr = pNewEntry->maStr;
     171             :         sal_uLong nLow, nHigh, nMid;
     172             : 
     173           0 :         nHigh = maEntries.size();
     174             : 
     175           0 :         ImplEntryType* pTemp = GetEntry( (sal_Int32)(nHigh-1) );
     176             : 
     177             :         try
     178             :         {
     179           0 :             sal_Int32 nComp = rSorter.compare(rStr, pTemp->maStr);
     180             : 
     181             :             // fast insert for sorted data
     182           0 :             if ( nComp >= 0 )
     183             :             {
     184           0 :                 insPos = maEntries.size();
     185           0 :                 maEntries.push_back(pNewEntry);
     186             :             }
     187             :             else
     188             :             {
     189           0 :                 nLow  = mnMRUCount;
     190           0 :                 pTemp = (ImplEntryType*)GetEntry( (sal_Int32)nLow );
     191             : 
     192           0 :                 nComp = rSorter.compare(rStr, pTemp->maStr);
     193           0 :                 if ( nComp <= 0 )
     194             :                 {
     195           0 :                     insPos = 0;
     196           0 :                     maEntries.insert(maEntries.begin(),pNewEntry);
     197             :                 }
     198             :                 else
     199             :                 {
     200             :                     // binary search
     201           0 :                     nHigh--;
     202           0 :                     do
     203             :                     {
     204           0 :                         nMid = (nLow + nHigh) / 2;
     205           0 :                         pTemp = (ImplEntryType*)GetEntry( nMid );
     206             : 
     207           0 :                         nComp = rSorter.compare(rStr, pTemp->maStr);
     208             : 
     209           0 :                         if ( nComp < 0 )
     210           0 :                             nHigh = nMid-1;
     211             :                         else
     212             :                         {
     213           0 :                             if ( nComp > 0 )
     214           0 :                                 nLow = nMid + 1;
     215             :                             else
     216           0 :                                 break;
     217             :                         }
     218             :                     }
     219             :                     while ( nLow <= nHigh );
     220             : 
     221           0 :                     if ( nComp >= 0 )
     222           0 :                         nMid++;
     223             : 
     224           0 :                     insPos = nMid;
     225           0 :                     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           0 :     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           0 : sal_Int32 ImplEntryList::FindEntry( const OUString& rString, bool bSearchMRUArea ) const
     258             : {
     259           0 :     sal_Int32 nEntries = maEntries.size();
     260           0 :     for ( sal_Int32 n = bSearchMRUArea ? 0 : GetMRUCount(); n < nEntries; n++ )
     261             :     {
     262           0 :         OUString aComp( vcl::I18nHelper::filterFormattingChars( maEntries[n].maStr ) );
     263           0 :         if ( aComp == rString )
     264           0 :             return n;
     265           0 :     }
     266           0 :     return LISTBOX_ENTRY_NOTFOUND;
     267             : }
     268             : 
     269           0 : sal_Int32 ImplEntryList::FindMatchingEntry( const OUString& rStr, sal_Int32 nStart, bool bForward, bool bLazy ) const
     270             : {
     271           0 :     sal_Int32  nPos = LISTBOX_ENTRY_NOTFOUND;
     272           0 :     sal_Int32  nEntryCount = GetEntryCount();
     273           0 :     if ( !bForward )
     274           0 :         nStart++;   // decrements right away
     275             : 
     276           0 :     const vcl::I18nHelper& rI18nHelper = mpWindow->GetSettings().GetLocaleI18nHelper();
     277           0 :     for ( sal_Int32 n = nStart; bForward ? n < nEntryCount : n != 0; )
     278             :     {
     279           0 :         if ( !bForward )
     280           0 :             n--;
     281             : 
     282           0 :         ImplEntryType* pImplEntry = GetEntry( n );
     283             :         bool bMatch;
     284           0 :         if ( bLazy  )
     285             :         {
     286           0 :             bMatch = rI18nHelper.MatchString( rStr, pImplEntry->maStr );
     287             :         }
     288             :         else
     289             :         {
     290           0 :             bMatch = rStr.isEmpty() || (rStr == pImplEntry->maStr );
     291             :         }
     292           0 :         if ( bMatch )
     293             :         {
     294           0 :             nPos = n;
     295           0 :             break;
     296             :         }
     297             : 
     298           0 :         if ( bForward )
     299           0 :             n++;
     300             :     }
     301             : 
     302           0 :     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           0 : long ImplEntryList::GetAddedHeight( sal_Int32 i_nEndIndex, sal_Int32 i_nBeginIndex, long i_nBeginHeight ) const
     321             : {
     322           0 :     long nHeight = i_nBeginHeight;
     323           0 :     sal_Int32 nStart = i_nEndIndex > i_nBeginIndex ? i_nBeginIndex : i_nEndIndex;
     324           0 :     sal_Int32 nStop  = i_nEndIndex > i_nBeginIndex ? i_nEndIndex : i_nBeginIndex;
     325           0 :     sal_Int32 nEntryCount = GetEntryCount();
     326           0 :     if( 0 <= nStop && nStop != LISTBOX_ENTRY_NOTFOUND && nEntryCount != 0 )
     327             :     {
     328             :         // sanity check
     329           0 :         if( nStop > nEntryCount-1 )
     330           0 :             nStop = nEntryCount-1;
     331           0 :         if (nStart < 0)
     332           0 :             nStart = 0;
     333           0 :         else if( nStart > nEntryCount-1 )
     334           0 :             nStart = nEntryCount-1;
     335             : 
     336           0 :         sal_Int32 nIndex = nStart;
     337           0 :         while( nIndex != LISTBOX_ENTRY_NOTFOUND && nIndex < nStop )
     338             :         {
     339           0 :             long nPosHeight = GetEntryPtr( nIndex )->mnHeight;
     340           0 :             if (nHeight > ::std::numeric_limits<long>::max() - nPosHeight)
     341             :             {
     342             :                 SAL_WARN( "vcl", "ImplEntryList::GetAddedHeight: truncated");
     343           0 :                 break;
     344             :             }
     345           0 :             nHeight += nPosHeight;
     346           0 :             nIndex++;
     347           0 :         }
     348             :     }
     349             :     else
     350           0 :         nHeight = 0;
     351           0 :     return i_nEndIndex > i_nBeginIndex ? nHeight : -nHeight;
     352             : }
     353             : 
     354           0 : long ImplEntryList::GetEntryHeight( sal_Int32 nPos ) const
     355             : {
     356           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     357           0 :     return pImplEntry ? pImplEntry->mnHeight : 0;
     358             : }
     359             : 
     360           0 : OUString ImplEntryList::GetEntryText( sal_Int32 nPos ) const
     361             : {
     362           0 :     OUString aEntryText;
     363           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     364           0 :     if ( pImplEntry )
     365           0 :         aEntryText = pImplEntry->maStr;
     366           0 :     return aEntryText;
     367             : }
     368             : 
     369           0 : bool ImplEntryList::HasEntryImage( sal_Int32 nPos ) const
     370             : {
     371           0 :     bool bImage = false;
     372           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     373           0 :     if ( pImplEntry )
     374           0 :         bImage = !!pImplEntry->maImage;
     375           0 :     return bImage;
     376             : }
     377             : 
     378           0 : Image ImplEntryList::GetEntryImage( sal_Int32 nPos ) const
     379             : {
     380           0 :     Image aImage;
     381           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     382           0 :     if ( pImplEntry )
     383           0 :         aImage = pImplEntry->maImage;
     384           0 :     return aImage;
     385             : }
     386             : 
     387           0 : void ImplEntryList::SetEntryData( sal_Int32 nPos, void* pNewData )
     388             : {
     389           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     390           0 :     if ( pImplEntry )
     391           0 :         pImplEntry->mpUserData = pNewData;
     392           0 : }
     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           0 : sal_Int32 ImplEntryList::GetSelectEntryCount() const
     414             : {
     415           0 :     sal_Int32 nSelCount = 0;
     416           0 :     for ( sal_Int32 n = GetEntryCount(); n; )
     417             :     {
     418           0 :         ImplEntryType* pImplEntry = GetEntry( --n );
     419           0 :         if ( pImplEntry->mbIsSelected )
     420           0 :             nSelCount++;
     421             :     }
     422           0 :     return nSelCount;
     423             : }
     424             : 
     425           0 : OUString ImplEntryList::GetSelectEntry( sal_Int32 nIndex ) const
     426             : {
     427           0 :     return GetEntryText( GetSelectEntryPos( nIndex ) );
     428             : }
     429             : 
     430           0 : sal_Int32 ImplEntryList::GetSelectEntryPos( sal_Int32 nIndex ) const
     431             : {
     432           0 :     sal_Int32 nSelEntryPos = LISTBOX_ENTRY_NOTFOUND;
     433           0 :     sal_Int32 nSel = 0;
     434           0 :     sal_Int32 nEntryCount = GetEntryCount();
     435             : 
     436           0 :     for ( sal_Int32 n = 0; n < nEntryCount; n++ )
     437             :     {
     438           0 :         ImplEntryType* pImplEntry = GetEntry( n );
     439           0 :         if ( pImplEntry->mbIsSelected )
     440             :         {
     441           0 :             if ( nSel == nIndex )
     442             :             {
     443           0 :                 nSelEntryPos = n;
     444           0 :                 break;
     445             :             }
     446           0 :             nSel++;
     447             :         }
     448             :     }
     449             : 
     450           0 :     return nSelEntryPos;
     451             : }
     452             : 
     453           0 : bool ImplEntryList::IsEntryPosSelected( sal_Int32 nIndex ) const
     454             : {
     455           0 :     ImplEntryType* pImplEntry = GetEntry( nIndex );
     456           0 :     return pImplEntry ? pImplEntry->mbIsSelected : false;
     457             : }
     458             : 
     459           0 : bool ImplEntryList::IsEntrySelectable( sal_Int32 nPos ) const
     460             : {
     461           0 :     ImplEntryType* pImplEntry = GetEntry( nPos );
     462           0 :     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           0 : ImplListBoxWindow::ImplListBoxWindow( Window* pParent, WinBits nWinStyle ) :
     492             :     Control( pParent, 0 ),
     493           0 :     maQuickSelectionEngine( *this )
     494             : {
     495           0 :     mpEntryList         = new ImplEntryList( this );
     496             : 
     497           0 :     mnTop               = 0;
     498           0 :     mnLeft              = 0;
     499           0 :     mnBorder            = 1;
     500           0 :     mnSelectModifier    = 0;
     501           0 :     mnUserDrawEntry     = LISTBOX_ENTRY_NOTFOUND;
     502           0 :     mbTrack             = false;
     503           0 :     mbImgsDiffSz        = false;
     504           0 :     mbTravelSelect      = false;
     505           0 :     mbTrackingSelect    = false;
     506           0 :     mbSelectionChanged  = false;
     507           0 :     mbMouseMoveSelect   = false;
     508           0 :     mbMulti             = false;
     509           0 :     mbStackMode         = false;
     510           0 :     mbGrabFocus         = false;
     511           0 :     mbUserDrawEnabled   = false;
     512           0 :     mbInUserDraw        = false;
     513           0 :     mbReadOnly          = false;
     514           0 :     mbHasFocusRect      = false;
     515           0 :     mbRight             = ( nWinStyle & WB_RIGHT );
     516           0 :     mbCenter            = ( nWinStyle & WB_CENTER );
     517           0 :     mbSimpleMode        = ( nWinStyle & WB_SIMPLEMODE );
     518           0 :     mbSort              = ( nWinStyle & WB_SORT );
     519           0 :     mbEdgeBlending      = false;
     520             : 
     521             :     // pb: #106948# explicit mirroring for calc
     522           0 :     mbMirroring         = false;
     523             : 
     524           0 :     mnCurrentPos            = LISTBOX_ENTRY_NOTFOUND;
     525           0 :     mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
     526           0 :     mnSeparatorPos          = LISTBOX_ENTRY_NOTFOUND;
     527           0 :     meProminentType         = PROMINENT_TOP;
     528             : 
     529           0 :     SetLineColor();
     530           0 :     SetTextFillColor();
     531           0 :     SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
     532             : 
     533           0 :     ImplInitSettings( true, true, true );
     534           0 :     ImplCalcMetrics();
     535           0 : }
     536             : 
     537           0 : ImplListBoxWindow::~ImplListBoxWindow()
     538             : {
     539           0 :     delete mpEntryList;
     540           0 : }
     541             : 
     542           0 : void ImplListBoxWindow::ImplInitSettings( bool bFont, bool bForeground, bool bBackground )
     543             : {
     544           0 :     ImplInitFieldSettings( this, bFont, bForeground, bBackground );
     545           0 : }
     546             : 
     547           0 : void ImplListBoxWindow::ImplCalcMetrics()
     548             : {
     549           0 :     mnMaxWidth      = 0;
     550           0 :     mnMaxTxtWidth   = 0;
     551           0 :     mnMaxImgWidth   = 0;
     552           0 :     mnMaxImgTxtWidth= 0;
     553           0 :     mnMaxImgHeight  = 0;
     554             : 
     555           0 :     mnTextHeight = (sal_uInt16)GetTextHeight();
     556           0 :     mnMaxTxtHeight = mnTextHeight + mnBorder;
     557           0 :     mnMaxHeight = mnMaxTxtHeight;
     558             : 
     559           0 :     if ( maUserItemSize.Height() > mnMaxHeight )
     560           0 :         mnMaxHeight = (sal_uInt16) maUserItemSize.Height();
     561           0 :     if ( maUserItemSize.Width() > mnMaxWidth )
     562           0 :         mnMaxWidth= (sal_uInt16) maUserItemSize.Width();
     563             : 
     564           0 :     for ( sal_Int32 n = mpEntryList->GetEntryCount(); n; )
     565             :     {
     566           0 :         ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( --n );
     567           0 :         ImplUpdateEntryMetrics( *pEntry );
     568             :     }
     569             : 
     570           0 :     if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND )
     571             :     {
     572           0 :         Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryPtr( mnCurrentPos )->mnHeight );
     573           0 :         maFocusRect.SetSize( aSz );
     574             :     }
     575           0 : }
     576             : 
     577           0 : void ImplListBoxWindow::Clear()
     578             : {
     579           0 :     mpEntryList->Clear();
     580             : 
     581           0 :     mnMaxHeight     = mnMaxTxtHeight;
     582           0 :     mnMaxWidth      = 0;
     583           0 :     mnMaxTxtWidth   = 0;
     584           0 :     mnMaxImgTxtWidth= 0;
     585           0 :     mnMaxImgWidth   = 0;
     586           0 :     mnMaxImgHeight  = 0;
     587           0 :     mnTop           = 0;
     588           0 :     mnLeft          = 0;
     589           0 :     mbImgsDiffSz    = false;
     590           0 :     ImplClearLayoutData();
     591             : 
     592           0 :     mnCurrentPos = LISTBOX_ENTRY_NOTFOUND;
     593           0 :     maQuickSelectionEngine.Reset();
     594             : 
     595           0 :     Invalidate();
     596           0 : }
     597             : 
     598           0 : void ImplListBoxWindow::SetUserItemSize( const Size& rSz )
     599             : {
     600           0 :     ImplClearLayoutData();
     601           0 :     maUserItemSize = rSz;
     602           0 :     ImplCalcMetrics();
     603           0 : }
     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           0 : void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType& rEntry )
     622             : {
     623             :     ImplEntryMetrics aMetrics;
     624           0 :     aMetrics.bText = !rEntry.maStr.isEmpty();
     625           0 :     aMetrics.bImage = !!rEntry.maImage;
     626           0 :     aMetrics.nEntryWidth = 0;
     627           0 :     aMetrics.nEntryHeight = 0;
     628           0 :     aMetrics.nTextWidth = 0;
     629           0 :     aMetrics.nImgWidth = 0;
     630           0 :     aMetrics.nImgHeight = 0;
     631             : 
     632           0 :     if ( aMetrics.bText )
     633             :     {
     634           0 :         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           0 :             aMetrics.nTextWidth = (sal_uInt16)GetTextWidth( rEntry.maStr );
     653           0 :             if( aMetrics.nTextWidth > mnMaxTxtWidth )
     654           0 :                 mnMaxTxtWidth = aMetrics.nTextWidth;
     655           0 :             aMetrics.nEntryWidth = mnMaxTxtWidth;
     656           0 :             aMetrics.nEntryHeight = mnTextHeight + mnBorder;
     657             :         }
     658             :     }
     659           0 :     if ( aMetrics.bImage )
     660             :     {
     661           0 :         Size aImgSz = rEntry.maImage.GetSizePixel();
     662           0 :         aMetrics.nImgWidth  = (sal_uInt16) CalcZoom( aImgSz.Width() );
     663           0 :         aMetrics.nImgHeight = (sal_uInt16) CalcZoom( aImgSz.Height() );
     664             : 
     665           0 :         if( mnMaxImgWidth && ( aMetrics.nImgWidth != mnMaxImgWidth ) )
     666           0 :             mbImgsDiffSz = true;
     667           0 :         else if ( mnMaxImgHeight && ( aMetrics.nImgHeight != mnMaxImgHeight ) )
     668           0 :             mbImgsDiffSz = true;
     669             : 
     670           0 :         if( aMetrics.nImgWidth > mnMaxImgWidth )
     671           0 :             mnMaxImgWidth = aMetrics.nImgWidth;
     672           0 :         if( aMetrics.nImgHeight > mnMaxImgHeight )
     673           0 :             mnMaxImgHeight = aMetrics.nImgHeight;
     674             : 
     675           0 :         mnMaxImgTxtWidth = std::max( mnMaxImgTxtWidth, aMetrics.nTextWidth );
     676           0 :         aMetrics.nEntryHeight = std::max( aMetrics.nImgHeight, aMetrics.nEntryHeight );
     677             : 
     678             :     }
     679           0 :     if ( IsUserDrawEnabled() || aMetrics.bImage )
     680             :     {
     681           0 :         aMetrics.nEntryWidth = std::max( aMetrics.nImgWidth, maUserItemSize.Width() );
     682           0 :         if ( aMetrics.bText )
     683           0 :             aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE;
     684           0 :         aMetrics.nEntryHeight = std::max( std::max( mnMaxImgHeight, maUserItemSize.Height() ) + 2,
     685           0 :                                      aMetrics.nEntryHeight );
     686             :     }
     687             : 
     688           0 :     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           0 :     if ( aMetrics.nEntryWidth > mnMaxWidth )
     696           0 :         mnMaxWidth = aMetrics.nEntryWidth;
     697           0 :     if ( aMetrics.nEntryHeight > mnMaxHeight )
     698           0 :         mnMaxHeight = aMetrics.nEntryHeight;
     699             : 
     700           0 :     rEntry.mnHeight = aMetrics.nEntryHeight;
     701           0 : }
     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           0 : sal_Int32 ImplListBoxWindow::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry )
     745             : {
     746           0 :     if (nPos < 0 || LISTBOX_MAX_ENTRIES <= mpEntryList->GetEntryCount())
     747           0 :         return LISTBOX_ERROR;
     748             : 
     749           0 :     ImplClearLayoutData();
     750           0 :     sal_Int32 nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort );
     751             : 
     752           0 :     if( (GetStyle() & WB_WORDBREAK) )
     753           0 :         pNewEntry->mnFlags |= LISTBOX_ENTRY_FLAG_MULTILINE;
     754             : 
     755           0 :     ImplUpdateEntryMetrics( *pNewEntry );
     756           0 :     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           0 : void ImplListBoxWindow::ImplHideFocusRect()
     785             : {
     786           0 :     if ( mbHasFocusRect )
     787             :     {
     788           0 :         HideFocus();
     789           0 :         mbHasFocusRect = false;
     790             :     }
     791           0 : }
     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           0 : bool ImplListBoxWindow::IsVisible( sal_Int32 i_nEntry ) const
     811             : {
     812           0 :     bool bRet = false;
     813             : 
     814           0 :     if( i_nEntry >= mnTop )
     815             :     {
     816           0 :         if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) <
     817           0 :             PixelToLogic( GetSizePixel() ).Height() )
     818             :         {
     819           0 :             bRet = true;
     820             :         }
     821             :     }
     822             : 
     823           0 :     return bRet;
     824             : }
     825             : 
     826           0 : sal_Int32 ImplListBoxWindow::GetLastVisibleEntry() const
     827             : {
     828           0 :     sal_Int32 nPos = mnTop;
     829           0 :     long nWindowHeight = GetSizePixel().Height();
     830           0 :     sal_Int32 nCount = mpEntryList->GetEntryCount();
     831             :     long nDiff;
     832           0 :     for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) )
     833           0 :         nPos++;
     834             : 
     835           0 :     if( nDiff > nWindowHeight && nPos > mnTop )
     836           0 :         nPos--;
     837             : 
     838           0 :     if( nPos >= nCount )
     839           0 :         nPos = nCount-1;
     840             : 
     841           0 :     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 :                 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           0 : void ImplListBoxWindow::DeselectAll()
     963             : {
     964           0 :     while ( GetEntryList()->GetSelectEntryCount() )
     965             :     {
     966           0 :         sal_Int32 nS = GetEntryList()->GetSelectEntryPos( 0 );
     967           0 :         SelectEntry( nS, false );
     968             :     }
     969           0 : }
     970             : 
     971           0 : void ImplListBoxWindow::SelectEntry( sal_Int32 nPos, bool bSelect )
     972             : {
     973           0 :     if( (mpEntryList->IsEntryPosSelected( nPos ) != bSelect) && mpEntryList->IsEntrySelectable( nPos ) )
     974             :     {
     975           0 :         ImplHideFocusRect();
     976           0 :         if( bSelect )
     977             :         {
     978           0 :             if( !mbMulti )
     979             :             {
     980             :                 // deselect the selected entry
     981           0 :                 sal_Int32 nDeselect = GetEntryList()->GetSelectEntryPos( 0 );
     982           0 :                 if( nDeselect != LISTBOX_ENTRY_NOTFOUND )
     983             :                 {
     984             :                     //SelectEntryPos( nDeselect, false );
     985           0 :                     GetEntryList()->SelectEntry( nDeselect, false );
     986           0 :                     if ( IsUpdateMode() && IsReallyVisible() )
     987           0 :                         ImplPaint( nDeselect, true );
     988             :                 }
     989             :             }
     990           0 :             mpEntryList->SelectEntry( nPos, true );
     991           0 :             mnCurrentPos = nPos;
     992           0 :             if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() )
     993             :             {
     994           0 :                 ImplPaint( nPos );
     995           0 :                 if ( !IsVisible( nPos ) )
     996             :                 {
     997           0 :                     ImplClearLayoutData();
     998           0 :                     sal_Int32 nVisibleEntries = GetLastVisibleEntry()-mnTop;
     999           0 :                     if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) )
    1000             :                     {
    1001           0 :                         Resize();
    1002           0 :                         ShowProminentEntry( nPos );
    1003             :                     }
    1004             :                     else
    1005             :                     {
    1006           0 :                         ShowProminentEntry( nPos );
    1007             :                     }
    1008             :                 }
    1009             :             }
    1010             :         }
    1011             :         else
    1012             :         {
    1013           0 :             mpEntryList->SelectEntry( nPos, false );
    1014           0 :             ImplPaint( nPos, true );
    1015             :         }
    1016           0 :         mbSelectionChanged = true;
    1017             :     }
    1018           0 : }
    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() ) ? true : !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 :     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 foreward
    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 + 1, _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           0 : void ImplListBoxWindow::ImplPaint( sal_Int32 nPos, bool bErase, bool bLayout )
    1697             : {
    1698           0 :     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    1699             : 
    1700           0 :     const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos );
    1701           0 :     if( ! pEntry )
    1702           0 :         return;
    1703             : 
    1704           0 :     long nWidth  = GetOutputSizePixel().Width();
    1705           0 :     long nY = mpEntryList->GetAddedHeight( nPos, mnTop );
    1706           0 :     Rectangle aRect( Point( 0, nY ), Size( nWidth, pEntry->mnHeight ) );
    1707             : 
    1708           0 :     if( ! bLayout )
    1709             :     {
    1710           0 :         if( mpEntryList->IsEntryPosSelected( nPos ) )
    1711             :         {
    1712           0 :             SetTextColor( !IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor() );
    1713           0 :             SetFillColor( rStyleSettings.GetHighlightColor() );
    1714           0 :             SetTextFillColor( rStyleSettings.GetHighlightColor() );
    1715           0 :             DrawRect( aRect );
    1716             :         }
    1717             :         else
    1718             :         {
    1719           0 :             ImplInitSettings( false, true, false );
    1720           0 :             if( !IsEnabled() )
    1721           0 :                 SetTextColor( rStyleSettings.GetDisableColor() );
    1722           0 :             SetTextFillColor();
    1723           0 :             if( bErase )
    1724           0 :                 Erase( aRect );
    1725             :         }
    1726             :     }
    1727             : 
    1728           0 :     if ( IsUserDrawEnabled() )
    1729             :     {
    1730           0 :         mbInUserDraw = true;
    1731           0 :         mnUserDrawEntry = nPos;
    1732           0 :         aRect.Left() -= mnLeft;
    1733           0 :         if ( nPos < GetEntryList()->GetMRUCount() )
    1734           0 :             nPos = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos ) );
    1735           0 :         nPos = nPos - GetEntryList()->GetMRUCount();
    1736           0 :         sal_Int32 nCurr = mnCurrentPos;
    1737           0 :         if ( mnCurrentPos < GetEntryList()->GetMRUCount() )
    1738           0 :             nCurr = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nCurr ) );
    1739           0 :         nCurr = sal::static_int_cast<sal_Int32>( nCurr - GetEntryList()->GetMRUCount());
    1740             : 
    1741           0 :         UserDrawEvent aUDEvt( this, aRect, nPos, nCurr );
    1742           0 :         maUserDrawHdl.Call( &aUDEvt );
    1743           0 :         mbInUserDraw = false;
    1744             :     }
    1745             :     else
    1746             :     {
    1747           0 :         DrawEntry( nPos, true, true, false, bLayout );
    1748             :     }
    1749             : }
    1750             : 
    1751           0 : void ImplListBoxWindow::DrawEntry( sal_Int32 nPos, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos, bool bLayout )
    1752             : {
    1753           0 :     const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos );
    1754           0 :     if( ! pEntry )
    1755           0 :         return;
    1756             : 
    1757             :     // when changing this function don't forget to adjust ImplWin::DrawEntry()
    1758             : 
    1759           0 :     if ( mbInUserDraw )
    1760           0 :         nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU
    1761             : 
    1762           0 :     long nY = mpEntryList->GetAddedHeight( nPos, mnTop );
    1763           0 :     Size aImgSz;
    1764             : 
    1765           0 :     if( bDrawImage && mpEntryList->HasImages() && !bLayout )
    1766             :     {
    1767           0 :         Image aImage = mpEntryList->GetEntryImage( nPos );
    1768           0 :         if( !!aImage )
    1769             :         {
    1770           0 :             aImgSz = aImage.GetSizePixel();
    1771           0 :             Point aPtImg( mnBorder - mnLeft, nY + ( ( pEntry->mnHeight - aImgSz.Height() ) / 2 ) );
    1772             : 
    1773             :             // pb: #106948# explicit mirroring for calc
    1774           0 :             if ( mbMirroring )
    1775             :                 // right aligned
    1776           0 :                 aPtImg.X() = mnMaxWidth + mnBorder - aImgSz.Width() - mnLeft;
    1777             : 
    1778           0 :             if ( !IsZoom() )
    1779             :             {
    1780           0 :                 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           0 :             const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    1790           0 :             const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
    1791             : 
    1792           0 :             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           0 :         }
    1805             :     }
    1806             : 
    1807           0 :     if( bDrawText )
    1808             :     {
    1809           0 :         MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
    1810           0 :         OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
    1811           0 :         OUString aStr( mpEntryList->GetEntryText( nPos ) );
    1812           0 :         if ( !aStr.isEmpty() )
    1813             :         {
    1814             :             long nMaxWidth = std::max( static_cast< long >( mnMaxWidth ),
    1815           0 :                                   GetOutputSizePixel().Width() - 2*mnBorder );
    1816             :             // a multiline entry should only be as wide a the window
    1817           0 :             if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) )
    1818           0 :                 nMaxWidth = GetOutputSizePixel().Width() - 2*mnBorder;
    1819             : 
    1820             :             Rectangle aTextRect( Point( mnBorder - mnLeft, nY ),
    1821           0 :                                  Size( nMaxWidth, pEntry->mnHeight ) );
    1822             : 
    1823           0 :             if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) )
    1824             :             {
    1825           0 :                 long nImageWidth = std::max( mnMaxImgWidth, maUserItemSize.Width() );
    1826           0 :                 aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE;
    1827             :             }
    1828             : 
    1829           0 :             if( bLayout )
    1830           0 :                 mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.getLength() );
    1831             : 
    1832             :             // pb: #106948# explicit mirroring for calc
    1833           0 :             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           0 :             sal_uInt16 nDrawStyle = ImplGetTextStyle();
    1842           0 :             if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) )
    1843           0 :                 nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS;
    1844           0 :             if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_DRAW_DISABLED) )
    1845           0 :                 nDrawStyle |= TEXT_DRAW_DISABLE;
    1846             : 
    1847           0 :             DrawText( aTextRect, aStr, nDrawStyle, pVector, pDisplayText );
    1848           0 :         }
    1849             :     }
    1850             : 
    1851           0 :     if( !bLayout )
    1852             :     {
    1853           0 :         if ( ( mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND ) &&
    1854           0 :              ( ( nPos == mnSeparatorPos ) || ( nPos == mnSeparatorPos+1 ) ) )
    1855             :         {
    1856           0 :             Color aOldLineColor( GetLineColor() );
    1857           0 :             SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY );
    1858           0 :             Point aStartPos( 0, nY );
    1859           0 :             if ( nPos == mnSeparatorPos )
    1860           0 :                 aStartPos.Y() += pEntry->mnHeight-1;
    1861           0 :             Point aEndPos( aStartPos );
    1862           0 :             aEndPos.X() = GetOutputSizePixel().Width();
    1863           0 :             DrawLine( aStartPos, aEndPos );
    1864           0 :             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           0 : void ImplListBoxWindow::ImplDoPaint( const Rectangle& rRect, bool bLayout )
    1877             : {
    1878           0 :     sal_Int32 nCount = mpEntryList->GetEntryCount();
    1879             : 
    1880           0 :     bool bShowFocusRect = mbHasFocusRect;
    1881           0 :     if ( mbHasFocusRect && ! bLayout )
    1882           0 :         ImplHideFocusRect();
    1883             : 
    1884           0 :     long nY = 0; // + mnBorder;
    1885           0 :     long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
    1886             : 
    1887           0 :     for( sal_Int32 i = (sal_Int32)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ )
    1888             :     {
    1889           0 :         const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( i );
    1890           0 :         if( nY + pEntry->mnHeight >= rRect.Top() &&
    1891           0 :             nY <= rRect.Bottom() + mnMaxHeight )
    1892             :         {
    1893           0 :             ImplPaint( i, false, bLayout );
    1894             :         }
    1895           0 :         nY += pEntry->mnHeight;
    1896             :     }
    1897             : 
    1898           0 :     long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 );
    1899           0 :     maFocusRect.SetPos( Point( 0, nHeightDiff ) );
    1900           0 :     Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
    1901           0 :     maFocusRect.SetSize( aSz );
    1902           0 :     if( HasFocus() && bShowFocusRect && !bLayout )
    1903           0 :         ImplShowFocusRect();
    1904           0 : }
    1905             : 
    1906           0 : void ImplListBoxWindow::Paint( const Rectangle& rRect )
    1907             : {
    1908           0 :     ImplDoPaint( rRect );
    1909           0 : }
    1910             : 
    1911           0 : sal_uInt16 ImplListBoxWindow::GetDisplayLineCount() const
    1912             : {
    1913             :     // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE
    1914             : 
    1915           0 :     sal_Int32 nCount = mpEntryList->GetEntryCount();
    1916           0 :     long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
    1917           0 :     sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight );
    1918           0 :     if( nEntries > nCount-mnTop )
    1919           0 :         nEntries = nCount-mnTop;
    1920             : 
    1921           0 :     return nEntries;
    1922             : }
    1923             : 
    1924           0 : void ImplListBoxWindow::Resize()
    1925             : {
    1926           0 :     Control::Resize();
    1927             : 
    1928           0 :     bool bShowFocusRect = mbHasFocusRect;
    1929           0 :     if ( bShowFocusRect )
    1930           0 :         ImplHideFocusRect();
    1931             : 
    1932           0 :     if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND )
    1933             :     {
    1934           0 :         Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
    1935           0 :         maFocusRect.SetSize( aSz );
    1936             :     }
    1937             : 
    1938           0 :     if ( bShowFocusRect )
    1939           0 :         ImplShowFocusRect();
    1940             : 
    1941           0 :     ImplClearLayoutData();
    1942           0 : }
    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           0 : void ImplListBoxWindow::SetTopEntry( sal_Int32 nTop )
    1964             : {
    1965           0 :     if( mpEntryList->GetEntryCount() == 0 )
    1966           0 :         return;
    1967             : 
    1968           0 :     long nWHeight = PixelToLogic( GetSizePixel() ).Height();
    1969             : 
    1970           0 :     sal_Int32 nLastEntry = mpEntryList->GetEntryCount()-1;
    1971           0 :     if( nTop > nLastEntry )
    1972           0 :         nTop = nLastEntry;
    1973           0 :     const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry );
    1974           0 :     while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->mnHeight <= nWHeight )
    1975           0 :         nTop--;
    1976             : 
    1977           0 :     if ( nTop != mnTop )
    1978             :     {
    1979           0 :         ImplClearLayoutData();
    1980           0 :         long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 );
    1981           0 :         Update();
    1982           0 :         ImplHideFocusRect();
    1983           0 :         mnTop = nTop;
    1984           0 :         Scroll( 0, nDiff );
    1985           0 :         Update();
    1986           0 :         if( HasFocus() )
    1987           0 :             ImplShowFocusRect();
    1988           0 :         maScrollHdl.Call( this );
    1989             :     }
    1990             : }
    1991             : 
    1992           0 : void ImplListBoxWindow::ShowProminentEntry( sal_Int32 nEntryPos )
    1993             : {
    1994           0 :     if( meProminentType == PROMINENT_MIDDLE )
    1995             :     {
    1996           0 :         sal_Int32 nPos = nEntryPos;
    1997           0 :         long nWHeight = PixelToLogic( GetSizePixel() ).Height();
    1998           0 :         while( nEntryPos > 0 && mpEntryList->GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 )
    1999           0 :             nEntryPos--;
    2000             :     }
    2001           0 :     SetTopEntry( nEntryPos );
    2002           0 : }
    2003             : 
    2004           0 : void ImplListBoxWindow::SetLeftIndent( long n )
    2005             : {
    2006           0 :     ScrollHorz( n - mnLeft );
    2007           0 : }
    2008             : 
    2009           0 : void ImplListBoxWindow::ScrollHorz( long n )
    2010             : {
    2011           0 :     long nDiff = 0;
    2012           0 :     if ( n > 0 )
    2013             :     {
    2014           0 :         long nWidth = GetOutputSizePixel().Width();
    2015           0 :         if( ( mnMaxWidth - mnLeft + n ) > nWidth )
    2016           0 :             nDiff = n;
    2017             :     }
    2018           0 :     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           0 :     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           0 : }
    2040             : 
    2041           0 : Size ImplListBoxWindow::CalcSize(sal_Int32 nMaxLines) const
    2042             : {
    2043             :     // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE
    2044             : 
    2045           0 :     Size aSz;
    2046           0 :     aSz.Height() =  nMaxLines * mnMaxHeight;
    2047           0 :     aSz.Width() = mnMaxWidth + 2*mnBorder;
    2048           0 :     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           0 : void ImplListBoxWindow::StateChanged( StateChangedType nType )
    2061             : {
    2062           0 :     Control::StateChanged( nType );
    2063             : 
    2064           0 :     if ( nType == STATE_CHANGE_ZOOM )
    2065             :     {
    2066           0 :         ImplInitSettings( true, false, false );
    2067           0 :         ImplCalcMetrics();
    2068           0 :         Invalidate();
    2069             :     }
    2070           0 :     else if ( nType == STATE_CHANGE_UPDATEMODE )
    2071             :     {
    2072           0 :         if ( IsUpdateMode() && IsReallyVisible() )
    2073           0 :             Invalidate();
    2074             :     }
    2075           0 :     else if ( nType == STATE_CHANGE_CONTROLFONT )
    2076             :     {
    2077           0 :         ImplInitSettings( true, false, false );
    2078           0 :         ImplCalcMetrics();
    2079           0 :         Invalidate();
    2080             :     }
    2081           0 :     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
    2082             :     {
    2083           0 :         ImplInitSettings( false, true, false );
    2084           0 :         Invalidate();
    2085             :     }
    2086           0 :     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
    2087             :     {
    2088           0 :         ImplInitSettings( false, false, true );
    2089           0 :         Invalidate();
    2090             :     }
    2091           0 :     else if( nType == STATE_CHANGE_ENABLE )
    2092             :     {
    2093           0 :         Invalidate();
    2094             :     }
    2095             : 
    2096           0 :     ImplClearLayoutData();
    2097           0 : }
    2098             : 
    2099           0 : void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt )
    2100             : {
    2101           0 :     Control::DataChanged( rDCEvt );
    2102             : 
    2103           0 :     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
    2104           0 :          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
    2105           0 :          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
    2106           0 :           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
    2107             :     {
    2108           0 :         ImplClearLayoutData();
    2109           0 :         ImplInitSettings( true, true, true );
    2110           0 :         ImplCalcMetrics();
    2111           0 :         Invalidate();
    2112             :     }
    2113           0 : }
    2114             : 
    2115           0 : sal_uInt16 ImplListBoxWindow::ImplGetTextStyle() const
    2116             : {
    2117           0 :     sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER;
    2118             : 
    2119           0 :     if ( mpEntryList->HasImages() )
    2120           0 :         nTextStyle |= TEXT_DRAW_LEFT;
    2121           0 :     else if ( mbCenter )
    2122           0 :         nTextStyle |= TEXT_DRAW_CENTER;
    2123           0 :     else if ( mbRight )
    2124           0 :         nTextStyle |= TEXT_DRAW_RIGHT;
    2125             :     else
    2126           0 :         nTextStyle |= TEXT_DRAW_LEFT;
    2127             : 
    2128           0 :     return nTextStyle;
    2129             : }
    2130             : 
    2131           0 : ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) :
    2132             :     Control( pParent, nWinStyle ),
    2133           0 :     maLBWindow( this, nWinStyle&(~WB_BORDER) )
    2134             : {
    2135             :     // for native widget rendering we must be able to detect this window type
    2136           0 :     SetType( WINDOW_LISTBOXWINDOW );
    2137             : 
    2138           0 :     mpVScrollBar    = new ScrollBar( this, WB_VSCROLL | WB_DRAG );
    2139           0 :     mpHScrollBar    = new ScrollBar( this, WB_HSCROLL | WB_DRAG );
    2140           0 :     mpScrollBarBox  = new ScrollBarBox( this );
    2141             : 
    2142           0 :     Link aLink( LINK( this, ImplListBox, ScrollBarHdl ) );
    2143           0 :     mpVScrollBar->SetScrollHdl( aLink );
    2144           0 :     mpHScrollBar->SetScrollHdl( aLink );
    2145             : 
    2146           0 :     mbVScroll       = false;
    2147           0 :     mbHScroll       = false;
    2148           0 :     mbAutoHScroll   = ( nWinStyle & WB_AUTOHSCROLL );
    2149           0 :     mbEdgeBlending  = false;
    2150             : 
    2151           0 :     maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) );
    2152           0 :     maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) );
    2153           0 :     maLBWindow.SetEdgeBlending(GetEdgeBlending());
    2154           0 :     maLBWindow.Show();
    2155           0 : }
    2156             : 
    2157           0 : ImplListBox::~ImplListBox()
    2158             : {
    2159           0 :     delete mpHScrollBar;
    2160           0 :     delete mpVScrollBar;
    2161           0 :     delete mpScrollBarBox;
    2162           0 : }
    2163             : 
    2164           0 : void ImplListBox::Clear()
    2165             : {
    2166           0 :     maLBWindow.Clear();
    2167           0 :     if ( GetEntryList()->GetMRUCount() )
    2168             :     {
    2169           0 :         maLBWindow.GetEntryList()->SetMRUCount( 0 );
    2170           0 :         maLBWindow.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
    2171             :     }
    2172           0 :     mpVScrollBar->SetThumbPos( 0 );
    2173           0 :     mpHScrollBar->SetThumbPos( 0 );
    2174           0 :     StateChanged( STATE_CHANGE_DATA );
    2175           0 : }
    2176             : 
    2177           0 : sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr )
    2178             : {
    2179           0 :     ImplEntryType* pNewEntry = new ImplEntryType( rStr );
    2180           0 :     sal_Int32 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry );
    2181           0 :     if (nNewPos == LISTBOX_ERROR)
    2182             :     {
    2183           0 :         delete pNewEntry;
    2184           0 :         return nNewPos;
    2185             :     }
    2186           0 :     StateChanged( STATE_CHANGE_DATA );
    2187           0 :     return nNewPos;
    2188             : }
    2189             : 
    2190           0 : sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr, const Image& rImage )
    2191             : {
    2192           0 :     ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage );
    2193           0 :     sal_Int32 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry );
    2194           0 :     if (nNewPos == LISTBOX_ERROR)
    2195             :     {
    2196           0 :         delete pNewEntry;
    2197           0 :         return nNewPos;
    2198             :     }
    2199           0 :     StateChanged( STATE_CHANGE_DATA );
    2200           0 :     return nNewPos;
    2201             : }
    2202             : 
    2203           0 : void ImplListBox::RemoveEntry( sal_Int32 nPos )
    2204             : {
    2205           0 :     maLBWindow.RemoveEntry( nPos );
    2206           0 :     StateChanged( STATE_CHANGE_DATA );
    2207           0 : }
    2208             : 
    2209           0 : void ImplListBox::SetEntryFlags( sal_Int32 nPos, long nFlags )
    2210             : {
    2211           0 :     maLBWindow.SetEntryFlags( nPos, nFlags );
    2212           0 : }
    2213             : 
    2214           0 : void ImplListBox::SelectEntry( sal_Int32 nPos, bool bSelect )
    2215             : {
    2216           0 :     maLBWindow.SelectEntry( nPos, bSelect );
    2217           0 : }
    2218             : 
    2219           0 : void ImplListBox::SetNoSelection()
    2220             : {
    2221           0 :     maLBWindow.DeselectAll();
    2222           0 : }
    2223             : 
    2224           0 : void ImplListBox::GetFocus()
    2225             : {
    2226           0 :     maLBWindow.GrabFocus();
    2227           0 : }
    2228             : 
    2229           0 : Window* ImplListBox::GetPreferredKeyInputWindow()
    2230             : {
    2231           0 :     return &maLBWindow;
    2232             : }
    2233             : 
    2234           0 : void ImplListBox::Resize()
    2235             : {
    2236           0 :     Control::Resize();
    2237           0 :     ImplResizeControls();
    2238           0 :     ImplCheckScrollBars();
    2239           0 : }
    2240             : 
    2241           0 : IMPL_LINK_NOARG(ImplListBox, MRUChanged)
    2242             : {
    2243           0 :     StateChanged( STATE_CHANGE_DATA );
    2244           0 :     return 1;
    2245             : }
    2246             : 
    2247           0 : IMPL_LINK_NOARG(ImplListBox, LBWindowScrolled)
    2248             : {
    2249           0 :     long nSet = GetTopEntry();
    2250           0 :     if( nSet > mpVScrollBar->GetRangeMax() )
    2251           0 :         mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() );
    2252           0 :     mpVScrollBar->SetThumbPos( GetTopEntry() );
    2253             : 
    2254           0 :     mpHScrollBar->SetThumbPos( GetLeftIndent() );
    2255             : 
    2256           0 :     maScrollHdl.Call( this );
    2257             : 
    2258           0 :     return 1;
    2259             : }
    2260             : 
    2261           0 : IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB )
    2262             : {
    2263           0 :     sal_uInt16 nPos = (sal_uInt16) pSB->GetThumbPos();
    2264           0 :     if( pSB == mpVScrollBar )
    2265           0 :         SetTopEntry( nPos );
    2266           0 :     else if( pSB == mpHScrollBar )
    2267           0 :         SetLeftIndent( nPos );
    2268             : 
    2269           0 :     return 1;
    2270             : }
    2271             : 
    2272           0 : void ImplListBox::ImplCheckScrollBars()
    2273             : {
    2274           0 :     bool bArrange = false;
    2275             : 
    2276           0 :     Size aOutSz = GetOutputSizePixel();
    2277           0 :     sal_Int32 nEntries = GetEntryList()->GetEntryCount();
    2278           0 :     sal_uInt16 nMaxVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight());
    2279             : 
    2280             :     // vertical ScrollBar
    2281           0 :     if( nEntries > nMaxVisEntries )
    2282             :     {
    2283           0 :         if( !mbVScroll )
    2284           0 :             bArrange = true;
    2285           0 :         mbVScroll = true;
    2286             : 
    2287             :         // check of the scrolled-out region
    2288           0 :         if( GetEntryList()->GetSelectEntryCount() == 1 &&
    2289           0 :             GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND )
    2290           0 :             ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) );
    2291             :         else
    2292           0 :             SetTopEntry( GetTopEntry() );   // MaxTop is being checked...
    2293             :     }
    2294             :     else
    2295             :     {
    2296           0 :         if( mbVScroll )
    2297           0 :             bArrange = true;
    2298           0 :         mbVScroll = false;
    2299           0 :         SetTopEntry( 0 );
    2300             :     }
    2301             : 
    2302             :     // horizontal ScrollBar
    2303           0 :     if( mbAutoHScroll )
    2304             :     {
    2305           0 :         long nWidth = (sal_uInt16) aOutSz.Width();
    2306           0 :         if ( mbVScroll )
    2307           0 :             nWidth -= mpVScrollBar->GetSizePixel().Width();
    2308             : 
    2309           0 :         long nMaxWidth = GetMaxEntryWidth();
    2310           0 :         if( nWidth < nMaxWidth )
    2311             :         {
    2312           0 :             if( !mbHScroll )
    2313           0 :                 bArrange = true;
    2314           0 :             mbHScroll = true;
    2315             : 
    2316           0 :             if ( !mbVScroll )   // maybe we do need one now
    2317             :             {
    2318           0 :                 nMaxVisEntries = (sal_uInt16) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() );
    2319           0 :                 if( nEntries > nMaxVisEntries )
    2320             :                 {
    2321           0 :                     bArrange = true;
    2322           0 :                     mbVScroll = true;
    2323             : 
    2324             :                     // check of the scrolled-out region
    2325           0 :                     if( GetEntryList()->GetSelectEntryCount() == 1 &&
    2326           0 :                         GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND )
    2327           0 :                         ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) );
    2328             :                     else
    2329           0 :                         SetTopEntry( GetTopEntry() );   // MaxTop is being checked...
    2330             :                 }
    2331             :             }
    2332             : 
    2333             :             // check of the scrolled-out region
    2334           0 :             sal_uInt16 nMaxLI = (sal_uInt16) (nMaxWidth - nWidth);
    2335           0 :             if ( nMaxLI < GetLeftIndent() )
    2336           0 :                 SetLeftIndent( nMaxLI );
    2337             :         }
    2338             :         else
    2339             :         {
    2340           0 :             if( mbHScroll )
    2341           0 :                 bArrange = true;
    2342           0 :             mbHScroll = false;
    2343           0 :             SetLeftIndent( 0 );
    2344             :         }
    2345             :     }
    2346             : 
    2347           0 :     if( bArrange )
    2348           0 :         ImplResizeControls();
    2349             : 
    2350           0 :     ImplInitScrollBars();
    2351           0 : }
    2352             : 
    2353           0 : void ImplListBox::ImplInitScrollBars()
    2354             : {
    2355           0 :     Size aOutSz = maLBWindow.GetOutputSizePixel();
    2356             : 
    2357           0 :     if ( mbVScroll )
    2358             :     {
    2359           0 :         sal_Int32 nEntries = GetEntryList()->GetEntryCount();
    2360           0 :         sal_uInt16 nVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight());
    2361           0 :         mpVScrollBar->SetRangeMax( nEntries );
    2362           0 :         mpVScrollBar->SetVisibleSize( nVisEntries );
    2363           0 :         mpVScrollBar->SetPageSize( nVisEntries - 1 );
    2364             :     }
    2365             : 
    2366           0 :     if ( mbHScroll )
    2367             :     {
    2368           0 :         mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL );
    2369           0 :         mpHScrollBar->SetVisibleSize( (sal_uInt16)aOutSz.Width() );
    2370           0 :         mpHScrollBar->SetLineSize( HORZ_SCROLL );
    2371           0 :         mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL );
    2372             :     }
    2373           0 : }
    2374             : 
    2375           0 : void ImplListBox::ImplResizeControls()
    2376             : {
    2377             :     // Here we only position the Controls; if the Scrollbars are to be
    2378             :     // visible is already determined in ImplCheckScrollBars
    2379             : 
    2380           0 :     Size aOutSz = GetOutputSizePixel();
    2381           0 :     long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
    2382           0 :     nSBWidth = CalcZoom( nSBWidth );
    2383             : 
    2384           0 :     Size aInnerSz( aOutSz );
    2385           0 :     if ( mbVScroll )
    2386           0 :         aInnerSz.Width() -= nSBWidth;
    2387           0 :     if ( mbHScroll )
    2388           0 :         aInnerSz.Height() -= nSBWidth;
    2389             : 
    2390             :     // pb: #106948# explicit mirroring for calc
    2391             :     // Scrollbar on left or right side?
    2392           0 :     bool bMirroring = maLBWindow.IsMirroring();
    2393           0 :     Point aWinPos( bMirroring && mbVScroll ? nSBWidth : 0, 0 );
    2394           0 :     maLBWindow.SetPosSizePixel( aWinPos, aInnerSz );
    2395             : 
    2396             :     // ScrollBarBox
    2397           0 :     if( mbVScroll && mbHScroll )
    2398             :     {
    2399           0 :         Point aBoxPos( bMirroring ? 0 : aInnerSz.Width(), aInnerSz.Height() );
    2400           0 :         mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) );
    2401           0 :         mpScrollBarBox->Show();
    2402             :     }
    2403             :     else
    2404             :     {
    2405           0 :         mpScrollBarBox->Hide();
    2406             :     }
    2407             : 
    2408             :     // vertical ScrollBar
    2409           0 :     if( mbVScroll )
    2410             :     {
    2411             :         // Scrollbar on left or right side?
    2412           0 :         Point aVPos( bMirroring ? 0 : aOutSz.Width() - nSBWidth, 0 );
    2413           0 :         mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) );
    2414           0 :         mpVScrollBar->Show();
    2415             :     }
    2416             :     else
    2417             :     {
    2418           0 :         mpVScrollBar->Hide();
    2419             :         // #107254# Don't reset top entry after resize, but check for max top entry
    2420           0 :         SetTopEntry( GetTopEntry() );
    2421             :     }
    2422             : 
    2423             :     // horizontal ScrollBar
    2424           0 :     if( mbHScroll )
    2425             :     {
    2426           0 :         Point aHPos( ( bMirroring && mbVScroll ) ? nSBWidth : 0, aOutSz.Height() - nSBWidth );
    2427           0 :         mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) );
    2428           0 :         mpHScrollBar->Show();
    2429             :     }
    2430             :     else
    2431             :     {
    2432           0 :         mpHScrollBar->Hide();
    2433           0 :         SetLeftIndent( 0 );
    2434             :     }
    2435           0 : }
    2436             : 
    2437           0 : void ImplListBox::StateChanged( StateChangedType nType )
    2438             : {
    2439           0 :     if ( nType == STATE_CHANGE_INITSHOW )
    2440             :     {
    2441           0 :         ImplCheckScrollBars();
    2442             :     }
    2443           0 :     else if ( ( nType == STATE_CHANGE_UPDATEMODE ) || ( nType == STATE_CHANGE_DATA ) )
    2444             :     {
    2445           0 :         bool bUpdate = IsUpdateMode();
    2446           0 :         maLBWindow.SetUpdateMode( bUpdate );
    2447           0 :         if ( bUpdate && IsReallyVisible() )
    2448           0 :             ImplCheckScrollBars();
    2449             :     }
    2450           0 :     else if( nType == STATE_CHANGE_ENABLE )
    2451             :     {
    2452           0 :         mpHScrollBar->Enable( IsEnabled() );
    2453           0 :         mpVScrollBar->Enable( IsEnabled() );
    2454           0 :         mpScrollBarBox->Enable( IsEnabled() );
    2455           0 :         maLBWindow.Enable( IsEnabled() );
    2456             : 
    2457           0 :         Invalidate();
    2458             :     }
    2459           0 :     else if ( nType == STATE_CHANGE_ZOOM )
    2460             :     {
    2461           0 :         maLBWindow.SetZoom( GetZoom() );
    2462           0 :         Resize();
    2463             :     }
    2464           0 :     else if ( nType == STATE_CHANGE_CONTROLFONT )
    2465             :     {
    2466           0 :         maLBWindow.SetControlFont( GetControlFont() );
    2467             :     }
    2468           0 :     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
    2469             :     {
    2470           0 :         maLBWindow.SetControlForeground( GetControlForeground() );
    2471             :     }
    2472           0 :     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
    2473             :     {
    2474           0 :         maLBWindow.SetControlBackground( GetControlBackground() );
    2475             :     }
    2476           0 :     else if( nType == STATE_CHANGE_MIRRORING )
    2477             :     {
    2478           0 :         maLBWindow.EnableRTL( IsRTLEnabled() );
    2479           0 :         mpHScrollBar->EnableRTL( IsRTLEnabled() );
    2480           0 :         mpVScrollBar->EnableRTL( IsRTLEnabled() );
    2481           0 :         ImplResizeControls();
    2482             :     }
    2483             : 
    2484           0 :     Control::StateChanged( nType );
    2485           0 : }
    2486             : 
    2487           0 : void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt )
    2488             : {
    2489           0 :         Control::DataChanged( rDCEvt );
    2490           0 : }
    2491             : 
    2492           0 : bool ImplListBox::Notify( NotifyEvent& rNEvt )
    2493             : {
    2494           0 :     bool nDone = false;
    2495           0 :     if ( rNEvt.GetType() == EVENT_COMMAND )
    2496             :     {
    2497           0 :         const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
    2498           0 :         if ( rCEvt.GetCommand() == COMMAND_WHEEL )
    2499             :         {
    2500           0 :             const CommandWheelData* pData = rCEvt.GetWheelData();
    2501           0 :             if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
    2502             :             {
    2503           0 :                 nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
    2504             :             }
    2505             :         }
    2506             :     }
    2507             : 
    2508           0 :     return nDone || Window::Notify( rNEvt );
    2509             : }
    2510             : 
    2511           0 : const Wallpaper& ImplListBox::GetDisplayBackground() const
    2512             : {
    2513           0 :     return maLBWindow.GetDisplayBackground();
    2514             : }
    2515             : 
    2516           0 : bool ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt )
    2517             : {
    2518           0 :     bool bDone = false;
    2519           0 :     if ( rCEvt.GetCommand() == COMMAND_WHEEL )
    2520             :     {
    2521           0 :         const CommandWheelData* pData = rCEvt.GetWheelData();
    2522           0 :         if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
    2523             :         {
    2524           0 :             sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP;
    2525           0 :             KeyEvent aKeyEvent( 0, KeyCode( nKey ) );
    2526           0 :             bDone = ProcessKeyInput( aKeyEvent );
    2527             :         }
    2528             :     }
    2529           0 :     return bDone;
    2530             : }
    2531             : 
    2532           0 : void ImplListBox::SetMRUEntries( const OUString& rEntries, sal_Unicode cSep )
    2533             : {
    2534           0 :     bool bChanges = GetEntryList()->GetMRUCount() ? true : false;
    2535             : 
    2536             :     // Remove old MRU entries
    2537           0 :     for ( sal_Int32 n = GetEntryList()->GetMRUCount();n; )
    2538           0 :         maLBWindow.RemoveEntry( --n );
    2539             : 
    2540           0 :     sal_Int32 nMRUCount = 0;
    2541           0 :     sal_Int32 nIndex = 0;
    2542           0 :     do
    2543             :     {
    2544           0 :         OUString aEntry = rEntries.getToken( 0, cSep, nIndex );
    2545             :         // Accept only existing entries
    2546           0 :         if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND )
    2547             :         {
    2548           0 :             ImplEntryType* pNewEntry = new ImplEntryType( aEntry );
    2549           0 :             maLBWindow.GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, false );
    2550           0 :             bChanges = true;
    2551           0 :         }
    2552             :     }
    2553           0 :     while ( nIndex >= 0 );
    2554             : 
    2555           0 :     if ( bChanges )
    2556             :     {
    2557           0 :         maLBWindow.GetEntryList()->SetMRUCount( nMRUCount );
    2558           0 :         SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
    2559           0 :         StateChanged( STATE_CHANGE_DATA );
    2560             :     }
    2561           0 : }
    2562             : 
    2563           0 : OUString ImplListBox::GetMRUEntries( sal_Unicode cSep ) const
    2564             : {
    2565           0 :     OUStringBuffer aEntries;
    2566           0 :     for ( sal_Int32 n = 0; n < GetEntryList()->GetMRUCount(); n++ )
    2567             :     {
    2568           0 :         aEntries.append(GetEntryList()->GetEntryText( n ));
    2569           0 :         if( n < ( GetEntryList()->GetMRUCount() - 1 ) )
    2570           0 :             aEntries.append(cSep);
    2571             :     }
    2572           0 :     return aEntries.makeStringAndClear();
    2573             : }
    2574             : 
    2575           0 : void ImplListBox::SetEdgeBlending(bool bNew)
    2576             : {
    2577           0 :     if(mbEdgeBlending != bNew)
    2578             :     {
    2579           0 :         mbEdgeBlending = bNew;
    2580           0 :         maLBWindow.SetEdgeBlending(GetEdgeBlending());
    2581             :     }
    2582           0 : }
    2583             : 
    2584           0 : ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) :
    2585           0 :     Control ( pParent, nWinStyle )
    2586             : {
    2587           0 :     if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
    2588           0 :             && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
    2589           0 :         SetBackground();
    2590             :     else
    2591           0 :         SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
    2592             : 
    2593           0 :     mbInUserDraw = false;
    2594           0 :     mbUserDrawEnabled = false;
    2595           0 :     mbEdgeBlending = false;
    2596           0 :     mnItemPos = LISTBOX_ENTRY_NOTFOUND;
    2597           0 : }
    2598             : 
    2599           0 : void ImplWin::MBDown()
    2600             : {
    2601           0 :     if( IsEnabled() )
    2602           0 :         maMBDownHdl.Call( this );
    2603           0 : }
    2604             : 
    2605           0 : void ImplWin::MouseButtonDown( const MouseEvent& )
    2606             : {
    2607           0 :     if( IsEnabled() )
    2608             :     {
    2609           0 :         MBDown();
    2610             :     }
    2611           0 : }
    2612             : 
    2613           0 : void ImplWin::FillLayoutData() const
    2614             : {
    2615           0 :     mpControlData->mpLayoutData = new vcl::ControlLayoutData();
    2616           0 :     const_cast<ImplWin*>(this)->ImplDraw( true );
    2617           0 : }
    2618             : 
    2619           0 : bool ImplWin::PreNotify( NotifyEvent& rNEvt )
    2620             : {
    2621           0 :     const MouseEvent* pMouseEvt = NULL;
    2622             : 
    2623           0 :     if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
    2624             :     {
    2625           0 :         if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() )
    2626             :         {
    2627             :             // trigger redraw as mouse over state has changed
    2628           0 :             if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
    2629           0 :             && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
    2630             :             {
    2631           0 :                 GetParent()->GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE );
    2632           0 :                 GetParent()->GetWindow( WINDOW_BORDER )->Update();
    2633             :             }
    2634             :         }
    2635             :     }
    2636             : 
    2637           0 :     return Control::PreNotify(rNEvt);
    2638             : }
    2639             : 
    2640           0 : void ImplWin::ImplDraw( bool bLayout )
    2641             : {
    2642           0 :     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    2643             : 
    2644           0 :     bool bNativeOK = false;
    2645             : 
    2646           0 :     if( ! bLayout )
    2647             :     {
    2648           0 :         ControlState nState = CTRL_STATE_ENABLED;
    2649           0 :         if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
    2650           0 :             && IsNativeControlSupported(CTRL_LISTBOX, HAS_BACKGROUND_TEXTURE) )
    2651             :         {
    2652             :             // Repaint the (focused) area similarly to
    2653             :             // ImplSmallBorderWindowView::DrawWindow() in
    2654             :             // vcl/source/window/brdwin.cxx
    2655           0 :             Window *pWin = GetParent();
    2656             : 
    2657           0 :             ImplControlValue aControlValue;
    2658           0 :             if ( !pWin->IsEnabled() )
    2659           0 :                 nState &= ~CTRL_STATE_ENABLED;
    2660           0 :             if ( pWin->HasFocus() )
    2661           0 :                 nState |= CTRL_STATE_FOCUSED;
    2662             : 
    2663             :             // The listbox is painted over the entire control including the
    2664             :             // border, but ImplWin does not contain the border => correction
    2665             :             // needed.
    2666             :             sal_Int32 nLeft, nTop, nRight, nBottom;
    2667           0 :             pWin->GetBorder( nLeft, nTop, nRight, nBottom );
    2668           0 :             Point aPoint( -nLeft, -nTop );
    2669           0 :             Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() );
    2670             : 
    2671           0 :             bool bMouseOver = false;
    2672           0 :             if( GetParent() )
    2673             :             {
    2674           0 :                 Window *pChild = GetParent()->GetWindow( WINDOW_FIRSTCHILD );
    2675           0 :                 while( pChild && !(bMouseOver = pChild->IsMouseOver()) )
    2676           0 :                     pChild = pChild->GetWindow( WINDOW_NEXT );
    2677             :             }
    2678             : 
    2679           0 :             if( bMouseOver )
    2680           0 :                 nState |= CTRL_STATE_ROLLOVER;
    2681             : 
    2682             :             // if parent has no border, then nobody has drawn the background
    2683             :             // since no border window exists. so draw it here.
    2684           0 :             WinBits nParentStyle = pWin->GetStyle();
    2685           0 :             if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) )
    2686             :             {
    2687           0 :                 Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() );
    2688             :                 pWin->DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aParentRect,
    2689           0 :                                          nState, aControlValue, OUString() );
    2690             :             }
    2691             : 
    2692             :             bNativeOK = DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
    2693           0 :                 aControlValue, OUString() );
    2694             :         }
    2695             : 
    2696           0 :         if( IsEnabled() )
    2697             :         {
    2698           0 :             if( HasFocus() )
    2699             :             {
    2700           0 :                 SetTextColor( rStyleSettings.GetHighlightTextColor() );
    2701           0 :                 SetFillColor( rStyleSettings.GetHighlightColor() );
    2702           0 :                 DrawRect( maFocusRect );
    2703             :             }
    2704             :             else
    2705             :             {
    2706           0 :                 Color aColor;
    2707           0 :                 if( ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea )
    2708             :                 {
    2709           0 :                     if( bNativeOK && (nState & CTRL_STATE_ROLLOVER) )
    2710           0 :                         aColor = rStyleSettings.GetButtonRolloverTextColor();
    2711             :                     else
    2712           0 :                         aColor = rStyleSettings.GetButtonTextColor();
    2713             :                 }
    2714             :                 else
    2715             :                 {
    2716           0 :                     if( bNativeOK && (nState & CTRL_STATE_ROLLOVER) )
    2717           0 :                         aColor = rStyleSettings.GetFieldRolloverTextColor();
    2718             :                     else
    2719           0 :                         aColor = rStyleSettings.GetFieldTextColor();
    2720             :                 }
    2721           0 :                 if( IsControlForeground() )
    2722           0 :                     aColor = GetControlForeground();
    2723           0 :                 SetTextColor( aColor );
    2724           0 :                 if ( !bNativeOK )
    2725           0 :                     Erase( maFocusRect );
    2726             :             }
    2727             :         }
    2728             :         else // Disabled
    2729             :         {
    2730           0 :             SetTextColor( rStyleSettings.GetDisableColor() );
    2731           0 :             if ( !bNativeOK )
    2732           0 :                 Erase( maFocusRect );
    2733             :         }
    2734             :     }
    2735             : 
    2736           0 :     if ( IsUserDrawEnabled() )
    2737             :     {
    2738           0 :         mbInUserDraw = true;
    2739           0 :         UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 );
    2740           0 :         maUserDrawHdl.Call( &aUDEvt );
    2741           0 :         mbInUserDraw = false;
    2742             :     }
    2743             :     else
    2744             :     {
    2745           0 :         DrawEntry( true, true, false, bLayout );
    2746             :     }
    2747           0 : }
    2748             : 
    2749           0 : void ImplWin::Paint( const Rectangle& )
    2750             : {
    2751           0 :     ImplDraw();
    2752           0 : }
    2753             : 
    2754           0 : void ImplWin::DrawEntry( bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos, bool bLayout )
    2755             : {
    2756           0 :     long nBorder = 1;
    2757           0 :     Size aOutSz = GetOutputSizePixel();
    2758             : 
    2759           0 :     bool bImage = !!maImage;
    2760           0 :     if( bDrawImage && bImage && !bLayout )
    2761             :     {
    2762           0 :         sal_uInt16 nStyle = 0;
    2763           0 :         Size aImgSz = maImage.GetSizePixel();
    2764           0 :         Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) );
    2765           0 :         const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    2766             : 
    2767             :         // check for HC mode
    2768           0 :         Image *pImage = &maImage;
    2769             : 
    2770           0 :         if ( !IsZoom() )
    2771             :         {
    2772           0 :             DrawImage( aPtImg, *pImage, nStyle );
    2773             :         }
    2774             :         else
    2775             :         {
    2776           0 :             aImgSz.Width() = CalcZoom( aImgSz.Width() );
    2777           0 :             aImgSz.Height() = CalcZoom( aImgSz.Height() );
    2778           0 :             DrawImage( aPtImg, aImgSz, *pImage, nStyle );
    2779             :         }
    2780             : 
    2781           0 :         const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
    2782             : 
    2783           0 :         if(nEdgeBlendingPercent)
    2784             :         {
    2785           0 :             const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
    2786           0 :             const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
    2787           0 :             const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
    2788           0 :             const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
    2789             : 
    2790           0 :             if(!aBlendFrame.IsEmpty())
    2791             :             {
    2792           0 :                 DrawBitmapEx(aPtImg, aBlendFrame);
    2793           0 :             }
    2794             :         }
    2795             :     }
    2796             : 
    2797           0 :     if( bDrawText && !maString.isEmpty() )
    2798             :     {
    2799           0 :         sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER;
    2800             : 
    2801           0 :         if ( bDrawImage && bImage && !bLayout )
    2802           0 :             nTextStyle |= TEXT_DRAW_LEFT;
    2803           0 :         else if ( GetStyle() & WB_CENTER )
    2804           0 :             nTextStyle |= TEXT_DRAW_CENTER;
    2805           0 :         else if ( GetStyle() & WB_RIGHT )
    2806           0 :             nTextStyle |= TEXT_DRAW_RIGHT;
    2807             :         else
    2808           0 :             nTextStyle |= TEXT_DRAW_LEFT;
    2809             : 
    2810           0 :         Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) );
    2811             : 
    2812           0 :         if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) )
    2813             :         {
    2814           0 :             long nMaxWidth = std::max( maImage.GetSizePixel().Width(), maUserItemSize.Width() );
    2815           0 :             aTextRect.Left() += nMaxWidth + IMG_TXT_DISTANCE;
    2816             :         }
    2817             : 
    2818           0 :         MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
    2819           0 :         OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
    2820           0 :         DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText );
    2821             :     }
    2822             : 
    2823           0 :     if( HasFocus() && !bLayout )
    2824           0 :         ShowFocus( maFocusRect );
    2825           0 : }
    2826             : 
    2827           0 : void ImplWin::Resize()
    2828             : {
    2829           0 :     Control::Resize();
    2830           0 :     maFocusRect.SetSize( GetOutputSizePixel() );
    2831           0 :     Invalidate();
    2832           0 : }
    2833             : 
    2834           0 : void ImplWin::GetFocus()
    2835             : {
    2836           0 :     ShowFocus( maFocusRect );
    2837           0 :     if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
    2838           0 :         IsNativeWidgetEnabled() &&
    2839           0 :         IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
    2840             :     {
    2841           0 :         Window* pWin = GetParent()->GetWindow( WINDOW_BORDER );
    2842           0 :         if( ! pWin )
    2843           0 :             pWin = GetParent();
    2844           0 :         pWin->Invalidate();
    2845             :     }
    2846             :     else
    2847           0 :         Invalidate();
    2848           0 :     Control::GetFocus();
    2849           0 : }
    2850             : 
    2851           0 : void ImplWin::LoseFocus()
    2852             : {
    2853           0 :     HideFocus();
    2854           0 :     if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
    2855           0 :         IsNativeWidgetEnabled() &&
    2856           0 :         IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
    2857             :     {
    2858           0 :         Window* pWin = GetParent()->GetWindow( WINDOW_BORDER );
    2859           0 :         if( ! pWin )
    2860           0 :             pWin = GetParent();
    2861           0 :         pWin->Invalidate();
    2862             :     }
    2863             :     else
    2864           0 :         Invalidate();
    2865           0 :     Control::LoseFocus();
    2866           0 : }
    2867             : 
    2868           0 : ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) :
    2869             :     PushButton(  pParent, nWinStyle ),
    2870           0 :     mbDown  ( false )
    2871             : {
    2872           0 : }
    2873             : 
    2874           0 : void ImplBtn::MBDown()
    2875             : {
    2876           0 :     if( IsEnabled() )
    2877           0 :        maMBDownHdl.Call( this );
    2878           0 : }
    2879             : 
    2880           0 : void ImplBtn::MouseButtonDown( const MouseEvent& )
    2881             : {
    2882             :     //PushButton::MouseButtonDown( rMEvt );
    2883           0 :     if( IsEnabled() )
    2884             :     {
    2885           0 :         MBDown();
    2886           0 :         mbDown = true;
    2887             :     }
    2888           0 : }
    2889             : 
    2890           0 : ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) :
    2891           0 :     FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW )    // no drop shadow for list boxes
    2892             : {
    2893           0 :     mpImplLB = NULL;
    2894           0 :     mnDDLineCount = 0;
    2895           0 :     mbAutoWidth = false;
    2896             : 
    2897           0 :     mnPopupModeStartSaveSelection = LISTBOX_ENTRY_NOTFOUND;
    2898             : 
    2899           0 :     EnableSaveBackground();
    2900             : 
    2901           0 :     Window * pBorderWindow = ImplGetBorderWindow();
    2902           0 :     if( pBorderWindow )
    2903             :     {
    2904           0 :         SetAccessibleRole(accessibility::AccessibleRole::PANEL);
    2905           0 :         pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
    2906             :     }
    2907             :     else
    2908             :     {
    2909           0 :         SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
    2910             :     }
    2911             : 
    2912           0 : }
    2913             : 
    2914           0 : bool ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt )
    2915             : {
    2916           0 :     if( rNEvt.GetType() == EVENT_LOSEFOCUS )
    2917             :     {
    2918           0 :         if( !GetParent()->HasChildPathFocus( true ) )
    2919           0 :             EndPopupMode();
    2920             :     }
    2921             : 
    2922           0 :     return FloatingWindow::PreNotify( rNEvt );
    2923             : }
    2924             : 
    2925           0 : void ImplListBoxFloatingWindow::setPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
    2926             : {
    2927           0 :     FloatingWindow::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
    2928             : 
    2929             :     // Fix #60890# ( MBA ): to be able to resize the Listbox even in its open state
    2930             :     // after a call to Resize(), we adjust its position if necessary
    2931           0 :     if ( IsReallyVisible() && ( nFlags & WINDOW_POSSIZE_HEIGHT ) )
    2932             :     {
    2933           0 :         Point aPos = GetParent()->GetPosPixel();
    2934           0 :         aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
    2935             : 
    2936           0 :         if ( nFlags & WINDOW_POSSIZE_X )
    2937           0 :             aPos.X() = nX;
    2938             : 
    2939           0 :         if ( nFlags & WINDOW_POSSIZE_Y )
    2940           0 :             aPos.Y() = nY;
    2941             : 
    2942             :         sal_uInt16 nIndex;
    2943           0 :         SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN, nIndex ) );
    2944             :     }
    2945             : 
    2946             : //  if( !IsReallyVisible() )
    2947             :     {
    2948             :         // The ImplListBox does not get a Resize() as not visible.
    2949             :         // But the windows must get a Resize(), so that the number of
    2950             :         // visible entries is correct for PgUp/PgDown.
    2951             :         // The number also cannot be calculated by List/Combobox, as for
    2952             :         // this the presence of the vertical Scrollbar has to be known.
    2953           0 :         mpImplLB->SetSizePixel( GetOutputSizePixel() );
    2954           0 :         ((Window*)mpImplLB)->Resize();
    2955           0 :         ((Window*)mpImplLB->GetMainWindow())->Resize();
    2956             :     }
    2957           0 : }
    2958             : 
    2959           0 : void ImplListBoxFloatingWindow::Resize()
    2960             : {
    2961           0 :     mpImplLB->GetMainWindow()->ImplClearLayoutData();
    2962           0 :     FloatingWindow::Resize();
    2963           0 : }
    2964             : 
    2965           0 : Size ImplListBoxFloatingWindow::CalcFloatSize()
    2966             : {
    2967           0 :     Size aFloatSz( maPrefSz );
    2968             : 
    2969             :     sal_Int32 nLeft, nTop, nRight, nBottom;
    2970           0 :     GetBorder( nLeft, nTop, nRight, nBottom );
    2971             : 
    2972           0 :     sal_Int32 nLines = mpImplLB->GetEntryList()->GetEntryCount();
    2973           0 :     if ( mnDDLineCount && ( nLines > mnDDLineCount ) )
    2974           0 :         nLines = mnDDLineCount;
    2975             : 
    2976           0 :     Size aSz = mpImplLB->CalcSize( nLines );
    2977           0 :     long nMaxHeight = aSz.Height() + nTop + nBottom;
    2978             : 
    2979           0 :     if ( mnDDLineCount )
    2980           0 :         aFloatSz.Height() = nMaxHeight;
    2981             : 
    2982           0 :     if( mbAutoWidth )
    2983             :     {
    2984             :         // AutoSize first only for width...
    2985             : 
    2986           0 :         aFloatSz.Width() = aSz.Width() + nLeft + nRight;
    2987           0 :         aFloatSz.Width() += nRight; // adding some space looks better...
    2988             : 
    2989           0 :         if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) )
    2990             :         {
    2991             :             // then we also need the vertical Scrollbar
    2992           0 :             long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
    2993           0 :             aFloatSz.Width() += nSBWidth;
    2994             :         }
    2995             : 
    2996           0 :         long nDesktopWidth = GetDesktopRectPixel().getWidth();
    2997           0 :         if (aFloatSz.Width() > nDesktopWidth)
    2998             :             // Don't exceed the desktop width.
    2999           0 :             aFloatSz.Width() = nDesktopWidth;
    3000             :     }
    3001             : 
    3002           0 :     if ( aFloatSz.Height() > nMaxHeight )
    3003           0 :         aFloatSz.Height() = nMaxHeight;
    3004             : 
    3005             :     // Minimal height, in case height is not set to Float height.
    3006             :     // The parent of FloatWin must be DropDown-Combo/Listbox.
    3007           0 :     Size aParentSz = GetParent()->GetSizePixel();
    3008           0 :     if( (!mnDDLineCount || !nLines) && ( aFloatSz.Height() < aParentSz.Height() ) )
    3009           0 :         aFloatSz.Height() = aParentSz.Height();
    3010             : 
    3011             :     // do not get narrower than the parent...
    3012           0 :     if( aFloatSz.Width() < aParentSz.Width() )
    3013           0 :         aFloatSz.Width() = aParentSz.Width();
    3014             : 
    3015             :     // align height to entries...
    3016           0 :     long nInnerHeight = aFloatSz.Height() - nTop - nBottom;
    3017           0 :     long nEntryHeight = mpImplLB->GetEntryHeight();
    3018           0 :     if ( nInnerHeight % nEntryHeight )
    3019             :     {
    3020           0 :         nInnerHeight /= nEntryHeight;
    3021           0 :         nInnerHeight++;
    3022           0 :         nInnerHeight *= nEntryHeight;
    3023           0 :         aFloatSz.Height() = nInnerHeight + nTop + nBottom;
    3024             :     }
    3025             : 
    3026           0 :     if (aFloatSz.Width() < aSz.Width())
    3027             :     {
    3028             :         // The max width of list box entries exceeds the window width.
    3029             :         // Account for the scroll bar height.
    3030           0 :         long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
    3031           0 :         aFloatSz.Height() += nSBWidth;
    3032             :     }
    3033             : 
    3034           0 :     return aFloatSz;
    3035             : }
    3036             : 
    3037           0 : void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
    3038             : {
    3039           0 :     if( !IsInPopupMode() )
    3040             :     {
    3041           0 :         Size aFloatSz = CalcFloatSize();
    3042             : 
    3043           0 :         SetSizePixel( aFloatSz );
    3044           0 :         mpImplLB->SetSizePixel( GetOutputSizePixel() );
    3045             : 
    3046           0 :         sal_Int32 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 );
    3047           0 :         mnPopupModeStartSaveSelection = nPos;
    3048             : 
    3049           0 :         Size aSz = GetParent()->GetSizePixel();
    3050           0 :         Point aPos = GetParent()->GetPosPixel();
    3051           0 :         aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
    3052             :         // FIXME: this ugly hack is for Mac/Aqua
    3053             :         // should be replaced by a real mechanism to place the float rectangle
    3054           0 :         if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
    3055           0 :             GetParent()->IsNativeWidgetEnabled() )
    3056             :         {
    3057           0 :             sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4;
    3058           0 :             aPos.X() += nLeft;
    3059           0 :             aPos.Y() += nTop;
    3060           0 :             aSz.Width() -= nLeft + nRight;
    3061           0 :             aSz.Height() -= nTop + nBottom;
    3062             :         }
    3063           0 :         Rectangle aRect( aPos, aSz );
    3064             : 
    3065             :         // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI
    3066             :         // where the document is unmirrored
    3067             :         // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror
    3068           0 :         Window *pGrandparent = GetParent()->GetParent();
    3069           0 :         const OutputDevice *pGrandparentOutDev = pGrandparent->GetOutDev();
    3070             : 
    3071           0 :         if( pGrandparent->ImplIsAntiparallel() )
    3072           0 :             pGrandparentOutDev->ReMirror( aRect );
    3073             : 
    3074           0 :         StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN );
    3075             : 
    3076           0 :         if( nPos != LISTBOX_ENTRY_NOTFOUND )
    3077           0 :             mpImplLB->ShowProminentEntry( nPos );
    3078             : 
    3079           0 :         if( bStartTracking )
    3080           0 :             mpImplLB->GetMainWindow()->EnableMouseMoveSelect( true );
    3081             : 
    3082           0 :         if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() )
    3083           0 :             mpImplLB->GetMainWindow()->GrabFocus();
    3084             : 
    3085           0 :         mpImplLB->GetMainWindow()->ImplClearLayoutData();
    3086             :     }
    3087           0 : }
    3088             : 
    3089             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10