From 6e26501b0c0ad3cbd98c0af9aab2f9afc8461886 Mon Sep 17 00:00:00 2001 From: RĂ¼diger Timm Date: Mon, 15 Dec 2008 12:14:02 +0000 Subject: CWS-TOOLING: integrate CWS ooo301gsl3_DEV300 --- vcl/inc/vcl/ilstbox.hxx | 54 +++--- vcl/inc/vcl/lstbox.h | 9 +- vcl/source/control/combobox.cxx | 2 - vcl/source/control/ilstbox.cxx | 363 +++++++++++++++++++++++++++++----------- vcl/source/control/lstbox.cxx | 2 - vcl/source/gdi/outdev3.cxx | 24 +++ 6 files changed, 327 insertions(+), 127 deletions(-) diff --git a/vcl/inc/vcl/ilstbox.hxx b/vcl/inc/vcl/ilstbox.hxx index be36d3a7dcc7..e5f6696005fa 100644 --- a/vcl/inc/vcl/ilstbox.hxx +++ b/vcl/inc/vcl/ilstbox.hxx @@ -70,11 +70,13 @@ struct ImplEntryType void* mpUserData; BOOL mbIsSelected; long mnFlags; + long mnHeight; ImplEntryType( const XubString& rStr, const Image& rImage ) : maStr( rStr ), maImage( rImage ), - mnFlags(0) + mnFlags( 0 ), + mnHeight( 0 ) { mbIsSelected = FALSE; mpUserData = NULL; @@ -82,7 +84,8 @@ struct ImplEntryType ImplEntryType( const XubString& rStr ) : maStr( rStr ), - mnFlags(0) + mnFlags( 0 ), + mnHeight( 0 ) { mbIsSelected = FALSE; mpUserData = NULL; @@ -90,7 +93,8 @@ struct ImplEntryType ImplEntryType( const Image& rImage ) : maImage( rImage ), - mnFlags( 0 ) + mnFlags( 0 ), + mnHeight( 0 ) { mbIsSelected = FALSE; mpUserData = NULL; @@ -124,12 +128,20 @@ public: USHORT InsertEntry( USHORT nPos, ImplEntryType* pNewEntry, BOOL bSort ); void RemoveEntry( USHORT nPos ); const ImplEntryType* GetEntryPtr( USHORT nPos ) const { return (const ImplEntryType*) GetObject( nPos ); } + ImplEntryType* GetMutableEntryPtr( USHORT nPos ) const { return (ImplEntryType*) GetObject( nPos ); } void Clear(); USHORT FindMatchingEntry( const XubString& rStr, USHORT nStart = 0, BOOL bForward = TRUE, BOOL bLazy = TRUE ) const; USHORT FindEntry( const XubString& rStr, BOOL bSearchMRUArea = FALSE ) const; USHORT FindEntry( const void* pData ) const; + // helper: add up heights up to index nEndIndex. + // GetAddedHeight( 0 ) returns 0 + // GetAddedHeight( LISTBOX_ENTRY_NOTFOUND ) returns 0 + // GetAddedHeight( i, k ) with k > i is equivalent -GetAddedHeight( k, i ) + long GetAddedHeight( USHORT nEndIndex, USHORT nBeginIndex = 0, long nBeginHeight = 0 ) const; + long GetEntryHeight( USHORT nPos ) const; + USHORT GetEntryCount() const { return (USHORT)List::Count(); } BOOL HasImages() const { return mnImages ? TRUE : FALSE; } @@ -194,17 +206,16 @@ private: Size maUserItemSize; - USHORT mnMaxTxtHeight; // Maximale Hoehe eines Text-Items - USHORT mnMaxTxtWidth; // Maximale Breite eines Text-Items + long mnMaxTxtHeight; // Maximale Hoehe eines Text-Items + long mnMaxTxtWidth; // Maximale Breite eines Text-Items // Entry ohne Image - USHORT mnMaxImgTxtWidth;// Maximale Breite eines Text-Items + long mnMaxImgTxtWidth;// Maximale Breite eines Text-Items // Entry UND Image - USHORT mnMaxImgWidth; // Maximale Breite eines Image-Items - USHORT mnMaxImgHeight; // Maximale Hoehe eines Image-Items - USHORT mnMaxWidth; // Maximale Breite eines Eintrags - USHORT mnMaxHeight; // Maximale Hoehe eines Eintrags + long mnMaxImgWidth; // Maximale Breite eines Image-Items + long mnMaxImgHeight; // Maximale Hoehe eines Image-Items + long mnMaxWidth; // Maximale Breite eines Eintrags + long mnMaxHeight; // Maximale Hoehe eines Eintrags - USHORT mnMaxVisibleEntries; // Anzahl der sichtbaren Eintraege USHORT mnCurrentPos; // Position (Focus) USHORT mnTrackingSaveSelection; // Selektion vor Tracking(); @@ -213,9 +224,9 @@ private: USHORT mnUserDrawEntry; USHORT mnTop; // Ausgabe ab Zeile - USHORT mnLeft; // Ausgabe ab Spalte - USHORT mnBorder; // Abstand Rahmen - Text - USHORT mnTextHeight; // Texthoehe + long mnLeft; // Ausgabe ab Spalte + long mnBorder; // Abstand Rahmen - Text + long mnTextHeight; // Texthoehe USHORT mnSelectModifier; // Modifiers @@ -261,7 +272,7 @@ protected: void ImplPaint( USHORT nPos, BOOL bErase = FALSE, bool bLayout = false ); void ImplDoPaint( const Rectangle& rRect, bool bLayout = false ); void ImplCalcMetrics(); - void ImplCalcEntryMetrics( const ImplEntryType& rEntry, BOOL bUpdateMetrics ); + void ImplUpdateEntryMetrics( ImplEntryType& rEntry ); void ImplCallSelect(); void ImplShowFocusRect(); @@ -285,23 +296,25 @@ public: void ResetCurrentPos() { mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; } USHORT GetCurrentPos() const { return mnCurrentPos; } USHORT GetDisplayLineCount() const; + void SetEntryFlags( USHORT nPos, long nFlags ); void DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos = FALSE, bool bLayout = false ); void SelectEntry( USHORT nPos, BOOL bSelect ); void DeselectAll(); USHORT GetEntryPosForPoint( const Point& rPoint ) const; + USHORT GetLastVisibleEntry() const; BOOL ProcessKeyInput( const KeyEvent& rKEvt ); void SetTopEntry( USHORT nTop ); USHORT GetTopEntry() const { return mnTop; } using Window::IsVisible; - BOOL IsVisible( USHORT nEntry ) const { return ( ( nEntry >= mnTop ) && ( nEntry < (mnTop+mnMaxVisibleEntries) ) ); } + BOOL IsVisible( USHORT nEntry ) const; - USHORT GetLeftIndent() const { return mnLeft; } - void SetLeftIndent( USHORT n ); - void ScrollHorz( short nDiff ); + long GetLeftIndent() const { return mnLeft; } + void SetLeftIndent( long n ); + void ScrollHorz( long nDiff ); void AllowGrabFocus( BOOL b ) { mbGrabFocus = b; } BOOL IsGrabFocusAllowed() const { return mbGrabFocus; } @@ -330,7 +343,6 @@ public: BOOL IsMouseMoveSelect() const { return mbMouseMoveSelect||mbStackMode; } Size CalcSize( USHORT nMaxLines ) const; - void CalcMaxVisibleEntries( const Size& rFloatSize); Rectangle GetBoundingRectangle( USHORT nItem ) const; long GetEntryHeight() const { return mnMaxHeight; } @@ -433,7 +445,7 @@ public: using Window::IsVisible; BOOL IsVisible( USHORT nEntry ) const { return maLBWindow.IsVisible( nEntry ); } - USHORT GetLeftIndent() const { return maLBWindow.GetLeftIndent(); } + long GetLeftIndent() const { return maLBWindow.GetLeftIndent(); } void SetLeftIndent( USHORT n ) { maLBWindow.SetLeftIndent( n ); } void ScrollHorz( short nDiff ) { maLBWindow.ScrollHorz( nDiff ); } diff --git a/vcl/inc/vcl/lstbox.h b/vcl/inc/vcl/lstbox.h index 1c58f7f7700b..6097422b556b 100644 --- a/vcl/inc/vcl/lstbox.h +++ b/vcl/inc/vcl/lstbox.h @@ -49,8 +49,15 @@ /** this flag disables a selection of an entry completly. It is not possible to select such entries either from the user interface nor from the ListBox methods. Cursor traveling is handled correctly. - This flag can be used to at titles to a ListBox. + This flag can be used to add titles to a ListBox. */ #define LISTBOX_ENTRY_FLAG_DISABLE_SELECTION 0x0000001 +/** this flag can be used to make an entry multine capable + A normal entry is single line and will therefore be clipped + at the right listbox border. Setting this flag enables + word breaks for the entry text. +*/ +#define LISTBOX_ENTRY_FLAG_MULTILINE 0x0000002 + #endif // _SV_LSTBOX_H diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx index 0d9523fa357b..3038f60267ee 100644 --- a/vcl/source/control/combobox.cxx +++ b/vcl/source/control/combobox.cxx @@ -840,8 +840,6 @@ long ComboBox::Notify( NotifyEvent& rNEvt ) } else { - if( mpFloatWin ) - mpImplLB->GetMainWindow()->CalcMaxVisibleEntries( mpFloatWin->CalcFloatSize() ); nDone = mpImplLB->ProcessKeyInput( aKeyEvt ); } } diff --git a/vcl/source/control/ilstbox.cxx b/vcl/source/control/ilstbox.cxx index 50816de2aaf7..df77e088a7a4 100644 --- a/vcl/source/control/ilstbox.cxx +++ b/vcl/source/control/ilstbox.cxx @@ -54,6 +54,8 @@ #include #endif +#define MULTILINE_ENTRY_DRAW_FLAGS ( TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_VCENTER ) + using namespace ::com::sun::star; // ======================================================================= @@ -328,6 +330,42 @@ USHORT ImplEntryList::FindEntry( const void* pData ) const // ----------------------------------------------------------------------- +long ImplEntryList::GetAddedHeight( USHORT i_nEndIndex, USHORT i_nBeginIndex, long i_nBeginHeight ) const +{ + long nHeight = i_nBeginHeight; + USHORT nStart = i_nEndIndex > i_nBeginIndex ? i_nBeginIndex : i_nEndIndex; + USHORT nStop = i_nEndIndex > i_nBeginIndex ? i_nEndIndex : i_nBeginIndex; + USHORT 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; + + USHORT 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( USHORT nPos ) const +{ + ImplEntryType* pImplEntry = GetEntry( nPos ); + return pImplEntry ? pImplEntry->mnHeight : 0; +} + +// ----------------------------------------------------------------------- + XubString ImplEntryList::GetEntryText( USHORT nPos ) const { XubString aEntryText; @@ -574,12 +612,15 @@ void ImplListBoxWindow::ImplCalcMetrics() for ( USHORT n = mpEntryList->GetEntryCount(); n; ) { - const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( --n ); - ImplCalcEntryMetrics( *pEntry, TRUE ); + ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( --n ); + ImplUpdateEntryMetrics( *pEntry ); } - Size aSz( GetOutputSizePixel().Width(), mnMaxHeight ); - maFocusRect.SetSize( aSz ); + if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) + { + Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryPtr( mnCurrentPos )->mnHeight ); + maFocusRect.SetSize( aSz ); + } } // ----------------------------------------------------------------------- @@ -625,24 +666,17 @@ struct ImplEntryMetrics { BOOL bText; BOOL bImage; - USHORT nEntryWidth; - USHORT nEntryHeight; - USHORT nTextWidth; - USHORT nImgWidth; - USHORT nImgHeight; + long nEntryWidth; + long nEntryHeight; + long nTextWidth; + long nImgWidth; + long nImgHeight; }; // ----------------------------------------------------------------------- -void ImplListBoxWindow::ImplCalcEntryMetrics( const ImplEntryType& rEntry, BOOL bUpdateMetrics ) +void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType& rEntry ) { - // bUpdateMetrics: Wenn Entry groesser als Max-Wert, dann uebernehmen - - // Diese Methode war mal auch fuer RemoveRentry gedacht, deshalb die - // ImplEntryMetrics-Struktur, damit die Werte zurueckgegeben werden. - // Jetzt werden die aktuellen Metriken aber doch immer angepasst, weil - // bei RemoveEntry einmal komplett durchgegangen wird. - ImplEntryMetrics aMetrics; aMetrics.bText = rEntry.maStr.Len() ? TRUE : FALSE; aMetrics.bImage = !!rEntry.maImage; @@ -654,10 +688,30 @@ void ImplListBoxWindow::ImplCalcEntryMetrics( const ImplEntryType& rEntry, BOOL if ( aMetrics.bText ) { - aMetrics.nTextWidth = (USHORT)GetTextWidth( rEntry.maStr ); - if( bUpdateMetrics && ( aMetrics.nTextWidth > mnMaxTxtWidth ) ) - mnMaxTxtWidth = aMetrics.nTextWidth; - aMetrics.nEntryWidth = mnMaxTxtWidth; + 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 = (USHORT)GetTextWidth( rEntry.maStr ); + if( aMetrics.nTextWidth > mnMaxTxtWidth ) + mnMaxTxtWidth = aMetrics.nTextWidth; + aMetrics.nEntryWidth = mnMaxTxtWidth; + aMetrics.nEntryHeight = mnTextHeight + mnBorder; + } } if ( aMetrics.bImage ) { @@ -665,36 +719,35 @@ void ImplListBoxWindow::ImplCalcEntryMetrics( const ImplEntryType& rEntry, BOOL aMetrics.nImgWidth = (USHORT) CalcZoom( aImgSz.Width() ); aMetrics.nImgHeight = (USHORT) CalcZoom( aImgSz.Height() ); - if ( bUpdateMetrics ) - { - if( mnMaxImgWidth && ( aMetrics.nImgWidth != mnMaxImgWidth ) ) - mbImgsDiffSz = TRUE; - else if ( mnMaxImgHeight && ( aMetrics.nImgHeight != mnMaxImgHeight ) ) - mbImgsDiffSz = TRUE; + 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; + 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 ); - mnMaxImgTxtWidth = Max( mnMaxImgTxtWidth, aMetrics.nTextWidth ); - } } if ( IsUserDrawEnabled() || aMetrics.bImage ) { - aMetrics.nEntryWidth = Max( aMetrics.nImgWidth, (USHORT)maUserItemSize.Width() ); + aMetrics.nEntryWidth = Max( aMetrics.nImgWidth, maUserItemSize.Width() ); if ( aMetrics.bText ) aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE; - aMetrics.nEntryHeight = Max( mnMaxImgHeight, (USHORT)maUserItemSize.Height() ) + 2; + aMetrics.nEntryHeight = Max( Max( mnMaxImgHeight, maUserItemSize.Height() ) + 2, + aMetrics.nEntryHeight ); } - if ( bUpdateMetrics ) - { - if ( aMetrics.nEntryWidth > mnMaxWidth ) - mnMaxWidth = aMetrics.nEntryWidth; - if ( aMetrics.nEntryHeight > mnMaxHeight ) - mnMaxHeight = aMetrics.nEntryHeight; - } + if ( aMetrics.nEntryWidth > mnMaxWidth ) + mnMaxWidth = aMetrics.nEntryWidth; + if ( aMetrics.nEntryHeight > mnMaxHeight ) + mnMaxHeight = aMetrics.nEntryHeight; + + rEntry.mnHeight = aMetrics.nEntryHeight; } // ----------------------------------------------------------------------- @@ -746,7 +799,10 @@ USHORT ImplListBoxWindow::InsertEntry( USHORT nPos, ImplEntryType* pNewEntry ) delete mpLayoutData, mpLayoutData = NULL; USHORT nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort ); - ImplCalcEntryMetrics( *pNewEntry, TRUE ); + if( (GetStyle() & WB_WORDBREAK) ) + pNewEntry->mnFlags |= LISTBOX_ENTRY_FLAG_MULTILINE; + + ImplUpdateEntryMetrics( *pNewEntry ); return nNewPos; } @@ -756,11 +812,23 @@ void ImplListBoxWindow::RemoveEntry( USHORT nPos ) { delete mpLayoutData, mpLayoutData = NULL; mpEntryList->RemoveEntry( nPos ); + if( mnCurrentPos >= mpEntryList->GetEntryCount() ) + mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; ImplCalcMetrics(); } // ----------------------------------------------------------------------- +void ImplListBoxWindow::SetEntryFlags( USHORT nPos, long nFlags ) +{ + mpEntryList->SetEntryFlags( nPos, nFlags ); + ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( nPos ); + if( pEntry ) + ImplUpdateEntryMetrics( *pEntry ); +} + +// ----------------------------------------------------------------------- + void ImplListBoxWindow::ImplShowFocusRect() { if ( mbHasFocusRect ) @@ -785,14 +853,57 @@ void ImplListBoxWindow::ImplHideFocusRect() USHORT ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const { - USHORT nSelect = (USHORT) ( ( rPoint.Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop; - if( nSelect < mnTop || nSelect >= mpEntryList->GetEntryCount() ) + long nY = mnBorder; + + USHORT 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; } // ----------------------------------------------------------------------- +BOOL ImplListBoxWindow::IsVisible( USHORT i_nEntry ) const +{ + BOOL bRet = FALSE; + + if( i_nEntry >= mnTop ) + { + if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) < + PixelToLogic( GetSizePixel() ).Height() ) + { + bRet = TRUE; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +USHORT ImplListBoxWindow::GetLastVisibleEntry() const +{ + USHORT nPos = mnTop; + long nWindowHeight = GetSizePixel().Height(); + USHORT nCount = mpEntryList->GetEntryCount(); + for( long nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) ) + nPos++; + + if( nPos >= nCount ) + nPos = nCount-1; + + return nPos; +} + +// ----------------------------------------------------------------------- + void ImplListBoxWindow::MouseButtonDown( const MouseEvent& rMEvt ) { mbMouseMoveSelect = FALSE; // Nur bis zum ersten MouseButtonDown @@ -863,8 +974,10 @@ void ImplListBoxWindow::MouseMove( const MouseEvent& rMEvt ) { if ( IsMouseMoveSelect() ) { - USHORT nSelect = (USHORT) ( ( rMEvt.GetPosPixel().Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop; - nSelect = Min( nSelect, (USHORT) ( mnTop + mnMaxVisibleEntries ) ); + USHORT nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() ); + if( nSelect == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->GetEntryCount() - 1; + nSelect = Min( nSelect, GetLastVisibleEntry() ); nSelect = Min( nSelect, (USHORT) ( mpEntryList->GetEntryCount() - 1 ) ); // Select only visible Entries with MouseMove, otherwise Tracking... if ( IsVisible( nSelect ) && @@ -944,14 +1057,15 @@ void ImplListBoxWindow::SelectEntry( USHORT nPos, BOOL bSelect ) if ( !IsVisible( nPos ) ) { delete mpLayoutData, mpLayoutData = NULL; - if ( !mnMaxVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) ) + USHORT nVisibleEntries = GetLastVisibleEntry()-mnTop; + if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) ) { Resize(); SetTopEntry( nPos ); } else { - SetTopEntry( nPos-mnMaxVisibleEntries+1 ); + SetTopEntry( nPos-nVisibleEntries+1 ); } } } @@ -1105,7 +1219,11 @@ BOOL ImplListBoxWindow::SelectEntries( USHORT nSelect, LB_EVENT_TYPE eLET, BOOL if( bFocusChanged ) { - maFocusRect.SetPos( Point( 0, ( nSelect - mnTop ) * mnMaxHeight ) ); + 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(); } @@ -1139,7 +1257,11 @@ void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) mbTrackingSelect = FALSE; if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND ) { - maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) ); + long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); + maFocusRect.SetPos( Point( 0, nHeightDiff ) ); + Size aSz( maFocusRect.GetWidth(), + mpEntryList->GetEntryHeight( mnCurrentPos ) ); + maFocusRect.SetSize( aSz ); ImplShowFocusRect(); } } @@ -1187,14 +1309,14 @@ void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) { nSelect = Min( (USHORT)(mnCurrentPos+1), (USHORT)(mpEntryList->GetEntryCount()-1) ); - if( nSelect >= mnTop + mnMaxVisibleEntries ) + if( nSelect >= GetLastVisibleEntry() ) SetTopEntry( mnTop+1 ); } } else { nSelect = (USHORT) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop; - nSelect = Min( nSelect, (USHORT) ( mnTop + mnMaxVisibleEntries ) ); + nSelect = Min( nSelect, GetLastVisibleEntry() ); nSelect = Min( nSelect, (USHORT) ( mpEntryList->GetEntryCount() - 1 ) ); } @@ -1268,7 +1390,10 @@ void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) } else { - maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) ); + long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); + maFocusRect.SetPos( Point( 0, nHeightDiff ) ); + Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); + maFocusRect.SetSize( aSz ); ImplShowFocusRect(); } } @@ -1351,7 +1476,7 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1, true ); } - if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= ( mnTop + mnMaxVisibleEntries ) ) ) + if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) ) SetTopEntry( mnTop+1 ); bDone = TRUE; @@ -1364,8 +1489,9 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) { if ( IsReadOnly() ) { - SetTopEntry( ( mnTop > mnMaxVisibleEntries ) ? - (mnTop-mnMaxVisibleEntries) : 0 ); + USHORT nCurVis = GetLastVisibleEntry() - mnTop +1; + SetTopEntry( ( mnTop > nCurVis ) ? + (mnTop-nCurVis) : 0 ); } else if ( !bCtrl && !bMod2 ) { @@ -1376,7 +1502,10 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) else if ( mnCurrentPos ) { if( mnCurrentPos == mnTop ) - SetTopEntry( ( mnTop > mnMaxVisibleEntries ) ? ( mnTop-mnMaxVisibleEntries+1 ) : 0 ); + { + USHORT nCurVis = GetLastVisibleEntry() - mnTop +1; + SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 ); + } // find first selectable starting from mnTop looking foreward nSelect = mpEntryList->FindFirstSelectable( mnTop, true ); @@ -1391,7 +1520,7 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) { if ( IsReadOnly() ) { - SetTopEntry( mnTop + mnMaxVisibleEntries ); + SetTopEntry( GetLastVisibleEntry() ); } else if ( !bCtrl && !bMod2 ) { @@ -1402,13 +1531,14 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) { USHORT nCount = mpEntryList->GetEntryCount(); - USHORT nTmp = Min( mnMaxVisibleEntries, nCount ); + USHORT nCurVis = GetLastVisibleEntry() - mnTop +1; + USHORT nTmp = Min( nCurVis, nCount ); nTmp += mnTop - 1; if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 ) { - long nTmp2 = Min( (long)(nCount-mnMaxVisibleEntries), (long)((long)mnTop+(long)mnMaxVisibleEntries-1) ); + long nTmp2 = Min( (long)(nCount-nCurVis), (long)((long)mnTop+(long)nCurVis-1) ); nTmp2 = Max( (long)0 , nTmp2 ); - nTmp = (USHORT)(nTmp2+(mnMaxVisibleEntries-1) ); + nTmp = (USHORT)(nTmp2+(nCurVis-1) ); SetTopEntry( (USHORT)nTmp2 ); } // find first selectable starting from nTmp looking backwards @@ -1457,8 +1587,9 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) { USHORT nCount = mpEntryList->GetEntryCount(); nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false ); - if( nCount > mnMaxVisibleEntries ) - SetTopEntry( nCount - mnMaxVisibleEntries ); + USHORT nCurVis = GetLastVisibleEntry() - mnTop + 1; + if( nCount > nCurVis ) + SetTopEntry( nCount - nCurVis ); } bDone = TRUE; } @@ -1565,10 +1696,11 @@ BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) if ( nSelect != LISTBOX_ENTRY_NOTFOUND ) { + USHORT nCurVis = GetLastVisibleEntry() - mnTop + 1; if( nSelect < mnTop ) SetTopEntry( nSelect ); - else if( nSelect >= (mnTop + mnMaxVisibleEntries) ) - SetTopEntry( nSelect - mnMaxVisibleEntries + 1 ); + else if( nSelect >= (mnTop + nCurVis) ) + SetTopEntry( nSelect - nCurVis + 1 ); if ( mpEntryList->IsEntryPosSelected( nSelect ) ) nSelect = LISTBOX_ENTRY_NOTFOUND; @@ -1610,9 +1742,13 @@ void ImplListBoxWindow::ImplPaint( USHORT nPos, BOOL bErase, bool bLayout ) { const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); + if( ! pEntry ) + return; + long nWidth = GetOutputSizePixel().Width(); - long nY = ( nPos - mnTop ) * mnMaxHeight; - Rectangle aRect( Point( 0, nY ), Size( nWidth, mnMaxHeight ) ); + long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); + Rectangle aRect( Point( 0, nY ), Size( nWidth, pEntry->mnHeight ) ); if( ! bLayout ) { @@ -1656,12 +1792,16 @@ void ImplListBoxWindow::ImplPaint( USHORT nPos, BOOL bErase, bool bLayout ) void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, 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 = ( nPos - mnTop ) * mnMaxHeight; + long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); Size aImgSz; if( bDrawImage && mpEntryList->HasImages() && !bLayout ) @@ -1670,7 +1810,7 @@ void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, if( !!aImage ) { aImgSz = aImage.GetSizePixel(); - Point aPtImg( mnBorder - mnLeft, nY + ( ( mnMaxHeight - aImgSz.Height() ) / 2 ) ); + Point aPtImg( mnBorder - mnLeft, nY + ( ( pEntry->mnHeight - aImgSz.Height() ) / 2 ) ); // pb: #106948# explicit mirroring for calc if ( mbMirroring ) @@ -1699,13 +1839,16 @@ void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, { 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, mnMaxHeight ) ); + Size( nMaxWidth, pEntry->mnHeight ) ); if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) ) { - USHORT nImageWidth = Max( mnMaxImgWidth, (USHORT)maUserItemSize.Width() ); + long nImageWidth = Max( mnMaxImgWidth, maUserItemSize.Width() ); aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE; } @@ -1721,7 +1864,11 @@ void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, aTextRect.Left() -= ( aImgSz.Width() + IMG_TXT_DISTANCE ); } - DrawText( aTextRect, aStr, ImplGetTextStyle(), pVector, pDisplayText ); + USHORT nDrawStyle = ImplGetTextStyle(); + if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) + nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS; + + DrawText( aTextRect, aStr, nDrawStyle, pVector, pDisplayText ); } } @@ -1734,7 +1881,7 @@ void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY ); Point aStartPos( 0, nY ); if ( nPos == mnSeparatorPos ) - aStartPos.Y() += mnMaxHeight-1; + aStartPos.Y() += pEntry->mnHeight-1; Point aEndPos( aStartPos ); aEndPos.X() = GetOutputSizePixel().Width(); DrawLine( aStartPos, aEndPos ); @@ -1767,15 +1914,19 @@ void ImplListBoxWindow::ImplDoPaint( const Rectangle& rRect, bool bLayout ) for( USHORT i = (USHORT)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ ) { - if( nY + mnMaxHeight >= rRect.Top() && + const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( i ); + if( nY + pEntry->mnHeight >= rRect.Top() && nY <= rRect.Bottom() + mnMaxHeight ) { ImplPaint( i, FALSE, bLayout ); } - nY += mnMaxHeight; + nY += pEntry->mnHeight; } - maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) ); + 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(); } @@ -1791,6 +1942,8 @@ void ImplListBoxWindow::Paint( const Rectangle& rRect ) USHORT ImplListBoxWindow::GetDisplayLineCount() const { + // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE + USHORT nCount = mpEntryList->GetEntryCount(); long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; USHORT nEntries = static_cast< USHORT >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight ); @@ -1810,9 +1963,11 @@ void ImplListBoxWindow::Resize() if ( bShowFocusRect ) ImplHideFocusRect(); - Size aSz( GetOutputSizePixel().Width(), mnMaxHeight ); - maFocusRect.SetSize( aSz ); - mnMaxVisibleEntries = (USHORT) ( GetOutputSizePixel().Height() / mnMaxHeight ); + if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) + { + Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); + maFocusRect.SetSize( aSz ); + } if ( bShowFocusRect ) ImplShowFocusRect(); @@ -1822,20 +1977,15 @@ void ImplListBoxWindow::Resize() // ----------------------------------------------------------------------- -void ImplListBoxWindow::CalcMaxVisibleEntries( const Size& rFloatSize ) -{ - if( mnMaxHeight ) - mnMaxVisibleEntries = (USHORT) ( (rFloatSize.Height()-4) / mnMaxHeight ); -} - -// ----------------------------------------------------------------------- - void ImplListBoxWindow::GetFocus() { USHORT nPos = mnCurrentPos; if ( nPos == LISTBOX_ENTRY_NOTFOUND ) nPos = 0; - maFocusRect.SetPos( Point( 0, ( nPos - mnTop ) * mnMaxHeight ) ); + 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(); } @@ -1864,14 +2014,22 @@ void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt ) void ImplListBoxWindow::SetTopEntry( USHORT nTop ) { - USHORT nMaxTop = 0; - if ( GetEntryList()->GetEntryCount() > mnMaxVisibleEntries ) - nMaxTop = GetEntryList()->GetEntryCount() - mnMaxVisibleEntries; - nTop = Min( nTop, nMaxTop ); + if( mpEntryList->GetEntryCount() == 0 ) + return; + + long nWHeight = PixelToLogic( GetSizePixel() ).Height(); + + USHORT 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 ) { delete mpLayoutData, mpLayoutData = NULL; - long nDiff = ( mnTop - nTop ) * mnMaxHeight; + long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 ); Update(); ImplHideFocusRect(); mnTop = nTop; @@ -1887,16 +2045,16 @@ void ImplListBoxWindow::SetTopEntry( USHORT nTop ) // ----------------------------------------------------------------------- -void ImplListBoxWindow::SetLeftIndent( USHORT n ) +void ImplListBoxWindow::SetLeftIndent( long n ) { ScrollHorz( n - mnLeft ); } // ----------------------------------------------------------------------- -void ImplListBoxWindow::ScrollHorz( short n ) +void ImplListBoxWindow::ScrollHorz( long n ) { - short nDiff = 0; + long nDiff = 0; if ( n > 0 ) { long nWidth = GetOutputSizePixel().Width(); @@ -1907,7 +2065,7 @@ void ImplListBoxWindow::ScrollHorz( short n ) { if( mnLeft ) { - USHORT nAbs = -n; + long nAbs = -n; nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft ); } } @@ -1930,6 +2088,8 @@ void ImplListBoxWindow::ScrollHorz( short n ) Size ImplListBoxWindow::CalcSize( USHORT nMaxLines ) const { + // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE + Size aSz; // USHORT nL = Min( nMaxLines, mpEntryList->GetEntryCount() ); aSz.Height() = nMaxLines * mnMaxHeight; @@ -1941,8 +2101,9 @@ Size ImplListBoxWindow::CalcSize( USHORT nMaxLines ) const Rectangle ImplListBoxWindow::GetBoundingRectangle( USHORT nItem ) const { - Size aSz( GetSizePixel().Width(), GetEntryHeight() ); - long nY = ( nItem - GetTopEntry() ) * GetEntryHeight(); + const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem ); + Size aSz( GetSizePixel().Width(), pEntry ? pEntry->mnHeight : GetEntryHeight() ); + long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) - mpEntryList->GetAddedHeight( GetTopEntry() ); Rectangle aRect( Point( 0, nY ), aSz ); return aRect; } @@ -2112,7 +2273,7 @@ void ImplListBox::RemoveEntry( USHORT nPos ) void ImplListBox::SetEntryFlags( USHORT nPos, long nFlags ) { - maLBWindow.GetEntryList()->SetEntryFlags( nPos, nFlags ); + maLBWindow.SetEntryFlags( nPos, nFlags ); } // ----------------------------------------------------------------------- diff --git a/vcl/source/control/lstbox.cxx b/vcl/source/control/lstbox.cxx index df79f1580583..2fcf24478ffe 100644 --- a/vcl/source/control/lstbox.cxx +++ b/vcl/source/control/lstbox.cxx @@ -934,8 +934,6 @@ long ListBox::PreNotify( NotifyEvent& rNEvt ) default: { - if( mpFloatWin ) - mpImplLB->GetMainWindow()->CalcMaxVisibleEntries( mpFloatWin->CalcFloatSize() ); nDone = mpImplLB->ProcessKeyInput( aKeyEvt ); } } diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index f61525f9a483..5bb7b0d9afcf 100644 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -5285,6 +5285,30 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, } nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos ); } + else + { + // fallback to something really simple + USHORT nSpacePos = STRING_LEN; + long nW = 0; + do + { + nSpacePos = rStr.SearchBackward( sal_Unicode(' '), nSpacePos ); + if( nSpacePos != STRING_NOTFOUND ) + { + if( nSpacePos > nPos ) + nSpacePos--; + nW = GetTextWidth( rStr, nPos, nSpacePos-nPos ); + } + } while( nW > nWidth ); + + if( nSpacePos != STRING_NOTFOUND ) + { + nBreakPos = nSpacePos; + nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos ); + if( nBreakPos < rStr.Len()-1 ) + nBreakPos++; + } + } } if ( nLineWidth > nMaxLineWidth ) -- cgit