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