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