xref: /AOO41X/main/vcl/source/control/lstbox.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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