diff options
Diffstat (limited to 'vcl/source/control/ilstbox.cxx')
-rw-r--r-- | vcl/source/control/ilstbox.cxx | 2387 |
1 files changed, 2387 insertions, 0 deletions
diff --git a/vcl/source/control/ilstbox.cxx b/vcl/source/control/ilstbox.cxx new file mode 100644 index 000000000000..3f1b977e7eab --- /dev/null +++ b/vcl/source/control/ilstbox.cxx @@ -0,0 +1,2387 @@ +/************************************************************************* + * + * $RCSfile: ilstbox.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _SV_ILSTBOX_CXX + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _SV_SVDATA_HXX +#include <svdata.hxx> +#endif +#ifndef _SV_SVAPP_HXX +#include <svapp.hxx> +#endif +#ifndef _SV_SETTINGS_HXX +#include <settings.hxx> +#endif +#ifndef _SV_EVENT_HXX +#include <event.hxx> +#endif +#ifndef _SV_SCRBAR_HXX +#include <scrbar.hxx> +#endif +#ifndef _SV_HELP_HXX +#include <help.hxx> +#endif + +#ifndef _SV_LSTBOX_H +#include <lstbox.h> +#endif +#ifndef _SV_ILSTBOX_HXX +#include <ilstbox.hxx> +#endif + +#pragma hdrstop + +// ======================================================================= + +void ImplInitFieldSettings( Window* pWin, BOOL bFont, BOOL bForeground, 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 ); +} + +// ======================================================================= + +ImplEntryList::ImplEntryList() +{ + mnLastSelected = LISTBOX_ENTRY_NOTFOUND; + mnSelectionAnchor = LISTBOX_ENTRY_NOTFOUND; + mnImages = 0; + mbCallSelectionChangedHdl = TRUE; + + mnMRUCount = 0; + mnMaxMRUCount = 0; +} + +// ----------------------------------------------------------------------- + +ImplEntryList::~ImplEntryList() +{ + Clear(); +} + +// ----------------------------------------------------------------------- + +void ImplEntryList::Clear() +{ + mnImages = 0; + for ( USHORT n = GetEntryCount(); n; ) + { + ImplEntryType* pImplEntry = GetEntry( --n ); + delete pImplEntry; + } + List::Clear(); +} + +// ----------------------------------------------------------------------- + +void ImplEntryList::SelectEntry( USHORT nPos, BOOL bSelect ) +{ + ImplEntryType* pImplEntry = GetEntry( nPos ); + if ( pImplEntry && ( pImplEntry->mbIsSelected != bSelect ) ) + { + pImplEntry->mbIsSelected = bSelect; + if ( mbCallSelectionChangedHdl ) + maSelectionChangedHdl.Call( (void*)nPos ); + } +} + +// ----------------------------------------------------------------------- + +USHORT ImplEntryList::InsertEntry( USHORT nPos, ImplEntryType* pNewEntry, BOOL bSort ) +{ + if ( !!pNewEntry->maImage ) + mnImages++; + + if ( !bSort || !Count() ) + { + Insert( pNewEntry, nPos ); + } + else + { + const XubString& rStr = pNewEntry->maStr; + ULONG nLow, nHigh, nMid; + + nHigh = Count(); + + const International& rIntl = Application::GetSettings().GetInternational(); + ImplEntryType* pTemp = GetEntry( (USHORT)(nHigh-1) ); + StringCompare eComp = rIntl.Compare( rStr, pTemp->maStr ); + + // Schnelles Einfuegen bei sortierten Daten + if ( eComp != COMPARE_LESS ) + { + Insert( pNewEntry, LIST_APPEND ); + } + else + { + nLow = mnMRUCount; + pTemp = (ImplEntryType*)GetEntry( (USHORT)nLow ); + eComp = rIntl.Compare( rStr, pTemp->maStr ); + if ( eComp != COMPARE_GREATER ) + { + Insert( pNewEntry, (ULONG)0 ); + } + else + { + // Binaeres Suchen + nHigh--; + do + { + nMid = (nLow + nHigh) / 2; + pTemp = (ImplEntryType*)GetObject( nMid ); + eComp = rIntl.Compare( 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 ); + } + } + } + + return (USHORT)GetPos( pNewEntry ); +} + +// ----------------------------------------------------------------------- + +void ImplEntryList::RemoveEntry( USHORT nPos ) +{ + ImplEntryType* pImplEntry = (ImplEntryType*)List::Remove( nPos ); + if ( pImplEntry ) + { + if ( !!pImplEntry->maImage ) + mnImages--; + + delete pImplEntry; + } +} + +// ----------------------------------------------------------------------- + +USHORT ImplEntryList::FindEntry( const XubString& rStr, MatchMode nMatchMode, USHORT nMatchLen, USHORT nStart, BOOL bForward ) const +{ + BOOL bEqual; + USHORT nPos = LISTBOX_ENTRY_NOTFOUND; + USHORT nEntryCount = GetEntryCount(); + if ( !bForward ) + nStart++; // wird sofort dekrementiert + for ( USHORT n = nStart; bForward ? ( n < nEntryCount ) : n; ) + { + if ( !bForward ) + n--; + + ImplEntryType* pImplEntry = GetEntry( n ); + if ( nMatchMode == MATCH_CASE ) + bEqual = pImplEntry->maStr.Equals( rStr, 0, nMatchLen ); + else + bEqual = pImplEntry->maStr.EqualsIgnoreCaseAscii( rStr, 0, nMatchLen ); + if ( bEqual ) + { + // Wenn Case-Insensitiv matching, dann einen Eintrag bevorzugen, + // der trotzdem case-sensitiv matched. + if ( (nMatchMode == MATCH_CASE) || + ((nMatchMode == MATCH_BEST) && (pImplEntry->maStr.Equals( rStr, 0, nMatchLen ))) ) + { + nPos = n; + break; + } + else if ( nPos == LISTBOX_ENTRY_NOTFOUND ) + nPos = n; // Bei Case-Insensitiv gewinnt der erste, wenn keiner 100% + } + + if ( bForward ) + n++; + } + return nPos; +} + +// ----------------------------------------------------------------------- + +USHORT ImplEntryList::FindEntry( const void* pData ) const +{ + USHORT nPos = LISTBOX_ENTRY_NOTFOUND; + for ( USHORT n = GetEntryCount(); n; ) + { + ImplEntryType* pImplEntry = GetEntry( --n ); + if ( pImplEntry->mpUserData == pData ) + { + nPos = n; + break; + } + } + return nPos; +} + +// ----------------------------------------------------------------------- + +XubString ImplEntryList::GetEntryText( USHORT nPos ) const +{ + XubString aEntryText; + ImplEntryType* pImplEntry = GetEntry( nPos ); + if ( pImplEntry ) + aEntryText = pImplEntry->maStr; + return aEntryText; +} + +// ----------------------------------------------------------------------- + +BOOL ImplEntryList::HasEntryImage( USHORT nPos ) const +{ + BOOL bImage = FALSE; + ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); + if ( pImplEntry ) + bImage = !!pImplEntry->maImage; + return bImage; +} + +// ----------------------------------------------------------------------- + +Image ImplEntryList::GetEntryImage( USHORT nPos ) const +{ + Image aImage; + ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); + if ( pImplEntry ) + aImage = pImplEntry->maImage; + return aImage; +} + +// ----------------------------------------------------------------------- + +void ImplEntryList::SetEntryData( USHORT nPos, void* pNewData ) +{ + ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); + if ( pImplEntry ) + pImplEntry->mpUserData = pNewData; +} + +// ----------------------------------------------------------------------- + +void* ImplEntryList::GetEntryData( USHORT nPos ) const +{ + ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); + return pImplEntry ? pImplEntry->mpUserData : NULL; +} + +// ----------------------------------------------------------------------- + +USHORT ImplEntryList::GetSelectEntryCount() const +{ + USHORT nSelCount = 0; + for ( USHORT n = GetEntryCount(); n; ) + { + ImplEntryType* pImplEntry = GetEntry( --n ); + if ( pImplEntry->mbIsSelected ) + nSelCount++; + } + return nSelCount; +} + +// ----------------------------------------------------------------------- + +XubString ImplEntryList::GetSelectEntry( USHORT nIndex ) const +{ + return GetEntryText( GetSelectEntryPos( nIndex ) ); +} + +// ----------------------------------------------------------------------- + +USHORT ImplEntryList::GetSelectEntryPos( USHORT nIndex ) const +{ + USHORT nSelEntryPos = LISTBOX_ENTRY_NOTFOUND; + USHORT nSel = 0; + USHORT nEntryCount = GetEntryCount(); + + for ( USHORT n = 0; n < nEntryCount; n++ ) + { + ImplEntryType* pImplEntry = GetEntry( n ); + if ( pImplEntry->mbIsSelected ) + { + if ( nSel == nIndex ) + { + nSelEntryPos = n; + break; + } + nSel++; + } + } + + return nSelEntryPos; +} + +// ----------------------------------------------------------------------- + +BOOL ImplEntryList::IsEntrySelected( const XubString& rStr ) const +{ + return IsEntryPosSelected( FindEntry( rStr ) ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplEntryList::IsEntryPosSelected( USHORT nIndex ) const +{ + ImplEntryType* pImplEntry = GetEntry( nIndex ); + return pImplEntry ? pImplEntry->mbIsSelected : FALSE; +} + +// ----------------------------------------------------------------------- + +void ImplEntryList::SetNoSelection() +{ + USHORT nEntryCount = GetEntryCount(); + for ( USHORT n = 0; n < nEntryCount; n++ ) + SelectEntry( n, FALSE ); +} + +// ======================================================================= + +ImplListBoxWindow::ImplListBoxWindow( Window* pParent, WinBits nWinStyle ) : + Control( pParent, 0 ) +{ + mpEntryList = new ImplEntryList; + + 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; + mbGrabFocus = FALSE; + mbUserDrawEnabled = FALSE; + mbInUserDraw = FALSE; + mbReadOnly = FALSE; + mbSimpleMode = ( nWinStyle & WB_SIMPLEMODE ) ? TRUE : FALSE; + mbSort = ( nWinStyle & WB_SORT ) ? TRUE : FALSE; + + mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; + mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; + mnSeparatorPos = LISTBOX_ENTRY_NOTFOUND; + + SetLineColor(); + SetTextFillColor(); + SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); + + maSearchTimeout.SetTimeout( 500 ); + maSearchTimeout.SetTimeoutHdl( LINK( this, ImplListBoxWindow, SearchStringTimeout ) ); + + ImplInitSettings( TRUE, TRUE, TRUE ); + ImplCalcMetrics(); +} + +// ----------------------------------------------------------------------- + +ImplListBoxWindow::~ImplListBoxWindow() +{ + maSearchTimeout.Stop(); + delete mpEntryList; +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::ImplInitSettings( BOOL bFont, BOOL bForeground, BOOL bBackground ) +{ + ImplInitFieldSettings( this, bFont, bForeground, bBackground ); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::ImplCalcMetrics() +{ + mnMaxWidth = 0; + mnMaxTxtWidth = 0; + mnMaxImgWidth = 0; + mnMaxImgTxtWidth= 0; + mnMaxImgHeight = 0; + + mnTextHeight = (USHORT)GetTextHeight(); + mnMaxTxtHeight = mnTextHeight + mnBorder; + mnMaxHeight = mnMaxTxtHeight; + + if ( maUserItemSize.Height() > mnMaxHeight ) + mnMaxHeight = (USHORT) maUserItemSize.Height(); + if ( maUserItemSize.Width() > mnMaxWidth ) + mnMaxWidth= (USHORT) maUserItemSize.Width(); + + for ( USHORT n = mpEntryList->GetEntryCount(); n; ) + { + const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( --n ); + ImplCalcEntryMetrics( *pEntry, TRUE ); + } + + Size aSz( GetOutputSizePixel().Width(), mnMaxHeight ); + maFocusRect.SetSize( aSz ); +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( ImplListBoxWindow, SearchStringTimeout, Timer*, EMPTYARG ) +{ + maSearchStr.Erase(); + return 1; +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::Clear() +{ + mpEntryList->Clear(); + + mnMaxHeight = mnMaxTxtHeight; + mnMaxWidth = 0; + mnMaxTxtWidth = 0; + mnMaxImgTxtWidth= 0; + mnMaxImgWidth = 0; + mnMaxImgHeight = 0; + mnTop = 0; + mnLeft = 0; + mbImgsDiffSz = FALSE; + + Invalidate(); +} + +void ImplListBoxWindow::SetUserItemSize( const Size& rSz ) +{ + maUserItemSize = rSz; + ImplCalcMetrics(); +} + +// ----------------------------------------------------------------------- + +struct ImplEntryMetrics +{ + BOOL bText; + BOOL bImage; + USHORT nEntryWidth; + USHORT nEntryHeight; + USHORT nTextWidth; + USHORT nImgWidth; + USHORT nImgHeight; +}; + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::ImplCalcEntryMetrics( const ImplEntryType& rEntry, BOOL bUpdateMetrics ) +{ + // 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; + aMetrics.nEntryWidth = 0; + aMetrics.nEntryHeight = 0; + aMetrics.nTextWidth = 0; + aMetrics.nImgWidth = 0; + aMetrics.nImgHeight = 0; + + if ( aMetrics.bText ) + { + aMetrics.nTextWidth = (USHORT)GetTextWidth( rEntry.maStr ); + if( bUpdateMetrics && ( aMetrics.nTextWidth > mnMaxTxtWidth ) ) + mnMaxTxtWidth = aMetrics.nTextWidth; + aMetrics.nEntryWidth = mnMaxTxtWidth; + } + if ( aMetrics.bImage ) + { + Size aImgSz = rEntry.maImage.GetSizePixel(); + 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( aMetrics.nImgWidth > mnMaxImgWidth ) + mnMaxImgWidth = aMetrics.nImgWidth; + if( aMetrics.nImgHeight > mnMaxImgHeight ) + mnMaxImgHeight = aMetrics.nImgHeight; + + mnMaxImgTxtWidth = Max( mnMaxImgTxtWidth, aMetrics.nTextWidth ); + } + } + if ( IsUserDrawEnabled() || aMetrics.bImage ) + { + aMetrics.nEntryWidth = Max( aMetrics.nImgWidth, (USHORT)maUserItemSize.Width() ); + if ( aMetrics.bText ) + aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE; + aMetrics.nEntryHeight = Max( mnMaxImgHeight, (USHORT)maUserItemSize.Height() ) + 2; + } + + if ( bUpdateMetrics ) + { + if ( aMetrics.nEntryWidth > mnMaxWidth ) + mnMaxWidth = aMetrics.nEntryWidth; + if ( aMetrics.nEntryHeight > mnMaxHeight ) + mnMaxHeight = aMetrics.nEntryHeight; + } +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::ImplCallSelect() +{ + if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() ) + { + // Insert the selected entry as MRU, if not allready first MRU + USHORT nSelected = GetEntryList()->GetSelectEntryPos( 0 ); + USHORT nMRUCount = GetEntryList()->GetMRUCount(); + String aSelected = GetEntryList()->GetEntryText( nSelected ); + USHORT nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected ); + if ( nFirstMatchingEntryPos || !nMRUCount ) + { + BOOL bSelectNewEntry = FALSE; + if ( nFirstMatchingEntryPos < nMRUCount ) + { + RemoveEntry( nFirstMatchingEntryPos ); + nMRUCount--; + if ( nFirstMatchingEntryPos == nSelected ) + bSelectNewEntry = TRUE; + } + else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() ) + { + RemoveEntry( nMRUCount - 1 ); + nMRUCount--; + } + + ImplEntryType* pNewEntry = new ImplEntryType( aSelected ); + pNewEntry->mbIsSelected = bSelectNewEntry; + GetEntryList()->InsertEntry( 0, pNewEntry, FALSE ); + GetEntryList()->SetMRUCount( ++nMRUCount ); + SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); + maMRUChangedHdl.Call( NULL ); + } + } + + maSelectHdl.Call( NULL ); + mbSelectionChanged = FALSE; +} + +// ----------------------------------------------------------------------- + +USHORT ImplListBoxWindow::InsertEntry( USHORT nPos, ImplEntryType* pNewEntry ) +{ + USHORT nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort ); + + ImplCalcEntryMetrics( *pNewEntry, TRUE ); + return nNewPos; +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::RemoveEntry( USHORT nPos ) +{ + mpEntryList->RemoveEntry( nPos ); + ImplCalcMetrics(); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + mbMouseMoveSelect = FALSE; // Nur bis zum ersten MouseButtonDown + + if ( !IsReadOnly() ) + { + if( rMEvt.GetClicks() == 1 ) + { + USHORT nSelect = (USHORT) ( ( rMEvt.GetPosPixel().Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop; + if( nSelect < mpEntryList->GetEntryCount() ) + { + if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) + mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 ); + else + mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; + + mnCurrentPos = nSelect; + mbTrackingSelect = TRUE; + SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ); + 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 ( !mbMulti && mbMouseMoveSelect && mpEntryList->GetEntryCount() && !rMEvt.IsLeaveWindow() ) + { + Point aPoint; + Rectangle aRect( aPoint, GetOutputSizePixel() ); + if( aRect.IsInside( rMEvt.GetPosPixel() ) ) + { + USHORT nSelect = (USHORT) ( ( rMEvt.GetPosPixel().Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop; + nSelect = Min( nSelect, (USHORT) ( mnTop + mnMaxVisibleEntries ) ); + nSelect = Min( nSelect, (USHORT) ( mpEntryList->GetEntryCount() - 1 ) ); + if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() || ( nSelect != GetEntryList()->GetSelectEntryPos( 0 ) ) ) + { + mbTrackingSelect = TRUE; + SelectEntries( nSelect, LET_TRACKING, FALSE, FALSE ); + 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; + StartTracking( STARTTRACK_SCROLLREPEAT ); + } + } + } +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::SelectEntry( USHORT nPos, BOOL bSelect ) +{ + if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect ) + { + HideFocus(); + if( bSelect ) + { + if( !mbMulti ) + { + // Selektierten Eintrag deselektieren + USHORT nDeselect = GetEntryList()->GetSelectEntryPos( 0 ); + if( nDeselect != LISTBOX_ENTRY_NOTFOUND ) + { + //SelectEntryPos( nDeselect, FALSE ); + GetEntryList()->SelectEntry( nDeselect, FALSE ); + if ( IsUpdateMode() && IsReallyVisible() ) + ImplPaint( nDeselect, TRUE ); + } + } + mpEntryList->SelectEntry( nPos, TRUE ); + mnCurrentPos = nPos; + if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() ) + { + ImplPaint( nPos ); + if ( !IsVisible( nPos ) ) + SetTopEntry( nPos ); + } + } + else + { + mpEntryList->SelectEntry( nPos, FALSE ); + ImplPaint( nPos, TRUE ); + } + } +} + +// ----------------------------------------------------------------------- + +BOOL ImplListBoxWindow::SelectEntries( USHORT nSelect, LB_EVENT_TYPE eLET, BOOL bShift, BOOL bCtrl ) +{ + BOOL bFocusChanged = FALSE; + BOOL bSelectionChanged = FALSE; + + if( IsEnabled() ) + { + // Hier (Single-ListBox) kann nur ein Eintrag deselektiert werden + if( !mbMulti ) + { + USHORT nDeselect = mpEntryList->GetSelectEntryPos( 0 ); + if( nSelect != nDeselect ) + { + SelectEntry( nSelect, TRUE ); + mpEntryList->SetLastSelected( nSelect ); + bFocusChanged = TRUE; + bSelectionChanged = TRUE; + } + } + // MultiListBox ohne Modifier + else if( mbSimpleMode && !bCtrl && !bShift ) + { + USHORT nEntryCount = mpEntryList->GetEntryCount(); + for ( USHORT nPos = 0; nPos < nEntryCount; nPos++ ) + { + BOOL bSelect = nPos == nSelect; + if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect ) + { + SelectEntry( nPos, bSelect ); + bFocusChanged = TRUE; + bSelectionChanged = TRUE; + } + } + mpEntryList->SetLastSelected( nSelect ); + mpEntryList->SetSelectionAnchor( nSelect ); + } + // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode + else if( ( !mbSimpleMode /* && !bShift */ ) || ( mbSimpleMode && ( bCtrl || bShift ) ) ) + { + // Space fuer Selektionswechsel + if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) ) + { + SelectEntry( nSelect, !mpEntryList->IsEntryPosSelected( nSelect ) ); + mpEntryList->SetLastSelected( nSelect ); + mpEntryList->SetSelectionAnchor( nSelect ); + if ( !mpEntryList->IsEntryPosSelected( nSelect ) ) + mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND ); + bFocusChanged = TRUE; + bSelectionChanged = TRUE; + } + else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) || + ( bShift && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) ) + { + mnCurrentPos = nSelect; + bFocusChanged = TRUE; + + USHORT nAnchor = mpEntryList->GetSelectionAnchor(); + if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && ( mpEntryList->GetSelectEntryCount() ) ) + { + nAnchor = mpEntryList->GetSelectEntryPos( mpEntryList->GetSelectEntryCount() - 1 ); + } + if( nAnchor != LISTBOX_ENTRY_NOTFOUND ) + { + // Alle Eintraege vom Anchor bis nSelect muessen selektiert sein + USHORT nStart = Min( nSelect, nAnchor ); + USHORT nEnd = Max( nSelect, nAnchor ); + for ( USHORT n = nStart; n <= nEnd; n++ ) + { + if ( !mpEntryList->IsEntryPosSelected( n ) ) + { + SelectEntry( n, TRUE ); + bSelectionChanged = TRUE; + } + } + + // Ggf. muss noch was deselektiert werden... + USHORT nLast = mpEntryList->GetLastSelected(); + if ( nLast != LISTBOX_ENTRY_NOTFOUND ) + { + if ( ( nLast > nSelect ) && ( nLast > nAnchor ) ) + { + for ( USHORT n = nSelect+1; n <= nLast; n++ ) + { + if ( mpEntryList->IsEntryPosSelected( n ) ) + { + SelectEntry( n, FALSE ); + bSelectionChanged = TRUE; + } + } + } + else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) ) + { + for ( USHORT n = nLast; n < nSelect; n++ ) + { + if ( mpEntryList->IsEntryPosSelected( n ) ) + { + SelectEntry( n, FALSE ); + bSelectionChanged = TRUE; + } + } + } + } + mpEntryList->SetLastSelected( nSelect ); + } + } + else if( eLET != LET_TRACKING ) + { + HideFocus(); + ImplPaint( nSelect, TRUE ); + bFocusChanged = TRUE; + } + } + else if( bShift ) + { + bFocusChanged = TRUE; + } + + if( bSelectionChanged ) + mbSelectionChanged = TRUE; + + if( bFocusChanged ) + { + maFocusRect.SetPos( Point( 0, ( nSelect - mnTop ) * mnMaxHeight ) ); + if( HasFocus() ) + ShowFocus( maFocusRect ); + } + } + return bSelectionChanged; +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) +{ + Point aPoint; + Rectangle aRect( aPoint, GetOutputSizePixel() ); + 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, TRUE ); + mbTrackingSelect = FALSE; + if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND ) + { + maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) ); + ShowFocus( maFocusRect ); + } + } + } + + mbTrack = FALSE; + } + else + { + 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 = TRUE; + mbTrack = FALSE; + } + } + + if( bTrackOrQuickClick ) + { + MouseEvent aMEvt = rTEvt.GetMouseEvent(); + Point aPt( aMEvt.GetPosPixel() ); + BOOL bShift = aMEvt.IsShift(); + BOOL bCtrl = aMEvt.IsMod1(); + + USHORT nSelect = LISTBOX_ENTRY_NOTFOUND; + if( aPt.Y() < 0 ) + { + nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0; + if( nSelect < mnTop ) + SetTopEntry( mnTop-1 ); + } + else if( aPt.Y() > GetOutputSizePixel().Height() ) + { + nSelect = Min( (USHORT)(mnCurrentPos+1), (USHORT)(mpEntryList->GetEntryCount()-1) ); + if( nSelect >= mnTop + mnMaxVisibleEntries ) + SetTopEntry( mnTop+1 ); + } + else + { + nSelect = (USHORT) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop; + nSelect = Min( nSelect, (USHORT) ( mnTop + mnMaxVisibleEntries ) ); + nSelect = Min( nSelect, (USHORT) ( mpEntryList->GetEntryCount() - 1 ) ); + } + + if ( bInside ) + { + if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() ) + { + mbTrackingSelect = TRUE; + SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ); + mbTrackingSelect = FALSE; + } + } + else + { + if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) + { + mbTrackingSelect = TRUE; + SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), FALSE ); + mbTrackingSelect = FALSE; + } + } + mnCurrentPos = nSelect; + } + } +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::KeyInput( const KeyEvent& rKEvt ) +{ + if( !ProcessKeyInput( rKEvt ) ) + Control::KeyInput( rKEvt ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) +{ + // zu selektierender Eintrag + USHORT nSelect = LISTBOX_ENTRY_NOTFOUND; + LB_EVENT_TYPE eLET = LET_KEYMOVE; + + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + BOOL bShift = aKeyCode.IsShift(); + BOOL bCtrl = aKeyCode.IsMod1(); + BOOL bMod2 = aKeyCode.IsMod2(); + BOOL bDone = FALSE; + + switch( aKeyCode.GetCode() ) + { + case KEY_UP: + { + if ( IsReadOnly() ) + { + if ( GetTopEntry() ) + SetTopEntry( GetTopEntry()-1 ); + } + else if ( !bMod2 ) + { + if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND; + else if ( mnCurrentPos ) + nSelect = mnCurrentPos - 1; + + if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) ) + SetTopEntry( mnTop-1 ); + + bDone = TRUE; + } + } + break; + + case KEY_DOWN: + { + if ( IsReadOnly() ) + { + SetTopEntry( GetTopEntry()+1 ); + } + else if ( !bMod2 ) + { + if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND; + else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) + nSelect = mnCurrentPos+1; + + if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= ( mnTop + mnMaxVisibleEntries ) ) ) + SetTopEntry( mnTop+1 ); + + bDone = TRUE; + } + } + break; + + case KEY_PAGEUP: + { + if ( IsReadOnly() ) + { + SetTopEntry( ( mnTop > mnMaxVisibleEntries ) ? + (mnTop-mnMaxVisibleEntries) : 0 ); + } + else if ( !bCtrl && !bMod2 ) + { + if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND; + else if ( mnCurrentPos ) + { + if( mnCurrentPos == mnTop ) + SetTopEntry( ( mnTop > mnMaxVisibleEntries ) ? + ( mnTop-mnMaxVisibleEntries+1 ) : 0 ); + nSelect = mnTop; + } + bDone = TRUE; + } + } + break; + + case KEY_PAGEDOWN: + { + if ( IsReadOnly() ) + { + SetTopEntry( mnTop + mnMaxVisibleEntries ); + } + else if ( !bCtrl && !bMod2 ) + { + if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND; + else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) + { + USHORT nCount = mpEntryList->GetEntryCount(); + USHORT nTmp = Min( mnMaxVisibleEntries, nCount ); + nTmp += mnTop - 1; + if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 ) + { + long nTmp2 = Min( (long)(nCount-mnMaxVisibleEntries), (long)((long)mnTop+(long)mnMaxVisibleEntries-1) ); + nTmp2 = Max( (long)0 , nTmp2 ); + nTmp = (USHORT)(nTmp2+(mnMaxVisibleEntries-1) ); + SetTopEntry( (USHORT)nTmp2 ); + } + nSelect = nTmp; + } + bDone = TRUE; + } + } + break; + + case KEY_HOME: + { + if ( IsReadOnly() ) + { + SetTopEntry( 0 ); + } + else if ( !bCtrl && !bMod2 ) + { + if ( mnCurrentPos ) + { + nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND; + if( mnTop != 0 ) + SetTopEntry( 0 ); + + bDone = TRUE; + } + } + } + break; + + case KEY_END: + { + if ( IsReadOnly() ) + { + SetTopEntry( 0xFFFF ); + } + else if ( !bCtrl && !bMod2 ) + { + if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND; + else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) + { + USHORT nCount = mpEntryList->GetEntryCount(); + nSelect = nCount - 1; + if( nCount > mnMaxVisibleEntries ) + SetTopEntry( nCount - mnMaxVisibleEntries ); + } + bDone = TRUE; + } + } + break; + + case KEY_LEFT: + { + if ( !bCtrl && !bMod2 ) + { + ScrollHorz( -HORZ_SCROLL ); + bDone = TRUE; + } + } + break; + + case KEY_RIGHT: + { + if ( !bCtrl && !bMod2 ) + { + ScrollHorz( HORZ_SCROLL ); + bDone = TRUE; + } + } + break; + + case KEY_RETURN: + { + if ( !bMod2 && !IsReadOnly() ) + { + mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); + ImplCallSelect(); + bDone = FALSE; // RETURN nicht abfangen. + } + } + break; + + case KEY_SPACE: + { + if ( !bMod2 && !IsReadOnly() ) + { + if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) ) ) + { + nSelect = mnCurrentPos; + eLET = LET_KEYSPACE; + } + bDone = TRUE; + } + } + break; + + default: + { + xub_Unicode c = rKEvt.GetCharCode(); + + if ( !IsReadOnly() && (c >= 32) && (c != 127) && + !rKEvt.GetKeyCode().IsControlMod() ) + { + maSearchStr += c; + XubString aTmpSearch( maSearchStr ); + + nSelect = mpEntryList->FindEntry( aTmpSearch, MATCH_IGNORECASE, aTmpSearch.Len(), mnCurrentPos ); + if ( (nSelect == LISTBOX_ENTRY_NOTFOUND) && (aTmpSearch.Len() > 1) ) + { + // Wenn alles die gleichen Buchstaben, dann anderer Such-Modus + BOOL bAllEqual = TRUE; + for ( USHORT n = aTmpSearch.Len(); n && bAllEqual; ) + bAllEqual = aTmpSearch.GetChar( --n ) == c; + if ( bAllEqual ) + { + aTmpSearch = c; + nSelect = mpEntryList->FindEntry( aTmpSearch, MATCH_IGNORECASE, aTmpSearch.Len(), mnCurrentPos+1 ); + } + } + if ( nSelect == LISTBOX_ENTRY_NOTFOUND ) + nSelect = mpEntryList->FindEntry( aTmpSearch, MATCH_IGNORECASE, aTmpSearch.Len(), 0 ); + + if ( nSelect != LISTBOX_ENTRY_NOTFOUND ) + { + if( nSelect < mnTop ) + SetTopEntry( nSelect ); + else if( nSelect >= (mnTop + mnMaxVisibleEntries) ) + SetTopEntry( nSelect - mnMaxVisibleEntries + 1 ); + + if ( nSelect == mnCurrentPos ) + nSelect = LISTBOX_ENTRY_NOTFOUND; + + maSearchTimeout.Start(); + } + else + maSearchStr.Erase(); + bDone = TRUE; + } + } + } + + if ( (nSelect != LISTBOX_ENTRY_NOTFOUND) && + ((nSelect != mnCurrentPos ) || ( eLET == LET_KEYSPACE)) ) + { + DBG_ASSERT( (nSelect != mnCurrentPos) || mbMulti, "ImplListBox: Selecting same Entry" ); + mnCurrentPos = nSelect; + if ( SelectEntries( nSelect, eLET, bShift, bCtrl ) ) + { + mbTravelSelect = TRUE; + mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); + ImplCallSelect(); + mbTravelSelect = FALSE; + } + } + + return bDone; +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::ImplPaint( USHORT nPos, BOOL bErase ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + long nWidth = GetOutputSizePixel().Width(); + long nY = ( nPos - mnTop ) * mnMaxHeight; + Rectangle aRect( Point( 0, nY ), Size( nWidth, mnMaxHeight ) ); + + if( IsEnabled() ) + { + if( mpEntryList->IsEntryPosSelected( nPos ) ) + { + SetTextColor( rStyleSettings.GetHighlightTextColor() ); + SetFillColor( rStyleSettings.GetHighlightColor() ); + DrawRect( aRect ); + } + else + { + ImplInitSettings( FALSE, TRUE, FALSE ); + if( bErase ) + Erase( aRect ); + } + } + else // Disabled + { + SetTextColor( rStyleSettings.GetDisableColor() ); + //SetFillColor( rStyleSettings.Get???Color() ); + //DrawRect( aRect ); + if( bErase ) + Erase( aRect ); + } + + if ( IsUserDrawEnabled() ) + { + mbInUserDraw = TRUE; + mnUserDrawEntry = nPos; + aRect.Left() -= mnLeft; + if ( nPos < GetEntryList()->GetMRUCount() ) + nPos = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos ), MATCH_CASE, STRING_LEN, GetEntryList()->GetMRUCount() ); + nPos -= GetEntryList()->GetMRUCount(); + UserDrawEvent aUDEvt( this, aRect, nPos, 0 ); + maUserDrawHdl.Call( &aUDEvt ); + mbInUserDraw = FALSE; + } + else + { + DrawEntry( nPos, TRUE, TRUE ); + } +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos ) +{ + // 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; + + if( bDrawImage && mpEntryList->HasImages() ) + { + Image aImage = mpEntryList->GetEntryImage( nPos ); + if( !!aImage ) + { + Size aImgSz = aImage.GetSizePixel(); + Point aPtImg( mnBorder - mnLeft, nY + ( ( mnMaxHeight - aImgSz.Height() ) / 2 ) ); + + if ( !IsZoom() ) + { + DrawImage( aPtImg, aImage ); + } + else + { + aImgSz.Width() = CalcZoom( aImgSz.Width() ); + aImgSz.Height() = CalcZoom( aImgSz.Height() ); + DrawImage( aPtImg, aImgSz, aImage ); + } + } + } + + if( bDrawText ) + { + XubString aStr( mpEntryList->GetEntryText( nPos ) ); + if ( aStr.Len() ) + { + Point aPtTxt( mnBorder - mnLeft, nY + ( ( mnMaxHeight - mnMaxTxtHeight ) / 2 ) ); + if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) ) + { + USHORT nMaxWidth = Max( mnMaxImgWidth, (USHORT)maUserItemSize.Width() ); + aPtTxt.X() += nMaxWidth + IMG_TXT_DISTANCE; + } + DrawText( aPtTxt, aStr ); + } + } + + 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() += mnMaxHeight-1; + Point aEndPos( aStartPos ); + aEndPos.X() = GetOutputSizePixel().Width(); + DrawLine( aStartPos, aEndPos ); + SetLineColor( aOldLineColor ); + } +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::Paint( const Rectangle& rRect ) +{ + USHORT nCount = mpEntryList->GetEntryCount(); + + if( HasFocus() ) + HideFocus(); + + long nY = 0; // + mnBorder; + long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; + + for( USHORT i = (USHORT)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ ) + { + if( nY + mnMaxHeight >= rRect.Top() && + nY <= rRect.Bottom() + mnMaxHeight ) + { + ImplPaint( i ); + } + nY += mnMaxHeight; + } + + maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) ); + if( HasFocus() ) + ShowFocus( maFocusRect ); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::Resize() +{ + Size aSz( GetOutputSizePixel().Width(), mnMaxHeight ); + maFocusRect.SetSize( aSz ); + mnMaxVisibleEntries = (USHORT) ( GetOutputSizePixel().Height() / mnMaxHeight ); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::GetFocus() +{ + USHORT nPos = mnCurrentPos; + if ( nPos == LISTBOX_ENTRY_NOTFOUND ) + nPos = 0; + maFocusRect.SetPos( Point( 0, ( nPos - mnTop ) * mnMaxHeight ) ); + ShowFocus( maFocusRect ); + Control::GetFocus(); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::LoseFocus() +{ + HideFocus(); + 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( USHORT nTop ) +{ + USHORT nMaxTop = 0; + if ( GetEntryList()->GetEntryCount() > mnMaxVisibleEntries ) + nMaxTop = GetEntryList()->GetEntryCount() - mnMaxVisibleEntries; + nTop = Min( nTop, nMaxTop ); + if ( nTop != mnTop ) + { + HideFocus(); + long nDiff = ( mnTop - nTop ) * mnMaxHeight; + mnTop = nTop; + Scroll( 0, nDiff ); + maFocusRect.Top() += nDiff; + maFocusRect.Bottom() += nDiff; + if( HasFocus() ) + ShowFocus( maFocusRect ); + maScrollHdl.Call( this ); + } +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::SetLeftIndent( USHORT n ) +{ + ScrollHorz( n - mnLeft ); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::ScrollHorz( short n ) +{ + short nDiff = 0; + if ( n > 0 ) + { + long nWidth = GetOutputSizePixel().Width(); + if( ( mnMaxWidth - mnLeft + n ) > nWidth ) + nDiff = n; + } + else if ( n < 0 ) + { + if( mnLeft ) + { + USHORT nAbs = -n; + nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft ); + } + } + + if ( nDiff ) + { + HideFocus(); + mnLeft += nDiff; + Scroll( -nDiff, 0 ); + if( HasFocus() ) + ShowFocus( maFocusRect ); + maScrollHdl.Call( this ); + } +} + +// ----------------------------------------------------------------------- + +Size ImplListBoxWindow::CalcSize( USHORT nMaxLines ) const +{ + Size aSz; +// USHORT nL = Min( nMaxLines, mpEntryList->GetEntryCount() ); + aSz.Height() = nMaxLines * mnMaxHeight; + aSz.Width() = mnMaxWidth + 2*mnBorder; + return aSz; +} + +// ----------------------------------------------------------------------- + +void ImplListBoxWindow::StateChanged( StateChangedType nType ) +{ + Control::StateChanged( nType ); + + if ( nType == STATE_CHANGE_ZOOM ) + { + ImplInitSettings( TRUE, FALSE, FALSE ); + ImplCalcMetrics(); + Invalidate(); + } + else if ( nType == STATE_CHANGE_UPDATEMODE ) + { + if ( IsUpdateMode() && IsReallyVisible() ) + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFONT ) + { + ImplInitSettings( TRUE, FALSE, FALSE ); + ImplCalcMetrics(); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) + { + ImplInitSettings( FALSE, TRUE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) + { + ImplInitSettings( FALSE, FALSE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +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)) ) + { + ImplInitSettings( TRUE, TRUE, TRUE ); + ImplCalcMetrics(); + Invalidate(); + } +} + +// ======================================================================= + +ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) : + Control( pParent, nWinStyle ), + maLBWindow( this, nWinStyle&(~WB_BORDER) ) +{ + 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 ) ? TRUE : FALSE; + + maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) ); + maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) ); + 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 ); +} + +// ----------------------------------------------------------------------- + +USHORT ImplListBox::InsertEntry( USHORT nPos, const XubString& rStr ) +{ + ImplEntryType* pNewEntry = new ImplEntryType( rStr ); + USHORT nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); + StateChanged( STATE_CHANGE_DATA ); + return nNewPos; +} + +// ----------------------------------------------------------------------- + +USHORT ImplListBox::InsertEntry( USHORT nPos, const Image& rImage ) +{ + ImplEntryType* pNewEntry = new ImplEntryType( rImage ); + USHORT nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); + StateChanged( STATE_CHANGE_DATA ); + return nNewPos; +} + +// ----------------------------------------------------------------------- + +USHORT ImplListBox::InsertEntry( USHORT nPos, const XubString& rStr, const Image& rImage ) +{ + ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage ); + USHORT nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); + StateChanged( STATE_CHANGE_DATA ); + return nNewPos; +} + +// ----------------------------------------------------------------------- + +void ImplListBox::RemoveEntry( USHORT nPos ) +{ + maLBWindow.RemoveEntry( nPos ); + StateChanged( STATE_CHANGE_DATA ); +} + +// ----------------------------------------------------------------------- + +void ImplListBox::SelectEntry( USHORT nPos, BOOL bSelect ) +{ + maLBWindow.SelectEntry( nPos, bSelect ); +} + +// ----------------------------------------------------------------------- + +void ImplListBox::SetNoSelection() +{ + USHORT nSelected = GetEntryList()->GetSelectEntryCount(); + for ( USHORT n = 0; n < nSelected; n++ ) + { + USHORT nS = GetEntryList()->GetSelectEntryPos( n ); + SelectEntry( nS, FALSE ); + } + maLBWindow.GetEntryList()->SetNoSelection(); +} + +// ----------------------------------------------------------------------- + +void ImplListBox::GetFocus() +{ + maLBWindow.GrabFocus(); +} + +// ----------------------------------------------------------------------- + +void ImplListBox::Resize() +{ + ImplResizeControls(); + ImplCheckScrollBars(); +} + + +// ----------------------------------------------------------------------- + +IMPL_LINK( ImplListBox, MRUChanged, void*, EMPTYARG ) +{ + StateChanged( STATE_CHANGE_DATA ); + return 1; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( ImplListBox, LBWindowScrolled, void*, EMPTYARG ) +{ + mpVScrollBar->SetThumbPos( GetTopEntry() ); + mpHScrollBar->SetThumbPos( GetLeftIndent() ); + + maScrollHdl.Call( this ); + + return 1; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB ) +{ + USHORT nPos = (USHORT) pSB->GetThumbPos(); + if( pSB == mpVScrollBar ) + SetTopEntry( nPos ); + else if( pSB == mpHScrollBar ) + SetLeftIndent( nPos ); + + return 1; +} + +// ----------------------------------------------------------------------- + +void ImplListBox::ImplCheckScrollBars() +{ + BOOL bArrange = FALSE; + + Size aOutSz = GetOutputSizePixel(); + USHORT nEntries = GetEntryList()->GetEntryCount(); + USHORT nMaxVisEntries = (USHORT) (aOutSz.Height() / GetEntryHeight()); + + // vert. ScrollBar + if( nEntries > nMaxVisEntries ) + { + if( !mbVScroll ) + bArrange = TRUE; + mbVScroll = TRUE; + + // Ueberpruefung des rausgescrollten Bereichs + SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... + } + else + { + if( mbVScroll ) + bArrange = TRUE; + mbVScroll = FALSE; + SetTopEntry( 0 ); + } + + // horz. ScrollBar + if( mbAutoHScroll ) + { + long nWidth = (USHORT) aOutSz.Width(); + if ( mbVScroll ) + nWidth -= mpVScrollBar->GetSizePixel().Width(); + + long nMaxWidth = GetMaxEntryWidth(); + if( nWidth < nMaxWidth ) + { + if( !mbHScroll ) + bArrange = TRUE; + mbHScroll = TRUE; + + if ( !mbVScroll ) // ggf. brauchen wir jetzt doch einen + { + nMaxVisEntries = (USHORT) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() ); + if( nEntries > nMaxVisEntries ) + { + bArrange = TRUE; + mbVScroll = TRUE; + + // Ueberpruefung des rausgescrollten Bereichs + SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... + } + } + + // Ueberpruefung des rausgescrollten Bereichs + USHORT nMaxLI = (USHORT) (nMaxWidth - nWidth); + if ( nMaxLI < GetLeftIndent() ) + SetLeftIndent( nMaxLI ); + } + else + { + if( mbHScroll ) + bArrange = TRUE; + mbHScroll = FALSE; + SetLeftIndent( 0 ); + } + } + + if( bArrange ) + ImplResizeControls(); + + ImplInitScrollBars(); +} + +// ----------------------------------------------------------------------- + +void ImplListBox::ImplInitScrollBars() +{ + Size aOutSz = maLBWindow.GetOutputSizePixel(); + + if ( mbVScroll ) + { + USHORT nEntries = GetEntryList()->GetEntryCount(); + USHORT nVisEntries = (USHORT) (aOutSz.Height() / GetEntryHeight()); + mpVScrollBar->SetRangeMax( nEntries ); + mpVScrollBar->SetVisibleSize( nVisEntries ); + mpVScrollBar->SetPageSize( nVisEntries - 1 ); + } + + if ( mbHScroll ) + { + mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL ); + mpHScrollBar->SetVisibleSize( (USHORT)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; + + maLBWindow.SetPosSizePixel( Point(), aInnerSz ); + + // ScrollBarBox + if( mbVScroll && mbHScroll ) + { + mpScrollBarBox->SetPosSizePixel( Point( aInnerSz.Width(), aInnerSz.Height() ), + Size( nSBWidth, nSBWidth ) ); + mpScrollBarBox->Show(); + } + else + { + mpScrollBarBox->Hide(); + } + + // vert. ScrollBar + if( mbVScroll ) + { + mpVScrollBar->SetPosSizePixel( Point( aOutSz.Width()-nSBWidth, 0 ), + Size( nSBWidth, aInnerSz.Height() ) ); + mpVScrollBar->Show(); + } + else + { + mpVScrollBar->Hide(); + SetTopEntry( 0 ); + } + + // horz. ScrollBar + if( mbHScroll ) + { + mpHScrollBar->SetPosSizePixel( Point( 0, aOutSz.Height()-nSBWidth ), + 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 ) ) + { + 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() ); + } + + 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 ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt ) +{ + BOOL bDone = FALSE; + if ( rCEvt.GetCommand() == COMMAND_WHEEL ) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) + { + USHORT 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 ) +{ + BOOL bChanges = GetEntryList()->GetMRUCount() ? TRUE : FALSE; + + // Remove old MRU entries + for ( USHORT n = GetEntryList()->GetMRUCount();n; ) + maLBWindow.RemoveEntry( --n ); + + USHORT nMRUCount = 0; + USHORT nEntries = rEntries.GetTokenCount( cSep ); + for ( USHORT 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, FALSE ); + bChanges = 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 ( USHORT n = 0; n < GetEntryList()->GetMRUCount(); n++ ) + { + aEntries += GetEntryList()->GetEntryText( n ); + if( n < ( GetEntryList()->GetMRUCount() - 1 ) ) + aEntries += cSep; + } + return aEntries; +} + +// ======================================================================= + +ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) : + Control ( pParent, nWinStyle ) +{ + SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); + mbInUserDraw = FALSE; + mbUserDrawEnabled = FALSE; + mnItemPos = LISTBOX_ENTRY_NOTFOUND; +} + +// ----------------------------------------------------------------------- + +void ImplWin::MBDown() +{ + if( IsEnabled() ) + maMBDownHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void ImplWin::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if( IsEnabled() ) + { +// Control::MouseButtonDown( rMEvt ); + MBDown(); + } +} + +// ----------------------------------------------------------------------- + +void ImplWin::Paint( const Rectangle& rRect ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + if( IsEnabled() ) + { + if( HasFocus() ) + { + SetTextColor( rStyleSettings.GetHighlightTextColor() ); + SetFillColor( rStyleSettings.GetHighlightColor() ); + DrawRect( maFocusRect ); + } + else + { + Color aColor = rStyleSettings.GetFieldTextColor(); + if( IsControlForeground() ) + aColor = GetControlForeground(); + SetTextColor( aColor ); + Erase( maFocusRect ); + } + } + else // Disabled + { + SetTextColor( rStyleSettings.GetDisableColor() ); + Erase( maFocusRect ); + } + + if ( IsUserDrawEnabled() ) + { + mbInUserDraw = TRUE; + UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 ); + maUserDrawHdl.Call( &aUDEvt ); + mbInUserDraw = FALSE; + } + else + { + DrawEntry( TRUE, TRUE ); + } +} + +// ----------------------------------------------------------------------- + +void ImplWin::DrawEntry( BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos ) +{ + long nBorder = 1; + Size aOutSz = GetOutputSizePixel(); + + BOOL bImage = !!maImage; + if( bDrawImage && bImage ) + { + Size aImgSz = maImage.GetSizePixel(); + Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) ); + + if ( !IsZoom() ) + { + DrawImage( aPtImg, maImage ); + } + else + { + aImgSz.Width() = CalcZoom( aImgSz.Width() ); + aImgSz.Height() = CalcZoom( aImgSz.Height() ); + DrawImage( aPtImg, aImgSz, maImage ); + } + } + + if( bDrawText && maString.Len() ) + { + long nTextHeight = GetTextHeight(); + Point aPtTxt( nBorder, (aOutSz.Height()-nTextHeight)/2 ); + if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) ) + { + long nMaxWidth = Max( maImage.GetSizePixel().Width(), maUserItemSize.Width() ); + aPtTxt.X() += nMaxWidth + IMG_TXT_DISTANCE; + } + DrawText( aPtTxt, maString ); + } + + if( HasFocus() ) + ShowFocus( maFocusRect ); +} + +// ----------------------------------------------------------------------- + +void ImplWin::Resize() +{ + maFocusRect.SetSize( GetOutputSizePixel() ); + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void ImplWin::GetFocus() +{ + ShowFocus( maFocusRect ); + Invalidate(); + Control::GetFocus(); +} + +// ----------------------------------------------------------------------- + +void ImplWin::LoseFocus() +{ + HideFocus(); + Invalidate(); + Control::LoseFocus(); +} + +// ======================================================================= + +ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) : + PushButton( pParent, nWinStyle ), + mbDown ( FALSE ) +{ +} + +// ----------------------------------------------------------------------- + +void ImplBtn::MBDown() +{ + if( IsEnabled() ) + maMBDownHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void ImplBtn::MouseButtonDown( const MouseEvent& rMEvt ) +{ + //PushButton::MouseButtonDown( rMEvt ); + if( IsEnabled() ) + { + MBDown(); + mbDown = TRUE; + } +} + +// ======================================================================= + +ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) : + FloatingWindow( pParent, WB_NOBORDER ) +{ + mpImplLB = NULL; + mnDDLineCount = 0; + mbAutoWidth = FALSE; + + EnableSaveBackground(); +} + +// ----------------------------------------------------------------------- + +long ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt ) +{ + if( rNEvt.GetType() == EVENT_LOSEFOCUS ) + { + if( !GetParent()->HasChildPathFocus( TRUE ) ) + EndPopupMode(); + } + + return FloatingWindow::PreNotify( rNEvt ); +} + +// ----------------------------------------------------------------------- + +void ImplListBoxFloatingWindow::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, USHORT 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; + + USHORT 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(); + } +} + +// ----------------------------------------------------------------------- + +Size ImplListBoxFloatingWindow::CalcFloatSize() +{ + Size aFloatSz( maPrefSz ); + + long nLeft, nTop, nRight, nBottom; + GetBorder( nLeft, nTop, nRight, nBottom ); + + USHORT 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 ) + { + // 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( 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( BOOL bStartTracking ) +{ + if( !IsInPopupMode() ) + { + Size aFloatSz = CalcFloatSize(); + + SetSizePixel( aFloatSz ); + mpImplLB->SetSizePixel( GetOutputSizePixel() ); + + Size aSz = GetParent()->GetSizePixel(); + Point aPos = GetParent()->GetPosPixel(); + aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); + Rectangle aRect( aPos, aSz ); + StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN ); + + USHORT nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 ); + if( nPos != LISTBOX_ENTRY_NOTFOUND ) + mpImplLB->SetTopEntry( nPos ); + + if( bStartTracking ) + mpImplLB->GetMainWindow()->EnableMouseMoveSelect( TRUE ); + + if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() ) + mpImplLB->GetMainWindow()->GrabFocus(); + } +} + |