/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



#ifndef _SV_ILSTBOX_HXX
#define _SV_ILSTBOX_HXX

#include <vcl/sv.h>
#include <vcl/image.hxx>
#include <vcl/ctrl.hxx>
#include <vcl/button.hxx>
#include <vcl/floatwin.hxx>
#include <vcl/lstbox.h>
#include <vcl/timer.hxx>

#include "vcl/quickselectionengine.hxx"

class ScrollBar;
class ScrollBarBox;

// -----------------
// - ListBox-Types -
// -----------------

#define HORZ_SCROLL 		4
#define IMG_TXT_DISTANCE	6

enum LB_EVENT_TYPE
{
	LET_MBDOWN,
	LET_TRACKING,
	LET_TRACKING_END,
	LET_KEYMOVE,
	LET_KEYSPACE
};

// -----------------
// - ImplEntryType -
// -----------------

struct ImplEntryType
{
	XubString	maStr;
	Image		maImage;
	void*		mpUserData;
	sal_Bool		mbIsSelected;
	long		mnFlags;
    long        mnHeight;

	ImplEntryType( const XubString& rStr, const Image& rImage ) :
		maStr( rStr ),
		maImage( rImage ),
		mnFlags( 0 ),
        mnHeight( 0 )
	{
		mbIsSelected = sal_False;
		mpUserData = NULL;
	}

	ImplEntryType( const XubString& rStr ) :
		maStr( rStr ),
		mnFlags( 0 ),
        mnHeight( 0 )
	{
		mbIsSelected = sal_False;
		mpUserData = NULL;
	}

	ImplEntryType( const Image& rImage ) :
		maImage( rImage ),
		mnFlags( 0 ),
        mnHeight( 0 )
	{
		mbIsSelected = sal_False;
		mpUserData = NULL;
	}
};

// -----------------
// - ImplEntryList -
// -----------------

class ImplEntryList : private List
{
private:
    Window*         mpWindow;   // For getting the current locale when matching strings
	sal_uInt16			mnLastSelected;
	sal_uInt16			mnSelectionAnchor;
	sal_uInt16			mnImages;

	sal_uInt16			mnMRUCount;
	sal_uInt16			mnMaxMRUCount;

	Link			maSelectionChangedHdl;
	sal_Bool			mbCallSelectionChangedHdl;

	ImplEntryType*	GetEntry( sal_uInt16 nPos )	const { return (ImplEntryType*)List::GetObject( nPos ); }

public:
					ImplEntryList( Window* pWindow );
					~ImplEntryList();

	sal_uInt16					InsertEntry( sal_uInt16 nPos, ImplEntryType* pNewEntry, sal_Bool bSort );
	void					RemoveEntry( sal_uInt16 nPos );
	const ImplEntryType* 	GetEntryPtr( sal_uInt16 nPos ) const { return (const ImplEntryType*) GetObject( nPos ); }
	ImplEntryType* 	        GetMutableEntryPtr( sal_uInt16 nPos ) const { return (ImplEntryType*) GetObject( nPos ); }
	void					Clear();

	sal_uInt16			FindMatchingEntry( const XubString& rStr, sal_uInt16 nStart = 0, sal_Bool bForward = sal_True, sal_Bool bLazy = sal_True ) const;
	sal_uInt16			FindEntry( const XubString& rStr, sal_Bool bSearchMRUArea = sal_False ) const;
	sal_uInt16			FindEntry( const void* pData ) const;

    // helper: add up heights up to index nEndIndex.
    // GetAddedHeight( 0 ) returns 0
    // GetAddedHeight( LISTBOX_ENTRY_NOTFOUND ) returns 0
    // GetAddedHeight( i, k ) with k > i is equivalent -GetAddedHeight( k, i )
    long            GetAddedHeight( sal_uInt16 nEndIndex, sal_uInt16 nBeginIndex = 0, long nBeginHeight = 0 ) const;
    long            GetEntryHeight( sal_uInt16 nPos ) const;

	sal_uInt16			GetEntryCount() const { return (sal_uInt16)List::Count(); }
	sal_Bool			HasImages() const { return mnImages ? sal_True : sal_False; }

	XubString		GetEntryText( sal_uInt16 nPos ) const;

	sal_Bool			HasEntryImage( sal_uInt16 nPos ) const;
	Image			GetEntryImage( sal_uInt16 nPos ) const;

	void			SetEntryData( sal_uInt16 nPos, void* pNewData );
	void*			GetEntryData( sal_uInt16 nPos ) const;

	void			SetEntryFlags( sal_uInt16 nPos, long nFlags );
	long			GetEntryFlags( sal_uInt16 nPos ) const;

	void			SelectEntry( sal_uInt16 nPos, sal_Bool bSelect );

	sal_uInt16			GetSelectEntryCount() const;
	XubString		GetSelectEntry( sal_uInt16 nIndex ) const;
	sal_uInt16			GetSelectEntryPos( sal_uInt16 nIndex ) const;
	sal_Bool			IsEntrySelected( const XubString& rStr ) const;
	sal_Bool			IsEntryPosSelected( sal_uInt16 nIndex ) const;

	void			SetLastSelected( sal_uInt16 nPos )	{ mnLastSelected = nPos; }
	sal_uInt16			GetLastSelected() const { return mnLastSelected; }

	void			SetSelectionAnchor( sal_uInt16 nPos )	{ mnSelectionAnchor = nPos; }
	sal_uInt16			GetSelectionAnchor() const { return mnSelectionAnchor; }


	void			SetSelectionChangedHdl( const Link& rLnk )	{ maSelectionChangedHdl = rLnk; }
	void			SetCallSelectionChangedHdl( sal_Bool bCall )	{ mbCallSelectionChangedHdl = bCall; }

	void			SetMRUCount( sal_uInt16 n )	{ mnMRUCount = n; }
	sal_uInt16			GetMRUCount() const		{ return mnMRUCount; }

	void			SetMaxMRUCount( sal_uInt16 n )	{ mnMaxMRUCount = n; }
	sal_uInt16			GetMaxMRUCount() const		{ return mnMaxMRUCount; }

	/**	An Entry is selectable if its mnFlags does not have the 
		LISTBOX_ENTRY_FLAG_DISABLE_SELECTION flag set. */
	bool			IsEntrySelectable( sal_uInt16 nPos ) const;

	/** returns the first entry found from the given position nPos that is selectable
		or LISTBOX_ENTRY_NOTFOUND if non is found. If the entry at nPos is not selectable,
		it returns the first selectable entry after nPos if bForward is true and the
		first selectable entry after nPos is bForward is false.
		*/
	sal_uInt16			FindFirstSelectable( sal_uInt16 nPos, bool bForward = true );
};

// ---------------------
// - ImplListBoxWindow -
// ---------------------

class ImplListBoxWindow : public Control, public ::vcl::ISearchableStringList
{
private:
	ImplEntryList*	mpEntryList;	 // EntryListe
	Rectangle		maFocusRect;

	Size			maUserItemSize;

	long			mnMaxTxtHeight;  // Maximale Hoehe eines Text-Items
	long			mnMaxTxtWidth;	 // Maximale Breite eines Text-Items
									 // Entry ohne Image
	long			mnMaxImgTxtWidth;// Maximale Breite eines Text-Items
									 // Entry UND Image
	long			mnMaxImgWidth;	 // Maximale Breite eines Image-Items
	long			mnMaxImgHeight;  // Maximale Hoehe eines Image-Items
	long			mnMaxWidth; 	 // Maximale Breite eines Eintrags
	long			mnMaxHeight;	 // Maximale Hoehe eines Eintrags

	sal_uInt16			mnCurrentPos;	 // Position (Focus)
	sal_uInt16			mnTrackingSaveSelection; // Selektion vor Tracking();

	sal_uInt16			mnSeparatorPos;	// Separator

	sal_uInt16			mnUserDrawEntry;

	sal_uInt16			mnTop;			 // Ausgabe ab Zeile
	long			mnLeft; 		 // Ausgabe ab Spalte
	long			mnBorder;		 // Abstand Rahmen - Text
	long			mnTextHeight;	 // Texthoehe
	ProminentEntry  meProminentType; // where is the "prominent" entry

	sal_uInt16			mnSelectModifier;	// Modifiers

    /// bitfield
    bool mbHasFocusRect : 1;
    bool mbSort : 1;             // ListBox sortiert
    bool mbTrack : 1;            // Tracking
    bool mbMulti : 1;            // MultiListBox
    bool mbStackMode : 1;        // StackSelection
    bool mbSimpleMode : 1;       // SimpleMode fuer MultiListBox
    bool mbImgsDiffSz : 1;       // Images haben verschiedene Groessen
    bool mbTravelSelect : 1;     // TravelSelect
    bool mbTrackingSelect : 1;   // Selektiert bei MouseMove
    bool mbSelectionChanged : 1; // Select() nicht zu oft rufen...
    bool mbMouseMoveSelect : 1;  // Selektieren bei MouseMove
    bool mbGrabFocus : 1;        // Focus bei MBDown grabben
    bool mbUserDrawEnabled : 1;  // UserDraw possible
    bool mbInUserDraw : 1;       // In UserDraw
    bool mbReadOnly : 1;         // ReadOnly
    bool mbMirroring : 1;        // pb: #106948# explicit mirroring for calc
    bool mbRight : 1;            // right align Text output
    bool mbCenter : 1;           // center Text output
    bool mbEdgeBlending : 1;

	Link			maScrollHdl;
	Link			maSelectHdl;
	Link			maCancelHdl;
	Link			maDoubleClickHdl;
	Link			maUserDrawHdl;
	Link			maMRUChangedHdl;
//IAccessibility2 Implementation 2009-----
	Link			maFocusHdl;
	Link			maListItemSelectHdl;
//-----IAccessibility2 Implementation 2009

    ::vcl::QuickSelectionEngine maQuickSelectionEngine;

protected:
	virtual void	KeyInput( const KeyEvent& rKEvt );
	virtual void	MouseButtonDown( const MouseEvent& rMEvt );
	virtual void	MouseMove( const MouseEvent& rMEvt );
	virtual void	Tracking( const TrackingEvent& rTEvt );
	virtual void	Paint( const Rectangle& rRect );
	virtual void	Resize();
	virtual void	GetFocus();
	virtual void	LoseFocus();

	//IAccessibility2 Implementation 2009-----
	//sal_Bool			SelectEntries( sal_uInt16 nSelect, LB_EVENT_TYPE eLET, sal_Bool bShift = sal_False, sal_Bool bCtrl = sal_False );
	sal_Bool			SelectEntries( sal_uInt16 nSelect, LB_EVENT_TYPE eLET, sal_Bool bShift = sal_False, sal_Bool bCtrl = sal_False, sal_Bool bSelectPosChange = sal_False );
	//-----IAccessibility2 Implementation 2009
	void			ImplPaint( sal_uInt16 nPos, sal_Bool bErase = sal_False, bool bLayout = false );
    void			ImplDoPaint( const Rectangle& rRect, bool bLayout = false );
	void			ImplCalcMetrics();
	void			ImplUpdateEntryMetrics( ImplEntryType& rEntry );
	void			ImplCallSelect();

    void            ImplShowFocusRect();
    void            ImplHideFocusRect();


	virtual void	StateChanged( StateChangedType nType );
	virtual void	DataChanged( const DataChangedEvent& rDCEvt );

public:
    virtual void  FillLayoutData() const;

					ImplListBoxWindow( Window* pParent, WinBits nWinStyle );
					~ImplListBoxWindow();

	ImplEntryList*	GetEntryList() const { return mpEntryList; }

	sal_uInt16			InsertEntry( sal_uInt16 nPos, ImplEntryType* pNewEntry );
	void			RemoveEntry( sal_uInt16 nPos );
	void			Clear();
	void			ResetCurrentPos()				{ mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; }
	sal_uInt16			GetCurrentPos()	const			{ return mnCurrentPos; }
    sal_uInt16			GetDisplayLineCount() const;
    void            SetEntryFlags( sal_uInt16 nPos, long nFlags );

	void 			DrawEntry( sal_uInt16 nPos, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos = sal_False, bool bLayout = false );

	void			SelectEntry( sal_uInt16 nPos, sal_Bool bSelect );
	void			DeselectAll();
    sal_uInt16			GetEntryPosForPoint( const Point& rPoint ) const;
    sal_uInt16          GetLastVisibleEntry() const;

	sal_Bool			ProcessKeyInput( const KeyEvent& rKEvt );

	void			SetTopEntry( sal_uInt16 nTop );
	sal_uInt16			GetTopEntry() const 			{ return mnTop; }
	// ShowProminentEntry will set the entry correspoding to nEntryPos
	// either at top or in the middle depending on the chosen style
	void            ShowProminentEntry( sal_uInt16 nEntryPos );
	void            SetProminentEntryType( ProminentEntry eType ) { meProminentType = eType; }
	ProminentEntry  GetProminentEntryType() const { return meProminentType; }
    using Window::IsVisible;
	sal_Bool			IsVisible( sal_uInt16 nEntry ) const;

	long			GetLeftIndent() const			{ return mnLeft; }
	void			SetLeftIndent( long n );
	void			ScrollHorz( long nDiff );

	void			AllowGrabFocus( bool b )		{ mbGrabFocus = b; }
	bool            IsGrabFocusAllowed() const		{ return mbGrabFocus; }

	void			SetSeparatorPos( sal_uInt16 n )		{ mnSeparatorPos = n; }
	sal_uInt16			GetSeparatorPos() const			{ return mnSeparatorPos; }

	void            SetTravelSelect( bool bTravelSelect ) { mbTravelSelect = bTravelSelect; }
	bool            IsTravelSelect() const			{ return mbTravelSelect; }
	bool            IsTrackingSelect() const		{ return mbTrackingSelect; }

	void			SetUserItemSize( const Size& rSz );
	const Size&		GetUserItemSize() const				{ return maUserItemSize; }

	void			EnableUserDraw( bool bUserDraw ) { mbUserDrawEnabled = bUserDraw; }
	bool            IsUserDrawEnabled() const 	{ return mbUserDrawEnabled; }

	void			EnableMultiSelection( bool bMulti, bool bStackMode ) { mbMulti = bMulti; mbStackMode = bStackMode; }
	bool            IsMultiSelectionEnabled() const 	{ return mbMulti; }

	void			SetMultiSelectionSimpleMode( bool bSimple )	{ mbSimpleMode = bSimple; }
	bool            IsMultiSelectionSimpleMode() const 			{ return mbSimpleMode; }

	void			EnableMouseMoveSelect( bool bMouseMoveSelect ) { mbMouseMoveSelect = bMouseMoveSelect; }
	bool            IsMouseMoveSelectEnabled() const 	{ return mbMouseMoveSelect; }
	bool            IsMouseMoveSelect() const 	{ return mbMouseMoveSelect||mbStackMode; }

	Size			CalcSize( sal_uInt16 nMaxLines ) const;
    Rectangle       GetBoundingRectangle( sal_uInt16 nItem ) const;

    long			GetEntryHeight() const				{ return mnMaxHeight; }
	long			GetMaxEntryWidth() const			{ return mnMaxWidth; }

	void			SetScrollHdl( const Link& rLink )	{ maScrollHdl = rLink; }
	const Link& 	GetScrollHdl() const				{ return maScrollHdl; }
	void			SetSelectHdl( const Link& rLink )	{ maSelectHdl = rLink; }
	const Link& 	GetSelectHdl() const				{ return maSelectHdl; }
	void			SetCancelHdl( const Link& rLink )	{ maCancelHdl = rLink; }
	const Link& 	GetCancelHdl() const				{ return maCancelHdl; }
	void			SetDoubleClickHdl( const Link& rLink )	{ maDoubleClickHdl = rLink; }
	const Link& 	GetDoubleClickHdl() const				{ return maDoubleClickHdl; }
	void			SetUserDrawHdl( const Link& rLink )	{ maUserDrawHdl = rLink; }
	const Link& 	GetUserDrawHdl() const				{ return maUserDrawHdl; }
	void			SetMRUChangedHdl( const Link& rLink )	{ maMRUChangedHdl = rLink; }
	const Link& 	GetMRUChangedHdl() const				{ return maMRUChangedHdl; }
//IAccessibility2 Implementation 2009-----
	void			SetFocusHdl( const Link& rLink )	{ maFocusHdl = rLink ; }
	const Link& 	GetFocusHdl() const				{ return maFocusHdl; }

	void			SetListItemSelectHdl( const Link& rLink )	{ maListItemSelectHdl = rLink ; }
	const Link& 	GetListItemSelectHdl() const				{ return maListItemSelectHdl; }
//-----IAccessibility2 Implementation 2009
	bool			IsSelectionChanged() const { return mbSelectionChanged; }
	sal_uInt16			GetSelectModifier() const { return mnSelectModifier; }

	void			EnableSort( bool b ) { mbSort = b; }

	void			SetReadOnly( bool bReadOnly ) 	{ mbReadOnly = bReadOnly; }
	bool            IsReadOnly() const 				{ return mbReadOnly; }

    using Control::ImplInitSettings;
	void			ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground );
    sal_uInt16          ImplGetTextStyle() const;

	// pb: #106948# explicit mirroring for calc
	inline void		EnableMirroring()		{ mbMirroring = true; }
	inline bool     IsMirroring() const { return mbMirroring; }

    bool GetEdgeBlending() const { return mbEdgeBlending; }
    void SetEdgeBlending(bool bNew) { mbEdgeBlending = bNew; }

protected:
    // ISearchableStringList
    virtual ::vcl::StringEntryIdentifier    CurrentEntry( String& _out_entryText ) const;
    virtual ::vcl::StringEntryIdentifier    NextEntry( ::vcl::StringEntryIdentifier _currentEntry, String& _out_entryText ) const;
    virtual void                            SelectEntry( ::vcl::StringEntryIdentifier _entry );
};

// ---------------
// - ImplListBox -
// ---------------

class ImplListBox : public Control
{
private:
	ImplListBoxWindow	maLBWindow;
	ScrollBar*			mpHScrollBar;
	ScrollBar*			mpVScrollBar;
	ScrollBarBox*		mpScrollBarBox;

    /// bitfield
    bool mbVScroll : 1;     // VScroll an oder aus
    bool mbHScroll : 1;     // HScroll an oder aus
    bool mbAutoHScroll : 1; // AutoHScroll an oder aus
    bool mbEdgeBlending : 1;

	Link				maScrollHdl;	// Weil der vom ImplListBoxWindow selbst benoetigt wird.
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > mxDNDListenerContainer;

protected:
	virtual void		GetFocus();
	virtual void		StateChanged( StateChangedType nType );
	virtual void		DataChanged( const DataChangedEvent& rDCEvt );

	long 				Notify( NotifyEvent& rNEvt );

	void				ImplResizeControls();
	void				ImplCheckScrollBars();
	void				ImplInitScrollBars();

	DECL_LINK(			ScrollBarHdl, ScrollBar* );
	DECL_LINK(			LBWindowScrolled, void* );
	DECL_LINK(			MRUChanged, void* );

public:
					ImplListBox( Window* pParent, WinBits nWinStyle );
					~ImplListBox();

	const ImplEntryList*	GetEntryList() const			{ return maLBWindow.GetEntryList(); }
	ImplListBoxWindow* 		GetMainWindow() 				{ return &maLBWindow; }

	virtual void	Resize();
    virtual const Wallpaper& GetDisplayBackground() const;
    virtual Window*     GetPreferredKeyInputWindow();

	sal_uInt16			InsertEntry( sal_uInt16 nPos, const XubString& rStr );
	sal_uInt16			InsertEntry( sal_uInt16 nPos, const Image& rImage );
	sal_uInt16			InsertEntry( sal_uInt16 nPos, const XubString& rStr, const Image& rImage );
	void			RemoveEntry( sal_uInt16 nPos );
	void			SetEntryData( sal_uInt16 nPos, void* pNewData )	{ maLBWindow.GetEntryList()->SetEntryData( nPos, pNewData ); }
	void			Clear();

	void			SetEntryFlags( sal_uInt16 nPos, long nFlags );
	long			GetEntryFlags( sal_uInt16 nPos ) const;

	void			SelectEntry( sal_uInt16 nPos, sal_Bool bSelect );
	void			SetNoSelection();
	void			ResetCurrentPos()				{ maLBWindow.ResetCurrentPos(); }
	sal_uInt16			GetCurrentPos()	const			{ return maLBWindow.GetCurrentPos(); }

	sal_Bool			ProcessKeyInput( const KeyEvent& rKEvt )	{ return maLBWindow.ProcessKeyInput( rKEvt ); }
	sal_Bool			HandleWheelAsCursorTravel( const CommandEvent& rCEvt );

	void			SetSeparatorPos( sal_uInt16 n )		{ maLBWindow.SetSeparatorPos( n ); }
	sal_uInt16			GetSeparatorPos() const			{ return maLBWindow.GetSeparatorPos(); }

	void			SetTopEntry( sal_uInt16 nTop )		{ maLBWindow.SetTopEntry( nTop ); }
	sal_uInt16			GetTopEntry() const 			{ return maLBWindow.GetTopEntry(); }
	void            ShowProminentEntry( sal_uInt16 nPos ) { maLBWindow.ShowProminentEntry( nPos ); }
    using Window::IsVisible;
	sal_Bool			IsVisible( sal_uInt16 nEntry ) const { return maLBWindow.IsVisible( nEntry ); }

	void            SetProminentEntryType( ProminentEntry eType ) { maLBWindow.SetProminentEntryType( eType ); }
	ProminentEntry  GetProminentEntryType() const { return maLBWindow.GetProminentEntryType(); }

	long			GetLeftIndent() const			{ return maLBWindow.GetLeftIndent(); }
	void			SetLeftIndent( sal_uInt16 n )		{ maLBWindow.SetLeftIndent( n ); }
	void			ScrollHorz( short nDiff )		{ maLBWindow.ScrollHorz( nDiff ); }

	void            SetTravelSelect( sal_Bool bTravelSelect ) { maLBWindow.SetTravelSelect( bTravelSelect ); }
	sal_Bool			IsTravelSelect() const			{ return maLBWindow.IsTravelSelect(); }
	sal_Bool			IsTrackingSelect() const			{ return maLBWindow.IsTrackingSelect(); }

	void			EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackMode ) { maLBWindow.EnableMultiSelection( bMulti, bStackMode ); }
	sal_Bool			IsMultiSelectionEnabled() const 	{ return maLBWindow.IsMultiSelectionEnabled(); }

	void			SetMultiSelectionSimpleMode( sal_Bool bSimple ) { maLBWindow.SetMultiSelectionSimpleMode( bSimple ); }
	sal_Bool			IsMultiSelectionSimpleMode() const 	{ return maLBWindow.IsMultiSelectionSimpleMode(); }

	void			SetReadOnly( sal_Bool b ) 			{ maLBWindow.SetReadOnly( b ); }
	sal_Bool			IsReadOnly() const 				{ return maLBWindow.IsReadOnly(); }


	Size			CalcSize( sal_uInt16 nMaxLines ) const				{ return maLBWindow.CalcSize( nMaxLines ); }
	long			GetEntryHeight() const			{ return maLBWindow.GetEntryHeight(); }
	long			GetMaxEntryWidth() const		{ return maLBWindow.GetMaxEntryWidth(); }

	void			SetScrollHdl( const Link& rLink )	{ maScrollHdl = rLink; }
	const Link& 	GetScrollHdl() const				{ return maScrollHdl; }
	void			SetSelectHdl( const Link& rLink )	{ maLBWindow.SetSelectHdl( rLink ); }
	const Link& 	GetSelectHdl() const				{ return maLBWindow.GetSelectHdl(); }
	void			SetCancelHdl( const Link& rLink )	{ maLBWindow.SetCancelHdl( rLink ); }
	const Link& 	GetCancelHdl() const				{ return maLBWindow.GetCancelHdl(); }
	void			SetDoubleClickHdl( const Link& rLink )	{ maLBWindow.SetDoubleClickHdl( rLink ); }
	const Link& 	GetDoubleClickHdl() const				{ return maLBWindow.GetDoubleClickHdl(); }
	void			SetUserDrawHdl( const Link& rLink )	{ maLBWindow.SetUserDrawHdl( rLink ); }
	const Link& 	GetUserDrawHdl() const				{ return maLBWindow.GetUserDrawHdl(); }

//IAccessibility2 Implementation 2009-----
	void			SetFocusHdl( const Link& rLink )	{ maLBWindow.SetFocusHdl( rLink ); }
	const Link& 	GetFocusHdl() const				{ return maLBWindow.GetFocusHdl(); }
	void			SetListItemSelectHdl( const Link& rLink )	{ maLBWindow.SetListItemSelectHdl( rLink ); }
	const Link& 	GetListItemSelectHdl() const	{ return maLBWindow.GetListItemSelectHdl(); }
//-----IAccessibility2 Implementation 2009
	void			SetSelectionChangedHdl( const Link& rLnk )	{ maLBWindow.GetEntryList()->SetSelectionChangedHdl( rLnk ); }
	void			SetCallSelectionChangedHdl( sal_Bool bCall )	{ maLBWindow.GetEntryList()->SetCallSelectionChangedHdl( bCall ); }
	sal_Bool			IsSelectionChanged() const 					{ return maLBWindow.IsSelectionChanged(); }
	sal_uInt16			GetSelectModifier() const 					{ return maLBWindow.GetSelectModifier(); }

	void			SetMRUEntries( const XubString& rEntries, xub_Unicode cSep );
	XubString		GetMRUEntries( xub_Unicode cSep ) const;
	void			SetMaxMRUCount( sal_uInt16 n )					{ maLBWindow.GetEntryList()->SetMaxMRUCount( n ); }
	sal_uInt16			GetMaxMRUCount() const						{ return maLBWindow.GetEntryList()->GetMaxMRUCount(); }
    sal_uInt16			GetDisplayLineCount() const
    { return maLBWindow.GetDisplayLineCount(); }

    bool GetEdgeBlending() const { return mbEdgeBlending; }
    void SetEdgeBlending(bool bNew);

    // pb: #106948# explicit mirroring for calc
	inline void		EnableMirroring()	{ maLBWindow.EnableMirroring(); }
    inline void     SetDropTraget(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& i_xDNDListenerContainer){ mxDNDListenerContainer= i_xDNDListenerContainer; }
};

// -----------------------------
// - ImplListBoxFloatingWindow -
// -----------------------------

class ImplListBoxFloatingWindow : public FloatingWindow
{
private:
	ImplListBox*	mpImplLB;
	Size			maPrefSz;
	sal_uInt16			mnDDLineCount;
    sal_uInt16          mnPopupModeStartSaveSelection;
	sal_Bool			mbAutoWidth;

protected:
	long			PreNotify( NotifyEvent& rNEvt );

public:
					ImplListBoxFloatingWindow( Window* pParent );

	void			SetImplListBox( ImplListBox* pLB )	{ mpImplLB = pLB; }

	void			SetPrefSize( const Size& rSz )		{ maPrefSz = rSz; }
	const Size& 	GetPrefSize() const 				{ return maPrefSz; }

	void			SetAutoWidth( sal_Bool b )				{ mbAutoWidth = b; }
    sal_Bool            IsAutoWidth() const                 { return mbAutoWidth; }

	Size			CalcFloatSize();
	void			StartFloat( sal_Bool bStartTracking );

	virtual void	SetPosSizePixel( long nX, long nY,
									 long nWidth, long nHeight, sal_uInt16 nFlags = WINDOW_POSSIZE_ALL );
	void			SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
						{ FloatingWindow::SetPosSizePixel( rNewPos, rNewSize ); }

	void			SetDropDownLineCount( sal_uInt16 n ) { mnDDLineCount = n; }
	sal_uInt16			GetDropDownLineCount() const { return mnDDLineCount; }

    sal_uInt16          GetPopupModeStartSaveSelection() const { return mnPopupModeStartSaveSelection; }

    virtual void	Resize();
};

// -----------
// - ImplWin -
// -----------

class ImplWin : public Control
{
private:

	sal_uInt16			mnItemPos;	// wegen UserDraw muss ich wissen, welches Item ich darstelle.
	XubString		maString;
	Image			maImage;
	Image			maImageHC;

	Rectangle		maFocusRect;
	Size			maUserItemSize;

	Link			maMBDownHdl;
	Link			maUserDrawHdl;

    /// bitfield
    bool            mbUserDrawEnabled : 1;
    bool            mbInUserDraw : 1;
    bool            mbEdgeBlending : 1;

    void ImplDraw( bool bLayout = false );
protected:
    virtual void  FillLayoutData() const;
public:

					ImplWin( Window* pParent, WinBits nWinStyle = 0 );
					~ImplWin() {};

	virtual void	MouseButtonDown( const MouseEvent& rMEvt );
	virtual void	Paint( const Rectangle& rRect );
	virtual void	Resize();
	virtual void	GetFocus();
	virtual void	LoseFocus();
    virtual long    PreNotify( NotifyEvent& rNEvt );

	sal_uInt16			GetItemPos() const { return mnItemPos; }
	void			SetItemPos( sal_uInt16 n ) { mnItemPos = n; }

	const XubString& GetString() const { return maString; }
	void			SetString( const XubString& rStr ) { maString = rStr; }

	const Image&	GetImage() const { return maImage; }
	void			SetImage( const Image& rImg ) { maImage = rImg; }

    sal_Bool            SetModeImage( const Image& rImage, BmpColorMode eMode = BMP_COLOR_NORMAL );
    const Image&    GetModeImage( BmpColorMode eMode = BMP_COLOR_NORMAL ) const;


	virtual void	MBDown();
	void			SetMBDownHdl( const Link& rLink ) { maMBDownHdl = rLink; }
	const Link& 	GetMBDownHdl() const { return maMBDownHdl; }

	void			SetUserDrawHdl( const Link& rLink )	{ maUserDrawHdl = rLink; }
	const Link& 	GetUserDrawHdl() const				{ return maUserDrawHdl; }

	void			SetUserItemSize( const Size& rSz )	{ maUserItemSize = rSz; }
	const Size&		GetUserItemSize() const				{ return maUserItemSize; }

	void			EnableUserDraw( bool bUserDraw ) 	{ mbUserDrawEnabled = bUserDraw; }
	bool            IsUserDrawEnabled() const 			{ return mbUserDrawEnabled; }

	void 			DrawEntry( sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos = sal_False, bool bLayout = false );

    bool GetEdgeBlending() const { return mbEdgeBlending; }
    void SetEdgeBlending(bool bNew) { mbEdgeBlending = bNew; }
};

// -----------
// - ImplBtn -
// -----------

class ImplBtn : public PushButton
{
private:
	sal_Bool			mbDown;

	Link			maMBDownHdl;

public:
					ImplBtn( Window* pParent, WinBits nWinStyle = 0 );
					~ImplBtn() {};

	virtual void	MouseButtonDown( const MouseEvent& rMEvt );

	virtual void	MBDown();
	void			SetMBDownHdl( const Link& rLink ) { maMBDownHdl = rLink; }
	const Link& 	GetMBDownHdl() const { return maMBDownHdl; }
};


void ImplInitFieldSettings( Window* pWin, sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground );
void ImplInitDropDownButton( PushButton* pButton );

#endif	// _SV_ILSTBOX_HXX
