update credits
[LibreOffice.git] / vcl / source / control / lstbox.cxx
blob31dfde2ac5e7ada45da9c14bed47f8b6c80346b4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "tools/rc.h"
22 #include "tools/debug.hxx"
25 #include "vcl/decoview.hxx"
26 #include "vcl/dialog.hxx"
27 #include "vcl/event.hxx"
28 #include "vcl/scrbar.hxx"
29 #include "vcl/button.hxx"
30 #include "vcl/edit.hxx"
31 #include "vcl/lstbox.hxx"
32 #include "vcl/combobox.hxx"
34 #include "svdata.hxx"
35 #include "controldata.hxx"
36 #include "ilstbox.hxx"
37 #include "dndevdis.hxx"
39 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
42 ListBox::ListBox( WindowType nType ) : Control( nType )
44 ImplInitListBoxData();
48 ListBox::ListBox( Window* pParent, WinBits nStyle ) : Control( WINDOW_LISTBOX )
50 ImplInitListBoxData();
51 ImplInit( pParent, nStyle );
55 ListBox::ListBox( Window* pParent, const ResId& rResId ) :
56 Control( WINDOW_LISTBOX )
58 rResId.SetRT( RSC_LISTBOX );
59 WinBits nStyle = ImplInitRes( rResId );
60 ImplInitListBoxData();
61 ImplInit( pParent, nStyle );
62 ImplLoadRes( rResId );
64 if ( !(nStyle & WB_HIDE ) )
65 Show();
69 ListBox::~ListBox()
71 ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
73 // When destroying the FloatWin TH does a GrabFocus to the Parent:
74 // that means this "ListBox => PreNotify() ..."
75 ImplListBox *pImplLB = mpImplLB;
76 mpImplLB = NULL;
77 delete pImplLB;
79 delete mpFloatWin;
80 delete mpImplWin;
81 delete mpBtn;
85 void ListBox::ImplInitListBoxData()
87 mpFloatWin = NULL;
88 mpImplWin = NULL;
89 mpBtn = NULL;
90 mnDDHeight = 0;
91 mnSaveValue = LISTBOX_ENTRY_NOTFOUND;
92 mnLineCount = 0;
93 m_nMaxWidthChars = -1;
94 mbDDAutoSize = true;
95 mbEdgeBlending = false;
99 void ListBox::ImplInit( Window* pParent, WinBits nStyle )
101 nStyle = ImplInitStyle( nStyle );
102 if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) )
103 nStyle |= WB_BORDER;
105 Control::ImplInit( pParent, nStyle, NULL );
106 SetBackground();
108 ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this);
110 if( nStyle & WB_DROPDOWN )
112 sal_Int32 nLeft, nTop, nRight, nBottom;
113 GetBorder( nLeft, nTop, nRight, nBottom );
114 mnDDHeight = (sal_uInt16)(GetTextHeight() + nTop + nBottom + 4);
116 if( IsNativeWidgetEnabled() &&
117 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
119 ImplControlValue aControlValue;
120 Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) );
121 Rectangle aBoundingRgn( aCtrlRegion );
122 Rectangle aContentRgn( aCtrlRegion );
123 if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
124 CTRL_STATE_ENABLED, aControlValue, OUString(),
125 aBoundingRgn, aContentRgn ) )
127 sal_Int32 nHeight = aBoundingRgn.GetHeight();
128 if( nHeight > mnDDHeight )
129 mnDDHeight = static_cast<sal_uInt16>(nHeight);
133 mpFloatWin = new ImplListBoxFloatingWindow( this );
134 mpFloatWin->SetAutoWidth( sal_True );
135 mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) );
136 mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop);
138 mpImplWin = new ImplWin( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER );
139 mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
140 mpImplWin->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
141 mpImplWin->Show();
142 mpImplWin->GetDropTarget()->addDropTargetListener(xDrop);
143 mpImplWin->SetEdgeBlending(GetEdgeBlending());
145 mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
146 ImplInitDropDownButton( mpBtn );
147 mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
148 mpBtn->Show();
149 mpBtn->GetDropTarget()->addDropTargetListener(xDrop);
152 Window* pLBParent = this;
153 if ( mpFloatWin )
154 pLBParent = mpFloatWin;
155 mpImplLB = new ImplListBox( pLBParent, nStyle&(~WB_BORDER) );
156 mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) );
157 mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl ) );
158 mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) );
159 mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) );
160 mpImplLB->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
161 mpImplLB->SetPosPixel( Point() );
162 mpImplLB->SetEdgeBlending(GetEdgeBlending());
163 mpImplLB->Show();
165 mpImplLB->GetDropTarget()->addDropTargetListener(xDrop);
166 mpImplLB->SetDropTraget(xDrop);
168 if ( mpFloatWin )
170 mpFloatWin->SetImplListBox( mpImplLB );
171 mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) );
173 else
174 mpImplLB->GetMainWindow()->AllowGrabFocus( sal_True );
176 SetCompoundControl( sal_True );
180 WinBits ListBox::ImplInitStyle( WinBits nStyle )
182 if ( !(nStyle & WB_NOTABSTOP) )
183 nStyle |= WB_TABSTOP;
184 if ( !(nStyle & WB_NOGROUP) )
185 nStyle |= WB_GROUP;
186 return nStyle;
190 void ListBox::ImplLoadRes( const ResId& rResId )
192 Control::ImplLoadRes( rResId );
194 sal_uInt16 nSelPos = ReadShortRes();
195 sal_uInt16 nNumber = sal::static_int_cast<sal_uInt16>(ReadLongRes());
197 for( sal_uInt16 i = 0; i < nNumber; i++ )
199 sal_uInt16 nPos = InsertEntry( ReadStringRes(), LISTBOX_APPEND );
201 long nId = ReadLongRes();
202 if( nId )
203 SetEntryData( nPos, (void *)nId ); // ID as UserData
206 if( nSelPos < nNumber )
207 SelectEntryPos( nSelPos );
211 IMPL_LINK_NOARG(ListBox, ImplSelectHdl)
213 sal_Bool bPopup = IsInDropDown();
214 if( IsDropDownBox() )
216 if( !mpImplLB->IsTravelSelect() )
218 mpFloatWin->EndPopupMode();
219 mpImplWin->GrabFocus();
222 mpImplWin->SetItemPos( GetSelectEntryPos() );
223 mpImplWin->SetString( GetSelectEntry() );
224 if( mpImplLB->GetEntryList()->HasImages() )
226 Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectEntryPos() );
227 mpImplWin->SetImage( aImage );
229 mpImplWin->Invalidate();
232 if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) )
233 Select();
235 return 1;
239 IMPL_LINK_NOARG(ListBox, ImplScrollHdl)
241 ImplCallEventListeners( VCLEVENT_LISTBOX_SCROLLED );
242 return 1;
246 IMPL_LINK_NOARG(ListBox, ImplCancelHdl)
248 if( IsInDropDown() )
249 mpFloatWin->EndPopupMode();
251 return 1;
255 IMPL_LINK( ListBox, ImplSelectionChangedHdl, void*, n )
257 if ( !mpImplLB->IsTrackingSelect() )
259 sal_uInt16 nChanged = (sal_uInt16)(sal_uLong)n;
260 const ImplEntryList* pEntryList = mpImplLB->GetEntryList();
261 if ( pEntryList->IsEntryPosSelected( nChanged ) )
263 // FIXME? This should've been turned into an ImplPaintEntry some time ago...
264 if ( nChanged < pEntryList->GetMRUCount() )
265 nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ) );
266 mpImplWin->SetItemPos( nChanged );
267 mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
268 if( mpImplLB->GetEntryList()->HasImages() )
270 Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged );
271 mpImplWin->SetImage( aImage );
274 else
276 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
277 mpImplWin->SetString( ImplGetSVEmptyStr() );
278 Image aImage;
279 mpImplWin->SetImage( aImage );
281 mpImplWin->Invalidate();
283 return 1;
287 IMPL_LINK_NOARG(ListBox, ImplDoubleClickHdl)
289 DoubleClick();
290 return 1;
294 IMPL_LINK_NOARG(ListBox, ImplClickBtnHdl)
296 if( !mpFloatWin->IsInPopupMode() )
298 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
299 mpImplWin->GrabFocus();
300 mpBtn->SetPressed( sal_True );
301 mpFloatWin->StartFloat( sal_True );
302 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
304 ImplClearLayoutData();
305 if( mpImplLB )
306 mpImplLB->GetMainWindow()->ImplClearLayoutData();
307 if( mpImplWin )
308 mpImplWin->ImplClearLayoutData();
311 return 0;
315 IMPL_LINK_NOARG(ListBox, ImplPopupModeEndHdl)
317 if( mpFloatWin->IsPopupModeCanceled() )
319 if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND )
320 && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) )
322 mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), sal_True );
323 sal_Bool bTravelSelect = mpImplLB->IsTravelSelect();
324 mpImplLB->SetTravelSelect( sal_True );
326 ImplDelData aCheckDelete;
327 ImplAddDel( &aCheckDelete );
328 Select();
329 if ( aCheckDelete.IsDead() )
330 return 0;
331 ImplRemoveDel( &aCheckDelete );
333 mpImplLB->SetTravelSelect( bTravelSelect );
337 ImplClearLayoutData();
338 if( mpImplLB )
339 mpImplLB->GetMainWindow()->ImplClearLayoutData();
340 if( mpImplWin )
341 mpImplWin->ImplClearLayoutData();
343 mpBtn->SetPressed( sal_False );
344 ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE );
345 return 0;
349 void ListBox::ToggleDropDown()
351 if( IsDropDownBox() )
353 if( mpFloatWin->IsInPopupMode() )
354 mpFloatWin->EndPopupMode();
355 else
357 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
358 mpImplWin->GrabFocus();
359 mpBtn->SetPressed( sal_True );
360 mpFloatWin->StartFloat( sal_True );
361 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
367 void ListBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
369 mpImplLB->GetMainWindow()->ImplInitSettings( sal_True, sal_True, sal_True );
371 Point aPos = pDev->LogicToPixel( rPos );
372 Size aSize = pDev->LogicToPixel( rSize );
373 Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
374 OutDevType eOutDevType = pDev->GetOutDevType();
376 pDev->Push();
377 pDev->SetMapMode();
378 pDev->SetFont( aFont );
379 pDev->SetTextFillColor();
381 // Border/Background
382 pDev->SetLineColor();
383 pDev->SetFillColor();
384 bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
385 bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
386 if ( bBorder || bBackground )
388 Rectangle aRect( aPos, aSize );
389 if ( bBorder )
391 ImplDrawFrame( pDev, aRect );
393 if ( bBackground )
395 pDev->SetFillColor( GetControlBackground() );
396 pDev->DrawRect( aRect );
400 // Content
401 if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
403 pDev->SetTextColor( Color( COL_BLACK ) );
405 else
407 if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
409 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
410 pDev->SetTextColor( rStyleSettings.GetDisableColor() );
412 else
414 pDev->SetTextColor( GetTextColor() );
418 long nOnePixel = GetDrawPixel( pDev, 1 );
419 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER;
420 Rectangle aTextRect( aPos, aSize );
422 if ( GetStyle() & WB_CENTER )
423 nTextStyle |= TEXT_DRAW_CENTER;
424 else if ( GetStyle() & WB_RIGHT )
425 nTextStyle |= TEXT_DRAW_RIGHT;
426 else
427 nTextStyle |= TEXT_DRAW_LEFT;
429 aTextRect.Left() += 3*nOnePixel;
430 aTextRect.Right() -= 3*nOnePixel;
432 if ( IsDropDownBox() )
434 XubString aText = GetSelectEntry();
435 long nTextHeight = pDev->GetTextHeight();
436 long nTextWidth = pDev->GetTextWidth( aText );
437 long nOffX = 3*nOnePixel;
438 long nOffY = (aSize.Height()-nTextHeight) / 2;
440 // Clipping?
441 if ( (nOffY < 0) ||
442 ((nOffY+nTextHeight) > aSize.Height()) ||
443 ((nOffX+nTextWidth) > aSize.Width()) )
445 Rectangle aClip( aPos, aSize );
446 if ( nTextHeight > aSize.Height() )
447 aClip.Bottom() += nTextHeight-aSize.Height()+1; // So that HP Printers don't optimize this away
448 pDev->IntersectClipRegion( aClip );
451 pDev->DrawText( aTextRect, aText, nTextStyle );
453 else
455 long nTextHeight = pDev->GetTextHeight();
456 sal_uInt16 nLines = (sal_uInt16)(aSize.Height() / nTextHeight);
457 Rectangle aClip( aPos, aSize );
459 pDev->IntersectClipRegion( aClip );
461 if ( !nLines )
462 nLines = 1;
464 for ( sal_uInt16 n = 0; n < nLines; n++ )
466 sal_uInt16 nEntry = n+mpImplLB->GetTopEntry();
467 sal_Bool bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry );
468 if ( bSelected )
470 pDev->SetFillColor( COL_BLACK );
471 pDev->DrawRect( Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ),
472 Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) );
473 pDev->SetFillColor();
474 pDev->SetTextColor( COL_WHITE );
477 aTextRect.Top() = aPos.Y() + n*nTextHeight;
478 aTextRect.Bottom() = aTextRect.Top() + nTextHeight;
480 pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( nEntry ), nTextStyle );
482 if ( bSelected )
483 pDev->SetTextColor( COL_BLACK );
487 pDev->Pop();
491 void ListBox::GetFocus()
493 if ( mpImplLB )
495 if( IsDropDownBox() )
496 mpImplWin->GrabFocus();
497 else
498 mpImplLB->GrabFocus();
501 Control::GetFocus();
505 Window* ListBox::GetPreferredKeyInputWindow()
507 if ( mpImplLB )
509 if( IsDropDownBox() )
510 return mpImplWin->GetPreferredKeyInputWindow();
511 else
512 return mpImplLB->GetPreferredKeyInputWindow();
515 return Control::GetPreferredKeyInputWindow();
519 void ListBox::LoseFocus()
521 if( IsDropDownBox() )
522 mpImplWin->HideFocus();
523 else
524 mpImplLB->HideFocus();
526 Control::LoseFocus();
530 void ListBox::DataChanged( const DataChangedEvent& rDCEvt )
532 Control::DataChanged( rDCEvt );
534 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
535 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
536 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
537 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
539 SetBackground(); // Due to a hack in Window::UpdateSettings the background must be reset
540 // otherwise it will overpaint NWF drawn listboxes
541 Resize();
542 mpImplLB->Resize(); // Is not called by ListBox::Resize() if the ImplLB does not change
544 if ( mpImplWin )
546 mpImplWin->SetSettings( GetSettings() ); // If not yet set...
547 ImplInitFieldSettings( mpImplWin, sal_True, sal_True, sal_True );
549 mpBtn->SetSettings( GetSettings() );
550 ImplInitDropDownButton( mpBtn );
554 if ( IsDropDownBox() )
555 Invalidate();
560 void ListBox::EnableAutoSize( bool bAuto )
562 mbDDAutoSize = bAuto;
563 if ( mpFloatWin )
565 if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
567 // use GetListBoxMaximumLineCount here; before, was on fixed number of five
568 AdaptDropDownLineCountToMaximum();
570 else if ( !bAuto )
572 mpFloatWin->SetDropDownLineCount( 0 );
578 void ListBox::EnableDDAutoWidth( sal_Bool b )
580 if ( mpFloatWin )
581 mpFloatWin->SetAutoWidth( b );
585 void ListBox::SetDropDownLineCount( sal_uInt16 nLines )
587 mnLineCount = nLines;
588 if ( mpFloatWin )
589 mpFloatWin->SetDropDownLineCount( mnLineCount );
593 void ListBox::AdaptDropDownLineCountToMaximum()
595 // adapt to maximum allowed number
596 SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
599 // -----------------------------------------------------------------------
601 sal_uInt16 ListBox::GetDropDownLineCount() const
603 if ( mpFloatWin )
604 return mpFloatWin->GetDropDownLineCount();
605 return mnLineCount;
609 void ListBox::setPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
611 if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) )
613 Size aPrefSz = mpFloatWin->GetPrefSize();
614 if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight >= 2*mnDDHeight ) )
615 aPrefSz.Height() = nHeight-mnDDHeight;
616 if ( nFlags & WINDOW_POSSIZE_WIDTH )
617 aPrefSz.Width() = nWidth;
618 mpFloatWin->SetPrefSize( aPrefSz );
620 if ( IsAutoSizeEnabled() && ! (nFlags & WINDOW_POSSIZE_DROPDOWN) )
621 nHeight = mnDDHeight;
624 Control::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
628 void ListBox::Resize()
630 Size aOutSz = GetOutputSizePixel();
631 if( IsDropDownBox() )
633 // Initialize the dropdown button size with the standard scrollbar width
634 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
635 long nBottom = aOutSz.Height();
637 // Note: in case of no border, pBorder will actually be this
638 Window *pBorder = GetWindow( WINDOW_BORDER );
639 ImplControlValue aControlValue;
640 Point aPoint;
641 Rectangle aContent, aBound;
643 // Use the full extent of the control
644 Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
646 if ( GetNativeControlRegion( CTRL_LISTBOX, PART_BUTTON_DOWN,
647 aArea, 0, aControlValue, OUString(), aBound, aContent) )
649 long nTop = 0;
650 // Convert back from border space to local coordinates
651 aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) );
652 aContent.Move( -aPoint.X(), -aPoint.Y() );
654 // Use the themes drop down size for the button
655 aOutSz.Width() = aContent.Left();
656 mpBtn->setPosSizePixel( aContent.Left(), nTop, aContent.Right(), (nBottom-nTop) );
658 // Adjust the size of the edit field
659 if ( GetNativeControlRegion( CTRL_LISTBOX, PART_SUB_EDIT,
660 aArea, 0, aControlValue, OUString(), aBound, aContent) )
662 // Convert back from border space to local coordinates
663 aContent.Move( -aPoint.X(), -aPoint.Y() );
665 // Use the themes drop down size
666 if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects )
668 // No border but focus ring behavior -> we have a problem; the
669 // native rect relies on the border to draw the focus
670 // let's do the best we can and center vertically, so it doesn't look
671 // completely wrong.
672 Size aSz( GetOutputSizePixel() );
673 long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2;
674 aContent.Top() -= nDiff;
675 aContent.Bottom() -= nDiff;
677 mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() );
679 else
680 mpImplWin->SetSizePixel( aOutSz );
682 else
684 nSBWidth = CalcZoom( nSBWidth );
685 mpImplWin->setPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() );
686 mpBtn->setPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
689 else
691 mpImplLB->SetSizePixel( aOutSz );
694 // Retain FloatingWindow size even when it's invisible, as we still process KEY_PGUP/DOWN ...
695 if ( mpFloatWin )
696 mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
698 Control::Resize();
701 void ListBox::FillLayoutData() const
703 mpControlData->mpLayoutData = new vcl::ControlLayoutData();
704 const Control* pMainWin = mpImplLB->GetMainWindow();
705 if( mpFloatWin )
707 // Dropdown mode
708 AppendLayoutData( *mpImplWin );
709 mpImplWin->SetLayoutDataParent( this );
710 if( mpFloatWin->IsReallyVisible() )
712 AppendLayoutData( *pMainWin );
713 pMainWin->SetLayoutDataParent( this );
716 else
718 AppendLayoutData( *pMainWin );
719 pMainWin->SetLayoutDataParent( this );
723 long ListBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const
725 if( !HasLayoutData() )
726 FillLayoutData();
728 // Check whether rPoint fits at all
729 long nIndex = Control::GetIndexForPoint( rPoint );
730 if( nIndex != -1 )
732 // Point must be either in main list window
733 // or in impl window (dropdown case)
734 ImplListBoxWindow* pMain = mpImplLB->GetMainWindow();
736 // Convert coordinates to ImplListBoxWindow pixel coordinate space
737 Point aConvPoint = LogicToPixel( rPoint );
738 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
739 aConvPoint = pMain->AbsoluteScreenToOutputPixel( aConvPoint );
740 aConvPoint = pMain->PixelToLogic( aConvPoint );
742 // Try to find entry
743 sal_uInt16 nEntry = pMain->GetEntryPosForPoint( aConvPoint );
744 if( nEntry == LISTBOX_ENTRY_NOTFOUND )
746 // Not found, maybe dropdown case
747 if( mpImplWin && mpImplWin->IsReallyVisible() )
749 // Convert to impl window pixel coordinates
750 aConvPoint = LogicToPixel( rPoint );
751 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
752 aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPoint );
754 // Check whether converted point is inside impl window
755 Size aImplWinSize = mpImplWin->GetOutputSizePixel();
756 if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() )
758 // Inside the impl window, the position is the current item pos
759 rPos = mpImplWin->GetItemPos();
761 else
762 nIndex = -1;
764 else
765 nIndex = -1;
767 else
768 rPos = nEntry;
770 DBG_ASSERT( nIndex != -1, "found index for point, but relative index failed" );
773 // Get line relative index
774 if( nIndex != -1 )
775 nIndex = ToRelativeLineIndex( nIndex );
777 return nIndex;
781 void ListBox::StateChanged( StateChangedType nType )
783 if( nType == STATE_CHANGE_READONLY )
785 if( mpImplWin )
786 mpImplWin->Enable( !IsReadOnly() );
787 if( mpBtn )
788 mpBtn->Enable( !IsReadOnly() );
790 else if( nType == STATE_CHANGE_ENABLE )
792 mpImplLB->Enable( IsEnabled() );
793 if( mpImplWin )
795 mpImplWin->Enable( IsEnabled() );
796 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
797 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
799 GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE );
801 else
802 mpImplWin->Invalidate();
804 if( mpBtn )
805 mpBtn->Enable( IsEnabled() );
807 else if( nType == STATE_CHANGE_UPDATEMODE )
809 mpImplLB->SetUpdateMode( IsUpdateMode() );
811 else if ( nType == STATE_CHANGE_ZOOM )
813 mpImplLB->SetZoom( GetZoom() );
814 if ( mpImplWin )
816 mpImplWin->SetZoom( GetZoom() );
817 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
818 mpImplWin->Invalidate();
820 Resize();
822 else if ( nType == STATE_CHANGE_CONTROLFONT )
824 mpImplLB->SetControlFont( GetControlFont() );
825 if ( mpImplWin )
827 mpImplWin->SetControlFont( GetControlFont() );
828 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
829 mpImplWin->Invalidate();
831 Resize();
833 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
835 mpImplLB->SetControlForeground( GetControlForeground() );
836 if ( mpImplWin )
838 mpImplWin->SetControlForeground( GetControlForeground() );
839 mpImplWin->SetTextColor( GetControlForeground() );
840 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
841 mpImplWin->Invalidate();
844 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
846 mpImplLB->SetControlBackground( GetControlBackground() );
847 if ( mpImplWin )
849 if ( mpImplWin->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) )
851 // Transparent background
852 mpImplWin->SetBackground();
853 mpImplWin->SetControlBackground();
855 else
857 mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
858 mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
860 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
861 mpImplWin->Invalidate();
864 else if ( nType == STATE_CHANGE_STYLE )
866 SetStyle( ImplInitStyle( GetStyle() ) );
867 mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? sal_True : sal_False );
868 sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False;
869 mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
871 else if( nType == STATE_CHANGE_MIRRORING )
873 if( mpBtn )
875 mpBtn->EnableRTL( IsRTLEnabled() );
876 ImplInitDropDownButton( mpBtn );
878 mpImplLB->EnableRTL( IsRTLEnabled() );
879 if( mpImplWin )
880 mpImplWin->EnableRTL( IsRTLEnabled() );
881 Resize();
884 Control::StateChanged( nType );
888 long ListBox::PreNotify( NotifyEvent& rNEvt )
890 long nDone = 0;
891 if ( mpImplLB )
893 if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) )
895 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
896 switch( aKeyEvt.GetKeyCode().GetCode() )
898 case KEY_DOWN:
900 if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
901 aKeyEvt.GetKeyCode().IsMod2() )
903 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
904 mpBtn->SetPressed( sal_True );
905 mpFloatWin->StartFloat( sal_False );
906 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
907 nDone = 1;
909 else
911 nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
914 break;
915 case KEY_UP:
917 if( mpFloatWin && mpFloatWin->IsInPopupMode() &&
918 aKeyEvt.GetKeyCode().IsMod2() )
920 mpFloatWin->EndPopupMode();
921 nDone = 1;
923 else
925 nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
928 break;
929 case KEY_RETURN:
931 if( IsInDropDown() )
933 mpImplLB->ProcessKeyInput( aKeyEvt );
934 nDone = 1;
937 break;
939 default:
941 nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
945 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
947 if ( IsInDropDown() && !HasChildPathFocus( sal_True ) )
948 mpFloatWin->EndPopupMode();
950 else if ( (rNEvt.GetType() == EVENT_COMMAND) &&
951 (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
952 (rNEvt.GetWindow() == mpImplWin) )
954 sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
955 if ( ( nWheelBehavior == MOUSE_WHEEL_ALWAYS )
956 || ( ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY )
957 && HasChildPathFocus()
961 nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
963 else
965 nDone = 0; // Don't consume this event, let the default handling take it (i.e. scroll the context)
970 return nDone ? nDone : Control::PreNotify( rNEvt );
974 void ListBox::Select()
976 ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_SELECT, maSelectHdl, this );
980 void ListBox::DoubleClick()
982 ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_DOUBLECLICK, maDoubleClickHdl, this );
986 void ListBox::Clear()
988 mpImplLB->Clear();
989 if( IsDropDownBox() )
991 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
992 mpImplWin->SetString( ImplGetSVEmptyStr() );
993 Image aImage;
994 mpImplWin->SetImage( aImage );
995 mpImplWin->Invalidate();
997 CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(-1) );
1001 void ListBox::SetNoSelection()
1003 mpImplLB->SetNoSelection();
1004 if( IsDropDownBox() )
1006 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
1007 mpImplWin->SetString( ImplGetSVEmptyStr() );
1008 Image aImage;
1009 mpImplWin->SetImage( aImage );
1010 mpImplWin->Invalidate();
1015 sal_uInt16 ListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
1017 sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
1018 nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1019 CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
1020 return nRealPos;
1024 sal_uInt16 ListBox::InsertEntry( const Image& rImage, sal_uInt16 nPos )
1026 sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rImage );
1027 nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1028 CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
1029 return nRealPos;
1033 sal_uInt16 ListBox::InsertEntry( const XubString& rStr, const Image& rImage, sal_uInt16 nPos )
1035 sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
1036 nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1037 CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
1038 return nRealPos;
1042 void ListBox::RemoveEntry( const XubString& rStr )
1044 RemoveEntry( GetEntryPos( rStr ) );
1048 void ListBox::RemoveEntry( sal_uInt16 nPos )
1050 mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1051 CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(nPos) );
1055 Image ListBox::GetEntryImage( sal_uInt16 nPos ) const
1057 if ( mpImplLB->GetEntryList()->HasEntryImage( nPos ) )
1058 return mpImplLB->GetEntryList()->GetEntryImage( nPos );
1059 return Image();
1063 sal_uInt16 ListBox::GetEntryPos( const XubString& rStr ) const
1065 sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( rStr );
1066 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1067 nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1068 return nPos;
1072 sal_uInt16 ListBox::GetEntryPos( const void* pData ) const
1074 sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( pData );
1075 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1076 nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1077 return nPos;
1081 XubString ListBox::GetEntry( sal_uInt16 nPos ) const
1083 return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1087 sal_uInt16 ListBox::GetEntryCount() const
1089 return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
1093 XubString ListBox::GetSelectEntry( sal_uInt16 nIndex ) const
1095 return GetEntry( GetSelectEntryPos( nIndex ) );
1099 sal_uInt16 ListBox::GetSelectEntryCount() const
1101 return mpImplLB->GetEntryList()->GetSelectEntryCount();
1105 sal_uInt16 ListBox::GetSelectEntryPos( sal_uInt16 nIndex ) const
1107 sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex );
1108 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1110 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1111 nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) );
1112 nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1114 return nPos;
1118 sal_Bool ListBox::IsEntrySelected( const XubString& rStr ) const
1120 return IsEntryPosSelected( GetEntryPos( rStr ) );
1124 sal_Bool ListBox::IsEntryPosSelected( sal_uInt16 nPos ) const
1126 return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1130 void ListBox::SelectEntry( const XubString& rStr, sal_Bool bSelect )
1132 SelectEntryPos( GetEntryPos( rStr ), bSelect );
1136 void ListBox::SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect )
1138 if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() )
1139 mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
1143 void ListBox::SetEntryData( sal_uInt16 nPos, void* pNewData )
1145 mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
1149 void* ListBox::GetEntryData( sal_uInt16 nPos ) const
1151 return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1155 void ListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags )
1157 mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount(), nFlags );
1161 long ListBox::GetEntryFlags( sal_uInt16 nPos ) const
1163 return mpImplLB->GetEntryList()->GetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1167 void ListBox::SetTopEntry( sal_uInt16 nPos )
1169 mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1173 sal_uInt16 ListBox::GetTopEntry() const
1175 sal_uInt16 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
1176 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1177 nPos = 0;
1178 return nPos;
1182 sal_Bool ListBox::IsTravelSelect() const
1184 return mpImplLB->IsTravelSelect();
1188 sal_Bool ListBox::IsInDropDown() const
1190 return mpFloatWin && mpFloatWin->IsInPopupMode();
1194 Rectangle ListBox::GetBoundingRectangle( sal_uInt16 nItem ) const
1196 Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
1197 Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( (Window*)this );
1198 aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
1199 return aRect;
1203 void ListBox::EnableMultiSelection( sal_Bool bMulti )
1205 EnableMultiSelection( bMulti, sal_False );
1208 void ListBox::EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackSelection )
1210 mpImplLB->EnableMultiSelection( bMulti, bStackSelection );
1212 // WB_SIMPLEMODE:
1213 // The MultiListBox behaves just like a normal ListBox
1214 // MultiSelection is possible via corresponding additional keys
1215 sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False;
1216 mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
1218 // In a MultiSelection, we can't see us travelling without focus
1219 if ( mpFloatWin )
1220 mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti );
1224 sal_Bool ListBox::IsMultiSelectionEnabled() const
1226 return mpImplLB->IsMultiSelectionEnabled();
1230 Size ListBox::CalcMinimumSize() const
1232 Size aSz;
1234 if (!mpImplLB)
1235 return aSz;
1237 aSz = CalcSubEditSize();
1239 bool bAddScrollWidth = false;
1241 if (IsDropDownBox())
1243 aSz.Height() += 4; // add a space between entry and border
1244 aSz.Width() += 4; // add a little breathing space
1245 bAddScrollWidth = true;
1247 else
1248 bAddScrollWidth = (GetStyle() & WB_VSCROLL) == WB_VSCROLL;
1250 if (bAddScrollWidth)
1252 // Try native borders; scrollbar size may not be a good indicator
1253 // See how large the edit area inside is to estimate what is needed for the dropdown
1254 ImplControlValue aControlValue;
1255 Point aPoint;
1256 Rectangle aContent, aBound;
1257 Size aTestSize( 100, 20 );
1258 Rectangle aArea( aPoint, aTestSize );
1259 if( const_cast<ListBox*>(this)->GetNativeControlRegion(
1260 CTRL_LISTBOX, PART_SUB_EDIT, aArea, 0, aControlValue, OUString(), aBound, aContent) )
1262 // use the themes drop down size
1263 aSz.Width() += aTestSize.Width() - aContent.GetWidth();
1265 else
1266 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1269 aSz = CalcWindowSize( aSz );
1271 if (IsDropDownBox()) // Check minimum height of dropdown box
1273 ImplControlValue aControlValue;
1274 Rectangle aRect( Point( 0, 0 ), aSz );
1275 Rectangle aContent, aBound;
1276 if( const_cast<ListBox*>(this)->GetNativeControlRegion(
1277 CTRL_LISTBOX, PART_ENTIRE_CONTROL, aRect, 0, aControlValue, OUString(), aBound, aContent) )
1279 if( aBound.GetHeight() > aSz.Height() )
1280 aSz.Height() = aBound.GetHeight();
1284 return aSz;
1287 Size ListBox::CalcSubEditSize() const
1289 Size aSz;
1291 if (!mpImplLB)
1292 return aSz;
1294 if ( !IsDropDownBox() )
1295 aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList()->GetEntryCount());
1296 else
1298 aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
1299 // Size to maxmimum entry width
1300 aSz.Width() = mpImplLB->GetMaxEntryWidth();
1302 if (m_nMaxWidthChars != -1)
1304 long nMaxWidth = m_nMaxWidthChars * approximate_char_width();
1305 aSz.Width() = std::min(aSz.Width(), nMaxWidth);
1308 // Do not create ultrathin ListBoxes, it doesn't look good
1309 if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() )
1310 aSz.Width() = GetSettings().GetStyleSettings().GetScrollBarSize();
1313 return aSz;
1317 Size ListBox::GetOptimalSize() const
1319 return CalcMinimumSize();
1323 Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const
1325 Size aSz = rPrefSize;
1326 sal_Int32 nLeft, nTop, nRight, nBottom;
1327 ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
1328 aSz.Height() -= nTop+nBottom;
1329 if ( !IsDropDownBox() )
1331 long nEntryHeight = CalcSize( 1, 1 ).Height();
1332 long nLines = aSz.Height() / nEntryHeight;
1333 if ( nLines < 1 )
1334 nLines = 1;
1335 aSz.Height() = nLines * nEntryHeight;
1337 else
1339 aSz.Height() = mnDDHeight;
1341 aSz.Height() += nTop+nBottom;
1343 aSz = CalcWindowSize( aSz );
1344 return aSz;
1348 Size ListBox::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1350 // ScrollBars are shown if needed
1351 Size aMinSz = CalcMinimumSize();
1352 // aMinSz = ImplCalcOutSz( aMinSz );
1354 Size aSz;
1356 // Height
1357 if ( nLines )
1359 if ( !IsDropDownBox() )
1360 aSz.Height() = mpImplLB->CalcSize( nLines ).Height();
1361 else
1362 aSz.Height() = mnDDHeight;
1364 else
1365 aSz.Height() = aMinSz.Height();
1367 // Width
1368 if ( nColumns )
1369 aSz.Width() = nColumns * GetTextWidth( OUString('X') );
1370 else
1371 aSz.Width() = aMinSz.Width();
1373 if ( IsDropDownBox() )
1374 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1376 if ( !IsDropDownBox() )
1378 if ( aSz.Width() < aMinSz.Width() )
1379 aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
1380 if ( aSz.Height() < aMinSz.Height() )
1381 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1384 aSz = CalcWindowSize( aSz );
1385 return aSz;
1389 void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1391 long nCharWidth = GetTextWidth( OUString(static_cast<sal_Unicode>('x')) );
1392 if ( !IsDropDownBox() )
1394 Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
1395 rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
1396 rnLines = (sal_uInt16) (aOutSz.Height()/mpImplLB->GetEntryHeight());
1398 else
1400 Size aOutSz = mpImplWin->GetOutputSizePixel();
1401 rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
1402 rnLines = 1;
1407 IMPL_LINK( ListBox, ImplUserDrawHdl, UserDrawEvent*, pEvent )
1409 UserDraw( *pEvent );
1410 return 1;
1414 void ListBox::UserDraw( const UserDrawEvent& )
1419 void ListBox::DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos )
1421 if ( rEvt.GetDevice() == mpImplLB->GetMainWindow() )
1422 mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
1423 else if ( rEvt.GetDevice() == mpImplWin )
1424 mpImplWin->DrawEntry( bDrawImage, bDrawText, bDrawTextAtImagePos );
1428 void ListBox::SetUserItemSize( const Size& rSz )
1430 mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
1431 if ( mpImplWin )
1432 mpImplWin->SetUserItemSize( rSz );
1436 void ListBox::EnableUserDraw( sal_Bool bUserDraw )
1438 mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
1439 if ( mpImplWin )
1440 mpImplWin->EnableUserDraw( bUserDraw );
1444 void ListBox::SetReadOnly( sal_Bool bReadOnly )
1446 if ( mpImplLB->IsReadOnly() != bReadOnly )
1448 mpImplLB->SetReadOnly( bReadOnly );
1449 StateChanged( STATE_CHANGE_READONLY );
1454 sal_Bool ListBox::IsReadOnly() const
1456 return mpImplLB->IsReadOnly();
1460 void ListBox::SetSeparatorPos( sal_uInt16 n )
1462 mpImplLB->SetSeparatorPos( n );
1466 sal_uInt16 ListBox::GetSeparatorPos() const
1468 return mpImplLB->GetSeparatorPos();
1472 sal_uInt16 ListBox::GetDisplayLineCount() const
1474 return mpImplLB->GetDisplayLineCount();
1477 void ListBox::EnableMirroring()
1479 mpImplLB->EnableMirroring();
1483 Rectangle ListBox::GetDropDownPosSizePixel() const
1485 return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ListBox*>(this) ) : Rectangle();
1488 const Wallpaper& ListBox::GetDisplayBackground() const
1490 // !!! Recursion does not occur because the ImplListBox is initialized by default
1491 // to a non-transparent color in Window::ImplInitData
1492 return mpImplLB->GetDisplayBackground();
1495 void ListBox::setMaxWidthChars(sal_Int32 nWidth)
1497 if (nWidth != m_nMaxWidthChars)
1499 m_nMaxWidthChars = nWidth;
1500 queue_resize();
1504 bool ListBox::set_property(const OString &rKey, const OString &rValue)
1506 if (rKey == "active")
1507 SelectEntryPos(rValue.toInt32());
1508 else if (rKey == "max-width-chars")
1509 setMaxWidthChars(rValue.toInt32());
1510 else
1511 return Control::set_property(rKey, rValue);
1512 return true;
1515 // -----------------------------------------------------------------------
1517 void ListBox::SetEdgeBlending(bool bNew)
1519 if(mbEdgeBlending != bNew)
1521 mbEdgeBlending = bNew;
1523 if(IsDropDownBox())
1525 mpImplWin->Invalidate();
1527 else
1529 mpImplLB->Invalidate();
1532 if(mpImplWin)
1534 mpImplWin->SetEdgeBlending(GetEdgeBlending());
1537 if(mpImplLB)
1539 mpImplLB->SetEdgeBlending(GetEdgeBlending());
1542 Invalidate();
1546 // =======================================================================
1547 MultiListBox::MultiListBox( Window* pParent, WinBits nStyle ) :
1548 ListBox( WINDOW_MULTILISTBOX )
1550 ImplInit( pParent, nStyle );
1551 EnableMultiSelection( sal_True );
1555 MultiListBox::MultiListBox( Window* pParent, const ResId& rResId ) :
1556 ListBox( WINDOW_MULTILISTBOX )
1558 rResId.SetRT( RSC_MULTILISTBOX );
1559 WinBits nStyle = ImplInitRes( rResId );
1560 ImplInit( pParent, nStyle );
1561 ImplLoadRes( rResId );
1563 if ( !(nStyle & WB_HIDE ) )
1564 Show();
1565 EnableMultiSelection( sal_True );
1568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */