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