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