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 as 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 maximum 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 // Height
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 // Width
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