1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <vcl/builder.hxx>
21 #include <vcl/commandevent.hxx>
22 #include <vcl/event.hxx>
23 #include <vcl/toolkit/lstbox.hxx>
24 #include <vcl/settings.hxx>
25 #include <vcl/uitest/uiobject.hxx>
26 #include <sal/log.hxx>
29 #include <listbox.hxx>
30 #include <dndeventdispatcher.hxx>
31 #include <comphelper/lok.hxx>
33 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
34 #include <boost/property_tree/ptree.hpp>
35 #include <tools/json_writer.hxx>
37 ListBox::ListBox(WindowType nType
)
41 ImplInitListBoxData();
44 ListBox::ListBox( vcl::Window
* pParent
, WinBits nStyle
) : Control( WindowType::LISTBOX
)
46 ImplInitListBoxData();
47 ImplInit( pParent
, nStyle
);
55 void ListBox::dispose()
57 CallEventListeners( VclEventId::ObjectDying
);
59 mpImplLB
.disposeAndClear();
60 mpFloatWin
.disposeAndClear();
61 mpImplWin
.disposeAndClear();
62 mpBtn
.disposeAndClear();
67 void ListBox::ImplInitListBoxData()
74 m_nMaxWidthChars
= -1;
78 void ListBox::ImplInit( vcl::Window
* pParent
, WinBits nStyle
)
80 nStyle
= ImplInitStyle( nStyle
);
81 if ( !(nStyle
& WB_NOBORDER
) && ( nStyle
& WB_DROPDOWN
) )
84 Control::ImplInit( pParent
, nStyle
, nullptr );
86 css::uno::Reference
< css::datatransfer::dnd::XDropTargetListener
> xDrop
= new DNDEventDispatcher(this);
88 if( nStyle
& WB_DROPDOWN
)
90 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
91 GetBorder( nLeft
, nTop
, nRight
, nBottom
);
92 mnDDHeight
= static_cast<sal_uInt16
>(GetTextHeight() + nTop
+ nBottom
+ 4);
94 if( IsNativeWidgetEnabled() &&
95 IsNativeControlSupported( ControlType::Listbox
, ControlPart::Entire
) )
97 ImplControlValue aControlValue
;
98 tools::Rectangle
aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight
) );
99 tools::Rectangle
aBoundingRgn( aCtrlRegion
);
100 tools::Rectangle
aContentRgn( aCtrlRegion
);
101 if( GetNativeControlRegion( ControlType::Listbox
, ControlPart::Entire
, aCtrlRegion
,
102 ControlState::ENABLED
, aControlValue
,
103 aBoundingRgn
, aContentRgn
) )
105 sal_Int32 nHeight
= aBoundingRgn
.GetHeight();
106 if( nHeight
> mnDDHeight
)
107 mnDDHeight
= static_cast<sal_uInt16
>(nHeight
);
111 mpFloatWin
= VclPtr
<ImplListBoxFloatingWindow
>::Create( this );
112 if (!IsNativeControlSupported(ControlType::Pushbutton
, ControlPart::Focus
))
113 mpFloatWin
->RequestDoubleBuffering(true);
114 mpFloatWin
->SetAutoWidth( true );
115 mpFloatWin
->SetPopupModeEndHdl( LINK( this, ListBox
, ImplPopupModeEndHdl
) );
116 mpFloatWin
->GetDropTarget()->addDropTargetListener(xDrop
);
118 mpImplWin
= VclPtr
<ImplWin
>::Create( this, (nStyle
& (WB_LEFT
|WB_RIGHT
|WB_CENTER
))|WB_NOBORDER
);
119 mpImplWin
->SetMBDownHdl( LINK( this, ListBox
, ImplClickBtnHdl
) );
121 mpImplWin
->GetDropTarget()->addDropTargetListener(xDrop
);
122 mpImplWin
->SetEdgeBlending(false);
124 mpBtn
= VclPtr
<ImplBtn
>::Create( this, WB_NOLIGHTBORDER
| WB_RECTSTYLE
);
125 ImplInitDropDownButton( mpBtn
);
126 mpBtn
->SetMBDownHdl( LINK( this, ListBox
, ImplClickBtnHdl
) );
128 mpBtn
->GetDropTarget()->addDropTargetListener(xDrop
);
131 vcl::Window
* pLBParent
= this;
133 pLBParent
= mpFloatWin
;
134 mpImplLB
= VclPtr
<ImplListBox
>::Create( pLBParent
, nStyle
&(~WB_BORDER
) );
135 mpImplLB
->SetSelectHdl( LINK( this, ListBox
, ImplSelectHdl
) );
136 mpImplLB
->SetScrollHdl( LINK( this, ListBox
, ImplScrollHdl
) );
137 mpImplLB
->SetCancelHdl( LINK( this, ListBox
, ImplCancelHdl
) );
138 mpImplLB
->SetDoubleClickHdl( LINK( this, ListBox
, ImplDoubleClickHdl
) );
139 mpImplLB
->SetFocusHdl( LINK( this, ListBox
, ImplFocusHdl
) );
140 mpImplLB
->SetListItemSelectHdl( LINK( this, ListBox
, ImplListItemSelectHdl
) );
141 mpImplLB
->SetPosPixel( Point() );
142 mpImplLB
->SetEdgeBlending(false);
145 mpImplLB
->GetDropTarget()->addDropTargetListener(xDrop
);
149 mpFloatWin
->SetImplListBox( mpImplLB
);
150 mpImplLB
->SetSelectionChangedHdl( LINK( this, ListBox
, ImplSelectionChangedHdl
) );
153 mpImplLB
->GetMainWindow()->AllowGrabFocus( true );
155 SetCompoundControl( true );
158 WinBits
ListBox::ImplInitStyle( WinBits nStyle
)
160 if ( !(nStyle
& WB_NOTABSTOP
) )
161 nStyle
|= WB_TABSTOP
;
162 if ( !(nStyle
& WB_NOGROUP
) )
167 IMPL_LINK_NOARG(ListBox
, ImplSelectHdl
, LinkParamNone
*, void)
169 bool bPopup
= IsInDropDown();
170 if( IsDropDownBox() )
172 if( !mpImplLB
->IsTravelSelect() )
174 mpFloatWin
->EndPopupMode();
175 mpImplWin
->GrabFocus();
178 mpImplWin
->SetItemPos( GetSelectedEntryPos() );
179 mpImplWin
->SetString( GetSelectedEntry() );
180 if( mpImplLB
->GetEntryList().HasImages() )
182 Image aImage
= mpImplLB
->GetEntryList().GetEntryImage( GetSelectedEntryPos() );
183 mpImplWin
->SetImage( aImage
);
185 mpImplWin
->Invalidate();
188 if ( ( !IsTravelSelect() || mpImplLB
->IsSelectionChanged() ) || ( bPopup
&& !IsMultiSelectionEnabled() ) )
192 IMPL_LINK( ListBox
, ImplFocusHdl
, sal_Int32
, nPos
, void )
194 CallEventListeners( VclEventId::ListboxFocus
, reinterpret_cast<void*>(static_cast<sal_IntPtr
>(nPos
)) );
197 IMPL_LINK_NOARG( ListBox
, ImplListItemSelectHdl
, LinkParamNone
*, void )
199 CallEventListeners( VclEventId::DropdownSelect
);
202 IMPL_LINK_NOARG(ListBox
, ImplScrollHdl
, ImplListBox
*, void)
204 CallEventListeners( VclEventId::ListboxScrolled
);
207 IMPL_LINK_NOARG(ListBox
, ImplCancelHdl
, LinkParamNone
*, void)
210 mpFloatWin
->EndPopupMode();
213 IMPL_LINK( ListBox
, ImplSelectionChangedHdl
, sal_Int32
, nChanged
, void )
215 if ( mpImplLB
->IsTrackingSelect() )
218 const ImplEntryList
& rEntryList
= mpImplLB
->GetEntryList();
219 if ( rEntryList
.IsEntryPosSelected( nChanged
) )
221 // FIXME? This should've been turned into an ImplPaintEntry some time ago...
222 if ( nChanged
< rEntryList
.GetMRUCount() )
223 nChanged
= rEntryList
.FindEntry( rEntryList
.GetEntryText( nChanged
) );
224 mpImplWin
->SetItemPos( nChanged
);
225 mpImplWin
->SetString( rEntryList
.GetEntryText( nChanged
) );
226 if( rEntryList
.HasImages() )
228 Image aImage
= rEntryList
.GetEntryImage( nChanged
);
229 mpImplWin
->SetImage( aImage
);
234 mpImplWin
->SetItemPos( LISTBOX_ENTRY_NOTFOUND
);
235 mpImplWin
->SetString( OUString() );
237 mpImplWin
->SetImage( aImage
);
239 mpImplWin
->Invalidate();
242 IMPL_LINK_NOARG(ListBox
, ImplDoubleClickHdl
, ImplListBoxWindow
*, void)
247 IMPL_LINK_NOARG(ListBox
, ImplClickBtnHdl
, void*, void)
249 if( mpFloatWin
->IsInPopupMode() )
252 CallEventListeners( VclEventId::DropdownPreOpen
);
253 mpImplWin
->GrabFocus();
254 mpBtn
->SetPressed( true );
255 mpFloatWin
->StartFloat( true );
256 CallEventListeners( VclEventId::DropdownOpen
);
258 ImplClearLayoutData();
260 mpImplLB
->GetMainWindow()->ImplClearLayoutData();
262 mpImplWin
->ImplClearLayoutData();
265 IMPL_LINK_NOARG(ListBox
, ImplPopupModeEndHdl
, FloatingWindow
*, void)
267 if( mpFloatWin
->IsPopupModeCanceled() )
269 if ( ( mpFloatWin
->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND
)
270 && !IsEntryPosSelected( mpFloatWin
->GetPopupModeStartSaveSelection() ) )
272 mpImplLB
->SelectEntry( mpFloatWin
->GetPopupModeStartSaveSelection(), true );
273 bool bTravelSelect
= mpImplLB
->IsTravelSelect();
274 mpImplLB
->SetTravelSelect( true );
276 VclPtr
<vcl::Window
> xWindow
= this;
278 if ( xWindow
->isDisposed() )
281 mpImplLB
->SetTravelSelect( bTravelSelect
);
285 ImplClearLayoutData();
287 mpImplLB
->GetMainWindow()->ImplClearLayoutData();
289 mpImplWin
->ImplClearLayoutData();
291 mpBtn
->SetPressed( false );
292 CallEventListeners( VclEventId::DropdownClose
);
295 void ListBox::ToggleDropDown()
297 if( !IsDropDownBox() )
300 if( mpFloatWin
->IsInPopupMode() )
301 mpFloatWin
->EndPopupMode();
304 CallEventListeners( VclEventId::DropdownPreOpen
);
305 mpImplWin
->GrabFocus();
306 mpBtn
->SetPressed( true );
307 mpFloatWin
->StartFloat( true );
308 CallEventListeners( VclEventId::DropdownOpen
);
312 void ListBox::ApplySettings(vcl::RenderContext
& rRenderContext
)
314 rRenderContext
.SetBackground();
317 void ListBox::Draw( OutputDevice
* pDev
, const Point
& rPos
, SystemTextColorFlags nFlags
)
319 mpImplLB
->GetMainWindow()->ApplySettings(*pDev
);
321 Point aPos
= pDev
->LogicToPixel( rPos
);
322 Size aSize
= GetSizePixel();
323 vcl::Font aFont
= mpImplLB
->GetMainWindow()->GetDrawPixelFont( pDev
);
327 pDev
->SetFont( aFont
);
328 pDev
->SetTextFillColor();
331 pDev
->SetLineColor();
332 pDev
->SetFillColor();
333 bool bBorder
= (GetStyle() & WB_BORDER
);
334 bool bBackground
= IsControlBackground();
335 if ( bBorder
|| bBackground
)
337 tools::Rectangle
aRect( aPos
, aSize
);
340 ImplDrawFrame( pDev
, aRect
);
344 pDev
->SetFillColor( GetControlBackground() );
345 pDev
->DrawRect( aRect
);
350 if ( nFlags
& SystemTextColorFlags::Mono
)
352 pDev
->SetTextColor( COL_BLACK
);
358 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
359 pDev
->SetTextColor( rStyleSettings
.GetDisableColor() );
363 pDev
->SetTextColor( GetTextColor() );
367 const tools::Long nOnePixel
= GetDrawPixel( pDev
, 1 );
368 const tools::Long nOffX
= 3*nOnePixel
;
369 DrawTextFlags nTextStyle
= DrawTextFlags::VCenter
;
370 tools::Rectangle
aTextRect( aPos
, aSize
);
372 if ( GetStyle() & WB_CENTER
)
373 nTextStyle
|= DrawTextFlags::Center
;
374 else if ( GetStyle() & WB_RIGHT
)
375 nTextStyle
|= DrawTextFlags::Right
;
377 nTextStyle
|= DrawTextFlags::Left
;
379 aTextRect
.AdjustLeft(nOffX
);
380 aTextRect
.AdjustRight( -nOffX
);
382 if ( IsDropDownBox() )
384 OUString aText
= GetSelectedEntry();
385 tools::Long nTextHeight
= pDev
->GetTextHeight();
386 tools::Long nTextWidth
= pDev
->GetTextWidth( aText
);
387 tools::Long nOffY
= (aSize
.Height()-nTextHeight
) / 2;
391 ((nOffY
+nTextHeight
) > aSize
.Height()) ||
392 ((nOffX
+nTextWidth
) > aSize
.Width()) )
394 tools::Rectangle
aClip( aPos
, aSize
);
395 if ( nTextHeight
> aSize
.Height() )
396 aClip
.AdjustBottom(nTextHeight
-aSize
.Height()+1 ); // So that HP Printers don't optimize this away
397 pDev
->IntersectClipRegion( aClip
);
400 pDev
->DrawText( aTextRect
, aText
, nTextStyle
);
404 tools::Long nTextHeight
= pDev
->GetTextHeight();
405 sal_uInt16 nLines
= ( nTextHeight
> 0 ) ? static_cast<sal_uInt16
>(aSize
.Height() / nTextHeight
) : 1;
406 tools::Rectangle
aClip( aPos
, aSize
);
408 pDev
->IntersectClipRegion( aClip
);
413 for ( sal_uInt16 n
= 0; n
< nLines
; n
++ )
415 sal_Int32 nEntry
= n
+mpImplLB
->GetTopEntry();
416 bool bSelected
= mpImplLB
->GetEntryList().IsEntryPosSelected( nEntry
);
419 pDev
->SetFillColor( COL_BLACK
);
420 pDev
->DrawRect( tools::Rectangle( Point( aPos
.X(), aPos
.Y() + n
*nTextHeight
),
421 Point( aPos
.X() + aSize
.Width(), aPos
.Y() + (n
+1)*nTextHeight
+ 2*nOnePixel
) ) );
422 pDev
->SetFillColor();
423 pDev
->SetTextColor( COL_WHITE
);
426 aTextRect
.SetTop( aPos
.Y() + n
*nTextHeight
);
427 aTextRect
.SetBottom( aTextRect
.Top() + nTextHeight
);
429 pDev
->DrawText( aTextRect
, mpImplLB
->GetEntryList().GetEntryText( nEntry
), nTextStyle
);
432 pDev
->SetTextColor( COL_BLACK
);
439 void ListBox::GetFocus()
443 if( IsDropDownBox() )
444 mpImplWin
->GrabFocus();
446 mpImplLB
->GrabFocus();
452 void ListBox::LoseFocus()
454 if( IsDropDownBox() )
457 mpImplWin
->HideFocus();
462 mpImplLB
->HideFocus();
465 Control::LoseFocus();
468 void ListBox::DataChanged( const DataChangedEvent
& rDCEvt
)
470 Control::DataChanged( rDCEvt
);
472 if ( !((rDCEvt
.GetType() == DataChangedEventType::FONTS
) ||
473 (rDCEvt
.GetType() == DataChangedEventType::FONTSUBSTITUTION
) ||
474 ((rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
475 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))) )
478 SetBackground(); // Due to a hack in Window::UpdateSettings the background must be reset
479 // otherwise it will overpaint NWF drawn listboxes
481 mpImplLB
->Resize(); // Is not called by ListBox::Resize() if the ImplLB does not change
485 mpImplWin
->GetOutDev()->SetSettings( GetSettings() ); // If not yet set...
486 mpImplWin
->ApplySettings(*mpImplWin
->GetOutDev());
488 mpBtn
->GetOutDev()->SetSettings( GetSettings() );
489 ImplInitDropDownButton( mpBtn
);
492 if ( IsDropDownBox() )
496 void ListBox::EnableAutoSize( bool bAuto
)
498 mbDDAutoSize
= bAuto
;
501 if ( bAuto
&& !mpFloatWin
->GetDropDownLineCount() )
503 // use GetListBoxMaximumLineCount here; before, was on fixed number of five
504 AdaptDropDownLineCountToMaximum();
508 mpFloatWin
->SetDropDownLineCount( 0 );
513 void ListBox::SetDropDownLineCount( sal_uInt16 nLines
)
515 mnLineCount
= nLines
;
517 mpFloatWin
->SetDropDownLineCount( mnLineCount
);
520 void ListBox::AdaptDropDownLineCountToMaximum()
522 // Adapt to maximum allowed number.
523 // Limit for LOK as we can't render outside of the dialog canvas.
524 if (comphelper::LibreOfficeKit::isActive())
525 SetDropDownLineCount(11);
527 SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
530 sal_uInt16
ListBox::GetDropDownLineCount() const
533 return mpFloatWin
->GetDropDownLineCount();
537 void ListBox::setPosSizePixel( tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
, PosSizeFlags nFlags
)
539 if( IsDropDownBox() && ( nFlags
& PosSizeFlags::Size
) )
541 Size aPrefSz
= mpFloatWin
->GetPrefSize();
542 if ( ( nFlags
& PosSizeFlags::Height
) && ( nHeight
>= 2*mnDDHeight
) )
543 aPrefSz
.setHeight( nHeight
-mnDDHeight
);
544 if ( nFlags
& PosSizeFlags::Width
)
545 aPrefSz
.setWidth( nWidth
);
546 mpFloatWin
->SetPrefSize( aPrefSz
);
548 if (IsAutoSizeEnabled())
549 nHeight
= mnDDHeight
;
552 Control::setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
555 void ListBox::Resize()
557 Size aOutSz
= GetOutputSizePixel();
558 if( IsDropDownBox() )
560 // Initialize the dropdown button size with the standard scrollbar width
561 tools::Long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
562 tools::Long nBottom
= aOutSz
.Height();
564 // Note: in case of no border, pBorder will actually be this
565 vcl::Window
*pBorder
= GetWindow( GetWindowType::Border
);
566 ImplControlValue aControlValue
;
568 tools::Rectangle aContent
, aBound
;
570 // Use the full extent of the control
571 tools::Rectangle
aArea( aPoint
, pBorder
->GetOutputSizePixel() );
573 if ( GetNativeControlRegion( ControlType::Listbox
, ControlPart::ButtonDown
,
574 aArea
, ControlState::NONE
, aControlValue
, aBound
, aContent
) )
576 // Convert back from border space to local coordinates
577 aPoint
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aPoint
) );
578 aContent
.Move( -aPoint
.X(), -aPoint
.Y() );
580 // Use the themes drop down size for the button
581 aOutSz
.setWidth( aContent
.Left() );
582 mpBtn
->setPosSizePixel( aContent
.Left(), 0, aContent
.GetWidth(), nBottom
);
584 // Adjust the size of the edit field
585 if ( GetNativeControlRegion( ControlType::Listbox
, ControlPart::SubEdit
,
586 aArea
, ControlState::NONE
, aControlValue
, aBound
, aContent
) )
588 // Convert back from border space to local coordinates
589 aContent
.Move( -aPoint
.X(), -aPoint
.Y() );
591 // Use the themes drop down size
592 if( ! (GetStyle() & WB_BORDER
) && ImplGetSVData()->maNWFData
.mbNoFocusRects
)
594 // No border but focus ring behavior -> we have a problem; the
595 // native rect relies on the border to draw the focus
596 // let's do the best we can and center vertically, so it doesn't look
598 Size
aSz( GetOutputSizePixel() );
599 tools::Long nDiff
= aContent
.Top() - (aSz
.Height() - aContent
.GetHeight())/2;
600 aContent
.AdjustTop( -nDiff
);
601 aContent
.AdjustBottom( -nDiff
);
603 mpImplWin
->SetPosSizePixel( aContent
.TopLeft(), aContent
.GetSize() );
606 mpImplWin
->SetSizePixel( aOutSz
);
610 nSBWidth
= CalcZoom( nSBWidth
);
611 mpImplWin
->setPosSizePixel( 0, 0, aOutSz
.Width() - nSBWidth
, aOutSz
.Height() );
612 mpBtn
->setPosSizePixel( aOutSz
.Width() - nSBWidth
, 0, nSBWidth
, aOutSz
.Height() );
617 mpImplLB
->SetSizePixel( aOutSz
);
620 // Retain FloatingWindow size even when it's invisible, as we still process KEY_PGUP/DOWN ...
622 mpFloatWin
->SetSizePixel( mpFloatWin
->CalcFloatSize() );
627 void ListBox::FillLayoutData() const
629 mxLayoutData
.emplace();
630 const ImplListBoxWindow
* rMainWin
= mpImplLB
->GetMainWindow();
634 AppendLayoutData( *mpImplWin
);
635 mpImplWin
->SetLayoutDataParent( this );
636 if( mpFloatWin
->IsReallyVisible() )
638 AppendLayoutData( *rMainWin
);
639 rMainWin
->SetLayoutDataParent( this );
644 AppendLayoutData( *rMainWin
);
645 rMainWin
->SetLayoutDataParent( this );
649 tools::Long
ListBox::GetIndexForPoint( const Point
& rPoint
, sal_Int32
& rPos
) const
651 if( !HasLayoutData() )
654 // Check whether rPoint fits at all
655 tools::Long nIndex
= Control::GetIndexForPoint( rPoint
);
658 // Point must be either in main list window
659 // or in impl window (dropdown case)
660 ImplListBoxWindow
* rMain
= mpImplLB
->GetMainWindow();
662 // Convert coordinates to ImplListBoxWindow pixel coordinate space
663 Point aConvPoint
= LogicToPixel( rPoint
);
664 AbsoluteScreenPixelPoint aConvPointAbs
= OutputToAbsoluteScreenPixel( aConvPoint
);
665 aConvPoint
= rMain
->AbsoluteScreenToOutputPixel( aConvPointAbs
);
666 aConvPoint
= rMain
->PixelToLogic( aConvPoint
);
669 sal_Int32 nEntry
= rMain
->GetEntryPosForPoint( aConvPoint
);
670 if( nEntry
== LISTBOX_ENTRY_NOTFOUND
)
672 // Not found, maybe dropdown case
673 if( mpImplWin
&& mpImplWin
->IsReallyVisible() )
675 // Convert to impl window pixel coordinates
676 aConvPoint
= LogicToPixel( rPoint
);
677 aConvPointAbs
= OutputToAbsoluteScreenPixel( aConvPoint
);
678 aConvPoint
= mpImplWin
->AbsoluteScreenToOutputPixel( aConvPointAbs
);
680 // Check whether converted point is inside impl window
681 Size aImplWinSize
= mpImplWin
->GetOutputSizePixel();
682 if( aConvPoint
.X() >= 0 && aConvPoint
.Y() >= 0 && aConvPoint
.X() < aImplWinSize
.Width() && aConvPoint
.Y() < aImplWinSize
.Height() )
684 // Inside the impl window, the position is the current item pos
685 rPos
= mpImplWin
->GetItemPos();
696 SAL_WARN_IF( nIndex
== -1, "vcl", "found index for point, but relative index failed" );
699 // Get line relative index
701 nIndex
= ToRelativeLineIndex( nIndex
);
706 void ListBox::StateChanged( StateChangedType nType
)
708 if( nType
== StateChangedType::ReadOnly
)
711 mpImplWin
->Enable( !IsReadOnly() );
713 mpBtn
->Enable( !IsReadOnly() );
715 else if( nType
== StateChangedType::Enable
)
717 mpImplLB
->Enable( IsEnabled() );
720 mpImplWin
->Enable( IsEnabled() );
721 if ( IsNativeControlSupported(ControlType::Listbox
, ControlPart::Entire
)
722 && ! IsNativeControlSupported(ControlType::Listbox
, ControlPart::ButtonDown
) )
724 GetWindow( GetWindowType::Border
)->Invalidate( InvalidateFlags::NoErase
);
727 mpImplWin
->Invalidate();
730 mpBtn
->Enable( IsEnabled() );
732 else if( nType
== StateChangedType::UpdateMode
)
734 mpImplLB
->SetUpdateMode( IsUpdateMode() );
736 else if ( nType
== StateChangedType::Zoom
)
738 mpImplLB
->SetZoom( GetZoom() );
741 mpImplWin
->SetZoom( GetZoom() );
742 mpImplWin
->SetFont( mpImplLB
->GetMainWindow()->GetFont() );
743 mpImplWin
->Invalidate();
747 else if ( nType
== StateChangedType::ControlFont
)
749 mpImplLB
->SetControlFont( GetControlFont() );
752 mpImplWin
->SetControlFont( GetControlFont() );
753 mpImplWin
->SetFont( mpImplLB
->GetMainWindow()->GetFont() );
754 mpImplWin
->Invalidate();
758 else if ( nType
== StateChangedType::ControlForeground
)
760 mpImplLB
->SetControlForeground( GetControlForeground() );
763 mpImplWin
->SetControlForeground( GetControlForeground() );
764 mpImplWin
->SetTextColor( GetControlForeground() );
765 mpImplWin
->SetFont( mpImplLB
->GetMainWindow()->GetFont() );
766 mpImplWin
->Invalidate();
769 else if ( nType
== StateChangedType::ControlBackground
)
771 mpImplLB
->SetControlBackground( GetControlBackground() );
775 mpImplWin
->SetBackground( GetControlBackground() );
776 mpImplWin
->SetControlBackground( GetControlBackground() );
777 mpImplWin
->SetFont( mpImplLB
->GetMainWindow()->GetFont() );
778 mpImplWin
->Invalidate();
781 else if ( nType
== StateChangedType::Style
)
783 SetStyle( ImplInitStyle( GetStyle() ) );
784 mpImplLB
->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT
) != 0 );
785 bool bSimpleMode
= ( GetStyle() & WB_SIMPLEMODE
) != 0;
786 mpImplLB
->SetMultiSelectionSimpleMode( bSimpleMode
);
788 else if( nType
== StateChangedType::Mirroring
)
792 mpBtn
->EnableRTL( IsRTLEnabled() );
793 ImplInitDropDownButton( mpBtn
);
795 mpImplLB
->EnableRTL( IsRTLEnabled() );
797 mpImplWin
->EnableRTL( IsRTLEnabled() );
801 Control::StateChanged( nType
);
804 bool ListBox::PreNotify( NotifyEvent
& rNEvt
)
809 if( ( rNEvt
.GetType() == NotifyEventType::KEYINPUT
) && ( rNEvt
.GetWindow() == mpImplWin
) )
811 KeyEvent aKeyEvt
= *rNEvt
.GetKeyEvent();
812 switch( aKeyEvt
.GetKeyCode().GetCode() )
816 if( mpFloatWin
&& !mpFloatWin
->IsInPopupMode() &&
817 aKeyEvt
.GetKeyCode().IsMod2() )
819 CallEventListeners( VclEventId::DropdownPreOpen
);
820 mpBtn
->SetPressed( true );
821 mpFloatWin
->StartFloat( false );
822 CallEventListeners( VclEventId::DropdownOpen
);
827 bDone
= mpImplLB
->ProcessKeyInput( aKeyEvt
);
833 if( mpFloatWin
&& mpFloatWin
->IsInPopupMode() &&
834 aKeyEvt
.GetKeyCode().IsMod2() )
836 mpFloatWin
->EndPopupMode();
841 bDone
= mpImplLB
->ProcessKeyInput( aKeyEvt
);
849 mpImplLB
->ProcessKeyInput( aKeyEvt
);
857 bDone
= mpImplLB
->ProcessKeyInput( aKeyEvt
);
861 else if ( rNEvt
.GetType() == NotifyEventType::LOSEFOCUS
)
863 if ( IsInDropDown() && !HasChildPathFocus( true ) )
864 mpFloatWin
->EndPopupMode();
866 else if ( (rNEvt
.GetType() == NotifyEventType::COMMAND
) &&
867 (rNEvt
.GetCommandEvent()->GetCommand() == CommandEventId::Wheel
) &&
868 (rNEvt
.GetWindow() == mpImplWin
) )
870 const Point
& rMousePos
= rNEvt
.GetCommandEvent()->GetMousePosPixel();
871 const tools::Rectangle
aWinRect(mpImplWin
->GetPosPixel(), mpImplWin
->GetSizePixel());
872 const bool bMousePositionedOverWin
= aWinRect
.Contains(rMousePos
);
874 MouseWheelBehaviour
nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
875 if (bMousePositionedOverWin
876 && ((nWheelBehavior
== MouseWheelBehaviour::ALWAYS
)
877 || ((nWheelBehavior
== MouseWheelBehaviour::FocusOnly
) && HasChildPathFocus())))
879 bDone
= mpImplLB
->HandleWheelAsCursorTravel(*rNEvt
.GetCommandEvent(), *this);
883 bDone
= false; // Don't consume this event, let the default handling take it (i.e. scroll the context)
888 if (rNEvt
.GetType() == NotifyEventType::MOUSEMOVE
)
890 const MouseEvent
* pMouseEvt
= rNEvt
.GetMouseEvent();
891 if (pMouseEvt
&& (pMouseEvt
->IsEnterWindow() || pMouseEvt
->IsLeaveWindow()))
893 // trigger redraw as mouse over state has changed
894 if (IsNativeControlSupported(ControlType::Listbox
, ControlPart::Entire
)
895 && !IsNativeControlSupported(ControlType::Listbox
, ControlPart::ButtonDown
))
897 GetWindow(GetWindowType::Border
)->Invalidate(InvalidateFlags::NoErase
);
902 return bDone
|| Control::PreNotify( rNEvt
);
905 void ListBox::Select()
907 ImplCallEventListenersAndHandler( VclEventId::ListboxSelect
, [this] () { maSelectHdl
.Call(*this); } );
910 void ListBox::DoubleClick()
912 ImplCallEventListenersAndHandler( VclEventId::ListboxDoubleClick
, {} );
915 void ListBox::Clear()
920 if( IsDropDownBox() )
922 mpImplWin
->SetItemPos( LISTBOX_ENTRY_NOTFOUND
);
923 mpImplWin
->SetString( OUString() );
925 mpImplWin
->SetImage( aImage
);
926 mpImplWin
->Invalidate();
928 CallEventListeners( VclEventId::ListboxItemRemoved
, reinterpret_cast<void*>(-1) );
931 void ListBox::SetNoSelection()
933 mpImplLB
->SetNoSelection();
934 if( IsDropDownBox() )
936 mpImplWin
->SetItemPos( LISTBOX_ENTRY_NOTFOUND
);
937 mpImplWin
->SetString( OUString() );
939 mpImplWin
->SetImage( aImage
);
940 mpImplWin
->Invalidate();
944 sal_Int32
ListBox::InsertEntry( const OUString
& rStr
, sal_Int32 nPos
)
946 sal_Int32 nRealPos
= mpImplLB
->InsertEntry( nPos
+ mpImplLB
->GetEntryList().GetMRUCount(), rStr
);
947 nRealPos
= sal::static_int_cast
<sal_Int32
>(nRealPos
- mpImplLB
->GetEntryList().GetMRUCount());
948 CallEventListeners( VclEventId::ListboxItemAdded
, reinterpret_cast<void*>(static_cast<sal_IntPtr
>(nRealPos
)) );
952 sal_Int32
ListBox::InsertEntry( const OUString
& rStr
, const Image
& rImage
, sal_Int32 nPos
)
954 sal_Int32 nRealPos
= mpImplLB
->InsertEntry( nPos
+ mpImplLB
->GetEntryList().GetMRUCount(), rStr
, rImage
);
955 nRealPos
= sal::static_int_cast
<sal_Int32
>(nRealPos
- mpImplLB
->GetEntryList().GetMRUCount());
956 CallEventListeners( VclEventId::ListboxItemAdded
, reinterpret_cast<void*>(static_cast<sal_IntPtr
>(nRealPos
)) );
960 void ListBox::RemoveEntry( sal_Int32 nPos
)
962 mpImplLB
->RemoveEntry( nPos
+ mpImplLB
->GetEntryList().GetMRUCount() );
963 CallEventListeners( VclEventId::ListboxItemRemoved
, reinterpret_cast<void*>(static_cast<sal_IntPtr
>(nPos
)) );
966 Image
ListBox::GetEntryImage( sal_Int32 nPos
) const
968 if ( mpImplLB
&& mpImplLB
->GetEntryList().HasEntryImage( nPos
) )
969 return mpImplLB
->GetEntryList().GetEntryImage( nPos
);
973 sal_Int32
ListBox::GetEntryPos( std::u16string_view rStr
) const
976 return LISTBOX_ENTRY_NOTFOUND
;
977 sal_Int32 nPos
= mpImplLB
->GetEntryList().FindEntry( rStr
);
978 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
979 nPos
= nPos
- mpImplLB
->GetEntryList().GetMRUCount();
983 OUString
ListBox::GetEntry( sal_Int32 nPos
) const
987 return mpImplLB
->GetEntryList().GetEntryText( nPos
+ mpImplLB
->GetEntryList().GetMRUCount() );
990 sal_Int32
ListBox::GetEntryCount() const
994 return mpImplLB
->GetEntryList().GetEntryCount() - mpImplLB
->GetEntryList().GetMRUCount();
997 OUString
ListBox::GetSelectedEntry(sal_Int32 nIndex
) const
999 return GetEntry( GetSelectedEntryPos( nIndex
) );
1002 sal_Int32
ListBox::GetSelectedEntryCount() const
1006 return mpImplLB
->GetEntryList().GetSelectedEntryCount();
1009 sal_Int32
ListBox::GetSelectedEntryPos( sal_Int32 nIndex
) const
1012 return LISTBOX_ENTRY_NOTFOUND
;
1014 sal_Int32 nPos
= mpImplLB
->GetEntryList().GetSelectedEntryPos( nIndex
);
1015 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
1017 if ( nPos
< mpImplLB
->GetEntryList().GetMRUCount() )
1018 nPos
= mpImplLB
->GetEntryList().FindEntry( mpImplLB
->GetEntryList().GetEntryText( nPos
) );
1019 nPos
= nPos
- mpImplLB
->GetEntryList().GetMRUCount();
1024 bool ListBox::IsEntryPosSelected( sal_Int32 nPos
) const
1026 return mpImplLB
->GetEntryList().IsEntryPosSelected( nPos
+ mpImplLB
->GetEntryList().GetMRUCount() );
1029 void ListBox::SelectEntry( std::u16string_view rStr
, bool bSelect
)
1031 SelectEntryPos( GetEntryPos( rStr
), bSelect
);
1034 void ListBox::SelectEntryPos( sal_Int32 nPos
, bool bSelect
)
1039 if ( 0 <= nPos
&& nPos
< mpImplLB
->GetEntryList().GetEntryCount() )
1041 sal_Int32 nCurrentPos
= mpImplLB
->GetCurrentPos();
1042 mpImplLB
->SelectEntry( nPos
+ mpImplLB
->GetEntryList().GetMRUCount(), bSelect
);
1043 //Only when bSelect == true, send both Selection & Focus events
1044 if (nCurrentPos
!= nPos
&& bSelect
)
1046 CallEventListeners( VclEventId::ListboxSelect
, reinterpret_cast<void*>(static_cast<sal_IntPtr
>(nPos
)));
1048 CallEventListeners( VclEventId::ListboxFocus
, reinterpret_cast<void*>(static_cast<sal_IntPtr
>(nPos
)));
1053 void ListBox::SelectEntriesPos( const std::vector
<sal_Int32
>& rPositions
, bool bSelect
)
1058 bool bCallListeners
= false;
1060 const sal_Int32 nCurrentPos
= mpImplLB
->GetCurrentPos();
1061 const auto nEntryCount
= mpImplLB
->GetEntryList().GetEntryCount();
1062 const auto nMRUCount
= mpImplLB
->GetEntryList().GetMRUCount();
1064 for (auto nPos
: rPositions
)
1066 if (0 <= nPos
&& nPos
< nEntryCount
)
1068 mpImplLB
->SelectEntry(nPos
+ nMRUCount
, bSelect
);
1069 if (nCurrentPos
!= nPos
&& bSelect
)
1070 bCallListeners
= true;
1074 //Only when bSelect == true, send both Selection & Focus events
1077 CallEventListeners(VclEventId::ListboxSelect
);
1079 CallEventListeners(VclEventId::ListboxFocus
);
1083 void ListBox::SetEntryData( sal_Int32 nPos
, void* pNewData
)
1085 mpImplLB
->SetEntryData( nPos
+ mpImplLB
->GetEntryList().GetMRUCount(), pNewData
);
1088 void* ListBox::GetEntryData( sal_Int32 nPos
) const
1090 return mpImplLB
->GetEntryList().GetEntryData( nPos
+ mpImplLB
->GetEntryList().GetMRUCount() );
1093 void ListBox::SetEntryFlags( sal_Int32 nPos
, ListBoxEntryFlags nFlags
)
1095 mpImplLB
->SetEntryFlags( nPos
+ mpImplLB
->GetEntryList().GetMRUCount(), nFlags
);
1098 void ListBox::SetTopEntry( sal_Int32 nPos
)
1100 mpImplLB
->SetTopEntry( nPos
+ mpImplLB
->GetEntryList().GetMRUCount() );
1103 sal_Int32
ListBox::GetTopEntry() const
1105 sal_Int32 nPos
= GetEntryCount() ? mpImplLB
->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND
;
1106 if ( nPos
< mpImplLB
->GetEntryList().GetMRUCount() )
1111 bool ListBox::IsTravelSelect() const
1113 return mpImplLB
->IsTravelSelect();
1116 bool ListBox::IsInDropDown() const
1118 // when the dropdown is dismissed, first mbInPopupMode is set to false, and on the next event iteration then
1119 // mbPopupMode is set to false
1120 return mpFloatWin
&& mpFloatWin
->IsInPopupMode() && mpFloatWin
->ImplIsInPrivatePopupMode();
1123 tools::Rectangle
ListBox::GetBoundingRectangle( sal_Int32 nItem
) const
1125 tools::Rectangle aRect
= mpImplLB
->GetMainWindow()->GetBoundingRectangle( nItem
);
1126 tools::Rectangle aOffset
= mpImplLB
->GetMainWindow()->GetWindowExtentsRelative( *static_cast<vcl::Window
*>(const_cast<ListBox
*>(this)) );
1127 aRect
.Move( aOffset
.Left(), aOffset
.Top() );
1131 void ListBox::EnableMultiSelection( bool bMulti
)
1133 mpImplLB
->EnableMultiSelection( bMulti
);
1136 // The MultiListBox behaves just like a normal ListBox
1137 // MultiSelection is possible via corresponding additional keys
1138 bool bSimpleMode
= ( GetStyle() & WB_SIMPLEMODE
) != 0;
1139 mpImplLB
->SetMultiSelectionSimpleMode( bSimpleMode
);
1141 // In a MultiSelection, we can't see us travelling without focus
1143 mpImplLB
->GetMainWindow()->AllowGrabFocus( bMulti
);
1146 bool ListBox::IsMultiSelectionEnabled() const
1148 return mpImplLB
->IsMultiSelectionEnabled();
1151 void ListBox::SetHighlightColor(const Color
& rColor
)
1153 AllSettings
aSettings(GetSettings());
1154 StyleSettings
aStyle(aSettings
.GetStyleSettings());
1155 aStyle
.SetHighlightColor(rColor
);
1156 aSettings
.SetStyleSettings(aStyle
);
1157 SetSettings(aSettings
);
1159 mpImplLB
->SetHighlightColor(rColor
);
1162 void ListBox::SetHighlightTextColor(const Color
& rColor
)
1164 AllSettings
aSettings(GetSettings());
1165 StyleSettings
aStyle(aSettings
.GetStyleSettings());
1166 aStyle
.SetHighlightTextColor(rColor
);
1167 aSettings
.SetStyleSettings(aStyle
);
1168 SetSettings(aSettings
);
1170 mpImplLB
->SetHighlightTextColor(rColor
);
1173 Size
ListBox::CalcMinimumSize() const
1180 aSz
= CalcSubEditSize();
1182 bool bAddScrollWidth
= false;
1184 if (IsDropDownBox())
1186 aSz
.AdjustHeight(4 ); // add a space between entry and border
1187 aSz
.AdjustWidth(4 ); // add a little breathing space
1188 bAddScrollWidth
= true;
1191 bAddScrollWidth
= (GetStyle() & WB_VSCROLL
) == WB_VSCROLL
;
1193 if (bAddScrollWidth
)
1195 // Try native borders; scrollbar size may not be a good indicator
1196 // See how large the edit area inside is to estimate what is needed for the dropdown
1197 ImplControlValue aControlValue
;
1198 tools::Rectangle aContent
, aBound
;
1199 Size
aTestSize( 100, 20 );
1200 tools::Rectangle
aArea( Point(), aTestSize
);
1201 if( GetNativeControlRegion( ControlType::Listbox
, ControlPart::SubEdit
, aArea
, ControlState::NONE
,
1202 aControlValue
, aBound
, aContent
) )
1204 // use the themes drop down size
1205 aSz
.AdjustWidth(aTestSize
.Width() - aContent
.GetWidth() );
1208 aSz
.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1211 aSz
= CalcWindowSize( aSz
);
1213 if (IsDropDownBox()) // Check minimum height of dropdown box
1215 ImplControlValue aControlValue
;
1216 tools::Rectangle
aRect( Point( 0, 0 ), aSz
);
1217 tools::Rectangle aContent
, aBound
;
1218 if( GetNativeControlRegion( ControlType::Listbox
, ControlPart::Entire
, aRect
, ControlState::NONE
,
1219 aControlValue
, aBound
, aContent
) )
1221 if( aBound
.GetHeight() > aSz
.Height() )
1222 aSz
.setHeight( aBound
.GetHeight() );
1229 Size
ListBox::CalcSubEditSize() const
1236 if ( !IsDropDownBox() )
1237 aSz
= mpImplLB
->CalcSize (mnLineCount
? mnLineCount
: mpImplLB
->GetEntryList().GetEntryCount());
1240 aSz
.setHeight( mpImplLB
->GetEntryHeight() );
1241 // Size to maximum entry width
1242 aSz
.setWidth( mpImplLB
->GetMaxEntryWidth() );
1244 if (m_nMaxWidthChars
!= -1)
1246 tools::Long nMaxWidth
= m_nMaxWidthChars
* approximate_char_width();
1247 aSz
.setWidth( std::min(aSz
.Width(), nMaxWidth
) );
1250 // Do not create ultrathin ListBoxes, it doesn't look good
1251 if( aSz
.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() )
1252 aSz
.setWidth( GetSettings().GetStyleSettings().GetScrollBarSize() );
1258 Size
ListBox::GetOptimalSize() const
1260 return CalcMinimumSize();
1263 Size
ListBox::CalcAdjustedSize( const Size
& rPrefSize
) const
1265 Size aSz
= rPrefSize
;
1266 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
1267 static_cast<vcl::Window
*>(const_cast<ListBox
*>(this))->GetBorder( nLeft
, nTop
, nRight
, nBottom
);
1268 aSz
.AdjustHeight( -(nTop
+nBottom
) );
1269 if ( !IsDropDownBox() )
1271 tools::Long nEntryHeight
= CalcBlockSize( 1, 1 ).Height();
1272 tools::Long nLines
= aSz
.Height() / nEntryHeight
;
1275 aSz
.setHeight( nLines
* nEntryHeight
);
1279 aSz
.setHeight( mnDDHeight
);
1281 aSz
.AdjustHeight(nTop
+nBottom
);
1283 aSz
= CalcWindowSize( aSz
);
1287 Size
ListBox::CalcBlockSize( sal_uInt16 nColumns
, sal_uInt16 nLines
) const
1289 // ScrollBars are shown if needed
1290 Size aMinSz
= CalcMinimumSize();
1291 // aMinSz = ImplCalcOutSz( aMinSz );
1298 if ( !IsDropDownBox() )
1299 aSz
.setHeight( mpImplLB
->CalcSize( nLines
).Height() );
1301 aSz
.setHeight( mnDDHeight
);
1304 aSz
.setHeight( aMinSz
.Height() );
1308 aSz
.setWidth( nColumns
* GetTextWidth( OUString('X') ) );
1310 aSz
.setWidth( aMinSz
.Width() );
1312 if ( IsDropDownBox() )
1313 aSz
.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1315 if ( !IsDropDownBox() )
1317 if ( aSz
.Width() < aMinSz
.Width() )
1318 aSz
.AdjustHeight(GetSettings().GetStyleSettings().GetScrollBarSize() );
1319 if ( aSz
.Height() < aMinSz
.Height() )
1320 aSz
.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1323 aSz
= CalcWindowSize( aSz
);
1327 void ListBox::GetMaxVisColumnsAndLines( sal_uInt16
& rnCols
, sal_uInt16
& rnLines
) const
1329 float nCharWidth
= approximate_char_width();
1330 if ( !IsDropDownBox() )
1332 Size aOutSz
= mpImplLB
->GetMainWindow()->GetOutputSizePixel();
1333 rnCols
= static_cast<sal_uInt16
>(aOutSz
.Width()/nCharWidth
);
1334 rnLines
= static_cast<sal_uInt16
>(aOutSz
.Height()/mpImplLB
->GetEntryHeightWithMargin());
1338 Size aOutSz
= mpImplWin
->GetOutputSizePixel();
1339 rnCols
= static_cast<sal_uInt16
>(aOutSz
.Width()/nCharWidth
);
1344 void ListBox::SetReadOnly( bool bReadOnly
)
1346 if ( mpImplLB
->IsReadOnly() != bReadOnly
)
1348 mpImplLB
->SetReadOnly( bReadOnly
);
1349 CompatStateChanged( StateChangedType::ReadOnly
);
1353 bool ListBox::IsReadOnly() const
1355 return mpImplLB
->IsReadOnly();
1358 void ListBox::SetSeparatorPos( sal_Int32 n
)
1360 mpImplLB
->SetSeparatorPos( n
);
1363 sal_Int32
ListBox::GetSeparatorPos() const
1365 return mpImplLB
->GetSeparatorPos();
1368 void ListBox::AddSeparator( sal_Int32 n
)
1370 mpImplLB
->AddSeparator( n
);
1373 sal_uInt16
ListBox::GetDisplayLineCount() const
1375 return mpImplLB
->GetDisplayLineCount();
1378 tools::Rectangle
ListBox::GetDropDownPosSizePixel() const
1380 return mpFloatWin
? mpFloatWin
->GetWindowExtentsRelative(*this) : tools::Rectangle();
1383 const Wallpaper
& ListBox::GetDisplayBackground() const
1385 // !!! Recursion does not occur because the ImplListBox is initialized by default
1386 // to a non-transparent color in Window::ImplInitData
1387 return mpImplLB
->GetDisplayBackground();
1390 void ListBox::setMaxWidthChars(sal_Int32 nWidth
)
1392 if (nWidth
!= m_nMaxWidthChars
)
1394 m_nMaxWidthChars
= nWidth
;
1399 bool ListBox::set_property(const OUString
&rKey
, const OUString
&rValue
)
1401 if (rKey
== "active")
1402 SelectEntryPos(rValue
.toInt32());
1403 else if (rKey
== "max-width-chars")
1404 setMaxWidthChars(rValue
.toInt32());
1405 else if (rKey
== "can-focus")
1407 // as far as I can see in Gtk, setting a ComboBox as can.focus means
1408 // the focus gets stuck in it, so try here to behave like gtk does
1409 // with the settings that work, i.e. can.focus of false doesn't
1410 // set the hard WB_NOTABSTOP
1411 WinBits nBits
= GetStyle();
1412 nBits
&= ~(WB_TABSTOP
|WB_NOTABSTOP
);
1414 nBits
|= WB_TABSTOP
;
1418 return Control::set_property(rKey
, rValue
);
1422 FactoryFunction
ListBox::GetUITestFactory() const
1424 return ListBoxUIObject::create
;
1427 void ListBox::DumpAsPropertyTree(tools::JsonWriter
& rJsonWriter
)
1429 Control::DumpAsPropertyTree(rJsonWriter
);
1432 auto entriesNode
= rJsonWriter
.startArray("entries");
1433 for (int i
= 0; i
< GetEntryCount(); ++i
)
1435 rJsonWriter
.putSimpleValue(GetEntry(i
));
1439 rJsonWriter
.put("selectedCount", GetSelectedEntryCount());
1442 auto entriesNode
= rJsonWriter
.startArray("selectedEntries");
1443 for (int i
= 0; i
< GetSelectedEntryCount(); ++i
)
1445 rJsonWriter
.putSimpleValue(OUString::number(GetSelectedEntryPos(i
)));
1450 MultiListBox::MultiListBox( vcl::Window
* pParent
, WinBits nStyle
) :
1451 ListBox( WindowType::MULTILISTBOX
)
1453 ImplInit( pParent
, nStyle
);
1454 EnableMultiSelection( true );
1457 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */