| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <tools/debug.hxx> |
| |
| #include <vcl/svapp.hxx> |
| #include <vcl/settings.hxx> |
| #include <vcl/event.hxx> |
| #include <vcl/scrbar.hxx> |
| #include <vcl/help.hxx> |
| #include <vcl/lstbox.h> |
| #include <vcl/unohelp.hxx> |
| #include <vcl/i18nhelp.hxx> |
| |
| #include <ilstbox.hxx> |
| #include <controldata.hxx> |
| #include <svdata.hxx> |
| |
| #include <com/sun/star/i18n/XCollator.hpp> |
| #include <com/sun/star/accessibility/XAccessible.hpp> |
| #include <com/sun/star/accessibility/AccessibleRole.hpp> |
| |
| #define MULTILINE_ENTRY_DRAW_FLAGS ( TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_VCENTER ) |
| |
| using namespace ::com::sun::star; |
| |
| // ======================================================================= |
| |
| void ImplInitFieldSettings( Window* pWin, sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ) |
| { |
| const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings(); |
| |
| if ( bFont ) |
| { |
| Font aFont = rStyleSettings.GetFieldFont(); |
| if ( pWin->IsControlFont() ) |
| aFont.Merge( pWin->GetControlFont() ); |
| pWin->SetZoomedPointFont( aFont ); |
| } |
| |
| if ( bFont || bForeground ) |
| { |
| Color aTextColor = rStyleSettings.GetFieldTextColor(); |
| if ( pWin->IsControlForeground() ) |
| aTextColor = pWin->GetControlForeground(); |
| pWin->SetTextColor( aTextColor ); |
| } |
| |
| if ( bBackground ) |
| { |
| if( pWin->IsControlBackground() ) |
| pWin->SetBackground( pWin->GetControlBackground() ); |
| else |
| pWin->SetBackground( rStyleSettings.GetFieldColor() ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplInitDropDownButton( PushButton* pButton ) |
| { |
| if ( pButton->GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN ) |
| pButton->SetSymbol( SYMBOL_SPIN_UPDOWN ); |
| else |
| pButton->SetSymbol( SYMBOL_SPIN_DOWN ); |
| |
| if ( pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) |
| && ! pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) |
| pButton->SetBackground(); |
| } |
| |
| // ======================================================================= |
| |
| ImplEntryList::ImplEntryList( Window* pWindow ) |
| { |
| mpWindow = pWindow; |
| mnLastSelected = LISTBOX_ENTRY_NOTFOUND; |
| mnSelectionAnchor = LISTBOX_ENTRY_NOTFOUND; |
| mnImages = 0; |
| mbCallSelectionChangedHdl = sal_True; |
| |
| mnMRUCount = 0; |
| mnMaxMRUCount = 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ImplEntryList::~ImplEntryList() |
| { |
| Clear(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplEntryList::Clear() |
| { |
| mnImages = 0; |
| for ( sal_uInt16 n = GetEntryCount(); n; ) |
| { |
| ImplEntryType* pImplEntry = GetEntry( --n ); |
| delete pImplEntry; |
| } |
| List::Clear(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplEntryList::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) |
| { |
| ImplEntryType* pImplEntry = GetEntry( nPos ); |
| if ( pImplEntry && |
| ( pImplEntry->mbIsSelected != bSelect ) && |
| ( (pImplEntry->mnFlags & LISTBOX_ENTRY_FLAG_DISABLE_SELECTION) == 0 ) ) |
| { |
| pImplEntry->mbIsSelected = bSelect; |
| if ( mbCallSelectionChangedHdl ) |
| maSelectionChangedHdl.Call( (void*)sal_IntPtr(nPos) ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| uno::Reference< i18n::XCollator > ImplGetCollator (lang::Locale &rLocale) |
| { |
| static uno::Reference< i18n::XCollator > xCollator; |
| if ( !xCollator.is() ) |
| xCollator = vcl::unohelper::CreateCollator(); |
| if( xCollator.is() ) |
| xCollator->loadDefaultCollator (rLocale, 0); |
| |
| return xCollator; |
| } |
| |
| sal_uInt16 ImplEntryList::InsertEntry( sal_uInt16 nPos, ImplEntryType* pNewEntry, sal_Bool bSort ) |
| { |
| if ( !!pNewEntry->maImage ) |
| mnImages++; |
| |
| if ( !bSort || !Count() ) |
| { |
| Insert( pNewEntry, nPos ); |
| } |
| else |
| { |
| lang::Locale aLocale = Application::GetSettings().GetLocale(); |
| uno::Reference< i18n::XCollator > xCollator = ImplGetCollator(aLocale); |
| |
| const XubString& rStr = pNewEntry->maStr; |
| sal_uLong nLow, nHigh, nMid; |
| |
| nHigh = Count(); |
| |
| ImplEntryType* pTemp = GetEntry( (sal_uInt16)(nHigh-1) ); |
| |
| try |
| { |
| // XXX even though XCollator::compareString returns a sal_Int32 the only |
| // defined values are {-1, 0, 1} which is compatible with StringCompare |
| StringCompare eComp = xCollator.is() ? |
| (StringCompare)xCollator->compareString (rStr, pTemp->maStr) |
| : COMPARE_EQUAL; |
| |
| // Schnelles Einfuegen bei sortierten Daten |
| if ( eComp != COMPARE_LESS ) |
| { |
| Insert( pNewEntry, LIST_APPEND ); |
| } |
| else |
| { |
| nLow = mnMRUCount; |
| pTemp = (ImplEntryType*)GetEntry( (sal_uInt16)nLow ); |
| |
| eComp = (StringCompare)xCollator->compareString (rStr, pTemp->maStr); |
| if ( eComp != COMPARE_GREATER ) |
| { |
| Insert( pNewEntry, (sal_uLong)0 ); |
| } |
| else |
| { |
| // Binaeres Suchen |
| nHigh--; |
| do |
| { |
| nMid = (nLow + nHigh) / 2; |
| pTemp = (ImplEntryType*)GetObject( nMid ); |
| |
| eComp = (StringCompare)xCollator->compareString (rStr, pTemp->maStr); |
| |
| if ( eComp == COMPARE_LESS ) |
| nHigh = nMid-1; |
| else |
| { |
| if ( eComp == COMPARE_GREATER ) |
| nLow = nMid + 1; |
| else |
| break; |
| } |
| } |
| while ( nLow <= nHigh ); |
| |
| if ( eComp != COMPARE_LESS ) |
| nMid++; |
| |
| Insert( pNewEntry, nMid ); |
| } |
| } |
| } |
| catch (uno::RuntimeException& ) |
| { |
| // XXX this is arguable, if the exception occured because pNewEntry is |
| // garbage you wouldn't insert it. If the exception occured because the |
| // Collator implementation is garbage then give the user a chance to see |
| // his stuff |
| Insert( pNewEntry, (sal_uLong)0 ); |
| } |
| |
| } |
| |
| return (sal_uInt16)GetPos( pNewEntry ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplEntryList::RemoveEntry( sal_uInt16 nPos ) |
| { |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::Remove( nPos ); |
| if ( pImplEntry ) |
| { |
| if ( !!pImplEntry->maImage ) |
| mnImages--; |
| |
| delete pImplEntry; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplEntryList::FindEntry( const XubString& rString, sal_Bool bSearchMRUArea ) const |
| { |
| sal_uInt16 nEntries = GetEntryCount(); |
| for ( sal_uInt16 n = bSearchMRUArea ? 0 : GetMRUCount(); n < nEntries; n++ ) |
| { |
| ImplEntryType* pImplEntry = GetEntry( n ); |
| String aComp( vcl::I18nHelper::filterFormattingChars( pImplEntry->maStr ) ); |
| if ( aComp == rString ) |
| return n; |
| } |
| return LISTBOX_ENTRY_NOTFOUND; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplEntryList::FindMatchingEntry( const XubString& rStr, sal_uInt16 nStart, sal_Bool bForward, sal_Bool bLazy ) const |
| { |
| sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; |
| sal_uInt16 nEntryCount = GetEntryCount(); |
| if ( !bForward ) |
| nStart++; // wird sofort dekrementiert |
| |
| const vcl::I18nHelper& rI18nHelper = mpWindow->GetSettings().GetLocaleI18nHelper(); |
| for ( sal_uInt16 n = nStart; bForward ? ( n < nEntryCount ) : n; ) |
| { |
| if ( !bForward ) |
| n--; |
| |
| ImplEntryType* pImplEntry = GetEntry( n ); |
| sal_Bool bMatch = bLazy ? rI18nHelper.MatchString( rStr, pImplEntry->maStr ) != 0 : ( rStr.Match( pImplEntry->maStr ) == STRING_MATCH ); |
| if ( bMatch ) |
| { |
| nPos = n; |
| break; |
| } |
| |
| if ( bForward ) |
| n++; |
| } |
| |
| return nPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplEntryList::FindEntry( const void* pData ) const |
| { |
| sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; |
| for ( sal_uInt16 n = GetEntryCount(); n; ) |
| { |
| ImplEntryType* pImplEntry = GetEntry( --n ); |
| if ( pImplEntry->mpUserData == pData ) |
| { |
| nPos = n; |
| break; |
| } |
| } |
| return nPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplEntryList::GetAddedHeight( sal_uInt16 i_nEndIndex, sal_uInt16 i_nBeginIndex, long i_nBeginHeight ) const |
| { |
| long nHeight = i_nBeginHeight; |
| sal_uInt16 nStart = i_nEndIndex > i_nBeginIndex ? i_nBeginIndex : i_nEndIndex; |
| sal_uInt16 nStop = i_nEndIndex > i_nBeginIndex ? i_nEndIndex : i_nBeginIndex; |
| sal_uInt16 nEntryCount = GetEntryCount(); |
| if( nStop != LISTBOX_ENTRY_NOTFOUND && nEntryCount != 0 ) |
| { |
| // sanity check |
| if( nStop > nEntryCount-1 ) |
| nStop = nEntryCount-1; |
| if( nStart > nEntryCount-1 ) |
| nStart = nEntryCount-1; |
| |
| sal_uInt16 nIndex = nStart; |
| while( nIndex != LISTBOX_ENTRY_NOTFOUND && nIndex < nStop ) |
| { |
| nHeight += GetEntryPtr( nIndex )-> mnHeight; |
| nIndex++; |
| } |
| } |
| else |
| nHeight = 0; |
| return i_nEndIndex > i_nBeginIndex ? nHeight : -nHeight; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplEntryList::GetEntryHeight( sal_uInt16 nPos ) const |
| { |
| ImplEntryType* pImplEntry = GetEntry( nPos ); |
| return pImplEntry ? pImplEntry->mnHeight : 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString ImplEntryList::GetEntryText( sal_uInt16 nPos ) const |
| { |
| XubString aEntryText; |
| ImplEntryType* pImplEntry = GetEntry( nPos ); |
| if ( pImplEntry ) |
| aEntryText = pImplEntry->maStr; |
| return aEntryText; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplEntryList::HasEntryImage( sal_uInt16 nPos ) const |
| { |
| sal_Bool bImage = sal_False; |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); |
| if ( pImplEntry ) |
| bImage = !!pImplEntry->maImage; |
| return bImage; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Image ImplEntryList::GetEntryImage( sal_uInt16 nPos ) const |
| { |
| Image aImage; |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); |
| if ( pImplEntry ) |
| aImage = pImplEntry->maImage; |
| return aImage; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplEntryList::SetEntryData( sal_uInt16 nPos, void* pNewData ) |
| { |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); |
| if ( pImplEntry ) |
| pImplEntry->mpUserData = pNewData; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void* ImplEntryList::GetEntryData( sal_uInt16 nPos ) const |
| { |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); |
| return pImplEntry ? pImplEntry->mpUserData : NULL; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplEntryList::SetEntryFlags( sal_uInt16 nPos, long nFlags ) |
| { |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); |
| if ( pImplEntry ) |
| pImplEntry->mnFlags = nFlags; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplEntryList::GetEntryFlags( sal_uInt16 nPos ) const |
| { |
| ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); |
| return pImplEntry ? pImplEntry->mnFlags : 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplEntryList::GetSelectEntryCount() const |
| { |
| sal_uInt16 nSelCount = 0; |
| for ( sal_uInt16 n = GetEntryCount(); n; ) |
| { |
| ImplEntryType* pImplEntry = GetEntry( --n ); |
| if ( pImplEntry->mbIsSelected ) |
| nSelCount++; |
| } |
| return nSelCount; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString ImplEntryList::GetSelectEntry( sal_uInt16 nIndex ) const |
| { |
| return GetEntryText( GetSelectEntryPos( nIndex ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplEntryList::GetSelectEntryPos( sal_uInt16 nIndex ) const |
| { |
| sal_uInt16 nSelEntryPos = LISTBOX_ENTRY_NOTFOUND; |
| sal_uInt16 nSel = 0; |
| sal_uInt16 nEntryCount = GetEntryCount(); |
| |
| for ( sal_uInt16 n = 0; n < nEntryCount; n++ ) |
| { |
| ImplEntryType* pImplEntry = GetEntry( n ); |
| if ( pImplEntry->mbIsSelected ) |
| { |
| if ( nSel == nIndex ) |
| { |
| nSelEntryPos = n; |
| break; |
| } |
| nSel++; |
| } |
| } |
| |
| return nSelEntryPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplEntryList::IsEntrySelected( const XubString& rStr ) const |
| { |
| return IsEntryPosSelected( FindEntry( rStr ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplEntryList::IsEntryPosSelected( sal_uInt16 nIndex ) const |
| { |
| ImplEntryType* pImplEntry = GetEntry( nIndex ); |
| return pImplEntry ? pImplEntry->mbIsSelected : sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| bool ImplEntryList::IsEntrySelectable( sal_uInt16 nPos ) const |
| { |
| ImplEntryType* pImplEntry = GetEntry( nPos ); |
| return pImplEntry ? ((pImplEntry->mnFlags & LISTBOX_ENTRY_FLAG_DISABLE_SELECTION) == 0) : true; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplEntryList::FindFirstSelectable( sal_uInt16 nPos, bool bForward /* = true */ ) |
| { |
| if( IsEntrySelectable( nPos ) ) |
| return nPos; |
| |
| if( bForward ) |
| { |
| for( nPos = nPos + 1; nPos < GetEntryCount(); nPos++ ) |
| { |
| if( IsEntrySelectable( nPos ) ) |
| return nPos; |
| } |
| } |
| else |
| { |
| while( nPos ) |
| { |
| nPos--; |
| if( IsEntrySelectable( nPos ) ) |
| return nPos; |
| } |
| } |
| |
| return LISTBOX_ENTRY_NOTFOUND; |
| } |
| |
| // ======================================================================= |
| |
| ImplListBoxWindow::ImplListBoxWindow( Window* pParent, WinBits nWinStyle ) : |
| Control( pParent, 0 ), |
| maQuickSelectionEngine( *this ) |
| { |
| mpEntryList = new ImplEntryList( this ); |
| |
| mnTop = 0; |
| mnLeft = 0; |
| mnBorder = 1; |
| mnSelectModifier = 0; |
| mnUserDrawEntry = LISTBOX_ENTRY_NOTFOUND; |
| mbTrack = false; |
| mbImgsDiffSz = false; |
| mbTravelSelect = false; |
| mbTrackingSelect = false; |
| mbSelectionChanged = false; |
| mbMouseMoveSelect = false; |
| mbMulti = false; |
| mbStackMode = false; |
| mbGrabFocus = false; |
| mbUserDrawEnabled = false; |
| mbInUserDraw = false; |
| mbReadOnly = false; |
| mbHasFocusRect = false; |
| mbRight = ( nWinStyle & WB_RIGHT ); |
| mbCenter = ( nWinStyle & WB_CENTER ); |
| mbSimpleMode = ( nWinStyle & WB_SIMPLEMODE ); |
| mbSort = ( nWinStyle & WB_SORT ); |
| mbEdgeBlending = false; |
| |
| // pb: #106948# explicit mirroring for calc |
| mbMirroring = false; |
| |
| mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; |
| mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; |
| mnSeparatorPos = LISTBOX_ENTRY_NOTFOUND; |
| meProminentType = PROMINENT_TOP; |
| |
| SetLineColor(); |
| SetTextFillColor(); |
| SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); |
| |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| ImplCalcMetrics(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ImplListBoxWindow::~ImplListBoxWindow() |
| { |
| delete mpEntryList; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ) |
| { |
| ImplInitFieldSettings( this, bFont, bForeground, bBackground ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplCalcMetrics() |
| { |
| mnMaxWidth = 0; |
| mnMaxTxtWidth = 0; |
| mnMaxImgWidth = 0; |
| mnMaxImgTxtWidth= 0; |
| mnMaxImgHeight = 0; |
| |
| mnTextHeight = (sal_uInt16)GetTextHeight(); |
| mnMaxTxtHeight = mnTextHeight + mnBorder; |
| mnMaxHeight = mnMaxTxtHeight; |
| |
| if ( maUserItemSize.Height() > mnMaxHeight ) |
| mnMaxHeight = (sal_uInt16) maUserItemSize.Height(); |
| if ( maUserItemSize.Width() > mnMaxWidth ) |
| mnMaxWidth= (sal_uInt16) maUserItemSize.Width(); |
| |
| for ( sal_uInt16 n = mpEntryList->GetEntryCount(); n; ) |
| { |
| ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( --n ); |
| ImplUpdateEntryMetrics( *pEntry ); |
| } |
| |
| if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryPtr( mnCurrentPos )->mnHeight ); |
| maFocusRect.SetSize( aSz ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::Clear() |
| { |
| mpEntryList->Clear(); |
| |
| mnMaxHeight = mnMaxTxtHeight; |
| mnMaxWidth = 0; |
| mnMaxTxtWidth = 0; |
| mnMaxImgTxtWidth= 0; |
| mnMaxImgWidth = 0; |
| mnMaxImgHeight = 0; |
| mnTop = 0; |
| mnLeft = 0; |
| mbImgsDiffSz = false; |
| ImplClearLayoutData(); |
| |
| mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; |
| maQuickSelectionEngine.Reset(); |
| |
| Invalidate(); |
| } |
| |
| void ImplListBoxWindow::SetUserItemSize( const Size& rSz ) |
| { |
| ImplClearLayoutData(); |
| maUserItemSize = rSz; |
| ImplCalcMetrics(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| struct ImplEntryMetrics |
| { |
| sal_Bool bText; |
| sal_Bool bImage; |
| long nEntryWidth; |
| long nEntryHeight; |
| long nTextWidth; |
| long nImgWidth; |
| long nImgHeight; |
| }; |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType& rEntry ) |
| { |
| ImplEntryMetrics aMetrics; |
| aMetrics.bText = rEntry.maStr.Len() ? sal_True : sal_False; |
| aMetrics.bImage = !!rEntry.maImage; |
| aMetrics.nEntryWidth = 0; |
| aMetrics.nEntryHeight = 0; |
| aMetrics.nTextWidth = 0; |
| aMetrics.nImgWidth = 0; |
| aMetrics.nImgHeight = 0; |
| |
| if ( aMetrics.bText ) |
| { |
| if( (rEntry.mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) |
| { |
| // multiline case |
| Size aCurSize( PixelToLogic( GetSizePixel() ) ); |
| // set the current size to a large number |
| // GetTextRect should shrink it to the actual size |
| aCurSize.Height() = 0x7fffff; |
| Rectangle aTextRect( Point( 0, 0 ), aCurSize ); |
| aTextRect = GetTextRect( aTextRect, rEntry.maStr, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE ); |
| aMetrics.nTextWidth = aTextRect.GetWidth(); |
| if( aMetrics.nTextWidth > mnMaxTxtWidth ) |
| mnMaxTxtWidth = aMetrics.nTextWidth; |
| aMetrics.nEntryWidth = mnMaxTxtWidth; |
| aMetrics.nEntryHeight = aTextRect.GetHeight() + mnBorder; |
| } |
| else |
| { |
| // normal single line case |
| aMetrics.nTextWidth = (sal_uInt16)GetTextWidth( rEntry.maStr ); |
| if( aMetrics.nTextWidth > mnMaxTxtWidth ) |
| mnMaxTxtWidth = aMetrics.nTextWidth; |
| aMetrics.nEntryWidth = mnMaxTxtWidth; |
| aMetrics.nEntryHeight = mnTextHeight + mnBorder; |
| } |
| } |
| if ( aMetrics.bImage ) |
| { |
| Size aImgSz = rEntry.maImage.GetSizePixel(); |
| aMetrics.nImgWidth = (sal_uInt16) CalcZoom( aImgSz.Width() ); |
| aMetrics.nImgHeight = (sal_uInt16) CalcZoom( aImgSz.Height() ); |
| |
| if( mnMaxImgWidth && ( aMetrics.nImgWidth != mnMaxImgWidth ) ) |
| mbImgsDiffSz = true; |
| else if ( mnMaxImgHeight && ( aMetrics.nImgHeight != mnMaxImgHeight ) ) |
| mbImgsDiffSz = true; |
| |
| if( aMetrics.nImgWidth > mnMaxImgWidth ) |
| mnMaxImgWidth = aMetrics.nImgWidth; |
| if( aMetrics.nImgHeight > mnMaxImgHeight ) |
| mnMaxImgHeight = aMetrics.nImgHeight; |
| |
| mnMaxImgTxtWidth = Max( mnMaxImgTxtWidth, aMetrics.nTextWidth ); |
| aMetrics.nEntryHeight = Max( aMetrics.nImgHeight, aMetrics.nEntryHeight ); |
| |
| } |
| if ( IsUserDrawEnabled() || aMetrics.bImage ) |
| { |
| aMetrics.nEntryWidth = Max( aMetrics.nImgWidth, maUserItemSize.Width() ); |
| if ( aMetrics.bText ) |
| aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE; |
| aMetrics.nEntryHeight = Max( Max( mnMaxImgHeight, maUserItemSize.Height() ) + 2, |
| aMetrics.nEntryHeight ); |
| } |
| |
| if ( !aMetrics.bText && !aMetrics.bImage && !IsUserDrawEnabled() ) |
| { |
| // entries which have no (aka an empty) text, and no image, and are not user-drawn, should be |
| // shown nonetheless |
| aMetrics.nEntryHeight = mnTextHeight + mnBorder; |
| } |
| |
| if ( aMetrics.nEntryWidth > mnMaxWidth ) |
| mnMaxWidth = aMetrics.nEntryWidth; |
| if ( aMetrics.nEntryHeight > mnMaxHeight ) |
| mnMaxHeight = aMetrics.nEntryHeight; |
| |
| rEntry.mnHeight = aMetrics.nEntryHeight; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplCallSelect() |
| { |
| if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() ) |
| { |
| // Insert the selected entry as MRU, if not allready first MRU |
| sal_uInt16 nSelected = GetEntryList()->GetSelectEntryPos( 0 ); |
| sal_uInt16 nMRUCount = GetEntryList()->GetMRUCount(); |
| String aSelected = GetEntryList()->GetEntryText( nSelected ); |
| sal_uInt16 nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected, sal_True ); |
| if ( nFirstMatchingEntryPos || !nMRUCount ) |
| { |
| sal_Bool bSelectNewEntry = sal_False; |
| if ( nFirstMatchingEntryPos < nMRUCount ) |
| { |
| RemoveEntry( nFirstMatchingEntryPos ); |
| nMRUCount--; |
| if ( nFirstMatchingEntryPos == nSelected ) |
| bSelectNewEntry = sal_True; |
| } |
| else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() ) |
| { |
| RemoveEntry( nMRUCount - 1 ); |
| nMRUCount--; |
| } |
| |
| ImplClearLayoutData(); |
| |
| ImplEntryType* pNewEntry = new ImplEntryType( aSelected ); |
| pNewEntry->mbIsSelected = bSelectNewEntry; |
| GetEntryList()->InsertEntry( 0, pNewEntry, sal_False ); |
| ImplUpdateEntryMetrics( *pNewEntry ); |
| GetEntryList()->SetMRUCount( ++nMRUCount ); |
| SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); |
| maMRUChangedHdl.Call( NULL ); |
| } |
| } |
| |
| maSelectHdl.Call( NULL ); |
| mbSelectionChanged = false; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBoxWindow::InsertEntry( sal_uInt16 nPos, ImplEntryType* pNewEntry ) |
| { |
| ImplClearLayoutData(); |
| sal_uInt16 nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort ); |
| |
| if( (GetStyle() & WB_WORDBREAK) ) |
| pNewEntry->mnFlags |= LISTBOX_ENTRY_FLAG_MULTILINE; |
| |
| ImplUpdateEntryMetrics( *pNewEntry ); |
| return nNewPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::RemoveEntry( sal_uInt16 nPos ) |
| { |
| ImplClearLayoutData(); |
| mpEntryList->RemoveEntry( nPos ); |
| if( mnCurrentPos >= mpEntryList->GetEntryCount() ) |
| mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; |
| ImplCalcMetrics(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::SetEntryFlags( sal_uInt16 nPos, long nFlags ) |
| { |
| mpEntryList->SetEntryFlags( nPos, nFlags ); |
| ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( nPos ); |
| if( pEntry ) |
| ImplUpdateEntryMetrics( *pEntry ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplShowFocusRect() |
| { |
| if ( mbHasFocusRect ) |
| HideFocus(); |
| ShowFocus( maFocusRect ); |
| mbHasFocusRect = true; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplHideFocusRect() |
| { |
| if ( mbHasFocusRect ) |
| { |
| HideFocus(); |
| mbHasFocusRect = false; |
| } |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const |
| { |
| long nY = mnBorder; |
| |
| sal_uInt16 nSelect = mnTop; |
| const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nSelect ); |
| while( pEntry && rPoint.Y() > pEntry->mnHeight + nY ) |
| { |
| nY += pEntry->mnHeight; |
| pEntry = mpEntryList->GetEntryPtr( ++nSelect ); |
| } |
| if( pEntry == NULL ) |
| nSelect = LISTBOX_ENTRY_NOTFOUND; |
| |
| return nSelect; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplListBoxWindow::IsVisible( sal_uInt16 i_nEntry ) const |
| { |
| sal_Bool bRet = sal_False; |
| |
| if( i_nEntry >= mnTop ) |
| { |
| if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) < |
| PixelToLogic( GetSizePixel() ).Height() ) |
| { |
| bRet = sal_True; |
| } |
| } |
| |
| return bRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBoxWindow::GetLastVisibleEntry() const |
| { |
| sal_uInt16 nPos = mnTop; |
| long nWindowHeight = GetSizePixel().Height(); |
| sal_uInt16 nCount = mpEntryList->GetEntryCount(); |
| long nDiff; |
| for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) ) |
| nPos++; |
| |
| if( nDiff > nWindowHeight && nPos > mnTop ) |
| nPos--; |
| |
| if( nPos >= nCount ) |
| nPos = nCount-1; |
| |
| return nPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::MouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| mbMouseMoveSelect = false; // Nur bis zum ersten MouseButtonDown |
| maQuickSelectionEngine.Reset(); |
| |
| if ( !IsReadOnly() ) |
| { |
| if( rMEvt.GetClicks() == 1 ) |
| { |
| sal_uInt16 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() ); |
| if( nSelect != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) |
| mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 ); |
| else |
| mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; |
| |
| mnCurrentPos = nSelect; |
| mbTrackingSelect = true; |
| sal_Bool bCurPosChange = (mnCurrentPos != nSelect); |
| //SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ); |
| SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ,bCurPosChange); |
| mbTrackingSelect = false; |
| if ( mbGrabFocus ) |
| GrabFocus(); |
| |
| StartTracking( STARTTRACK_SCROLLREPEAT ); |
| } |
| } |
| if( rMEvt.GetClicks() == 2 ) |
| { |
| maDoubleClickHdl.Call( this ); |
| } |
| } |
| else // if ( mbGrabFocus ) |
| { |
| GrabFocus(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::MouseMove( const MouseEvent& rMEvt ) |
| { |
| if ( rMEvt.IsLeaveWindow() ) |
| { |
| if ( mbStackMode && IsMouseMoveSelect() && IsReallyVisible() ) |
| { |
| if ( rMEvt.GetPosPixel().Y() < 0 ) |
| { |
| DeselectAll(); |
| mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; |
| SetTopEntry( 0 ); |
| if ( mbStackMode ) // #87072#, #92323# |
| { |
| mbTravelSelect = true; |
| mnSelectModifier = rMEvt.GetModifier(); |
| ImplCallSelect(); |
| mbTravelSelect = false; |
| } |
| |
| } |
| } |
| } |
| else if ( ( ( !mbMulti && IsMouseMoveSelect() ) || mbStackMode ) && mpEntryList->GetEntryCount() ) |
| { |
| Point aPoint; |
| Rectangle aRect( aPoint, GetOutputSizePixel() ); |
| if( aRect.IsInside( rMEvt.GetPosPixel() ) ) |
| { |
| if ( IsMouseMoveSelect() ) |
| { |
| sal_uInt16 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() ); |
| if( nSelect == LISTBOX_ENTRY_NOTFOUND ) |
| nSelect = mpEntryList->GetEntryCount() - 1; |
| nSelect = Min( nSelect, GetLastVisibleEntry() ); |
| nSelect = Min( nSelect, (sal_uInt16) ( mpEntryList->GetEntryCount() - 1 ) ); |
| // Select only visible Entries with MouseMove, otherwise Tracking... |
| if ( IsVisible( nSelect ) && |
| mpEntryList->IsEntrySelectable( nSelect ) && |
| ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() || ( nSelect != GetEntryList()->GetSelectEntryPos( 0 ) ) ) ) |
| { |
| mbTrackingSelect = true; |
| if ( SelectEntries( nSelect, LET_TRACKING, sal_False, sal_False ) ) |
| { |
| if ( mbStackMode ) // #87072# |
| { |
| mbTravelSelect = true; |
| mnSelectModifier = rMEvt.GetModifier(); |
| ImplCallSelect(); |
| mbTravelSelect = false; |
| } |
| // When list box selection change by mouse move, notity |
| // VCLEVENT_LISTBOX_SELECT vcl event. |
| else |
| { |
| maListItemSelectHdl.Call(NULL); |
| } |
| } |
| mbTrackingSelect = false; |
| } |
| } |
| |
| // Falls der DD-Button gedrueckt wurde und jemand mit gedrueckter |
| // Maustaste in die ListBox faehrt... |
| if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() ) |
| { |
| if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) |
| mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 ); |
| else |
| mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; |
| |
| if ( mbStackMode && ( mpEntryList->GetSelectionAnchor() == LISTBOX_ENTRY_NOTFOUND ) ) |
| mpEntryList->SetSelectionAnchor( 0 ); |
| |
| StartTracking( STARTTRACK_SCROLLREPEAT ); |
| } |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::DeselectAll() |
| { |
| while ( GetEntryList()->GetSelectEntryCount() ) |
| { |
| sal_uInt16 nS = GetEntryList()->GetSelectEntryPos( 0 ); |
| SelectEntry( nS, sal_False ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) |
| { |
| if( (mpEntryList->IsEntryPosSelected( nPos ) != bSelect) && mpEntryList->IsEntrySelectable( nPos ) ) |
| { |
| ImplHideFocusRect(); |
| if( bSelect ) |
| { |
| if( !mbMulti ) |
| { |
| // Selektierten Eintrag deselektieren |
| sal_uInt16 nDeselect = GetEntryList()->GetSelectEntryPos( 0 ); |
| if( nDeselect != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| //SelectEntryPos( nDeselect, sal_False ); |
| GetEntryList()->SelectEntry( nDeselect, sal_False ); |
| if ( IsUpdateMode() && IsReallyVisible() ) |
| ImplPaint( nDeselect, sal_True ); |
| } |
| } |
| mpEntryList->SelectEntry( nPos, sal_True ); |
| mnCurrentPos = nPos; |
| if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() ) |
| { |
| ImplPaint( nPos ); |
| if ( !IsVisible( nPos ) ) |
| { |
| ImplClearLayoutData(); |
| sal_uInt16 nVisibleEntries = GetLastVisibleEntry()-mnTop; |
| if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) ) |
| { |
| Resize(); |
| ShowProminentEntry( nPos ); |
| } |
| else |
| { |
| ShowProminentEntry( nPos ); |
| } |
| } |
| } |
| } |
| else |
| { |
| mpEntryList->SelectEntry( nPos, sal_False ); |
| ImplPaint( nPos, sal_True ); |
| } |
| mbSelectionChanged = true; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplListBoxWindow::SelectEntries( sal_uInt16 nSelect, LB_EVENT_TYPE eLET, sal_Bool bShift, sal_Bool bCtrl, sal_Bool bSelectPosChange /*=FALSE*/ ) |
| { |
| sal_Bool bFocusChanged = sal_False; |
| sal_Bool bSelectionChanged = sal_False; |
| |
| if( IsEnabled() && mpEntryList->IsEntrySelectable( nSelect ) ) |
| { |
| // Hier (Single-ListBox) kann nur ein Eintrag deselektiert werden |
| if( !mbMulti ) |
| { |
| sal_uInt16 nDeselect = mpEntryList->GetSelectEntryPos( 0 ); |
| if( nSelect != nDeselect ) |
| { |
| SelectEntry( nSelect, sal_True ); |
| mpEntryList->SetLastSelected( nSelect ); |
| bFocusChanged = sal_True; |
| bSelectionChanged = sal_True; |
| } |
| } |
| // MultiListBox ohne Modifier |
| else if( mbSimpleMode && !bCtrl && !bShift ) |
| { |
| sal_uInt16 nEntryCount = mpEntryList->GetEntryCount(); |
| for ( sal_uInt16 nPos = 0; nPos < nEntryCount; nPos++ ) |
| { |
| sal_Bool bSelect = nPos == nSelect; |
| if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect ) |
| { |
| SelectEntry( nPos, bSelect ); |
| bFocusChanged = sal_True; |
| bSelectionChanged = sal_True; |
| } |
| } |
| mpEntryList->SetLastSelected( nSelect ); |
| mpEntryList->SetSelectionAnchor( nSelect ); |
| } |
| // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode |
| else if( ( !mbSimpleMode /* && !bShift */ ) || ( (mbSimpleMode && ( bCtrl || bShift )) || mbStackMode ) ) |
| { |
| // Space fuer Selektionswechsel |
| if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) ) |
| { |
| sal_Bool bSelect = ( mbStackMode && IsMouseMoveSelect() ) ? sal_True : !mpEntryList->IsEntryPosSelected( nSelect ); |
| if ( mbStackMode ) |
| { |
| sal_uInt16 n; |
| if ( bSelect ) |
| { |
| // All entries before nSelect must be selected... |
| for ( n = 0; n < nSelect; n++ ) |
| SelectEntry( n, sal_True ); |
| } |
| if ( !bSelect ) |
| { |
| for ( n = nSelect+1; n < mpEntryList->GetEntryCount(); n++ ) |
| SelectEntry( n, sal_False ); |
| } |
| } |
| SelectEntry( nSelect, bSelect ); |
| mpEntryList->SetLastSelected( nSelect ); |
| mpEntryList->SetSelectionAnchor( mbStackMode ? 0 : nSelect ); |
| if ( !mpEntryList->IsEntryPosSelected( nSelect ) ) |
| mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND ); |
| bFocusChanged = sal_True; |
| bSelectionChanged = sal_True; |
| } |
| else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) || |
| ( (bShift||mbStackMode) && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) ) |
| { |
| mnCurrentPos = nSelect; |
| bFocusChanged = sal_True; |
| |
| sal_uInt16 nAnchor = mpEntryList->GetSelectionAnchor(); |
| if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && ( mpEntryList->GetSelectEntryCount() || mbStackMode ) ) |
| { |
| nAnchor = mbStackMode ? 0 : mpEntryList->GetSelectEntryPos( mpEntryList->GetSelectEntryCount() - 1 ); |
| } |
| if( nAnchor != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| // Alle Eintraege vom Anchor bis nSelect muessen selektiert sein |
| sal_uInt16 nStart = Min( nSelect, nAnchor ); |
| sal_uInt16 nEnd = Max( nSelect, nAnchor ); |
| for ( sal_uInt16 n = nStart; n <= nEnd; n++ ) |
| { |
| if ( !mpEntryList->IsEntryPosSelected( n ) ) |
| { |
| SelectEntry( n, sal_True ); |
| bSelectionChanged = sal_True; |
| } |
| } |
| |
| // Ggf. muss noch was deselektiert werden... |
| sal_uInt16 nLast = mpEntryList->GetLastSelected(); |
| if ( nLast != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| if ( ( nLast > nSelect ) && ( nLast > nAnchor ) ) |
| { |
| for ( sal_uInt16 n = nSelect+1; n <= nLast; n++ ) |
| { |
| if ( mpEntryList->IsEntryPosSelected( n ) ) |
| { |
| SelectEntry( n, sal_False ); |
| bSelectionChanged = sal_True; |
| } |
| } |
| } |
| else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) ) |
| { |
| for ( sal_uInt16 n = nLast; n < nSelect; n++ ) |
| { |
| if ( mpEntryList->IsEntryPosSelected( n ) ) |
| { |
| SelectEntry( n, sal_False ); |
| bSelectionChanged = sal_True; |
| } |
| } |
| } |
| } |
| mpEntryList->SetLastSelected( nSelect ); |
| } |
| } |
| else if( eLET != LET_TRACKING ) |
| { |
| ImplHideFocusRect(); |
| ImplPaint( nSelect, sal_True ); |
| bFocusChanged = sal_True; |
| } |
| } |
| else if( bShift ) |
| { |
| bFocusChanged = sal_True; |
| } |
| |
| if( bSelectionChanged ) |
| mbSelectionChanged = true; |
| |
| if( bFocusChanged ) |
| { |
| long nHeightDiff = mpEntryList->GetAddedHeight( nSelect, mnTop, 0 ); |
| maFocusRect.SetPos( Point( 0, nHeightDiff ) ); |
| Size aSz( maFocusRect.GetWidth(), |
| mpEntryList->GetEntryHeight( nSelect ) ); |
| maFocusRect.SetSize( aSz ); |
| if( HasFocus() ) |
| ImplShowFocusRect(); |
| if (bSelectPosChange) |
| { |
| maFocusHdl.Call(reinterpret_cast<void*>(nSelect)); |
| } |
| } |
| ImplClearLayoutData(); |
| } |
| return bSelectionChanged; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) |
| { |
| Point aPoint; |
| Rectangle aRect( aPoint, GetOutputSizePixel() ); |
| sal_Bool bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ); |
| |
| if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp |
| { |
| if ( bInside && !rTEvt.IsTrackingCanceled() ) |
| { |
| mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); |
| ImplCallSelect(); |
| } |
| else |
| { |
| maCancelHdl.Call( NULL ); |
| if ( !mbMulti ) |
| { |
| mbTrackingSelect = true; |
| SelectEntry( mnTrackingSaveSelection, sal_True ); |
| mbTrackingSelect = false; |
| if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); |
| maFocusRect.SetPos( Point( 0, nHeightDiff ) ); |
| Size aSz( maFocusRect.GetWidth(), |
| mpEntryList->GetEntryHeight( mnCurrentPos ) ); |
| maFocusRect.SetSize( aSz ); |
| ImplShowFocusRect(); |
| } |
| } |
| } |
| |
| mbTrack = false; |
| } |
| else |
| { |
| sal_Bool bTrackOrQuickClick = mbTrack; |
| if( !mbTrack ) |
| { |
| if ( bInside ) |
| { |
| mbTrack = true; |
| } |
| |
| // Folgender Fall tritt nur auf, wenn man ganz kurz die Maustaste drueckt |
| if( rTEvt.IsTrackingEnded() && mbTrack ) |
| { |
| bTrackOrQuickClick = sal_True; |
| mbTrack = false; |
| } |
| } |
| |
| if( bTrackOrQuickClick ) |
| { |
| MouseEvent aMEvt = rTEvt.GetMouseEvent(); |
| Point aPt( aMEvt.GetPosPixel() ); |
| sal_Bool bShift = aMEvt.IsShift(); |
| sal_Bool bCtrl = aMEvt.IsMod1(); |
| |
| sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; |
| if( aPt.Y() < 0 ) |
| { |
| if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0; |
| if( nSelect < mnTop ) |
| SetTopEntry( mnTop-1 ); |
| } |
| } |
| else if( aPt.Y() > GetOutputSizePixel().Height() ) |
| { |
| if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = Min( (sal_uInt16)(mnCurrentPos+1), (sal_uInt16)(mpEntryList->GetEntryCount()-1) ); |
| if( nSelect >= GetLastVisibleEntry() ) |
| SetTopEntry( mnTop+1 ); |
| } |
| } |
| else |
| { |
| nSelect = (sal_uInt16) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (sal_uInt16) mnTop; |
| nSelect = Min( nSelect, GetLastVisibleEntry() ); |
| nSelect = Min( nSelect, (sal_uInt16) ( mpEntryList->GetEntryCount() - 1 ) ); |
| } |
| |
| if ( bInside ) |
| { |
| if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() ) |
| { |
| mbTrackingSelect = true; |
| if ( SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ) ) |
| { |
| if ( mbStackMode ) // #87734# (#87072#) |
| { |
| mbTravelSelect = true; |
| mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); |
| ImplCallSelect(); |
| mbTravelSelect = false; |
| } |
| } |
| mbTrackingSelect = false; |
| } |
| } |
| else |
| { |
| if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) |
| { |
| mbTrackingSelect = true; |
| SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), sal_False ); |
| mbTrackingSelect = false; |
| } |
| else if ( mbStackMode ) |
| { |
| if ( ( rTEvt.GetMouseEvent().GetPosPixel().X() > 0 ) && ( rTEvt.GetMouseEvent().GetPosPixel().X() < aRect.Right() ) ) |
| { |
| if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) || ( rTEvt.GetMouseEvent().GetPosPixel().Y() > GetOutputSizePixel().Height() ) ) |
| { |
| sal_Bool bSelectionChanged = sal_False; |
| if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) |
| && !mnCurrentPos ) |
| { |
| if ( mpEntryList->IsEntryPosSelected( 0 ) ) |
| { |
| SelectEntry( 0, sal_False ); |
| bSelectionChanged = sal_True; |
| nSelect = LISTBOX_ENTRY_NOTFOUND; |
| |
| } |
| } |
| else |
| { |
| mbTrackingSelect = true; |
| bSelectionChanged = SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ); |
| mbTrackingSelect = false; |
| } |
| |
| if ( bSelectionChanged ) |
| { |
| mbSelectionChanged = true; |
| mbTravelSelect = true; |
| mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); |
| ImplCallSelect(); |
| mbTravelSelect = false; |
| } |
| } |
| } |
| } |
| } |
| mnCurrentPos = nSelect; |
| if ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| ImplHideFocusRect(); |
| } |
| else |
| { |
| long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); |
| maFocusRect.SetPos( Point( 0, nHeightDiff ) ); |
| Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); |
| maFocusRect.SetSize( aSz ); |
| ImplShowFocusRect(); |
| } |
| } |
| } |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::KeyInput( const KeyEvent& rKEvt ) |
| { |
| if( !ProcessKeyInput( rKEvt ) ) |
| Control::KeyInput( rKEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| #define IMPL_SELECT_NODIRECTION 0 |
| #define IMPL_SELECT_UP 1 |
| #define IMPL_SELECT_DOWN 2 |
| |
| sal_Bool ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) |
| { |
| // zu selektierender Eintrag |
| sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; |
| LB_EVENT_TYPE eLET = LET_KEYMOVE; |
| |
| KeyCode aKeyCode = rKEvt.GetKeyCode(); |
| |
| sal_Bool bShift = aKeyCode.IsShift(); |
| sal_Bool bCtrl = aKeyCode.IsMod1() || aKeyCode.IsMod3(); |
| sal_Bool bMod2 = aKeyCode.IsMod2(); |
| sal_Bool bDone = sal_False; |
| |
| switch( aKeyCode.GetCode() ) |
| { |
| case KEY_UP: |
| { |
| if ( IsReadOnly() ) |
| { |
| if ( GetTopEntry() ) |
| SetTopEntry( GetTopEntry()-1 ); |
| } |
| else if ( !bMod2 ) |
| { |
| if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mpEntryList->FindFirstSelectable( 0, true ); |
| } |
| else if ( mnCurrentPos ) |
| { |
| // search first selectable above the current position |
| nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos - 1, false ); |
| } |
| |
| if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) ) |
| SetTopEntry( mnTop-1 ); |
| |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_DOWN: |
| { |
| if ( IsReadOnly() ) |
| { |
| SetTopEntry( GetTopEntry()+1 ); |
| } |
| else if ( !bMod2 ) |
| { |
| if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mpEntryList->FindFirstSelectable( 0, true ); |
| } |
| else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) |
| { |
| // search first selectable below the current position |
| nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1, true ); |
| } |
| |
| if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) ) |
| SetTopEntry( mnTop+1 ); |
| |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_PAGEUP: |
| { |
| if ( IsReadOnly() ) |
| { |
| sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop +1; |
| SetTopEntry( ( mnTop > nCurVis ) ? |
| (mnTop-nCurVis) : 0 ); |
| } |
| else if ( !bCtrl && !bMod2 ) |
| { |
| if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mpEntryList->FindFirstSelectable( 0, true ); |
| } |
| else if ( mnCurrentPos ) |
| { |
| if( mnCurrentPos == mnTop ) |
| { |
| sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop +1; |
| SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 ); |
| } |
| |
| // find first selectable starting from mnTop looking foreward |
| nSelect = mpEntryList->FindFirstSelectable( mnTop, true ); |
| } |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_PAGEDOWN: |
| { |
| if ( IsReadOnly() ) |
| { |
| SetTopEntry( GetLastVisibleEntry() ); |
| } |
| else if ( !bCtrl && !bMod2 ) |
| { |
| if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mpEntryList->FindFirstSelectable( 0, true ); |
| } |
| else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) |
| { |
| sal_uInt16 nCount = mpEntryList->GetEntryCount(); |
| sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop; |
| sal_uInt16 nTmp = Min( nCurVis, nCount ); |
| nTmp += mnTop - 1; |
| if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 ) |
| { |
| long nTmp2 = Min( (long)(nCount-nCurVis), (long)((long)mnTop+(long)nCurVis-1) ); |
| nTmp2 = Max( (long)0 , nTmp2 ); |
| nTmp = (sal_uInt16)(nTmp2+(nCurVis-1) ); |
| SetTopEntry( (sal_uInt16)nTmp2 ); |
| } |
| // find first selectable starting from nTmp looking backwards |
| nSelect = mpEntryList->FindFirstSelectable( nTmp, false ); |
| } |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_HOME: |
| { |
| if ( IsReadOnly() ) |
| { |
| SetTopEntry( 0 ); |
| } |
| else if ( !bCtrl && !bMod2 ) |
| { |
| if ( mnCurrentPos ) |
| { |
| nSelect = mpEntryList->FindFirstSelectable( mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND, true ); |
| if( mnTop != 0 ) |
| SetTopEntry( 0 ); |
| |
| bDone = sal_True; |
| } |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_END: |
| { |
| if ( IsReadOnly() ) |
| { |
| SetTopEntry( 0xFFFF ); |
| } |
| else if ( !bCtrl && !bMod2 ) |
| { |
| if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mpEntryList->FindFirstSelectable( 0, true ); |
| } |
| else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) |
| { |
| sal_uInt16 nCount = mpEntryList->GetEntryCount(); |
| nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false ); |
| sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop + 1; |
| if( nCount > nCurVis ) |
| SetTopEntry( nCount - nCurVis ); |
| } |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_LEFT: |
| { |
| if ( !bCtrl && !bMod2 ) |
| { |
| ScrollHorz( -HORZ_SCROLL ); |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_RIGHT: |
| { |
| if ( !bCtrl && !bMod2 ) |
| { |
| ScrollHorz( HORZ_SCROLL ); |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_RETURN: |
| { |
| if ( !bMod2 && !IsReadOnly() ) |
| { |
| mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); |
| ImplCallSelect(); |
| bDone = sal_False; // RETURN nicht abfangen. |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_SPACE: |
| { |
| if ( !bMod2 && !IsReadOnly() ) |
| { |
| if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) || mbStackMode ) ) |
| { |
| nSelect = mnCurrentPos; |
| eLET = LET_KEYSPACE; |
| } |
| bDone = sal_True; |
| } |
| maQuickSelectionEngine.Reset(); |
| } |
| break; |
| |
| case KEY_A: |
| { |
| if( bCtrl && mbMulti ) |
| { |
| // paint only once |
| sal_Bool bUpdates = IsUpdateMode(); |
| SetUpdateMode( sal_False ); |
| |
| sal_uInt16 nEntryCount = mpEntryList->GetEntryCount(); |
| for( sal_uInt16 i = 0; i < nEntryCount; i++ ) |
| SelectEntry( i, sal_True ); |
| |
| // restore update mode |
| SetUpdateMode( bUpdates ); |
| Invalidate(); |
| |
| maQuickSelectionEngine.Reset(); |
| |
| bDone = sal_True; |
| break; |
| } |
| } |
| // fall through intentional |
| default: |
| { |
| if ( !IsReadOnly() ) |
| { |
| bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt ); |
| } |
| } |
| break; |
| } |
| |
| if ( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) |
| && ( ( !mpEntryList->IsEntryPosSelected( nSelect ) ) |
| || ( eLET == LET_KEYSPACE ) |
| ) |
| ) |
| { |
| DBG_ASSERT( !mpEntryList->IsEntryPosSelected( nSelect ) || mbMulti, "ImplListBox: Selecting same Entry" ); |
| if( nSelect >= mpEntryList->GetEntryCount() ) |
| nSelect = mpEntryList->GetEntryCount()-1; |
| sal_Bool bCurPosChange = (mnCurrentPos != nSelect); |
| mnCurrentPos = nSelect; |
| //if ( SelectEntries( nSelect, eLET, bShift, bCtrl ) ) |
| if(SelectEntries( nSelect, eLET, bShift, bCtrl ,bCurPosChange)) |
| { |
| mbTravelSelect = true; |
| mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); |
| ImplCallSelect(); |
| mbTravelSelect = false; |
| } |
| } |
| |
| return bDone; |
| } |
| |
| // ----------------------------------------------------------------------- |
| namespace |
| { |
| static ::vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_uInt16 _nPos, String& _out_entryText ) |
| { |
| OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" ); |
| sal_uInt16 nEntryCount( _rList.GetEntryCount() ); |
| if ( _nPos >= nEntryCount ) |
| _nPos = 0; |
| _out_entryText = _rList.GetEntryText( _nPos ); |
| |
| // ::vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based |
| // => normalize |
| return reinterpret_cast< ::vcl::StringEntryIdentifier >( _nPos + 1 ); |
| } |
| |
| static sal_uInt16 lcl_getEntryPos( ::vcl::StringEntryIdentifier _entry ) |
| { |
| // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL |
| return static_cast< sal_uInt16 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| ::vcl::StringEntryIdentifier ImplListBoxWindow::CurrentEntry( String& _out_entryText ) const |
| { |
| return lcl_getEntry( *GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos + 1, _out_entryText ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| ::vcl::StringEntryIdentifier ImplListBoxWindow::NextEntry( ::vcl::StringEntryIdentifier _currentEntry, String& _out_entryText ) const |
| { |
| sal_uInt16 nNextPos = lcl_getEntryPos( _currentEntry ) + 1; |
| return lcl_getEntry( *GetEntryList(), nNextPos, _out_entryText ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| void ImplListBoxWindow::SelectEntry( ::vcl::StringEntryIdentifier _entry ) |
| { |
| sal_uInt16 nSelect = lcl_getEntryPos( _entry ); |
| if ( mpEntryList->IsEntryPosSelected( nSelect ) ) |
| { |
| // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted |
| // to select the given entry by typing its starting letters. No need to act. |
| return; |
| } |
| |
| // normalize |
| OSL_ENSURE( nSelect < mpEntryList->GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" ); |
| if( nSelect >= mpEntryList->GetEntryCount() ) |
| nSelect = mpEntryList->GetEntryCount()-1; |
| |
| // make visible |
| ShowProminentEntry( nSelect ); |
| |
| // actually select |
| mnCurrentPos = nSelect; |
| if ( SelectEntries( nSelect, LET_KEYMOVE, sal_False, sal_False ) ) |
| { |
| mbTravelSelect = true; |
| mnSelectModifier = 0; |
| ImplCallSelect(); |
| mbTravelSelect = false; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplPaint( sal_uInt16 nPos, sal_Bool bErase, bool bLayout ) |
| { |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| |
| const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); |
| if( ! pEntry ) |
| return; |
| |
| long nWidth = GetOutputSizePixel().Width(); |
| long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); |
| Rectangle aRect( Point( 0, nY ), Size( nWidth, pEntry->mnHeight ) ); |
| |
| if( ! bLayout ) |
| { |
| if( mpEntryList->IsEntryPosSelected( nPos ) ) |
| { |
| SetTextColor( !IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor() ); |
| SetFillColor( rStyleSettings.GetHighlightColor() ); |
| SetTextFillColor( rStyleSettings.GetHighlightColor() ); |
| DrawRect( aRect ); |
| } |
| else |
| { |
| ImplInitSettings( sal_False, sal_True, sal_False ); |
| if( !IsEnabled() ) |
| SetTextColor( rStyleSettings.GetDisableColor() ); |
| SetTextFillColor(); |
| if( bErase ) |
| Erase( aRect ); |
| } |
| } |
| |
| if ( IsUserDrawEnabled() ) |
| { |
| mbInUserDraw = true; |
| mnUserDrawEntry = nPos; |
| aRect.Left() -= mnLeft; |
| if ( nPos < GetEntryList()->GetMRUCount() ) |
| nPos = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos ) ); |
| nPos = sal::static_int_cast<sal_uInt16>(nPos - GetEntryList()->GetMRUCount()); |
| UserDrawEvent aUDEvt( this, aRect, nPos, 0 ); |
| maUserDrawHdl.Call( &aUDEvt ); |
| mbInUserDraw = false; |
| } |
| else |
| { |
| DrawEntry( nPos, sal_True, sal_True, sal_False, bLayout ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::DrawEntry( sal_uInt16 nPos, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) |
| { |
| const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); |
| if( ! pEntry ) |
| return; |
| |
| // Bei Aenderungen in dieser Methode ggf. auch ImplWin::DrawEntry() anpassen. |
| |
| if ( mbInUserDraw ) |
| nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU |
| |
| long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); |
| Size aImgSz; |
| |
| if( bDrawImage && mpEntryList->HasImages() && !bLayout ) |
| { |
| Image aImage = mpEntryList->GetEntryImage( nPos ); |
| if( !!aImage ) |
| { |
| aImgSz = aImage.GetSizePixel(); |
| Point aPtImg( mnBorder - mnLeft, nY + ( ( pEntry->mnHeight - aImgSz.Height() ) / 2 ) ); |
| |
| // pb: #106948# explicit mirroring for calc |
| if ( mbMirroring ) |
| // right aligned |
| aPtImg.X() = mnMaxWidth + mnBorder - aImgSz.Width() - mnLeft; |
| |
| if ( !IsZoom() ) |
| { |
| DrawImage( aPtImg, aImage ); |
| } |
| else |
| { |
| aImgSz.Width() = CalcZoom( aImgSz.Width() ); |
| aImgSz.Height() = CalcZoom( aImgSz.Height() ); |
| DrawImage( aPtImg, aImgSz, aImage ); |
| } |
| |
| const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
| const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0); |
| |
| if(nEdgeBlendingPercent && aImgSz.Width() && aImgSz.Height()) |
| { |
| const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); |
| const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); |
| const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); |
| const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight)); |
| |
| if(!aBlendFrame.IsEmpty()) |
| { |
| DrawBitmapEx(aPtImg, aBlendFrame); |
| } |
| } |
| } |
| } |
| |
| if( bDrawText ) |
| { |
| MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; |
| String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; |
| XubString aStr( mpEntryList->GetEntryText( nPos ) ); |
| if ( aStr.Len() ) |
| { |
| long nMaxWidth = Max( static_cast< long >( mnMaxWidth ), |
| GetOutputSizePixel().Width() - 2*mnBorder ); |
| // a multiline entry should only be as wide a the window |
| if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) |
| nMaxWidth = GetOutputSizePixel().Width() - 2*mnBorder; |
| |
| Rectangle aTextRect( Point( mnBorder - mnLeft, nY ), |
| Size( nMaxWidth, pEntry->mnHeight ) ); |
| |
| if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) ) |
| { |
| long nImageWidth = Max( mnMaxImgWidth, maUserItemSize.Width() ); |
| aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE; |
| } |
| |
| if( bLayout ) |
| mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() ); |
| |
| // pb: #106948# explicit mirroring for calc |
| if ( mbMirroring ) |
| { |
| // right aligned |
| aTextRect.Left() = nMaxWidth + mnBorder - GetTextWidth( aStr ) - mnLeft; |
| if ( aImgSz.Width() > 0 ) |
| aTextRect.Left() -= ( aImgSz.Width() + IMG_TXT_DISTANCE ); |
| } |
| |
| sal_uInt16 nDrawStyle = ImplGetTextStyle(); |
| if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) |
| nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS; |
| if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_DRAW_DISABLED) ) |
| nDrawStyle |= TEXT_DRAW_DISABLE; |
| |
| DrawText( aTextRect, aStr, nDrawStyle, pVector, pDisplayText ); |
| } |
| } |
| |
| if( !bLayout ) |
| { |
| if ( ( mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND ) && |
| ( ( nPos == mnSeparatorPos ) || ( nPos == mnSeparatorPos+1 ) ) ) |
| { |
| Color aOldLineColor( GetLineColor() ); |
| SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY ); |
| Point aStartPos( 0, nY ); |
| if ( nPos == mnSeparatorPos ) |
| aStartPos.Y() += pEntry->mnHeight-1; |
| Point aEndPos( aStartPos ); |
| aEndPos.X() = GetOutputSizePixel().Width(); |
| DrawLine( aStartPos, aEndPos ); |
| SetLineColor( aOldLineColor ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::FillLayoutData() const |
| { |
| mpControlData->mpLayoutData = new vcl::ControlLayoutData(); |
| const_cast<ImplListBoxWindow*>(this)-> |
| ImplDoPaint( Rectangle( Point( 0, 0 ), GetOutputSize() ), true ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ImplDoPaint( const Rectangle& rRect, bool bLayout ) |
| { |
| sal_uInt16 nCount = mpEntryList->GetEntryCount(); |
| |
| sal_Bool bShowFocusRect = mbHasFocusRect; |
| if ( mbHasFocusRect && ! bLayout ) |
| ImplHideFocusRect(); |
| |
| long nY = 0; // + mnBorder; |
| long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; |
| |
| for( sal_uInt16 i = (sal_uInt16)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ ) |
| { |
| const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( i ); |
| if( nY + pEntry->mnHeight >= rRect.Top() && |
| nY <= rRect.Bottom() + mnMaxHeight ) |
| { |
| ImplPaint( i, sal_False, bLayout ); |
| } |
| nY += pEntry->mnHeight; |
| } |
| |
| long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); |
| maFocusRect.SetPos( Point( 0, nHeightDiff ) ); |
| Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); |
| maFocusRect.SetSize( aSz ); |
| if( HasFocus() && bShowFocusRect && !bLayout ) |
| ImplShowFocusRect(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::Paint( const Rectangle& rRect ) |
| { |
| ImplDoPaint( rRect ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBoxWindow::GetDisplayLineCount() const |
| { |
| // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE |
| |
| sal_uInt16 nCount = mpEntryList->GetEntryCount(); |
| long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; |
| sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight ); |
| if( nEntries > nCount-mnTop ) |
| nEntries = nCount-mnTop; |
| |
| return nEntries; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::Resize() |
| { |
| Control::Resize(); |
| |
| sal_Bool bShowFocusRect = mbHasFocusRect; |
| if ( bShowFocusRect ) |
| ImplHideFocusRect(); |
| |
| if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); |
| maFocusRect.SetSize( aSz ); |
| } |
| |
| if ( bShowFocusRect ) |
| ImplShowFocusRect(); |
| |
| ImplClearLayoutData(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::GetFocus() |
| { |
| sal_uInt16 nPos = mnCurrentPos; |
| if ( nPos == LISTBOX_ENTRY_NOTFOUND ) |
| nPos = 0; |
| long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop, 0 ); |
| maFocusRect.SetPos( Point( 0, nHeightDiff ) ); |
| Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) ); |
| maFocusRect.SetSize( aSz ); |
| ImplShowFocusRect(); |
| Control::GetFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::LoseFocus() |
| { |
| ImplHideFocusRect(); |
| Control::LoseFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| /* |
| void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt ) |
| { |
| if ( rHEvt.GetMode() & HELPMODE_BALLOON ) |
| Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), String() ); |
| |
| Window::RequestHelp( rHEvt ); |
| } |
| */ |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::SetTopEntry( sal_uInt16 nTop ) |
| { |
| if( mpEntryList->GetEntryCount() == 0 ) |
| return; |
| |
| long nWHeight = PixelToLogic( GetSizePixel() ).Height(); |
| |
| sal_uInt16 nLastEntry = mpEntryList->GetEntryCount()-1; |
| if( nTop > nLastEntry ) |
| nTop = nLastEntry; |
| const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry ); |
| while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->mnHeight <= nWHeight ) |
| nTop--; |
| |
| if ( nTop != mnTop ) |
| { |
| ImplClearLayoutData(); |
| long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 ); |
| Update(); |
| ImplHideFocusRect(); |
| mnTop = nTop; |
| Scroll( 0, nDiff ); |
| Update(); |
| if( HasFocus() ) |
| ImplShowFocusRect(); |
| maScrollHdl.Call( this ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ShowProminentEntry( sal_uInt16 nEntryPos ) |
| { |
| if( meProminentType == PROMINENT_MIDDLE ) |
| { |
| sal_uInt16 nPos = nEntryPos; |
| long nWHeight = PixelToLogic( GetSizePixel() ).Height(); |
| while( nEntryPos > 0 && mpEntryList->GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 ) |
| nEntryPos--; |
| } |
| SetTopEntry( nEntryPos ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::SetLeftIndent( long n ) |
| { |
| ScrollHorz( n - mnLeft ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::ScrollHorz( long n ) |
| { |
| long nDiff = 0; |
| if ( n > 0 ) |
| { |
| long nWidth = GetOutputSizePixel().Width(); |
| if( ( mnMaxWidth - mnLeft + n ) > nWidth ) |
| nDiff = n; |
| } |
| else if ( n < 0 ) |
| { |
| if( mnLeft ) |
| { |
| long nAbs = -n; |
| nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft ); |
| } |
| } |
| |
| if ( nDiff ) |
| { |
| ImplClearLayoutData(); |
| mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff); |
| Update(); |
| ImplHideFocusRect(); |
| Scroll( -nDiff, 0 ); |
| Update(); |
| if( HasFocus() ) |
| ImplShowFocusRect(); |
| maScrollHdl.Call( this ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size ImplListBoxWindow::CalcSize( sal_uInt16 nMaxLines ) const |
| { |
| // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE |
| |
| Size aSz; |
| // sal_uInt16 nL = Min( nMaxLines, mpEntryList->GetEntryCount() ); |
| aSz.Height() = nMaxLines * mnMaxHeight; |
| aSz.Width() = mnMaxWidth + 2*mnBorder; |
| return aSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle ImplListBoxWindow::GetBoundingRectangle( sal_uInt16 nItem ) const |
| { |
| const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem ); |
| Size aSz( GetSizePixel().Width(), pEntry ? pEntry->mnHeight : GetEntryHeight() ); |
| //long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) - mpEntryList->GetAddedHeight( GetTopEntry() ); |
| long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) + GetEntryList()->GetMRUCount()*GetEntryHeight(); |
| Rectangle aRect( Point( 0, nY ), aSz ); |
| return aRect; |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::StateChanged( StateChangedType nType ) |
| { |
| Control::StateChanged( nType ); |
| |
| if ( nType == STATE_CHANGE_ZOOM ) |
| { |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| ImplCalcMetrics(); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_UPDATEMODE ) |
| { |
| if ( IsUpdateMode() && IsReallyVisible() ) |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFONT ) |
| { |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| ImplCalcMetrics(); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) |
| { |
| ImplInitSettings( sal_False, sal_True, sal_False ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) |
| { |
| ImplInitSettings( sal_False, sal_False, sal_True ); |
| Invalidate(); |
| } |
| ImplClearLayoutData(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Control::DataChanged( rDCEvt ); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || |
| (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || |
| ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) |
| { |
| ImplClearLayoutData(); |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| ImplCalcMetrics(); |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBoxWindow::ImplGetTextStyle() const |
| { |
| sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; |
| |
| if ( mpEntryList->HasImages() ) |
| nTextStyle |= TEXT_DRAW_LEFT; |
| else if ( mbCenter ) |
| nTextStyle |= TEXT_DRAW_CENTER; |
| else if ( mbRight ) |
| nTextStyle |= TEXT_DRAW_RIGHT; |
| else |
| nTextStyle |= TEXT_DRAW_LEFT; |
| |
| return nTextStyle; |
| } |
| |
| // ======================================================================= |
| |
| ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) : |
| Control( pParent, nWinStyle ), |
| maLBWindow( this, nWinStyle&(~WB_BORDER) ) |
| { |
| // for native widget rendering we must be able to detect this window type |
| SetType( WINDOW_LISTBOXWINDOW ); |
| |
| mpVScrollBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG ); |
| mpHScrollBar = new ScrollBar( this, WB_HSCROLL | WB_DRAG ); |
| mpScrollBarBox = new ScrollBarBox( this ); |
| |
| Link aLink( LINK( this, ImplListBox, ScrollBarHdl ) ); |
| mpVScrollBar->SetScrollHdl( aLink ); |
| mpHScrollBar->SetScrollHdl( aLink ); |
| |
| mbVScroll = false; |
| mbHScroll = false; |
| mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL ); |
| mbEdgeBlending = false; |
| |
| maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) ); |
| maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) ); |
| maLBWindow.SetEdgeBlending(GetEdgeBlending()); |
| maLBWindow.Show(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ImplListBox::~ImplListBox() |
| { |
| delete mpHScrollBar; |
| delete mpVScrollBar; |
| delete mpScrollBarBox; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::Clear() |
| { |
| maLBWindow.Clear(); |
| if ( GetEntryList()->GetMRUCount() ) |
| { |
| maLBWindow.GetEntryList()->SetMRUCount( 0 ); |
| maLBWindow.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND ); |
| } |
| mpVScrollBar->SetThumbPos( 0 ); |
| mpHScrollBar->SetThumbPos( 0 ); |
| StateChanged( STATE_CHANGE_DATA ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr ) |
| { |
| ImplEntryType* pNewEntry = new ImplEntryType( rStr ); |
| sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); |
| StateChanged( STATE_CHANGE_DATA ); |
| return nNewPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const Image& rImage ) |
| { |
| ImplEntryType* pNewEntry = new ImplEntryType( rImage ); |
| sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); |
| StateChanged( STATE_CHANGE_DATA ); |
| return nNewPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr, const Image& rImage ) |
| { |
| ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage ); |
| sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); |
| StateChanged( STATE_CHANGE_DATA ); |
| return nNewPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::RemoveEntry( sal_uInt16 nPos ) |
| { |
| maLBWindow.RemoveEntry( nPos ); |
| StateChanged( STATE_CHANGE_DATA ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags ) |
| { |
| maLBWindow.SetEntryFlags( nPos, nFlags ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplListBox::GetEntryFlags( sal_uInt16 nPos ) const |
| { |
| return maLBWindow.GetEntryList()->GetEntryFlags( nPos ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) |
| { |
| maLBWindow.SelectEntry( nPos, bSelect ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::SetNoSelection() |
| { |
| maLBWindow.DeselectAll(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::GetFocus() |
| { |
| maLBWindow.GrabFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Window* ImplListBox::GetPreferredKeyInputWindow() |
| { |
| return &maLBWindow; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::Resize() |
| { |
| Control::Resize(); |
| ImplResizeControls(); |
| ImplCheckScrollBars(); |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ImplListBox, MRUChanged, void*, EMPTYARG ) |
| { |
| StateChanged( STATE_CHANGE_DATA ); |
| return 1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ImplListBox, LBWindowScrolled, void*, EMPTYARG ) |
| { |
| long nSet = GetTopEntry(); |
| if( nSet > mpVScrollBar->GetRangeMax() ) |
| mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() ); |
| mpVScrollBar->SetThumbPos( GetTopEntry() ); |
| |
| mpHScrollBar->SetThumbPos( GetLeftIndent() ); |
| |
| maScrollHdl.Call( this ); |
| |
| return 1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB ) |
| { |
| sal_uInt16 nPos = (sal_uInt16) pSB->GetThumbPos(); |
| if( pSB == mpVScrollBar ) |
| SetTopEntry( nPos ); |
| else if( pSB == mpHScrollBar ) |
| SetLeftIndent( nPos ); |
| |
| return 1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::ImplCheckScrollBars() |
| { |
| sal_Bool bArrange = sal_False; |
| |
| Size aOutSz = GetOutputSizePixel(); |
| sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); |
| sal_uInt16 nMaxVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); |
| |
| // vert. ScrollBar |
| if( nEntries > nMaxVisEntries ) |
| { |
| if( !mbVScroll ) |
| bArrange = sal_True; |
| mbVScroll = true; |
| |
| // Ueberpruefung des rausgescrollten Bereichs |
| if( GetEntryList()->GetSelectEntryCount() == 1 && |
| GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) |
| ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); |
| else |
| SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... |
| } |
| else |
| { |
| if( mbVScroll ) |
| bArrange = sal_True; |
| mbVScroll = false; |
| SetTopEntry( 0 ); |
| } |
| |
| // horz. ScrollBar |
| if( mbAutoHScroll ) |
| { |
| long nWidth = (sal_uInt16) aOutSz.Width(); |
| if ( mbVScroll ) |
| nWidth -= mpVScrollBar->GetSizePixel().Width(); |
| |
| long nMaxWidth = GetMaxEntryWidth(); |
| if( nWidth < nMaxWidth ) |
| { |
| if( !mbHScroll ) |
| bArrange = sal_True; |
| mbHScroll = true; |
| |
| if ( !mbVScroll ) // ggf. brauchen wir jetzt doch einen |
| { |
| nMaxVisEntries = (sal_uInt16) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() ); |
| if( nEntries > nMaxVisEntries ) |
| { |
| bArrange = sal_True; |
| mbVScroll = true; |
| |
| // Ueberpruefung des rausgescrollten Bereichs |
| if( GetEntryList()->GetSelectEntryCount() == 1 && |
| GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) |
| ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); |
| else |
| SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... |
| } |
| } |
| |
| // Ueberpruefung des rausgescrollten Bereichs |
| sal_uInt16 nMaxLI = (sal_uInt16) (nMaxWidth - nWidth); |
| if ( nMaxLI < GetLeftIndent() ) |
| SetLeftIndent( nMaxLI ); |
| } |
| else |
| { |
| if( mbHScroll ) |
| bArrange = sal_True; |
| mbHScroll = false; |
| SetLeftIndent( 0 ); |
| } |
| } |
| |
| if( bArrange ) |
| ImplResizeControls(); |
| |
| ImplInitScrollBars(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::ImplInitScrollBars() |
| { |
| Size aOutSz = maLBWindow.GetOutputSizePixel(); |
| |
| if ( mbVScroll ) |
| { |
| sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); |
| sal_uInt16 nVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); |
| mpVScrollBar->SetRangeMax( nEntries ); |
| mpVScrollBar->SetVisibleSize( nVisEntries ); |
| mpVScrollBar->SetPageSize( nVisEntries - 1 ); |
| } |
| |
| if ( mbHScroll ) |
| { |
| mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL ); |
| mpHScrollBar->SetVisibleSize( (sal_uInt16)aOutSz.Width() ); |
| mpHScrollBar->SetLineSize( HORZ_SCROLL ); |
| mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::ImplResizeControls() |
| { |
| // Hier werden die Controls nur angeordnet, ob die Scrollbars |
| // sichtbar sein sollen wird bereits in ImplCheckScrollBars ermittelt. |
| |
| Size aOutSz = GetOutputSizePixel(); |
| long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); |
| nSBWidth = CalcZoom( nSBWidth ); |
| |
| Size aInnerSz( aOutSz ); |
| if ( mbVScroll ) |
| aInnerSz.Width() -= nSBWidth; |
| if ( mbHScroll ) |
| aInnerSz.Height() -= nSBWidth; |
| |
| // pb: #106948# explicit mirroring for calc |
| // Scrollbar on left or right side? |
| sal_Bool bMirroring = maLBWindow.IsMirroring(); |
| Point aWinPos( bMirroring && mbVScroll ? nSBWidth : 0, 0 ); |
| maLBWindow.SetPosSizePixel( aWinPos, aInnerSz ); |
| |
| // ScrollBarBox |
| if( mbVScroll && mbHScroll ) |
| { |
| Point aBoxPos( bMirroring ? 0 : aInnerSz.Width(), aInnerSz.Height() ); |
| mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) ); |
| mpScrollBarBox->Show(); |
| } |
| else |
| { |
| mpScrollBarBox->Hide(); |
| } |
| |
| // vert. ScrollBar |
| if( mbVScroll ) |
| { |
| // Scrollbar on left or right side? |
| Point aVPos( bMirroring ? 0 : aOutSz.Width() - nSBWidth, 0 ); |
| mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) ); |
| mpVScrollBar->Show(); |
| } |
| else |
| { |
| mpVScrollBar->Hide(); |
| // #107254# Don't reset top entry after resize, but check for max top entry |
| SetTopEntry( GetTopEntry() ); |
| } |
| |
| // horz. ScrollBar |
| if( mbHScroll ) |
| { |
| Point aHPos( ( bMirroring && mbVScroll ) ? nSBWidth : 0, aOutSz.Height() - nSBWidth ); |
| mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) ); |
| mpHScrollBar->Show(); |
| } |
| else |
| { |
| mpHScrollBar->Hide(); |
| SetLeftIndent( 0 ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::StateChanged( StateChangedType nType ) |
| { |
| if ( nType == STATE_CHANGE_INITSHOW ) |
| { |
| ImplCheckScrollBars(); |
| } |
| else if ( ( nType == STATE_CHANGE_UPDATEMODE ) || ( nType == STATE_CHANGE_DATA ) ) |
| { |
| sal_Bool bUpdate = IsUpdateMode(); |
| maLBWindow.SetUpdateMode( bUpdate ); |
| // mpHScrollBar->SetUpdateMode( bUpdate ); |
| // mpVScrollBar->SetUpdateMode( bUpdate ); |
| if ( bUpdate && IsReallyVisible() ) |
| ImplCheckScrollBars(); |
| } |
| else if( nType == STATE_CHANGE_ENABLE ) |
| { |
| mpHScrollBar->Enable( IsEnabled() ); |
| mpVScrollBar->Enable( IsEnabled() ); |
| mpScrollBarBox->Enable( IsEnabled() ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_ZOOM ) |
| { |
| maLBWindow.SetZoom( GetZoom() ); |
| Resize(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFONT ) |
| { |
| maLBWindow.SetControlFont( GetControlFont() ); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) |
| { |
| maLBWindow.SetControlForeground( GetControlForeground() ); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) |
| { |
| maLBWindow.SetControlBackground( GetControlBackground() ); |
| } |
| else if( nType == STATE_CHANGE_MIRRORING ) |
| { |
| maLBWindow.EnableRTL( IsRTLEnabled() ); |
| mpHScrollBar->EnableRTL( IsRTLEnabled() ); |
| mpVScrollBar->EnableRTL( IsRTLEnabled() ); |
| ImplResizeControls(); |
| } |
| |
| Control::StateChanged( nType ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| // if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| // (rDCEvt.GetFlags() & SETTINGS_STYLE) ) |
| // { |
| // maLBWindow.SetSettings( GetSettings() ); |
| // Resize(); |
| // } |
| // else |
| Control::DataChanged( rDCEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplListBox::Notify( NotifyEvent& rNEvt ) |
| { |
| long nDone = 0; |
| if ( rNEvt.GetType() == EVENT_COMMAND ) |
| { |
| const CommandEvent& rCEvt = *rNEvt.GetCommandEvent(); |
| if ( rCEvt.GetCommand() == COMMAND_WHEEL ) |
| { |
| const CommandWheelData* pData = rCEvt.GetWheelData(); |
| if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) |
| { |
| nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar ); |
| } |
| } |
| } |
| |
| return nDone ? nDone : Window::Notify( rNEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const Wallpaper& ImplListBox::GetDisplayBackground() const |
| { |
| return maLBWindow.GetDisplayBackground(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt ) |
| { |
| sal_Bool bDone = sal_False; |
| if ( rCEvt.GetCommand() == COMMAND_WHEEL ) |
| { |
| const CommandWheelData* pData = rCEvt.GetWheelData(); |
| if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) |
| { |
| sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP; |
| KeyEvent aKeyEvent( 0, KeyCode( nKey ) ); |
| bDone = ProcessKeyInput( aKeyEvent ); |
| } |
| } |
| return bDone; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep ) |
| { |
| sal_Bool bChanges = GetEntryList()->GetMRUCount() ? sal_True : sal_False; |
| |
| // Remove old MRU entries |
| for ( sal_uInt16 n = GetEntryList()->GetMRUCount();n; ) |
| maLBWindow.RemoveEntry( --n ); |
| |
| sal_uInt16 nMRUCount = 0; |
| sal_uInt16 nEntries = rEntries.GetTokenCount( cSep ); |
| for ( sal_uInt16 nEntry = 0; nEntry < nEntries; nEntry++ ) |
| { |
| XubString aEntry = rEntries.GetToken( nEntry, cSep ); |
| // Accept only existing entries |
| if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| ImplEntryType* pNewEntry = new ImplEntryType( aEntry ); |
| maLBWindow.GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, sal_False ); |
| bChanges = sal_True; |
| } |
| } |
| |
| if ( bChanges ) |
| { |
| maLBWindow.GetEntryList()->SetMRUCount( nMRUCount ); |
| SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); |
| StateChanged( STATE_CHANGE_DATA ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString ImplListBox::GetMRUEntries( xub_Unicode cSep ) const |
| { |
| String aEntries; |
| for ( sal_uInt16 n = 0; n < GetEntryList()->GetMRUCount(); n++ ) |
| { |
| aEntries += GetEntryList()->GetEntryText( n ); |
| if( n < ( GetEntryList()->GetMRUCount() - 1 ) ) |
| aEntries += cSep; |
| } |
| return aEntries; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBox::SetEdgeBlending(bool bNew) |
| { |
| if(mbEdgeBlending != bNew) |
| { |
| mbEdgeBlending = bNew; |
| maLBWindow.SetEdgeBlending(GetEdgeBlending()); |
| } |
| } |
| |
| // ======================================================================= |
| |
| ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) : |
| Control ( pParent, nWinStyle ) |
| { |
| if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) |
| && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) |
| SetBackground(); |
| else |
| SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); |
| |
| mbInUserDraw = false; |
| mbUserDrawEnabled = false; |
| mbEdgeBlending = false; |
| mnItemPos = LISTBOX_ENTRY_NOTFOUND; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ImplWin::SetModeImage( const Image& rImage, BmpColorMode eMode ) |
| { |
| if( eMode == BMP_COLOR_NORMAL ) |
| SetImage( rImage ); |
| else if( eMode == BMP_COLOR_HIGHCONTRAST ) |
| maImageHC = rImage; |
| else |
| return sal_False; |
| return sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const Image& ImplWin::GetModeImage( BmpColorMode eMode ) const |
| { |
| if( eMode == BMP_COLOR_HIGHCONTRAST ) |
| return maImageHC; |
| else |
| return maImage; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::MBDown() |
| { |
| if( IsEnabled() ) |
| maMBDownHdl.Call( this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::MouseButtonDown( const MouseEvent& ) |
| { |
| if( IsEnabled() ) |
| { |
| // Control::MouseButtonDown( rMEvt ); |
| MBDown(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::FillLayoutData() const |
| { |
| mpControlData->mpLayoutData = new vcl::ControlLayoutData(); |
| const_cast<ImplWin*>(this)->ImplDraw( true ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplWin::PreNotify( NotifyEvent& rNEvt ) |
| { |
| long nDone = 0; |
| const MouseEvent* pMouseEvt = NULL; |
| |
| if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) |
| { |
| if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) |
| { |
| // trigger redraw as mouse over state has changed |
| if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) |
| && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) |
| { |
| GetParent()->GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE ); |
| GetParent()->GetWindow( WINDOW_BORDER )->Update(); |
| } |
| } |
| } |
| |
| return nDone ? nDone : Control::PreNotify(rNEvt); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::ImplDraw( bool bLayout ) |
| { |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| |
| sal_Bool bNativeOK = sal_False; |
| |
| if( ! bLayout ) |
| { |
| ControlState nState = CTRL_STATE_ENABLED; |
| if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) |
| && IsNativeControlSupported(CTRL_LISTBOX, HAS_BACKGROUND_TEXTURE) ) |
| { |
| // Repaint the (focused) area similarly to |
| // ImplSmallBorderWindowView::DrawWindow() in |
| // vcl/source/window/brdwin.cxx |
| Window *pWin = GetParent(); |
| |
| ImplControlValue aControlValue; |
| if ( !pWin->IsEnabled() ) |
| nState &= ~CTRL_STATE_ENABLED; |
| if ( pWin->HasFocus() ) |
| nState |= CTRL_STATE_FOCUSED; |
| |
| // The listbox is painted over the entire control including the |
| // border, but ImplWin does not contain the border => correction |
| // needed. |
| sal_Int32 nLeft, nTop, nRight, nBottom; |
| pWin->GetBorder( nLeft, nTop, nRight, nBottom ); |
| Point aPoint( -nLeft, -nTop ); |
| Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() ); |
| |
| sal_Bool bMouseOver = sal_False; |
| if( GetParent() ) |
| { |
| Window *pChild = GetParent()->GetWindow( WINDOW_FIRSTCHILD ); |
| while( pChild && (bMouseOver = pChild->IsMouseOver()) == sal_False ) |
| pChild = pChild->GetWindow( WINDOW_NEXT ); |
| } |
| |
| if( bMouseOver ) |
| nState |= CTRL_STATE_ROLLOVER; |
| |
| // if parent has no border, then nobody has drawn the background |
| // since no border window exists. so draw it here. |
| WinBits nParentStyle = pWin->GetStyle(); |
| if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) ) |
| { |
| Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() ); |
| pWin->DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aParentRect, |
| nState, aControlValue, rtl::OUString() ); |
| } |
| |
| bNativeOK = DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState, |
| aControlValue, rtl::OUString() ); |
| } |
| |
| if( IsEnabled() ) |
| { |
| if( HasFocus() ) |
| { |
| SetTextColor( rStyleSettings.GetHighlightTextColor() ); |
| SetFillColor( rStyleSettings.GetHighlightColor() ); |
| DrawRect( maFocusRect ); |
| } |
| else |
| { |
| Color aColor; |
| if( bNativeOK && (nState & CTRL_STATE_ROLLOVER) ) |
| aColor = rStyleSettings.GetFieldRolloverTextColor(); |
| else |
| aColor = rStyleSettings.GetFieldTextColor(); |
| if( IsControlForeground() ) |
| aColor = GetControlForeground(); |
| SetTextColor( aColor ); |
| if ( !bNativeOK ) |
| Erase( maFocusRect ); |
| } |
| } |
| else // Disabled |
| { |
| SetTextColor( rStyleSettings.GetDisableColor() ); |
| if ( !bNativeOK ) |
| Erase( maFocusRect ); |
| } |
| } |
| |
| if ( IsUserDrawEnabled() ) |
| { |
| mbInUserDraw = true; |
| UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 ); |
| maUserDrawHdl.Call( &aUDEvt ); |
| mbInUserDraw = false; |
| } |
| else |
| { |
| DrawEntry( sal_True, sal_True, sal_False, bLayout ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::Paint( const Rectangle& ) |
| { |
| ImplDraw(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::DrawEntry( sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) |
| { |
| long nBorder = 1; |
| Size aOutSz = GetOutputSizePixel(); |
| |
| sal_Bool bImage = !!maImage; |
| if( bDrawImage && bImage && !bLayout ) |
| { |
| sal_uInt16 nStyle = 0; |
| Size aImgSz = maImage.GetSizePixel(); |
| Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) ); |
| const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
| |
| // check for HC mode |
| Image *pImage = &maImage; |
| |
| if( !!maImageHC ) |
| { |
| if( rStyleSettings.GetHighContrastMode() ) |
| pImage = &maImageHC; |
| } |
| |
| if ( !IsZoom() ) |
| { |
| DrawImage( aPtImg, *pImage, nStyle ); |
| } |
| else |
| { |
| aImgSz.Width() = CalcZoom( aImgSz.Width() ); |
| aImgSz.Height() = CalcZoom( aImgSz.Height() ); |
| DrawImage( aPtImg, aImgSz, *pImage, nStyle ); |
| } |
| |
| const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0); |
| |
| if(nEdgeBlendingPercent) |
| { |
| const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); |
| const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); |
| const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); |
| const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight)); |
| |
| if(!aBlendFrame.IsEmpty()) |
| { |
| DrawBitmapEx(aPtImg, aBlendFrame); |
| } |
| } |
| } |
| |
| if( bDrawText && maString.Len() ) |
| { |
| sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; |
| |
| if ( bDrawImage && bImage && !bLayout ) |
| nTextStyle |= TEXT_DRAW_LEFT; |
| else if ( GetStyle() & WB_CENTER ) |
| nTextStyle |= TEXT_DRAW_CENTER; |
| else if ( GetStyle() & WB_RIGHT ) |
| nTextStyle |= TEXT_DRAW_RIGHT; |
| else |
| nTextStyle |= TEXT_DRAW_LEFT; |
| |
| Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) ); |
| |
| if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) ) |
| { |
| long nMaxWidth = Max( maImage.GetSizePixel().Width(), maUserItemSize.Width() ); |
| aTextRect.Left() += nMaxWidth + IMG_TXT_DISTANCE; |
| } |
| |
| MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; |
| String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; |
| DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText ); |
| } |
| |
| if( HasFocus() && !bLayout ) |
| ShowFocus( maFocusRect ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::Resize() |
| { |
| Control::Resize(); |
| maFocusRect.SetSize( GetOutputSizePixel() ); |
| Invalidate(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::GetFocus() |
| { |
| ShowFocus( maFocusRect ); |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| IsNativeWidgetEnabled() && |
| IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) |
| { |
| Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); |
| if( ! pWin ) |
| pWin = GetParent(); |
| pWin->Invalidate(); |
| } |
| else |
| Invalidate(); |
| Control::GetFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplWin::LoseFocus() |
| { |
| HideFocus(); |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| IsNativeWidgetEnabled() && |
| IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) |
| { |
| Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); |
| if( ! pWin ) |
| pWin = GetParent(); |
| pWin->Invalidate(); |
| } |
| else |
| Invalidate(); |
| Control::LoseFocus(); |
| } |
| |
| // ======================================================================= |
| |
| ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) : |
| PushButton( pParent, nWinStyle ), |
| mbDown ( sal_False ) |
| { |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplBtn::MBDown() |
| { |
| if( IsEnabled() ) |
| maMBDownHdl.Call( this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplBtn::MouseButtonDown( const MouseEvent& ) |
| { |
| //PushButton::MouseButtonDown( rMEvt ); |
| if( IsEnabled() ) |
| { |
| MBDown(); |
| mbDown = sal_True; |
| } |
| } |
| |
| // ======================================================================= |
| |
| ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) : |
| FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes |
| { |
| mpImplLB = NULL; |
| mnDDLineCount = 0; |
| mbAutoWidth = sal_False; |
| |
| mnPopupModeStartSaveSelection = LISTBOX_ENTRY_NOTFOUND; |
| |
| EnableSaveBackground(); |
| |
| Window * pBorderWindow = ImplGetBorderWindow(); |
| if( pBorderWindow ) |
| { |
| SetAccessibleRole(accessibility::AccessibleRole::PANEL); |
| pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW); |
| } |
| else |
| { |
| SetAccessibleRole(accessibility::AccessibleRole::WINDOW); |
| } |
| |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt ) |
| { |
| if( rNEvt.GetType() == EVENT_LOSEFOCUS ) |
| { |
| if( !GetParent()->HasChildPathFocus( sal_True ) ) |
| EndPopupMode(); |
| } |
| |
| return FloatingWindow::PreNotify( rNEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxFloatingWindow::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) |
| { |
| FloatingWindow::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); |
| |
| // Fix #60890# ( MBA ): um auch im aufgeklappten Zustand der Listbox die Gr"o\se einfach zu einen |
| // Aufruf von Resize() "andern zu k"onnen, wird die Position hier ggf. angepa\t |
| if ( IsReallyVisible() && ( nFlags & WINDOW_POSSIZE_HEIGHT ) ) |
| { |
| Point aPos = GetParent()->GetPosPixel(); |
| aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); |
| |
| if ( nFlags & WINDOW_POSSIZE_X ) |
| aPos.X() = nX; |
| |
| if ( nFlags & WINDOW_POSSIZE_Y ) |
| aPos.Y() = nY; |
| |
| sal_uInt16 nIndex; |
| SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN, nIndex ) ); |
| } |
| |
| // if( !IsReallyVisible() ) |
| { |
| // Die ImplListBox erhaelt kein Resize, weil nicht sichtbar. |
| // Die Fenster muessen aber ein Resize() erhalten, damit die |
| // Anzahl der sichtbaren Eintraege fuer PgUp/PgDown stimmt. |
| // Die Anzahl kann auch nicht von List/Combobox berechnet werden, |
| // weil hierfuer auch die ggf. vorhandene vertikale Scrollbar |
| // beruecksichtigt werden muss. |
| mpImplLB->SetSizePixel( GetOutputSizePixel() ); |
| ((Window*)mpImplLB)->Resize(); |
| ((Window*)mpImplLB->GetMainWindow())->Resize(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxFloatingWindow::Resize() |
| { |
| mpImplLB->GetMainWindow()->ImplClearLayoutData(); |
| FloatingWindow::Resize(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size ImplListBoxFloatingWindow::CalcFloatSize() |
| { |
| Size aFloatSz( maPrefSz ); |
| |
| sal_Int32 nLeft, nTop, nRight, nBottom; |
| GetBorder( nLeft, nTop, nRight, nBottom ); |
| |
| sal_uInt16 nLines = mpImplLB->GetEntryList()->GetEntryCount(); |
| if ( mnDDLineCount && ( nLines > mnDDLineCount ) ) |
| nLines = mnDDLineCount; |
| |
| Size aSz = mpImplLB->CalcSize( nLines ); |
| long nMaxHeight = aSz.Height() + nTop + nBottom; |
| |
| if ( mnDDLineCount ) |
| aFloatSz.Height() = nMaxHeight; |
| |
| if( mbAutoWidth ) |
| { |
| // AutoSize erstmal nur fuer die Breite... |
| |
| aFloatSz.Width() = aSz.Width() + nLeft + nRight; |
| aFloatSz.Width() += nRight; // etwas mehr Platz sieht besser aus... |
| |
| if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) ) |
| { |
| // dann wird noch der vertikale Scrollbar benoetigt |
| long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); |
| aFloatSz.Width() += nSBWidth; |
| } |
| } |
| |
| if ( aFloatSz.Height() > nMaxHeight ) |
| aFloatSz.Height() = nMaxHeight; |
| |
| // Minimale Hoehe, falls Hoehe nicht auf Float-Hoehe eingestellt wurde. |
| // Der Parent vom FloatWin muss die DropDown-Combo/Listbox sein. |
| Size aParentSz = GetParent()->GetSizePixel(); |
| if( !mnDDLineCount && ( aFloatSz.Height() < aParentSz.Height() ) ) |
| aFloatSz.Height() = aParentSz.Height(); |
| |
| // Nicht schmaler als der Parent werden... |
| if( aFloatSz.Width() < aParentSz.Width() ) |
| aFloatSz.Width() = aParentSz.Width(); |
| |
| // Hoehe auf Entries alignen... |
| long nInnerHeight = aFloatSz.Height() - nTop - nBottom; |
| long nEntryHeight = mpImplLB->GetEntryHeight(); |
| if ( nInnerHeight % nEntryHeight ) |
| { |
| nInnerHeight /= nEntryHeight; |
| nInnerHeight++; |
| nInnerHeight *= nEntryHeight; |
| aFloatSz.Height() = nInnerHeight + nTop + nBottom; |
| } |
| |
| return aFloatSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplListBoxFloatingWindow::StartFloat( sal_Bool bStartTracking ) |
| { |
| if( !IsInPopupMode() ) |
| { |
| Size aFloatSz = CalcFloatSize(); |
| |
| SetSizePixel( aFloatSz ); |
| mpImplLB->SetSizePixel( GetOutputSizePixel() ); |
| |
| sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 ); |
| mnPopupModeStartSaveSelection = nPos; |
| |
| Size aSz = GetParent()->GetSizePixel(); |
| Point aPos = GetParent()->GetPosPixel(); |
| aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); |
| // FIXME: this ugly hack is for Mac/Aqua |
| // should be replaced by a real mechanism to place the float rectangle |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| GetParent()->IsNativeWidgetEnabled() ) |
| { |
| sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4; |
| aPos.X() += nLeft; |
| aPos.Y() += nTop; |
| aSz.Width() -= nLeft + nRight; |
| aSz.Height() -= nTop + nBottom; |
| } |
| Rectangle aRect( aPos, aSz ); |
| |
| // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI |
| // where the document is unmirrored |
| // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror |
| if( GetParent()->GetParent()->ImplIsAntiparallel() ) |
| GetParent()->GetParent()->ImplReMirror( aRect ); |
| |
| StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN ); |
| |
| if( nPos != LISTBOX_ENTRY_NOTFOUND ) |
| mpImplLB->ShowProminentEntry( nPos ); |
| |
| if( bStartTracking ) |
| mpImplLB->GetMainWindow()->EnableMouseMoveSelect( sal_True ); |
| |
| if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() ) |
| mpImplLB->GetMainWindow()->GrabFocus(); |
| |
| mpImplLB->GetMainWindow()->ImplClearLayoutData(); |
| } |
| } |