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