xref: /AOO41X/main/vcl/source/control/lstbox.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include "tools/rc.h"
32 #include "tools/debug.hxx"
33 
34 
35 #include "vcl/decoview.hxx"
36 #include "vcl/event.hxx"
37 #include "vcl/scrbar.hxx"
38 #include "vcl/button.hxx"
39 #include "vcl/edit.hxx"
40 #include "vcl/lstbox.hxx"
41 #include "vcl/combobox.hxx"
42 
43 #include "svdata.hxx"
44 #include "controldata.hxx"
45 #include "subedit.hxx"
46 #include "ilstbox.hxx"
47 #include "dndevdis.hxx"
48 
49 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
50 
51 // =======================================================================
52 
53 ListBox::ListBox( WindowType nType ) : Control( nType )
54 {
55 	ImplInitListBoxData();
56 }
57 
58 // -----------------------------------------------------------------------
59 
60 ListBox::ListBox( Window* pParent, WinBits nStyle ) : Control( WINDOW_LISTBOX )
61 {
62 	ImplInitListBoxData();
63 	ImplInit( pParent, nStyle );
64 }
65 
66 // -----------------------------------------------------------------------
67 
68 ListBox::ListBox( Window* pParent, const ResId& rResId ) :
69 	Control( WINDOW_LISTBOX )
70 {
71 	ImplInitListBoxData();
72 	rResId.SetRT( RSC_LISTBOX );
73 	WinBits nStyle = ImplInitRes( rResId );
74 	ImplInit( pParent, nStyle );
75 	ImplLoadRes( rResId );
76 
77 	if ( !(nStyle & WB_HIDE ) )
78 		Show();
79 }
80 
81 // -----------------------------------------------------------------------
82 
83 ListBox::~ListBox()
84 {
85     //#109201#
86     ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
87 
88     delete mpImplLB;
89 
90 	// Beim zerstoeren des FloatWins macht TH ein GrabFocus auf den Parent,
91 	// also diese ListBox => PreNotify()...
92 	mpImplLB = NULL;
93 
94 	delete mpFloatWin;
95 	delete mpImplWin;
96 	delete mpBtn;
97 }
98 
99 // -----------------------------------------------------------------------
100 
101 void ListBox::ImplInitListBoxData()
102 {
103 	mpFloatWin		= NULL;
104 	mpImplWin		= NULL;
105 	mpBtn			= NULL;
106 
107 	mnDDHeight		= 0;
108 	mbDDAutoSize	= sal_True;
109 	mnSaveValue 	= LISTBOX_ENTRY_NOTFOUND;
110     mnLineCount     = 0;
111 }
112 
113 // -----------------------------------------------------------------------
114 
115 void ListBox::ImplInit( Window* pParent, WinBits nStyle )
116 {
117 	nStyle = ImplInitStyle( nStyle );
118 	if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) )
119 		nStyle |= WB_BORDER;
120 
121 	Control::ImplInit( pParent, nStyle, NULL );
122 	SetBackground();
123 
124     ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this);
125 
126 	if( nStyle & WB_DROPDOWN )
127 	{
128         sal_Int32 nLeft, nTop, nRight, nBottom;
129         GetBorder( nLeft, nTop, nRight, nBottom );
130         mnDDHeight = (sal_uInt16)(GetTextHeight() + nTop + nBottom + 4);
131 
132         if( IsNativeWidgetEnabled() &&
133             IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
134         {
135                 ImplControlValue aControlValue;
136                 Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) );
137                 Rectangle aBoundingRgn( aCtrlRegion );
138                 Rectangle aContentRgn( aCtrlRegion );
139                 if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
140                                             CTRL_STATE_ENABLED, aControlValue, rtl::OUString(),
141                                             aBoundingRgn, aContentRgn ) )
142                 {
143                     sal_Int32 nHeight = aBoundingRgn.GetHeight();
144                     if( nHeight > mnDDHeight )
145                         mnDDHeight = static_cast<sal_uInt16>(nHeight);
146                 }
147         }
148 
149 		mpFloatWin = new ImplListBoxFloatingWindow( this );
150 		mpFloatWin->SetAutoWidth( sal_True );
151 		mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) );
152         mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop);
153 
154 		mpImplWin = new ImplWin( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER );
155 		mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
156 		mpImplWin->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
157 		mpImplWin->Show();
158         mpImplWin->GetDropTarget()->addDropTargetListener(xDrop);
159 
160 		mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
161 		ImplInitDropDownButton( mpBtn );
162 		mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
163 		mpBtn->Show();
164         mpBtn->GetDropTarget()->addDropTargetListener(xDrop);
165 
166 	}
167 
168 	Window* pLBParent = this;
169 	if ( mpFloatWin )
170 		pLBParent = mpFloatWin;
171 	mpImplLB = new ImplListBox( pLBParent, nStyle&(~WB_BORDER) );
172 	mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) );
173 	mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl ) );
174 	mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) );
175 	mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) );
176 	mpImplLB->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
177 	mpImplLB->SetPosPixel( Point() );
178 	mpImplLB->Show();
179 
180     mpImplLB->GetDropTarget()->addDropTargetListener(xDrop);
181     mpImplLB->SetDropTraget(xDrop);
182 
183 	if ( mpFloatWin )
184 	{
185 		mpFloatWin->SetImplListBox( mpImplLB );
186 		mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) );
187 	}
188 	else
189 		mpImplLB->GetMainWindow()->AllowGrabFocus( sal_True );
190 
191 	SetCompoundControl( sal_True );
192 }
193 
194 // -----------------------------------------------------------------------
195 
196 WinBits ListBox::ImplInitStyle( WinBits nStyle )
197 {
198 	if ( !(nStyle & WB_NOTABSTOP) )
199 		nStyle |= WB_TABSTOP;
200 	if ( !(nStyle & WB_NOGROUP) )
201 		nStyle |= WB_GROUP;
202 	return nStyle;
203 }
204 
205 // -----------------------------------------------------------------------
206 
207 void ListBox::ImplLoadRes( const ResId& rResId )
208 {
209 	Control::ImplLoadRes( rResId );
210 
211 	sal_uInt16 nSelPos = ReadShortRes();
212 	sal_uInt16 nNumber = sal::static_int_cast<sal_uInt16>(ReadLongRes());
213 
214 	for( sal_uInt16 i = 0; i < nNumber; i++ )
215 	{
216 		sal_uInt16 nPos = InsertEntry( ReadStringRes(), LISTBOX_APPEND );
217 
218 		long nId = ReadLongRes();
219 		if( nId )
220 			SetEntryData( nPos, (void *)nId );	// ID als UserData
221 	}
222 
223 	if( nSelPos < nNumber )
224 		SelectEntryPos( nSelPos );
225 }
226 
227 // -----------------------------------------------------------------------
228 
229 IMPL_LINK( ListBox, ImplSelectHdl, void*, EMPTYARG )
230 {
231 	sal_Bool bPopup = IsInDropDown();
232 	if( IsDropDownBox() )
233 	{
234 		if( !mpImplLB->IsTravelSelect() )
235 		{
236 			mpFloatWin->EndPopupMode();
237 			mpImplWin->GrabFocus();
238 		}
239 
240 		mpImplWin->SetItemPos( GetSelectEntryPos() );
241 		mpImplWin->SetString( GetSelectEntry() );
242 		if( mpImplLB->GetEntryList()->HasImages() )
243 		{
244 			Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectEntryPos() );
245 			mpImplWin->SetImage( aImage );
246 		}
247 		mpImplWin->Invalidate();
248 	}
249 
250 	if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) )
251 		Select();
252 
253 	return 1;
254 }
255 
256 // -----------------------------------------------------------------------
257 
258 IMPL_LINK( ListBox, ImplScrollHdl, void*, EMPTYARG )
259 {
260     ImplCallEventListeners( VCLEVENT_LISTBOX_SCROLLED );
261 	return 1;
262 }
263 
264 // -----------------------------------------------------------------------
265 
266 IMPL_LINK( ListBox, ImplCancelHdl, void*, EMPTYARG )
267 {
268 	if( IsInDropDown() )
269 		mpFloatWin->EndPopupMode();
270 
271 	return 1;
272 }
273 
274 // -----------------------------------------------------------------------
275 
276 IMPL_LINK( ListBox, ImplSelectionChangedHdl, void*, n )
277 {
278 	if ( !mpImplLB->IsTrackingSelect() )
279 	{
280 		sal_uInt16 nChanged = (sal_uInt16)(sal_uLong)n;
281 		const ImplEntryList* pEntryList = mpImplLB->GetEntryList();
282 		if ( pEntryList->IsEntryPosSelected( nChanged ) )
283 		{
284 			// Sollte mal ein ImplPaintEntry werden...
285 			if ( nChanged < pEntryList->GetMRUCount() )
286 				nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ) );
287 			mpImplWin->SetItemPos( nChanged );
288 			mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
289 			if( mpImplLB->GetEntryList()->HasImages() )
290 			{
291 				Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged );
292 				mpImplWin->SetImage( aImage );
293 			}
294 		}
295 		else
296 		{
297 			mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
298 			mpImplWin->SetString( ImplGetSVEmptyStr() );
299 			Image aImage;
300 			mpImplWin->SetImage( aImage );
301 		}
302 		mpImplWin->Invalidate();
303 	}
304 	return 1;
305 }
306 
307 // -----------------------------------------------------------------------
308 
309 IMPL_LINK( ListBox, ImplDoubleClickHdl, void*, EMPTYARG )
310 {
311 	DoubleClick();
312 	return 1;
313 }
314 
315 // -----------------------------------------------------------------------
316 
317 IMPL_LINK( ListBox, ImplClickBtnHdl, void*, EMPTYARG )
318 {
319 	if( !mpFloatWin->IsInPopupMode() )
320 	{
321         ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
322 		mpImplWin->GrabFocus();
323 		mpBtn->SetPressed( sal_True );
324 		mpFloatWin->StartFloat( sal_True );
325         ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
326 
327         ImplClearLayoutData();
328         if( mpImplLB )
329             mpImplLB->GetMainWindow()->ImplClearLayoutData();
330         if( mpImplWin )
331             mpImplWin->ImplClearLayoutData();
332 	}
333 
334 	return 0;
335 }
336 
337 // -----------------------------------------------------------------------
338 
339 IMPL_LINK( ListBox, ImplPopupModeEndHdl, void*, EMPTYARG )
340 {
341     if( mpFloatWin->IsPopupModeCanceled() )
342     {
343         if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND )
344                 && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) )
345         {
346             mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), sal_True );
347             sal_Bool bTravelSelect = mpImplLB->IsTravelSelect();
348             mpImplLB->SetTravelSelect( sal_True );
349 
350             ImplDelData aCheckDelete;
351             ImplAddDel( &aCheckDelete );
352             Select();
353             if ( aCheckDelete.IsDelete() )
354                 return 0;
355             ImplRemoveDel( &aCheckDelete );
356 
357             mpImplLB->SetTravelSelect( bTravelSelect );
358         }
359     }
360 
361     ImplClearLayoutData();
362     if( mpImplLB )
363         mpImplLB->GetMainWindow()->ImplClearLayoutData();
364     if( mpImplWin )
365         mpImplWin->ImplClearLayoutData();
366 
367     mpBtn->SetPressed( sal_False );
368     ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE );
369 	return 0;
370 }
371 
372 // -----------------------------------------------------------------------
373 
374 void ListBox::ToggleDropDown()
375 {
376     if( IsDropDownBox() )
377     {
378         if( mpFloatWin->IsInPopupMode() )
379             mpFloatWin->EndPopupMode();
380         else
381         {
382             ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
383             mpImplWin->GrabFocus();
384             mpBtn->SetPressed( sal_True );
385             mpFloatWin->StartFloat( sal_True );
386             ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
387         }
388     }
389 }
390 
391 // -----------------------------------------------------------------------
392 
393 void ListBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
394 {
395 	mpImplLB->GetMainWindow()->ImplInitSettings( sal_True, sal_True, sal_True );
396 
397 	Point aPos = pDev->LogicToPixel( rPos );
398 	Size aSize = pDev->LogicToPixel( rSize );
399 	Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
400 	OutDevType eOutDevType = pDev->GetOutDevType();
401 
402 	pDev->Push();
403 	pDev->SetMapMode();
404 	pDev->SetFont( aFont );
405 	pDev->SetTextFillColor();
406 
407 	// Border/Background
408 	pDev->SetLineColor();
409 	pDev->SetFillColor();
410 	sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
411 	sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
412 	if ( bBorder || bBackground )
413 	{
414 		Rectangle aRect( aPos, aSize );
415 		if ( bBorder )
416 		{
417             ImplDrawFrame( pDev, aRect );
418 		}
419 		if ( bBackground )
420 		{
421 			pDev->SetFillColor( GetControlBackground() );
422 			pDev->DrawRect( aRect );
423 		}
424 	}
425 
426 	// Inhalt
427 	if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
428 	{
429 		pDev->SetTextColor( Color( COL_BLACK ) );
430 	}
431 	else
432 	{
433 		if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
434 		{
435 			const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
436 			pDev->SetTextColor( rStyleSettings.GetDisableColor() );
437 		}
438 		else
439 		{
440 			pDev->SetTextColor( GetTextColor() );
441 		}
442 	}
443 
444 	long        nOnePixel = GetDrawPixel( pDev, 1 );
445     sal_uInt16      nTextStyle = TEXT_DRAW_VCENTER;
446     Rectangle   aTextRect( aPos, aSize );
447 
448     if ( GetStyle() & WB_CENTER )
449         nTextStyle |= TEXT_DRAW_CENTER;
450     else if ( GetStyle() & WB_RIGHT )
451         nTextStyle |= TEXT_DRAW_RIGHT;
452     else
453         nTextStyle |= TEXT_DRAW_LEFT;
454 
455     aTextRect.Left() += 3*nOnePixel;
456     aTextRect.Right() -= 3*nOnePixel;
457 
458     if ( IsDropDownBox() )
459 	{
460 		XubString	aText = GetSelectEntry();
461 		long		nTextHeight = pDev->GetTextHeight();
462 		long		nTextWidth = pDev->GetTextWidth( aText );
463 		long		nOffX = 3*nOnePixel;
464 		long		nOffY = (aSize.Height()-nTextHeight) / 2;
465 
466 		// Clipping?
467 		if ( (nOffY < 0) ||
468 			 ((nOffY+nTextHeight) > aSize.Height()) ||
469 			 ((nOffX+nTextWidth) > aSize.Width()) )
470 		{
471 			Rectangle aClip( aPos, aSize );
472 			if ( nTextHeight > aSize.Height() )
473 				aClip.Bottom() += nTextHeight-aSize.Height()+1;  // Damit HP-Drucker nicht 'weg-optimieren'
474 			pDev->IntersectClipRegion( aClip );
475 		}
476 
477 		pDev->DrawText( aTextRect, aText, nTextStyle );
478 	}
479 	else
480 	{
481 		long		nTextHeight = pDev->GetTextHeight();
482 		sal_uInt16		nLines = (sal_uInt16)(aSize.Height() / nTextHeight);
483 		Rectangle	aClip( aPos, aSize );
484 
485         pDev->IntersectClipRegion( aClip );
486 
487         if ( !nLines )
488 			nLines = 1;
489 
490         for ( sal_uInt16 n = 0; n < nLines; n++ )
491 		{
492 			sal_uInt16 nEntry = n+mpImplLB->GetTopEntry();
493 			sal_Bool bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry );
494 			if ( bSelected )
495 			{
496 				pDev->SetFillColor( COL_BLACK );
497 				pDev->DrawRect( Rectangle(	Point( aPos.X(), aPos.Y() + n*nTextHeight ),
498 											Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) );
499 				pDev->SetFillColor();
500 				pDev->SetTextColor( COL_WHITE );
501 			}
502 
503             aTextRect.Top() = aPos.Y() + n*nTextHeight;
504             aTextRect.Bottom() = aTextRect.Top() + nTextHeight;
505 
506             pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( nEntry ), nTextStyle );
507 
508             if ( bSelected )
509 				pDev->SetTextColor( COL_BLACK );
510 		}
511 	}
512 
513 	pDev->Pop();
514 }
515 
516 // -----------------------------------------------------------------------
517 
518 void ListBox::GetFocus()
519 {
520 	if ( mpImplLB )
521 	{
522 		if( IsDropDownBox() )
523 			mpImplWin->GrabFocus();
524 		else
525 			mpImplLB->GrabFocus();
526 	}
527 
528 	Control::GetFocus();
529 }
530 
531 // -----------------------------------------------------------------------
532 
533 Window* ListBox::GetPreferredKeyInputWindow()
534 {
535 	if ( mpImplLB )
536 	{
537 		if( IsDropDownBox() )
538 			return mpImplWin->GetPreferredKeyInputWindow();
539 		else
540 			return mpImplLB->GetPreferredKeyInputWindow();
541 	}
542 
543 	return Control::GetPreferredKeyInputWindow();
544 }
545 
546 // -----------------------------------------------------------------------
547 
548 void ListBox::LoseFocus()
549 {
550 	if( IsDropDownBox() )
551 		mpImplWin->HideFocus();
552 	else
553 		mpImplLB->HideFocus();
554 
555 	Control::LoseFocus();
556 }
557 
558 // -----------------------------------------------------------------------
559 
560 void ListBox::DataChanged( const DataChangedEvent& rDCEvt )
561 {
562 	Control::DataChanged( rDCEvt );
563 
564 	if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
565 		 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
566 		 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
567 		  (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
568 	{
569         SetBackground();    // due to a hack in Window::UpdateSettings the background must be reset
570                             // otherwise it will overpaint NWF drawn listboxes
571 		Resize();
572 		mpImplLB->Resize(); // Wird nicht durch ListBox::Resize() gerufen, wenn sich die ImplLB nicht aendert.
573 
574 		if ( mpImplWin )
575 		{
576 			mpImplWin->SetSettings( GetSettings() );	// Falls noch nicht eingestellt...
577 			ImplInitFieldSettings( mpImplWin, sal_True, sal_True, sal_True );
578 
579 			mpBtn->SetSettings( GetSettings() );
580 			ImplInitDropDownButton( mpBtn );
581 		}
582 
583 
584 		if ( IsDropDownBox() )
585 			Invalidate();
586 	}
587 }
588 
589 // -----------------------------------------------------------------------
590 
591 void ListBox::EnableAutoSize( sal_Bool bAuto )
592 {
593 	mbDDAutoSize = bAuto;
594 	if ( mpFloatWin )
595 	{
596 		if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
597 			mpFloatWin->SetDropDownLineCount( 5 );
598 		else if ( !bAuto )
599 			mpFloatWin->SetDropDownLineCount( 0 );
600 	}
601 }
602 
603 // -----------------------------------------------------------------------
604 
605 void ListBox::EnableDDAutoWidth( sal_Bool b )
606 {
607     if ( mpFloatWin )
608         mpFloatWin->SetAutoWidth( b );
609 }
610 
611 // -----------------------------------------------------------------------
612 
613 sal_Bool ListBox::IsDDAutoWidthEnabled() const
614 {
615     return mpFloatWin ? mpFloatWin->IsAutoWidth() : sal_False;
616 }
617 
618 // -----------------------------------------------------------------------
619 
620 void ListBox::SetDropDownLineCount( sal_uInt16 nLines )
621 {
622     mnLineCount = nLines;
623 	if ( mpFloatWin )
624 		mpFloatWin->SetDropDownLineCount( mnLineCount );
625 }
626 
627 // -----------------------------------------------------------------------
628 
629 sal_uInt16 ListBox::GetDropDownLineCount() const
630 {
631     if ( mpFloatWin )
632         return mpFloatWin->GetDropDownLineCount();
633 	return mnLineCount;
634 }
635 
636 // -----------------------------------------------------------------------
637 
638 void ListBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
639 {
640 	if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) )
641 	{
642 		Size aPrefSz = mpFloatWin->GetPrefSize();
643 		if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight >= 2*mnDDHeight ) )
644 			aPrefSz.Height() = nHeight-mnDDHeight;
645 		if ( nFlags & WINDOW_POSSIZE_WIDTH )
646 			aPrefSz.Width() = nWidth;
647 		mpFloatWin->SetPrefSize( aPrefSz );
648 
649 		if ( IsAutoSizeEnabled() && ! (nFlags & WINDOW_POSSIZE_DROPDOWN) )
650 			nHeight = mnDDHeight;
651 	}
652 
653 	Control::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
654 }
655 
656 // -----------------------------------------------------------------------
657 
658 void ListBox::Resize()
659 {
660 	Size aOutSz = GetOutputSizePixel();
661 	if( IsDropDownBox() )
662 	{
663 		// initialize the dropdown button size with the standard scrollbar width
664 		long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
665 		long	nTop = 0;
666 		long	nBottom = aOutSz.Height();
667 
668         // note: in case of no border, pBorder will actually be this
669 		Window *pBorder = GetWindow( WINDOW_BORDER );
670 		ImplControlValue aControlValue;
671 		Point aPoint;
672 		Rectangle aContent, aBound;
673 
674 		// use the full extent of the control
675 		Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
676 
677 		if ( GetNativeControlRegion( CTRL_LISTBOX, PART_BUTTON_DOWN,
678 					aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
679 		{
680 			// convert back from border space to local coordinates
681 			aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) );
682 			aContent.Move( -aPoint.X(), -aPoint.Y() );
683 
684 			// use the themes drop down size for the button
685 			aOutSz.Width() = aContent.Left();
686 			mpBtn->SetPosSizePixel( aContent.Left(), nTop, aContent.Right(), (nBottom-nTop) );
687 
688 			// adjust the size of the edit field
689 			if ( GetNativeControlRegion( CTRL_LISTBOX, PART_SUB_EDIT,
690 						aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
691 			{
692 				// convert back from border space to local coordinates
693 				aContent.Move( -aPoint.X(), -aPoint.Y() );
694 
695 				// use the themes drop down size
696                 if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects )
697                 {
698                     // no border but focus ring behavior -> we have a problem; the
699                     // native rect relies on the border to draw the focus
700                     // let's do the best we can and center vertically, so it doesn't look
701                     // completely wrong.
702                     Size aSz( GetOutputSizePixel() );
703                     long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2;
704                     aContent.Top() -= nDiff;
705                     aContent.Bottom() -= nDiff;
706                 }
707                 mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() );
708 			}
709 			else
710 				mpImplWin->SetSizePixel( aOutSz );
711 		}
712 		else
713 		{
714 			nSBWidth = CalcZoom( nSBWidth );
715 			mpImplWin->SetPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() );
716 			mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
717 		}
718 	}
719 	else
720 	{
721 		mpImplLB->SetSizePixel( aOutSz );
722 	}
723 
724 	// FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten,
725 	// weil KEY_PGUP/DOWN ausgewertet wird...
726 	if ( mpFloatWin )
727 		mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
728 
729     Control::Resize();
730 }
731 
732 // -----------------------------------------------------------------------
733 
734 void ListBox::FillLayoutData() const
735 {
736     mpControlData->mpLayoutData = new vcl::ControlLayoutData();
737     const Control* pMainWin = mpImplLB->GetMainWindow();
738     if( mpFloatWin )
739     {
740         // dropdown mode
741         AppendLayoutData( *mpImplWin );
742         mpImplWin->SetLayoutDataParent( this );
743         if( mpFloatWin->IsReallyVisible() )
744         {
745             AppendLayoutData( *pMainWin );
746             pMainWin->SetLayoutDataParent( this );
747         }
748     }
749     else
750     {
751         AppendLayoutData( *pMainWin );
752         pMainWin->SetLayoutDataParent( this );
753     }
754 }
755 
756 // -----------------------------------------------------------------------
757 
758 long ListBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const
759 {
760     if( !HasLayoutData() )
761         FillLayoutData();
762 
763     // check whether rPoint fits at all
764     long nIndex = Control::GetIndexForPoint( rPoint );
765     if( nIndex != -1 )
766     {
767         // point must be either in main list window
768         // or in impl window (dropdown case)
769         ImplListBoxWindow* pMain = mpImplLB->GetMainWindow();
770 
771         // convert coordinates to ImplListBoxWindow pixel coordinate space
772         Point aConvPoint = LogicToPixel( rPoint );
773         aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
774         aConvPoint = pMain->AbsoluteScreenToOutputPixel( aConvPoint );
775         aConvPoint = pMain->PixelToLogic( aConvPoint );
776 
777         // try to find entry
778         sal_uInt16 nEntry = pMain->GetEntryPosForPoint( aConvPoint );
779         if( nEntry == LISTBOX_ENTRY_NOTFOUND )
780         {
781             // not found, maybe dropdown case
782             if( mpImplWin && mpImplWin->IsReallyVisible() )
783             {
784                 // convert to impl window pixel coordinates
785                 aConvPoint = LogicToPixel( rPoint );
786                 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
787                 aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPoint );
788 
789                 // check whether converted point is inside impl window
790                 Size aImplWinSize = mpImplWin->GetOutputSizePixel();
791                 if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() )
792                 {
793                     // inside the impl window, the position is the current item pos
794                     rPos = mpImplWin->GetItemPos();
795                 }
796                 else
797                     nIndex = -1;
798             }
799             else
800                 nIndex = -1;
801         }
802         else
803             rPos = nEntry;
804 
805         DBG_ASSERT( nIndex != -1, "found index for point, but relative index failed" );
806     }
807 
808     // get line relative index
809     if( nIndex != -1 )
810         nIndex = ToRelativeLineIndex( nIndex );
811 
812     return nIndex;
813 }
814 
815 // -----------------------------------------------------------------------
816 
817 void ListBox::StateChanged( StateChangedType nType )
818 {
819 	if( nType == STATE_CHANGE_READONLY )
820 	{
821 		if( mpImplWin )
822 			mpImplWin->Enable( !IsReadOnly() );
823 		if( mpBtn )
824 			mpBtn->Enable( !IsReadOnly() );
825 	}
826 	else if( nType == STATE_CHANGE_ENABLE )
827 	{
828 		mpImplLB->Enable( IsEnabled() );
829 		if( mpImplWin )
830 		{
831 			mpImplWin->Enable( IsEnabled() );
832 			if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
833 					&& ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
834 			{
835 				GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE );
836 			}
837 			else
838 				mpImplWin->Invalidate();
839 		}
840 		if( mpBtn )
841 			mpBtn->Enable( IsEnabled() );
842 	}
843 	else if( nType == STATE_CHANGE_UPDATEMODE )
844 	{
845 		mpImplLB->SetUpdateMode( IsUpdateMode() );
846 	}
847 	else if ( nType == STATE_CHANGE_ZOOM )
848 	{
849 		mpImplLB->SetZoom( GetZoom() );
850 		if ( mpImplWin )
851 		{
852 			mpImplWin->SetZoom( GetZoom() );
853 			mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
854 			mpImplWin->Invalidate();
855 		}
856 		Resize();
857 	}
858 	else if ( nType == STATE_CHANGE_CONTROLFONT )
859 	{
860 		mpImplLB->SetControlFont( GetControlFont() );
861 		if ( mpImplWin )
862 		{
863 			mpImplWin->SetControlFont( GetControlFont() );
864 			mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
865 			mpImplWin->Invalidate();
866 		}
867 		Resize();
868 	}
869 	else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
870 	{
871 		mpImplLB->SetControlForeground( GetControlForeground() );
872 		if ( mpImplWin )
873 		{
874 			mpImplWin->SetControlForeground( GetControlForeground() );
875 			mpImplWin->SetTextColor( GetControlForeground() );
876 			mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
877 			mpImplWin->Invalidate();
878 		}
879 	}
880 	else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
881 	{
882 		mpImplLB->SetControlBackground( GetControlBackground() );
883 		if ( mpImplWin )
884 		{
885 			if ( mpImplWin->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) )
886 			{
887 				// Transparent background
888 				mpImplWin->SetBackground();
889 				mpImplWin->SetControlBackground();
890 			}
891 			else
892 			{
893 				mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
894 				mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
895 			}
896 			mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
897 			mpImplWin->Invalidate();
898 		}
899 	}
900 	else if ( nType == STATE_CHANGE_STYLE )
901 	{
902 		SetStyle( ImplInitStyle( GetStyle() ) );
903 		mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? sal_True : sal_False );
904 	    sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False;
905 	    mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
906 	}
907     else if( nType == STATE_CHANGE_MIRRORING )
908     {
909         if( mpBtn )
910         {
911             mpBtn->EnableRTL( IsRTLEnabled() );
912             ImplInitDropDownButton( mpBtn );
913         }
914         mpImplLB->EnableRTL( IsRTLEnabled() );
915         if( mpImplWin )
916             mpImplWin->EnableRTL( IsRTLEnabled() );
917         Resize();
918     }
919 
920 	Control::StateChanged( nType );
921 }
922 
923 // -----------------------------------------------------------------------
924 
925 long ListBox::PreNotify( NotifyEvent& rNEvt )
926 {
927 	long nDone = 0;
928 	if ( mpImplLB )
929 	{
930 		if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) )
931 		{
932 			KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
933 			switch( aKeyEvt.GetKeyCode().GetCode() )
934 			{
935 				case KEY_DOWN:
936 				{
937 					if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
938 						aKeyEvt.GetKeyCode().IsMod2() )
939 					{
940                         ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
941 						mpBtn->SetPressed( sal_True );
942 						mpFloatWin->StartFloat( sal_False );
943                         ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
944 						nDone = 1;
945 					}
946 					else
947 					{
948 						nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
949 					}
950 				}
951 				break;
952 				case KEY_UP:
953 				{
954 					if( mpFloatWin && mpFloatWin->IsInPopupMode() &&
955 						aKeyEvt.GetKeyCode().IsMod2() )
956 					{
957 						mpFloatWin->EndPopupMode();
958 						nDone = 1;
959 					}
960 					else
961 					{
962 						nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
963 					}
964 				}
965 				break;
966 				case KEY_RETURN:
967 				{
968 					if( IsInDropDown() )
969 					{
970 						mpImplLB->ProcessKeyInput( aKeyEvt );
971 						nDone = 1;
972 					}
973 				}
974 				break;
975 
976 				default:
977                 {
978 					nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
979                 }
980 			}
981 		}
982 		else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
983 		{
984 			if ( IsInDropDown() && !HasChildPathFocus( sal_True ) )
985 				mpFloatWin->EndPopupMode();
986 		}
987 		else if ( (rNEvt.GetType() == EVENT_COMMAND) &&
988 				  (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
989 				  (rNEvt.GetWindow() == mpImplWin) )
990 		{
991             sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
992             if  (   ( nWheelBehavior == MOUSE_WHEEL_ALWAYS )
993                 ||  (   ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY )
994                     &&  HasChildPathFocus()
995                     )
996                 )
997             {
998                 nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
999             }
1000             else
1001             {
1002                 nDone = 0;  // don't eat this event, let the default handling happen (i.e. scroll the context)
1003             }
1004 		}
1005 	}
1006 
1007 	return nDone ? nDone : Control::PreNotify( rNEvt );
1008 }
1009 
1010 // -----------------------------------------------------------------------
1011 
1012 void ListBox::Select()
1013 {
1014     ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_SELECT, maSelectHdl, this );
1015 }
1016 
1017 // -----------------------------------------------------------------------
1018 
1019 void ListBox::DoubleClick()
1020 {
1021     ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_DOUBLECLICK, maDoubleClickHdl, this );
1022 }
1023 
1024 // -----------------------------------------------------------------------
1025 
1026 void ListBox::Clear()
1027 {
1028 	mpImplLB->Clear();
1029 	if( IsDropDownBox() )
1030 	{
1031 		mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
1032 		mpImplWin->SetString( ImplGetSVEmptyStr() );
1033 		Image aImage;
1034 		mpImplWin->SetImage( aImage );
1035 		mpImplWin->Invalidate();
1036 	}
1037     CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(-1) );
1038 }
1039 
1040 // -----------------------------------------------------------------------
1041 
1042 void ListBox::SetNoSelection()
1043 {
1044 	mpImplLB->SetNoSelection();
1045 	if( IsDropDownBox() )
1046 	{
1047 		mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
1048 		mpImplWin->SetString( ImplGetSVEmptyStr() );
1049 		Image aImage;
1050 		mpImplWin->SetImage( aImage );
1051 		mpImplWin->Invalidate();
1052 	}
1053 }
1054 
1055 // -----------------------------------------------------------------------
1056 
1057 sal_uInt16 ListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
1058 {
1059 	sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
1060 	nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1061     CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
1062 	return nRealPos;
1063 }
1064 
1065 // -----------------------------------------------------------------------
1066 
1067 sal_uInt16 ListBox::InsertEntry( const Image& rImage, sal_uInt16 nPos )
1068 {
1069 	sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rImage );
1070 	nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1071     CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
1072 	return nRealPos;
1073 }
1074 
1075 // -----------------------------------------------------------------------
1076 
1077 sal_uInt16 ListBox::InsertEntry( const XubString& rStr, const Image& rImage, sal_uInt16 nPos )
1078 {
1079 	sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
1080 	nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1081     CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
1082 	return nRealPos;
1083 }
1084 
1085 // -----------------------------------------------------------------------
1086 
1087 void ListBox::RemoveEntry( const XubString& rStr )
1088 {
1089 	RemoveEntry( GetEntryPos( rStr ) );
1090 }
1091 
1092 // -----------------------------------------------------------------------
1093 
1094 void ListBox::RemoveEntry( sal_uInt16 nPos )
1095 {
1096 	mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1097     CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(nPos) );
1098 }
1099 
1100 // -----------------------------------------------------------------------
1101 
1102 Image ListBox::GetEntryImage( sal_uInt16 nPos ) const
1103 {
1104     if ( mpImplLB->GetEntryList()->HasEntryImage( nPos ) )
1105         return mpImplLB->GetEntryList()->GetEntryImage( nPos );
1106     return Image();
1107 }
1108 
1109 // -----------------------------------------------------------------------
1110 
1111 sal_uInt16 ListBox::GetEntryPos( const XubString& rStr ) const
1112 {
1113 	sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( rStr );
1114 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1115 		nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1116 	return nPos;
1117 }
1118 
1119 // -----------------------------------------------------------------------
1120 
1121 sal_uInt16 ListBox::GetEntryPos( const void* pData ) const
1122 {
1123 	sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( pData );
1124 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1125 		nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1126 	return nPos;
1127 }
1128 
1129 // -----------------------------------------------------------------------
1130 
1131 XubString ListBox::GetEntry( sal_uInt16 nPos ) const
1132 {
1133 	return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1134 }
1135 
1136 // -----------------------------------------------------------------------
1137 
1138 sal_uInt16 ListBox::GetEntryCount() const
1139 {
1140 	return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
1141 }
1142 
1143 // -----------------------------------------------------------------------
1144 
1145 XubString ListBox::GetSelectEntry( sal_uInt16 nIndex ) const
1146 {
1147 	return GetEntry( GetSelectEntryPos( nIndex ) );
1148 }
1149 
1150 // -----------------------------------------------------------------------
1151 
1152 sal_uInt16 ListBox::GetSelectEntryCount() const
1153 {
1154 	return mpImplLB->GetEntryList()->GetSelectEntryCount();
1155 }
1156 
1157 // -----------------------------------------------------------------------
1158 
1159 sal_uInt16 ListBox::GetSelectEntryPos( sal_uInt16 nIndex ) const
1160 {
1161 	sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex );
1162 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1163 	{
1164 		if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1165 			nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) );
1166 		nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1167 	}
1168 	return nPos;
1169 }
1170 
1171 // -----------------------------------------------------------------------
1172 
1173 sal_Bool ListBox::IsEntrySelected( const XubString& rStr ) const
1174 {
1175 	return IsEntryPosSelected( GetEntryPos( rStr ) );
1176 }
1177 
1178 // -----------------------------------------------------------------------
1179 
1180 sal_Bool ListBox::IsEntryPosSelected( sal_uInt16 nPos ) const
1181 {
1182 	return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1183 }
1184 
1185 // -----------------------------------------------------------------------
1186 
1187 void ListBox::SelectEntry( const XubString& rStr, sal_Bool bSelect )
1188 {
1189 	SelectEntryPos( GetEntryPos( rStr ), bSelect );
1190 }
1191 
1192 // -----------------------------------------------------------------------
1193 
1194 void ListBox::SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect )
1195 {
1196 	if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() )
1197 		mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
1198 }
1199 
1200 // -----------------------------------------------------------------------
1201 
1202 void ListBox::SetEntryData( sal_uInt16 nPos, void* pNewData )
1203 {
1204 	mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
1205 }
1206 
1207 // -----------------------------------------------------------------------
1208 
1209 void* ListBox::GetEntryData( sal_uInt16 nPos ) const
1210 {
1211 	return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1212 }
1213 
1214 // -----------------------------------------------------------------------
1215 
1216 void ListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags )
1217 {
1218 	mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount(), nFlags );
1219 }
1220 
1221 // -----------------------------------------------------------------------
1222 
1223 long ListBox::GetEntryFlags( sal_uInt16 nPos ) const
1224 {
1225 	return mpImplLB->GetEntryList()->GetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1226 }
1227 
1228 // -----------------------------------------------------------------------
1229 
1230 void ListBox::SetTopEntry( sal_uInt16 nPos )
1231 {
1232 	mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1233 }
1234 
1235 // -----------------------------------------------------------------------
1236 
1237 void ListBox::ShowProminentEntry( sal_uInt16 nPos )
1238 {
1239 	mpImplLB->ShowProminentEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1240 }
1241 
1242 // -----------------------------------------------------------------------
1243 
1244 sal_uInt16 ListBox::GetTopEntry() const
1245 {
1246 	sal_uInt16 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
1247 	if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1248 		nPos = 0;
1249 	return nPos;
1250 }
1251 
1252 // -----------------------------------------------------------------------
1253 
1254 void ListBox::SetProminentEntryType( ProminentEntry eType )
1255 {
1256     mpImplLB->SetProminentEntryType( eType );
1257 }
1258 
1259 // -----------------------------------------------------------------------
1260 
1261 ProminentEntry ListBox::GetProminentEntryType() const
1262 {
1263     return mpImplLB->GetProminentEntryType();
1264 }
1265 
1266 // -----------------------------------------------------------------------
1267 
1268 sal_Bool ListBox::IsTravelSelect() const
1269 {
1270 	return mpImplLB->IsTravelSelect();
1271 }
1272 
1273 // -----------------------------------------------------------------------
1274 
1275 sal_Bool ListBox::IsInDropDown() const
1276 {
1277 	return mpFloatWin && mpFloatWin->IsInPopupMode();
1278 }
1279 
1280 // -----------------------------------------------------------------------
1281 
1282 long ListBox::CalcWindowSizePixel( sal_uInt16 nLines ) const
1283 {
1284 	return mpImplLB->GetEntryHeight() * nLines;
1285 }
1286 
1287 Rectangle ListBox::GetBoundingRectangle( sal_uInt16 nItem ) const
1288 {
1289     Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
1290     Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( (Window*)this );
1291     aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
1292     return aRect;
1293 }
1294 
1295 // -----------------------------------------------------------------------
1296 
1297 void ListBox::EnableMultiSelection( sal_Bool bMulti )
1298 {
1299 	EnableMultiSelection( bMulti, sal_False );
1300 }
1301 
1302 void ListBox::EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackSelection )
1303 {
1304 	mpImplLB->EnableMultiSelection( bMulti, bStackSelection );
1305 
1306 	// WB_SIMPLEMODE:
1307 	// Die MultiListBox verh�lt sich wie eine normale ListBox.
1308 	// Die Mehrfachselektion kann nur �ber entsprechende Zusatztasten erfolgen.
1309 
1310 	sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False;
1311 	mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
1312 
1313 	// ohne Focus ist das Traveln in einer MultiSelection nicht zu sehen:
1314 	if ( mpFloatWin )
1315 		mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti );
1316 }
1317 
1318 // -----------------------------------------------------------------------
1319 
1320 sal_Bool ListBox::IsMultiSelectionEnabled() const
1321 {
1322 	return mpImplLB->IsMultiSelectionEnabled();
1323 }
1324 
1325 // -----------------------------------------------------------------------
1326 
1327 Size ListBox::CalcMinimumSize() const
1328 {
1329 	Size aSz;
1330 	if ( !IsDropDownBox() )
1331         aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList()->GetEntryCount());
1332 	else
1333 	{
1334 		aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
1335 		aSz.Height() += 4; // add a space between entry and border
1336         // size to maxmimum entry width and add a little breathing space
1337 		aSz.Width() = mpImplLB->GetMaxEntryWidth() + 4;
1338         // do not create ultrathin ListBoxes, it doesn't look good
1339         if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() )
1340             aSz.Width() = GetSettings().GetStyleSettings().GetScrollBarSize();
1341 
1342         // try native borders; scrollbar size may not be a good indicator
1343         // see how large the edit area inside is to estimate what is needed for the dropdown
1344 		ImplControlValue aControlValue;
1345 		Point aPoint;
1346 		Rectangle aContent, aBound;
1347         Size aTestSize( 100, 20 );
1348 		Rectangle aArea( aPoint, aTestSize );
1349         if( const_cast<ListBox*>(this)->GetNativeControlRegion(
1350                        CTRL_LISTBOX, PART_SUB_EDIT, aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
1351         {
1352             // use the themes drop down size
1353             aSz.Width() += aTestSize.Width() - aContent.GetWidth();
1354         }
1355         else
1356             aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1357 	}
1358 
1359 	aSz = CalcWindowSize( aSz );
1360 
1361 	if ( IsDropDownBox() ) // check minimum height of dropdown box
1362     {
1363         ImplControlValue aControlValue;
1364         Rectangle aRect( Point( 0, 0 ), aSz );
1365         Rectangle aContent, aBound;
1366         if( const_cast<ListBox*>(this)->GetNativeControlRegion(
1367                        CTRL_LISTBOX, PART_ENTIRE_CONTROL, aRect, 0, aControlValue, rtl::OUString(), aBound, aContent) )
1368         {
1369             if( aBound.GetHeight() > aSz.Height() )
1370                 aSz.Height() = aBound.GetHeight();
1371         }
1372     }
1373 
1374 	return aSz;
1375 }
1376 
1377 // -----------------------------------------------------------------------
1378 
1379 Size ListBox::GetOptimalSize(WindowSizeType eType) const
1380 {
1381     switch (eType) {
1382     case WINDOWSIZE_MINIMUM:
1383         return CalcMinimumSize();
1384     default:
1385         return Control::GetOptimalSize( eType );
1386     }
1387 }
1388 
1389 // -----------------------------------------------------------------------
1390 
1391 Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const
1392 {
1393 	Size aSz = rPrefSize;
1394 	sal_Int32 nLeft, nTop, nRight, nBottom;
1395 	((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
1396 	aSz.Height() -= nTop+nBottom;
1397 	if ( !IsDropDownBox() )
1398 	{
1399 		long nEntryHeight = CalcSize( 1, 1 ).Height();
1400 		long nLines = aSz.Height() / nEntryHeight;
1401 		if ( nLines < 1 )
1402 			nLines = 1;
1403 		aSz.Height() = nLines * nEntryHeight;
1404 	}
1405 	else
1406 	{
1407 		aSz.Height() = mnDDHeight;
1408 	}
1409 	aSz.Height() += nTop+nBottom;
1410 
1411 	aSz = CalcWindowSize( aSz );
1412 	return aSz;
1413 }
1414 
1415 // -----------------------------------------------------------------------
1416 
1417 Size ListBox::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1418 {
1419 	// ggf. werden ScrollBars eingeblendet
1420 	Size aMinSz = CalcMinimumSize();
1421 //	aMinSz = ImplCalcOutSz( aMinSz );
1422 
1423 	Size aSz;
1424 
1425 	// Hoehe
1426 	if ( nLines )
1427 	{
1428 		if ( !IsDropDownBox() )
1429 			aSz.Height() = mpImplLB->CalcSize( nLines ).Height();
1430 		else
1431 			aSz.Height() = mnDDHeight;
1432 	}
1433 	else
1434 		aSz.Height() = aMinSz.Height();
1435 
1436 	// Breite
1437 	if ( nColumns )
1438 		aSz.Width() = nColumns * GetTextWidth( XubString( 'X' ) );
1439 	else
1440 		aSz.Width() = aMinSz.Width();
1441 
1442 	if ( IsDropDownBox() )
1443 		aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1444 
1445 	if ( !IsDropDownBox() )
1446 	{
1447 		if ( aSz.Width() < aMinSz.Width() )
1448 			aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
1449 		if ( aSz.Height() < aMinSz.Height() )
1450 			aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1451 	}
1452 
1453 	aSz = CalcWindowSize( aSz );
1454 	return aSz;
1455 }
1456 
1457 // -----------------------------------------------------------------------
1458 
1459 void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1460 {
1461 	long nCharWidth = GetTextWidth( UniString( 'x' ) );
1462 	if ( !IsDropDownBox() )
1463 	{
1464 		Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
1465 		rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
1466 		rnLines = (sal_uInt16) (aOutSz.Height()/mpImplLB->GetEntryHeight());
1467 	}
1468 	else
1469 	{
1470 		Size aOutSz = mpImplWin->GetOutputSizePixel();
1471 		rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
1472 		rnLines = 1;
1473 	}
1474 }
1475 
1476 // -----------------------------------------------------------------------
1477 
1478 IMPL_LINK( ListBox, ImplUserDrawHdl, UserDrawEvent*, pEvent )
1479 {
1480 	UserDraw( *pEvent );
1481 	return 1;
1482 }
1483 
1484 // -----------------------------------------------------------------------
1485 
1486 void ListBox::UserDraw( const UserDrawEvent& )
1487 {
1488 }
1489 
1490 // -----------------------------------------------------------------------
1491 
1492 void ListBox::DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos )
1493 {
1494 	if ( rEvt.GetDevice() == mpImplLB->GetMainWindow() )
1495 		mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
1496 	else if ( rEvt.GetDevice() == mpImplWin )
1497 		mpImplWin->DrawEntry( bDrawImage, bDrawText, bDrawTextAtImagePos );
1498 }
1499 
1500 // -----------------------------------------------------------------------
1501 
1502 void ListBox::SetUserItemSize( const Size& rSz )
1503 {
1504 	mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
1505 	if ( mpImplWin )
1506 		mpImplWin->SetUserItemSize( rSz );
1507 }
1508 
1509 // -----------------------------------------------------------------------
1510 
1511 const Size& ListBox::GetUserItemSize() const
1512 {
1513 	return mpImplLB->GetMainWindow()->GetUserItemSize();
1514 }
1515 
1516 // -----------------------------------------------------------------------
1517 
1518 void ListBox::EnableUserDraw( sal_Bool bUserDraw )
1519 {
1520 	mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
1521 	if ( mpImplWin )
1522 		mpImplWin->EnableUserDraw( bUserDraw );
1523 }
1524 
1525 // -----------------------------------------------------------------------
1526 
1527 sal_Bool ListBox::IsUserDrawEnabled() const
1528 {
1529 	return mpImplLB->GetMainWindow()->IsUserDrawEnabled();
1530 }
1531 
1532 // -----------------------------------------------------------------------
1533 
1534 void ListBox::SetReadOnly( sal_Bool bReadOnly )
1535 {
1536 	if ( mpImplLB->IsReadOnly() != bReadOnly )
1537 	{
1538 		mpImplLB->SetReadOnly( bReadOnly );
1539 		StateChanged( STATE_CHANGE_READONLY );
1540 	}
1541 }
1542 
1543 // -----------------------------------------------------------------------
1544 
1545 sal_Bool ListBox::IsReadOnly() const
1546 {
1547 	return mpImplLB->IsReadOnly();
1548 }
1549 
1550 // -----------------------------------------------------------------------
1551 
1552 void ListBox::SetSeparatorPos( sal_uInt16 n )
1553 {
1554 	mpImplLB->SetSeparatorPos( n );
1555 }
1556 
1557 // -----------------------------------------------------------------------
1558 
1559 void ListBox::SetSeparatorPos()
1560 {
1561 	mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
1562 }
1563 
1564 // -----------------------------------------------------------------------
1565 
1566 sal_uInt16 ListBox::GetSeparatorPos() const
1567 {
1568 	return mpImplLB->GetSeparatorPos();
1569 }
1570 
1571 // -----------------------------------------------------------------------
1572 
1573 void ListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep )
1574 {
1575 	mpImplLB->SetMRUEntries( rEntries, cSep );
1576 }
1577 
1578 // -----------------------------------------------------------------------
1579 
1580 XubString ListBox::GetMRUEntries( xub_Unicode cSep ) const
1581 {
1582 	return mpImplLB->GetMRUEntries( cSep );
1583 }
1584 
1585 // -----------------------------------------------------------------------
1586 
1587 void ListBox::SetMaxMRUCount( sal_uInt16 n )
1588 {
1589 	mpImplLB->SetMaxMRUCount( n );
1590 }
1591 
1592 // -----------------------------------------------------------------------
1593 
1594 sal_uInt16 ListBox::GetMaxMRUCount() const
1595 {
1596 	return mpImplLB->GetMaxMRUCount();
1597 }
1598 
1599 // -----------------------------------------------------------------------
1600 
1601 sal_uInt16 ListBox::GetDisplayLineCount() const
1602 {
1603     return mpImplLB->GetDisplayLineCount();
1604 }
1605 
1606 // -----------------------------------------------------------------------
1607 
1608 // pb: #106948# explicit mirroring for calc
1609 
1610 void ListBox::EnableMirroring()
1611 {
1612     mpImplLB->EnableMirroring();
1613 }
1614 
1615 // -----------------------------------------------------------------------
1616 
1617 Rectangle ListBox::GetDropDownPosSizePixel() const
1618 {
1619     return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ListBox*>(this) ) : Rectangle();
1620 }
1621 
1622 // -----------------------------------------------------------------------
1623 
1624 const Wallpaper& ListBox::GetDisplayBackground() const
1625 {
1626     // !!! recursion does not occur because the ImplListBox is default
1627     // initialized to a nontransparent color in Window::ImplInitData
1628     return mpImplLB->GetDisplayBackground();
1629 }
1630 
1631 // =======================================================================
1632 MultiListBox::MultiListBox( Window* pParent, WinBits nStyle ) :
1633 	ListBox( WINDOW_MULTILISTBOX )
1634 {
1635 	ImplInit( pParent, nStyle );
1636 	EnableMultiSelection( sal_True );
1637 }
1638 
1639 // -----------------------------------------------------------------------
1640 
1641 MultiListBox::MultiListBox( Window* pParent, const ResId& rResId ) :
1642 	ListBox( WINDOW_MULTILISTBOX )
1643 {
1644 	rResId.SetRT( RSC_MULTILISTBOX );
1645 	WinBits nStyle = ImplInitRes( rResId );
1646 	ImplInit( pParent, nStyle );
1647 	ImplLoadRes( rResId );
1648 
1649 	if ( !(nStyle & WB_HIDE ) )
1650 		Show();
1651 	EnableMultiSelection( sal_True );
1652 }
1653