summaryrefslogtreecommitdiff
path: root/vcl/source/control/lstbox.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/control/lstbox.cxx')
-rw-r--r--vcl/source/control/lstbox.cxx1647
1 files changed, 1647 insertions, 0 deletions
diff --git a/vcl/source/control/lstbox.cxx b/vcl/source/control/lstbox.cxx
new file mode 100644
index 000000000000..88b583a3240d
--- /dev/null
+++ b/vcl/source/control/lstbox.cxx
@@ -0,0 +1,1647 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "tools/rc.h"
+
+#include "vcl/svdata.hxx"
+#include "vcl/decoview.hxx"
+#include "vcl/event.hxx"
+#include "vcl/scrbar.hxx"
+#include "vcl/button.hxx"
+#include "vcl/edit.hxx"
+#include "vcl/subedit.hxx"
+#include "vcl/ilstbox.hxx"
+#include "vcl/lstbox.hxx"
+#include "vcl/combobox.hxx"
+#include "vcl/controldata.hxx"
+
+#include "tools/debug.hxx"
+
+#include <vcl/dndevdis.hxx>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+
+// =======================================================================
+
+ListBox::ListBox( WindowType nType ) : Control( nType )
+{
+ ImplInitListBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+ListBox::ListBox( Window* pParent, WinBits nStyle ) : Control( WINDOW_LISTBOX )
+{
+ ImplInitListBoxData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ListBox::ListBox( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_LISTBOX )
+{
+ ImplInitListBoxData();
+ rResId.SetRT( RSC_LISTBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ListBox::~ListBox()
+{
+ //#109201#
+ ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
+
+ delete mpImplLB;
+
+ // Beim zerstoeren des FloatWins macht TH ein GrabFocus auf den Parent,
+ // also diese ListBox => PreNotify()...
+ mpImplLB = NULL;
+
+ delete mpFloatWin;
+ delete mpImplWin;
+ delete mpBtn;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ImplInitListBoxData()
+{
+ mpFloatWin = NULL;
+ mpImplWin = NULL;
+ mpBtn = NULL;
+
+ mnDDHeight = 0;
+ mbDDAutoSize = sal_True;
+ mnSaveValue = LISTBOX_ENTRY_NOTFOUND;
+ mnLineCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) )
+ nStyle |= WB_BORDER;
+
+ Control::ImplInit( pParent, nStyle, NULL );
+ SetBackground();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this);
+
+ if( nStyle & WB_DROPDOWN )
+ {
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+ GetBorder( nLeft, nTop, nRight, nBottom );
+ mnDDHeight = (sal_uInt16)(GetTextHeight() + nTop + nBottom + 4);
+
+ if( IsNativeWidgetEnabled() &&
+ IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
+ {
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) );
+ Rectangle aBoundingRgn( aCtrlRegion );
+ Rectangle aContentRgn( aCtrlRegion );
+ if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
+ CTRL_STATE_ENABLED, aControlValue, rtl::OUString(),
+ aBoundingRgn, aContentRgn ) )
+ {
+ sal_Int32 nHeight = aBoundingRgn.GetHeight();
+ if( nHeight > mnDDHeight )
+ mnDDHeight = static_cast<sal_uInt16>(nHeight);
+ }
+ }
+
+ mpFloatWin = new ImplListBoxFloatingWindow( this );
+ mpFloatWin->SetAutoWidth( sal_True );
+ mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) );
+ mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop);
+
+ mpImplWin = new ImplWin( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER );
+ mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
+ mpImplWin->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
+ mpImplWin->Show();
+ mpImplWin->GetDropTarget()->addDropTargetListener(xDrop);
+
+ mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
+ ImplInitDropDownButton( mpBtn );
+ mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
+ mpBtn->Show();
+ mpBtn->GetDropTarget()->addDropTargetListener(xDrop);
+
+ }
+
+ Window* pLBParent = this;
+ if ( mpFloatWin )
+ pLBParent = mpFloatWin;
+ mpImplLB = new ImplListBox( pLBParent, nStyle&(~WB_BORDER) );
+ mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) );
+ mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl ) );
+ mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) );
+ mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) );
+ mpImplLB->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
+ mpImplLB->SetPosPixel( Point() );
+ mpImplLB->Show();
+
+ mpImplLB->GetDropTarget()->addDropTargetListener(xDrop);
+ mpImplLB->SetDropTraget(xDrop);
+
+ if ( mpFloatWin )
+ {
+ mpFloatWin->SetImplListBox( mpImplLB );
+ mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) );
+ }
+ else
+ mpImplLB->GetMainWindow()->AllowGrabFocus( sal_True );
+
+ SetCompoundControl( sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits ListBox::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ sal_uInt16 nSelPos = ReadShortRes();
+ sal_uInt16 nNumber = sal::static_int_cast<sal_uInt16>(ReadLongRes());
+
+ for( sal_uInt16 i = 0; i < nNumber; i++ )
+ {
+ sal_uInt16 nPos = InsertEntry( ReadStringRes(), LISTBOX_APPEND );
+
+ long nId = ReadLongRes();
+ if( nId )
+ SetEntryData( nPos, (void *)nId ); // ID als UserData
+ }
+
+ if( nSelPos < nNumber )
+ SelectEntryPos( nSelPos );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplSelectHdl, void*, EMPTYARG )
+{
+ sal_Bool bPopup = IsInDropDown();
+ if( IsDropDownBox() )
+ {
+ if( !mpImplLB->IsTravelSelect() )
+ {
+ mpFloatWin->EndPopupMode();
+ mpImplWin->GrabFocus();
+ }
+
+ mpImplWin->SetItemPos( GetSelectEntryPos() );
+ mpImplWin->SetString( GetSelectEntry() );
+ if( mpImplLB->GetEntryList()->HasImages() )
+ {
+ Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectEntryPos() );
+ mpImplWin->SetImage( aImage );
+ }
+ mpImplWin->Invalidate();
+ }
+
+ if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) )
+ Select();
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplScrollHdl, void*, EMPTYARG )
+{
+ ImplCallEventListeners( VCLEVENT_LISTBOX_SCROLLED );
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplCancelHdl, void*, EMPTYARG )
+{
+ if( IsInDropDown() )
+ mpFloatWin->EndPopupMode();
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplSelectionChangedHdl, void*, n )
+{
+ if ( !mpImplLB->IsTrackingSelect() )
+ {
+ sal_uInt16 nChanged = (sal_uInt16)(sal_uLong)n;
+ const ImplEntryList* pEntryList = mpImplLB->GetEntryList();
+ if ( pEntryList->IsEntryPosSelected( nChanged ) )
+ {
+ // Sollte mal ein ImplPaintEntry werden...
+ if ( nChanged < pEntryList->GetMRUCount() )
+ nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ) );
+ mpImplWin->SetItemPos( nChanged );
+ mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
+ if( mpImplLB->GetEntryList()->HasImages() )
+ {
+ Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged );
+ mpImplWin->SetImage( aImage );
+ }
+ mpImplWin->Invalidate();
+ }
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplDoubleClickHdl, void*, EMPTYARG )
+{
+ DoubleClick();
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplClickBtnHdl, void*, EMPTYARG )
+{
+ if( !mpFloatWin->IsInPopupMode() )
+ {
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
+ mpImplWin->GrabFocus();
+ mpBtn->SetPressed( sal_True );
+ mpFloatWin->StartFloat( sal_True );
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
+
+ ImplClearLayoutData();
+ if( mpImplLB )
+ mpImplLB->GetMainWindow()->ImplClearLayoutData();
+ if( mpImplWin )
+ mpImplWin->ImplClearLayoutData();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplPopupModeEndHdl, void*, EMPTYARG )
+{
+ if( mpFloatWin->IsPopupModeCanceled() )
+ {
+ if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND )
+ && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) )
+ {
+ mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), sal_True );
+ sal_Bool bTravelSelect = mpImplLB->IsTravelSelect();
+ mpImplLB->SetTravelSelect( sal_True );
+
+ ImplDelData aCheckDelete;
+ ImplAddDel( &aCheckDelete );
+ Select();
+ if ( aCheckDelete.IsDelete() )
+ return 0;
+ ImplRemoveDel( &aCheckDelete );
+
+ mpImplLB->SetTravelSelect( bTravelSelect );
+ }
+ }
+
+ ImplClearLayoutData();
+ if( mpImplLB )
+ mpImplLB->GetMainWindow()->ImplClearLayoutData();
+ if( mpImplWin )
+ mpImplWin->ImplClearLayoutData();
+
+ mpBtn->SetPressed( sal_False );
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ToggleDropDown()
+{
+ if( IsDropDownBox() )
+ {
+ if( mpFloatWin->IsInPopupMode() )
+ mpFloatWin->EndPopupMode();
+ else
+ {
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
+ mpImplWin->GrabFocus();
+ mpBtn->SetPressed( sal_True );
+ mpFloatWin->StartFloat( sal_True );
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
+{
+ mpImplLB->GetMainWindow()->ImplInitSettings( sal_True, sal_True, sal_True );
+
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
+ OutDevType eOutDevType = pDev->GetOutDevType();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ pDev->SetTextFillColor();
+
+ // Border/Background
+ pDev->SetLineColor();
+ pDev->SetFillColor();
+ sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
+ sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
+ if ( bBorder || bBackground )
+ {
+ Rectangle aRect( aPos, aSize );
+ if ( bBorder )
+ {
+ ImplDrawFrame( pDev, aRect );
+ }
+ if ( bBackground )
+ {
+ pDev->SetFillColor( GetControlBackground() );
+ pDev->DrawRect( aRect );
+ }
+ }
+
+ // Inhalt
+ if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
+ {
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ }
+ else
+ {
+ if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ pDev->SetTextColor( rStyleSettings.GetDisableColor() );
+ }
+ else
+ {
+ pDev->SetTextColor( GetTextColor() );
+ }
+ }
+
+ long nOnePixel = GetDrawPixel( pDev, 1 );
+ sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER;
+ Rectangle aTextRect( aPos, aSize );
+
+ if ( GetStyle() & WB_CENTER )
+ nTextStyle |= TEXT_DRAW_CENTER;
+ else if ( GetStyle() & WB_RIGHT )
+ nTextStyle |= TEXT_DRAW_RIGHT;
+ else
+ nTextStyle |= TEXT_DRAW_LEFT;
+
+ aTextRect.Left() += 3*nOnePixel;
+ aTextRect.Right() -= 3*nOnePixel;
+
+ if ( IsDropDownBox() )
+ {
+ XubString aText = GetSelectEntry();
+ long nTextHeight = pDev->GetTextHeight();
+ long nTextWidth = pDev->GetTextWidth( aText );
+ long nOffX = 3*nOnePixel;
+ long nOffY = (aSize.Height()-nTextHeight) / 2;
+
+ // Clipping?
+ if ( (nOffY < 0) ||
+ ((nOffY+nTextHeight) > aSize.Height()) ||
+ ((nOffX+nTextWidth) > aSize.Width()) )
+ {
+ Rectangle aClip( aPos, aSize );
+ if ( nTextHeight > aSize.Height() )
+ aClip.Bottom() += nTextHeight-aSize.Height()+1; // Damit HP-Drucker nicht 'weg-optimieren'
+ pDev->IntersectClipRegion( aClip );
+ }
+
+ pDev->DrawText( aTextRect, aText, nTextStyle );
+ }
+ else
+ {
+ long nTextHeight = pDev->GetTextHeight();
+ sal_uInt16 nLines = (sal_uInt16)(aSize.Height() / nTextHeight);
+ Rectangle aClip( aPos, aSize );
+
+ pDev->IntersectClipRegion( aClip );
+
+ if ( !nLines )
+ nLines = 1;
+
+ for ( sal_uInt16 n = 0; n < nLines; n++ )
+ {
+ sal_uInt16 nEntry = n+mpImplLB->GetTopEntry();
+ sal_Bool bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry );
+ if ( bSelected )
+ {
+ pDev->SetFillColor( COL_BLACK );
+ pDev->DrawRect( Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ),
+ Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) );
+ pDev->SetFillColor();
+ pDev->SetTextColor( COL_WHITE );
+ }
+
+ aTextRect.Top() = aPos.Y() + n*nTextHeight;
+ aTextRect.Bottom() = aTextRect.Top() + nTextHeight;
+
+ pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( nEntry ), nTextStyle );
+
+ if ( bSelected )
+ pDev->SetTextColor( COL_BLACK );
+ }
+ }
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::GetFocus()
+{
+ if ( mpImplLB )
+ {
+ if( IsDropDownBox() )
+ mpImplWin->GrabFocus();
+ else
+ mpImplLB->GrabFocus();
+ }
+
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+Window* ListBox::GetPreferredKeyInputWindow()
+{
+ if ( mpImplLB )
+ {
+ if( IsDropDownBox() )
+ return mpImplWin->GetPreferredKeyInputWindow();
+ else
+ return mpImplLB->GetPreferredKeyInputWindow();
+ }
+
+ return Control::GetPreferredKeyInputWindow();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::LoseFocus()
+{
+ if( IsDropDownBox() )
+ mpImplWin->HideFocus();
+ else
+ mpImplLB->HideFocus();
+
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset
+ // otherwise it will overpaint NWF drawn listboxes
+ Resize();
+ mpImplLB->Resize(); // Wird nicht durch ListBox::Resize() gerufen, wenn sich die ImplLB nicht aendert.
+
+ if ( mpImplWin )
+ {
+ mpImplWin->SetSettings( GetSettings() ); // Falls noch nicht eingestellt...
+ ImplInitFieldSettings( mpImplWin, sal_True, sal_True, sal_True );
+
+ mpBtn->SetSettings( GetSettings() );
+ ImplInitDropDownButton( mpBtn );
+ }
+
+
+ if ( IsDropDownBox() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableAutoSize( sal_Bool bAuto )
+{
+ mbDDAutoSize = bAuto;
+ if ( mpFloatWin )
+ {
+ if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
+ mpFloatWin->SetDropDownLineCount( 5 );
+ else if ( !bAuto )
+ mpFloatWin->SetDropDownLineCount( 0 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableDDAutoWidth( sal_Bool b )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetAutoWidth( b );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsDDAutoWidthEnabled() const
+{
+ return mpFloatWin ? mpFloatWin->IsAutoWidth() : sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetDropDownLineCount( sal_uInt16 nLines )
+{
+ mnLineCount = nLines;
+ if ( mpFloatWin )
+ mpFloatWin->SetDropDownLineCount( mnLineCount );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetDropDownLineCount() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetDropDownLineCount();
+ return mnLineCount;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
+{
+ if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) )
+ {
+ Size aPrefSz = mpFloatWin->GetPrefSize();
+ if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight >= 2*mnDDHeight ) )
+ aPrefSz.Height() = nHeight-mnDDHeight;
+ if ( nFlags & WINDOW_POSSIZE_WIDTH )
+ aPrefSz.Width() = nWidth;
+ mpFloatWin->SetPrefSize( aPrefSz );
+
+ if ( IsAutoSizeEnabled() && ! (nFlags & WINDOW_POSSIZE_DROPDOWN) )
+ nHeight = mnDDHeight;
+ }
+
+ Control::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Resize()
+{
+ Size aOutSz = GetOutputSizePixel();
+ if( IsDropDownBox() )
+ {
+ // initialize the dropdown button size with the standard scrollbar width
+ long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
+ long nTop = 0;
+ long nBottom = aOutSz.Height();
+
+ // note: in case of no border, pBorder will actually be this
+ Window *pBorder = GetWindow( WINDOW_BORDER );
+ ImplControlValue aControlValue;
+ Point aPoint;
+ Rectangle aContent, aBound;
+
+ // use the full extent of the control
+ Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
+
+ if ( GetNativeControlRegion( CTRL_LISTBOX, PART_BUTTON_DOWN,
+ aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ // convert back from border space to local coordinates
+ aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) );
+ aContent.Move( -aPoint.X(), -aPoint.Y() );
+
+ // use the themes drop down size for the button
+ aOutSz.Width() = aContent.Left();
+ mpBtn->SetPosSizePixel( aContent.Left(), nTop, aContent.Right(), (nBottom-nTop) );
+
+ // adjust the size of the edit field
+ if ( GetNativeControlRegion( CTRL_LISTBOX, PART_SUB_EDIT,
+ aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ // convert back from border space to local coordinates
+ aContent.Move( -aPoint.X(), -aPoint.Y() );
+
+ // use the themes drop down size
+ if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects )
+ {
+ // no border but focus ring behavior -> we have a problem; the
+ // native rect relies on the border to draw the focus
+ // let's do the best we can and center vertically, so it doesn't look
+ // completely wrong.
+ Size aSz( GetOutputSizePixel() );
+ long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2;
+ aContent.Top() -= nDiff;
+ aContent.Bottom() -= nDiff;
+ }
+ mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() );
+ }
+ else
+ mpImplWin->SetSizePixel( aOutSz );
+ }
+ else
+ {
+ nSBWidth = CalcZoom( nSBWidth );
+ mpImplWin->SetPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() );
+ mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
+ }
+ }
+ else
+ {
+ mpImplLB->SetSizePixel( aOutSz );
+ }
+
+ // FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten,
+ // weil KEY_PGUP/DOWN ausgewertet wird...
+ if ( mpFloatWin )
+ mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
+
+ Control::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::FillLayoutData() const
+{
+ mpControlData->mpLayoutData = new vcl::ControlLayoutData();
+ const Control* pMainWin = mpImplLB->GetMainWindow();
+ if( mpFloatWin )
+ {
+ // dropdown mode
+ AppendLayoutData( *mpImplWin );
+ mpImplWin->SetLayoutDataParent( this );
+ if( mpFloatWin->IsReallyVisible() )
+ {
+ AppendLayoutData( *pMainWin );
+ pMainWin->SetLayoutDataParent( this );
+ }
+ }
+ else
+ {
+ AppendLayoutData( *pMainWin );
+ pMainWin->SetLayoutDataParent( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ListBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const
+{
+ if( !HasLayoutData() )
+ FillLayoutData();
+
+ // check whether rPoint fits at all
+ long nIndex = Control::GetIndexForPoint( rPoint );
+ if( nIndex != -1 )
+ {
+ // point must be either in main list window
+ // or in impl window (dropdown case)
+ ImplListBoxWindow* pMain = mpImplLB->GetMainWindow();
+
+ // convert coordinates to ImplListBoxWindow pixel coordinate space
+ Point aConvPoint = LogicToPixel( rPoint );
+ aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
+ aConvPoint = pMain->AbsoluteScreenToOutputPixel( aConvPoint );
+ aConvPoint = pMain->PixelToLogic( aConvPoint );
+
+ // try to find entry
+ sal_uInt16 nEntry = pMain->GetEntryPosForPoint( aConvPoint );
+ if( nEntry == LISTBOX_ENTRY_NOTFOUND )
+ {
+ // not found, maybe dropdown case
+ if( mpImplWin && mpImplWin->IsReallyVisible() )
+ {
+ // convert to impl window pixel coordinates
+ aConvPoint = LogicToPixel( rPoint );
+ aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
+ aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPoint );
+
+ // check whether converted point is inside impl window
+ Size aImplWinSize = mpImplWin->GetOutputSizePixel();
+ if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() )
+ {
+ // inside the impl window, the position is the current item pos
+ rPos = mpImplWin->GetItemPos();
+ }
+ else
+ nIndex = -1;
+ }
+ else
+ nIndex = -1;
+ }
+ else
+ rPos = nEntry;
+
+ DBG_ASSERT( nIndex != -1, "found index for point, but relative index failed" );
+ }
+
+ // get line relative index
+ if( nIndex != -1 )
+ nIndex = ToRelativeLineIndex( nIndex );
+
+ return nIndex;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::StateChanged( StateChangedType nType )
+{
+ if( nType == STATE_CHANGE_READONLY )
+ {
+ if( mpImplWin )
+ mpImplWin->Enable( !IsReadOnly() );
+ if( mpBtn )
+ mpBtn->Enable( !IsReadOnly() );
+ }
+ else if( nType == STATE_CHANGE_ENABLE )
+ {
+ mpImplLB->Enable( IsEnabled() );
+ if( mpImplWin )
+ {
+ mpImplWin->Enable( IsEnabled() );
+ if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
+ && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
+ {
+ GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE );
+ }
+ else
+ mpImplWin->Invalidate();
+ }
+ if( mpBtn )
+ mpBtn->Enable( IsEnabled() );
+ }
+ else if( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ mpImplLB->SetUpdateMode( IsUpdateMode() );
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ mpImplLB->SetZoom( GetZoom() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetZoom( GetZoom() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ mpImplLB->SetControlFont( GetControlFont() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetControlFont( GetControlFont() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ mpImplLB->SetControlForeground( GetControlForeground() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetControlForeground( GetControlForeground() );
+ mpImplWin->SetTextColor( GetControlForeground() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ mpImplLB->SetControlBackground( GetControlBackground() );
+ if ( mpImplWin )
+ {
+ if ( mpImplWin->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) )
+ {
+ // Transparent background
+ mpImplWin->SetBackground();
+ mpImplWin->SetControlBackground();
+ }
+ else
+ {
+ mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
+ mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
+ }
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? sal_True : sal_False );
+ sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False;
+ mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
+ }
+ else if( nType == STATE_CHANGE_MIRRORING )
+ {
+ if( mpBtn )
+ {
+ mpBtn->EnableRTL( IsRTLEnabled() );
+ ImplInitDropDownButton( mpBtn );
+ }
+ mpImplLB->EnableRTL( IsRTLEnabled() );
+ if( mpImplWin )
+ mpImplWin->EnableRTL( IsRTLEnabled() );
+ Resize();
+ }
+
+ Control::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+long ListBox::PreNotify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+ if ( mpImplLB )
+ {
+ if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) )
+ {
+ KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
+ switch( aKeyEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_DOWN:
+ {
+ if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
+ aKeyEvt.GetKeyCode().IsMod2() )
+ {
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
+ mpBtn->SetPressed( sal_True );
+ mpFloatWin->StartFloat( sal_False );
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
+ nDone = 1;
+ }
+ else
+ {
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ }
+ break;
+ case KEY_UP:
+ {
+ if( mpFloatWin && mpFloatWin->IsInPopupMode() &&
+ aKeyEvt.GetKeyCode().IsMod2() )
+ {
+ mpFloatWin->EndPopupMode();
+ nDone = 1;
+ }
+ else
+ {
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ }
+ break;
+ case KEY_RETURN:
+ {
+ if( IsInDropDown() )
+ {
+ mpImplLB->ProcessKeyInput( aKeyEvt );
+ nDone = 1;
+ }
+ }
+ break;
+
+ default:
+ {
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ }
+ }
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( IsInDropDown() && !HasChildPathFocus( sal_True ) )
+ mpFloatWin->EndPopupMode();
+ }
+ else if ( (rNEvt.GetType() == EVENT_COMMAND) &&
+ (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
+ (rNEvt.GetWindow() == mpImplWin) )
+ {
+ sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
+ if ( ( nWheelBehavior == MOUSE_WHEEL_ALWAYS )
+ || ( ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY )
+ && HasChildPathFocus()
+ )
+ )
+ {
+ nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
+ }
+ else
+ {
+ nDone = 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
+ }
+ }
+ }
+
+ return nDone ? nDone : Control::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Select()
+{
+ ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_SELECT, maSelectHdl, this );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::DoubleClick()
+{
+ ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_DOUBLECLICK, maDoubleClickHdl, this );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Clear()
+{
+ mpImplLB->Clear();
+ if( IsDropDownBox() )
+ {
+ mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
+ mpImplWin->SetString( ImplGetSVEmptyStr() );
+ Image aImage;
+ mpImplWin->SetImage( aImage );
+ mpImplWin->Invalidate();
+ }
+ CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(-1) );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetNoSelection()
+{
+ mpImplLB->SetNoSelection();
+ if( IsDropDownBox() )
+ {
+ mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
+ mpImplWin->SetString( ImplGetSVEmptyStr() );
+ Image aImage;
+ mpImplWin->SetImage( aImage );
+ mpImplWin->Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
+{
+ sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
+ nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
+ CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::InsertEntry( const Image& rImage, sal_uInt16 nPos )
+{
+ sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rImage );
+ nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
+ CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::InsertEntry( const XubString& rStr, const Image& rImage, sal_uInt16 nPos )
+{
+ sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
+ nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
+ CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::RemoveEntry( const XubString& rStr )
+{
+ RemoveEntry( GetEntryPos( rStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::RemoveEntry( sal_uInt16 nPos )
+{
+ mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+ CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(nPos) );
+}
+
+// -----------------------------------------------------------------------
+
+Image ListBox::GetEntryImage( sal_uInt16 nPos ) const
+{
+ if ( mpImplLB->GetEntryList()->HasEntryImage( nPos ) )
+ return mpImplLB->GetEntryList()->GetEntryImage( nPos );
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetEntryPos( const XubString& rStr ) const
+{
+ sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( rStr );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetEntryPos( const void* pData ) const
+{
+ sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( pData );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+XubString ListBox::GetEntry( sal_uInt16 nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetEntryCount() const
+{
+ return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
+}
+
+// -----------------------------------------------------------------------
+
+XubString ListBox::GetSelectEntry( sal_uInt16 nIndex ) const
+{
+ return GetEntry( GetSelectEntryPos( nIndex ) );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetSelectEntryCount() const
+{
+ return mpImplLB->GetEntryList()->GetSelectEntryCount();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetSelectEntryPos( sal_uInt16 nIndex ) const
+{
+ sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ {
+ if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
+ nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) );
+ nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsEntrySelected( const XubString& rStr ) const
+{
+ return IsEntryPosSelected( GetEntryPos( rStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsEntryPosSelected( sal_uInt16 nPos ) const
+{
+ return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SelectEntry( const XubString& rStr, sal_Bool bSelect )
+{
+ SelectEntryPos( GetEntryPos( rStr ), bSelect );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect )
+{
+ if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() )
+ mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetEntryData( sal_uInt16 nPos, void* pNewData )
+{
+ mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
+}
+
+// -----------------------------------------------------------------------
+
+void* ListBox::GetEntryData( sal_uInt16 nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags )
+{
+ mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount(), nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+long ListBox::GetEntryFlags( sal_uInt16 nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetTopEntry( sal_uInt16 nPos )
+{
+ mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ShowProminentEntry( sal_uInt16 nPos )
+{
+ mpImplLB->ShowProminentEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetTopEntry() const
+{
+ sal_uInt16 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
+ if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
+ nPos = 0;
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetProminentEntryType( ProminentEntry eType )
+{
+ mpImplLB->SetProminentEntryType( eType );
+}
+
+// -----------------------------------------------------------------------
+
+ProminentEntry ListBox::GetProminentEntryType() const
+{
+ return mpImplLB->GetProminentEntryType();
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsTravelSelect() const
+{
+ return mpImplLB->IsTravelSelect();
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsInDropDown() const
+{
+ return mpFloatWin && mpFloatWin->IsInPopupMode();
+}
+
+// -----------------------------------------------------------------------
+
+long ListBox::CalcWindowSizePixel( sal_uInt16 nLines ) const
+{
+ return mpImplLB->GetEntryHeight() * nLines;
+}
+
+Rectangle ListBox::GetBoundingRectangle( sal_uInt16 nItem ) const
+{
+ Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
+ Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( (Window*)this );
+ aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableMultiSelection( sal_Bool bMulti )
+{
+ EnableMultiSelection( bMulti, sal_False );
+}
+
+void ListBox::EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackSelection )
+{
+ mpImplLB->EnableMultiSelection( bMulti, bStackSelection );
+
+ // WB_SIMPLEMODE:
+ // Die MultiListBox verh�lt sich wie eine normale ListBox.
+ // Die Mehrfachselektion kann nur �ber entsprechende Zusatztasten erfolgen.
+
+ sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False;
+ mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
+
+ // ohne Focus ist das Traveln in einer MultiSelection nicht zu sehen:
+ if ( mpFloatWin )
+ mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsMultiSelectionEnabled() const
+{
+ return mpImplLB->IsMultiSelectionEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::CalcMinimumSize() const
+{
+ Size aSz;
+ if ( !IsDropDownBox() )
+ aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList()->GetEntryCount());
+ else
+ {
+ aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
+ aSz.Height() += 4; // add a space between entry and border
+ // size to maxmimum entry width and add a little breathing space
+ aSz.Width() = mpImplLB->GetMaxEntryWidth() + 4;
+ // do not create ultrathin ListBoxes, it doesn't look good
+ if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() )
+ aSz.Width() = GetSettings().GetStyleSettings().GetScrollBarSize();
+
+ // try native borders; scrollbar size may not be a good indicator
+ // see how large the edit area inside is to estimate what is needed for the dropdown
+ ImplControlValue aControlValue;
+ Point aPoint;
+ Rectangle aContent, aBound;
+ Size aTestSize( 100, 20 );
+ Rectangle aArea( aPoint, aTestSize );
+ if( const_cast<ListBox*>(this)->GetNativeControlRegion(
+ CTRL_LISTBOX, PART_SUB_EDIT, aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ // use the themes drop down size
+ aSz.Width() += aTestSize.Width() - aContent.GetWidth();
+ }
+ else
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ }
+
+ aSz = CalcWindowSize( aSz );
+
+ if ( IsDropDownBox() ) // check minimum height of dropdown box
+ {
+ ImplControlValue aControlValue;
+ Rectangle aRect( Point( 0, 0 ), aSz );
+ Rectangle aContent, aBound;
+ if( const_cast<ListBox*>(this)->GetNativeControlRegion(
+ CTRL_LISTBOX, PART_ENTIRE_CONTROL, aRect, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ if( aBound.GetHeight() > aSz.Height() )
+ aSz.Height() = aBound.GetHeight();
+ }
+ }
+
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::GetOptimalSize(WindowSizeType eType) const
+{
+ switch (eType) {
+ case WINDOWSIZE_MINIMUM:
+ return CalcMinimumSize();
+ default:
+ return Control::GetOptimalSize( eType );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const
+{
+ Size aSz = rPrefSize;
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+ ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
+ aSz.Height() -= nTop+nBottom;
+ if ( !IsDropDownBox() )
+ {
+ long nEntryHeight = CalcSize( 1, 1 ).Height();
+ long nLines = aSz.Height() / nEntryHeight;
+ if ( nLines < 1 )
+ nLines = 1;
+ aSz.Height() = nLines * nEntryHeight;
+ }
+ else
+ {
+ aSz.Height() = mnDDHeight;
+ }
+ aSz.Height() += nTop+nBottom;
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
+{
+ // ggf. werden ScrollBars eingeblendet
+ Size aMinSz = CalcMinimumSize();
+// aMinSz = ImplCalcOutSz( aMinSz );
+
+ Size aSz;
+
+ // Hoehe
+ if ( nLines )
+ {
+ if ( !IsDropDownBox() )
+ aSz.Height() = mpImplLB->CalcSize( nLines ).Height();
+ else
+ aSz.Height() = mnDDHeight;
+ }
+ else
+ aSz.Height() = aMinSz.Height();
+
+ // Breite
+ if ( nColumns )
+ aSz.Width() = nColumns * GetTextWidth( XubString( 'X' ) );
+ else
+ aSz.Width() = aMinSz.Width();
+
+ if ( IsDropDownBox() )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+
+ if ( !IsDropDownBox() )
+ {
+ if ( aSz.Width() < aMinSz.Width() )
+ aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( aSz.Height() < aMinSz.Height() )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ }
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
+{
+ long nCharWidth = GetTextWidth( UniString( 'x' ) );
+ if ( !IsDropDownBox() )
+ {
+ Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
+ rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
+ rnLines = (sal_uInt16) (aOutSz.Height()/mpImplLB->GetEntryHeight());
+ }
+ else
+ {
+ Size aOutSz = mpImplWin->GetOutputSizePixel();
+ rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
+ rnLines = 1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplUserDrawHdl, UserDrawEvent*, pEvent )
+{
+ UserDraw( *pEvent );
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos )
+{
+ if ( rEvt.GetDevice() == mpImplLB->GetMainWindow() )
+ mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
+ else if ( rEvt.GetDevice() == mpImplWin )
+ mpImplWin->DrawEntry( bDrawImage, bDrawText, bDrawTextAtImagePos );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetUserItemSize( const Size& rSz )
+{
+ mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
+ if ( mpImplWin )
+ mpImplWin->SetUserItemSize( rSz );
+}
+
+// -----------------------------------------------------------------------
+
+const Size& ListBox::GetUserItemSize() const
+{
+ return mpImplLB->GetMainWindow()->GetUserItemSize();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableUserDraw( sal_Bool bUserDraw )
+{
+ mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
+ if ( mpImplWin )
+ mpImplWin->EnableUserDraw( bUserDraw );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsUserDrawEnabled() const
+{
+ return mpImplLB->GetMainWindow()->IsUserDrawEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetReadOnly( sal_Bool bReadOnly )
+{
+ if ( mpImplLB->IsReadOnly() != bReadOnly )
+ {
+ mpImplLB->SetReadOnly( bReadOnly );
+ StateChanged( STATE_CHANGE_READONLY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ListBox::IsReadOnly() const
+{
+ return mpImplLB->IsReadOnly();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetSeparatorPos( sal_uInt16 n )
+{
+ mpImplLB->SetSeparatorPos( n );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetSeparatorPos()
+{
+ mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetSeparatorPos() const
+{
+ return mpImplLB->GetSeparatorPos();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep )
+{
+ mpImplLB->SetMRUEntries( rEntries, cSep );
+}
+
+// -----------------------------------------------------------------------
+
+XubString ListBox::GetMRUEntries( xub_Unicode cSep ) const
+{
+ return mpImplLB->GetMRUEntries( cSep );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetMaxMRUCount( sal_uInt16 n )
+{
+ mpImplLB->SetMaxMRUCount( n );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetMaxMRUCount() const
+{
+ return mpImplLB->GetMaxMRUCount();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ListBox::GetDisplayLineCount() const
+{
+ return mpImplLB->GetDisplayLineCount();
+}
+
+// -----------------------------------------------------------------------
+
+// pb: #106948# explicit mirroring for calc
+
+void ListBox::EnableMirroring()
+{
+ mpImplLB->EnableMirroring();
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ListBox::GetDropDownPosSizePixel() const
+{
+ return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ListBox*>(this) ) : Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+const Wallpaper& ListBox::GetDisplayBackground() const
+{
+ // !!! recursion does not occur because the ImplListBox is default
+ // initialized to a nontransparent color in Window::ImplInitData
+ return mpImplLB->GetDisplayBackground();
+}
+
+// =======================================================================
+MultiListBox::MultiListBox( Window* pParent, WinBits nStyle ) :
+ ListBox( WINDOW_MULTILISTBOX )
+{
+ ImplInit( pParent, nStyle );
+ EnableMultiSelection( sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+MultiListBox::MultiListBox( Window* pParent, const ResId& rResId ) :
+ ListBox( WINDOW_MULTILISTBOX )
+{
+ rResId.SetRT( RSC_MULTILISTBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+ EnableMultiSelection( sal_True );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */