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