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