/src/libreoffice/vcl/source/control/listbox.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <vcl/builder.hxx> |
21 | | #include <vcl/commandevent.hxx> |
22 | | #include <vcl/dndlistenercontainer.hxx> |
23 | | #include <vcl/event.hxx> |
24 | | #include <vcl/toolkit/lstbox.hxx> |
25 | | #include <vcl/rendercontext/SystemTextColorFlags.hxx> |
26 | | #include <vcl/salnativewidgets.hxx> |
27 | | #include <vcl/settings.hxx> |
28 | | #include <vcl/uitest/uiobject.hxx> |
29 | | #include <sal/log.hxx> |
30 | | |
31 | | #include <accessibility/vclxaccessibledropdownlistbox.hxx> |
32 | | #include <accessibility/vclxaccessiblelistbox.hxx> |
33 | | #include <svdata.hxx> |
34 | | #include <listbox.hxx> |
35 | | #include <dndeventdispatcher.hxx> |
36 | | #include <comphelper/lok.hxx> |
37 | | |
38 | | #include <boost/property_tree/ptree.hpp> |
39 | | #include <tools/json_writer.hxx> |
40 | | |
41 | | ListBox::ListBox(WindowType eType) |
42 | 0 | : Control(eType) |
43 | 0 | , mpImplLB(nullptr) |
44 | 0 | { |
45 | 0 | ImplInitListBoxData(); |
46 | 0 | } Unexecuted instantiation: ListBox::ListBox(WindowType) Unexecuted instantiation: ListBox::ListBox(WindowType) |
47 | | |
48 | 0 | ListBox::ListBox( vcl::Window* pParent, WinBits nStyle ) : Control( WindowType::LISTBOX ) |
49 | 0 | { |
50 | 0 | ImplInitListBoxData(); |
51 | 0 | ImplInit( pParent, nStyle ); |
52 | 0 | } Unexecuted instantiation: ListBox::ListBox(vcl::Window*, long) Unexecuted instantiation: ListBox::ListBox(vcl::Window*, long) |
53 | | |
54 | | ListBox::~ListBox() |
55 | 0 | { |
56 | 0 | disposeOnce(); |
57 | 0 | } |
58 | | |
59 | | void ListBox::dispose() |
60 | 0 | { |
61 | 0 | CallEventListeners( VclEventId::ObjectDying ); |
62 | |
|
63 | 0 | mpImplLB.disposeAndClear(); |
64 | 0 | mpFloatWin.disposeAndClear(); |
65 | 0 | mpImplWin.disposeAndClear(); |
66 | 0 | mpBtn.disposeAndClear(); |
67 | |
|
68 | 0 | Control::dispose(); |
69 | 0 | } |
70 | | |
71 | | void ListBox::ImplInitListBoxData() |
72 | 0 | { |
73 | 0 | mpFloatWin = nullptr; |
74 | 0 | mpImplWin = nullptr; |
75 | 0 | mpBtn = nullptr; |
76 | 0 | mnDDHeight = 0; |
77 | 0 | mnLineCount = 0; |
78 | 0 | m_nMaxWidthChars = -1; |
79 | 0 | mbDDAutoSize = true; |
80 | 0 | } |
81 | | |
82 | | void ListBox::ImplInit( vcl::Window* pParent, WinBits nStyle ) |
83 | 0 | { |
84 | 0 | nStyle = ImplInitStyle( nStyle ); |
85 | 0 | if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) ) |
86 | 0 | nStyle |= WB_BORDER; |
87 | |
|
88 | 0 | Control::ImplInit( pParent, nStyle, nullptr ); |
89 | |
|
90 | 0 | css::uno::Reference< css::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this); |
91 | |
|
92 | 0 | if( nStyle & WB_DROPDOWN ) |
93 | 0 | { |
94 | 0 | sal_Int32 nLeft, nTop, nRight, nBottom; |
95 | 0 | GetBorder( nLeft, nTop, nRight, nBottom ); |
96 | 0 | mnDDHeight = static_cast<sal_uInt16>(GetTextHeight() + nTop + nBottom + 4); |
97 | |
|
98 | 0 | if( IsNativeWidgetEnabled() && |
99 | 0 | IsNativeControlSupported( ControlType::Listbox, ControlPart::Entire ) ) |
100 | 0 | { |
101 | 0 | ImplControlValue aControlValue; |
102 | 0 | tools::Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) ); |
103 | 0 | tools::Rectangle aBoundingRgn( aCtrlRegion ); |
104 | 0 | tools::Rectangle aContentRgn( aCtrlRegion ); |
105 | 0 | if( GetNativeControlRegion( ControlType::Listbox, ControlPart::Entire, aCtrlRegion, |
106 | 0 | ControlState::ENABLED, aControlValue, |
107 | 0 | aBoundingRgn, aContentRgn ) ) |
108 | 0 | { |
109 | 0 | sal_Int32 nHeight = aBoundingRgn.GetHeight(); |
110 | 0 | if( nHeight > mnDDHeight ) |
111 | 0 | mnDDHeight = static_cast<sal_uInt16>(nHeight); |
112 | 0 | } |
113 | 0 | } |
114 | |
|
115 | 0 | mpFloatWin = VclPtr<ImplListBoxFloatingWindow>::Create( this ); |
116 | | // For Kit jsdialogs we don't need or want a buffer the size of |
117 | | // the ListBox dropdown taking up memory which is unnecessary |
118 | | // in that case. |
119 | 0 | if (!comphelper::LibreOfficeKit::isActive()) |
120 | 0 | { |
121 | 0 | if (!IsNativeControlSupported(ControlType::Pushbutton, ControlPart::Focus)) |
122 | 0 | mpFloatWin->RequestDoubleBuffering(true); |
123 | 0 | } |
124 | 0 | mpFloatWin->SetAutoWidth( true ); |
125 | 0 | mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) ); |
126 | 0 | mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop); |
127 | |
|
128 | 0 | mpImplWin = VclPtr<ImplWin>::Create( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER ); |
129 | 0 | mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) ); |
130 | 0 | mpImplWin->Show(); |
131 | 0 | mpImplWin->GetDropTarget()->addDropTargetListener(xDrop); |
132 | 0 | mpImplWin->SetEdgeBlending(false); |
133 | |
|
134 | 0 | mpBtn = VclPtr<ImplBtn>::Create( this, WB_NOLIGHTBORDER | WB_RECTSTYLE ); |
135 | 0 | ImplInitDropDownButton( mpBtn ); |
136 | 0 | mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) ); |
137 | 0 | mpBtn->Show(); |
138 | 0 | mpBtn->GetDropTarget()->addDropTargetListener(xDrop); |
139 | 0 | } |
140 | |
|
141 | 0 | vcl::Window* pLBParent = this; |
142 | 0 | if ( mpFloatWin ) |
143 | 0 | pLBParent = mpFloatWin; |
144 | 0 | mpImplLB = VclPtr<ImplListBox>::Create( pLBParent, nStyle&(~WB_BORDER) ); |
145 | 0 | mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) ); |
146 | 0 | mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl ) ); |
147 | 0 | mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) ); |
148 | 0 | mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) ); |
149 | 0 | mpImplLB->SetFocusHdl( LINK( this, ListBox, ImplFocusHdl ) ); |
150 | 0 | mpImplLB->SetListItemSelectHdl( LINK( this, ListBox, ImplListItemSelectHdl ) ); |
151 | 0 | mpImplLB->SetPosPixel( Point() ); |
152 | 0 | mpImplLB->SetEdgeBlending(false); |
153 | 0 | mpImplLB->Show(); |
154 | |
|
155 | 0 | mpImplLB->GetDropTarget()->addDropTargetListener(xDrop); |
156 | |
|
157 | 0 | if ( mpFloatWin ) |
158 | 0 | { |
159 | 0 | mpFloatWin->SetImplListBox( mpImplLB ); |
160 | 0 | mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) ); |
161 | 0 | } |
162 | 0 | else |
163 | 0 | mpImplLB->GetMainWindow()->AllowGrabFocus( true ); |
164 | |
|
165 | 0 | SetCompoundControl( true ); |
166 | 0 | } |
167 | | |
168 | | WinBits ListBox::ImplInitStyle( WinBits nStyle ) |
169 | 0 | { |
170 | 0 | if ( !(nStyle & WB_NOTABSTOP) ) |
171 | 0 | nStyle |= WB_TABSTOP; |
172 | 0 | if ( !(nStyle & WB_NOGROUP) ) |
173 | 0 | nStyle |= WB_GROUP; |
174 | 0 | return nStyle; |
175 | 0 | } |
176 | | |
177 | | IMPL_LINK_NOARG(ListBox, ImplSelectHdl, LinkParamNone*, void) |
178 | 0 | { |
179 | 0 | bool bPopup = IsInDropDown(); |
180 | 0 | if( IsDropDownBox() ) |
181 | 0 | { |
182 | 0 | if( !mpImplLB->IsTravelSelect() ) |
183 | 0 | { |
184 | 0 | mpFloatWin->EndPopupMode(); |
185 | 0 | mpImplWin->GrabFocus(); |
186 | 0 | } |
187 | |
|
188 | 0 | mpImplWin->SetItemPos( GetSelectedEntryPos() ); |
189 | 0 | mpImplWin->SetString( GetSelectedEntry() ); |
190 | 0 | if( mpImplLB->GetEntryList().HasImages() ) |
191 | 0 | { |
192 | 0 | Image aImage = mpImplLB->GetEntryList().GetEntryImage( GetSelectedEntryPos() ); |
193 | 0 | mpImplWin->SetImage( aImage ); |
194 | 0 | } |
195 | 0 | mpImplWin->Invalidate(); |
196 | 0 | } |
197 | |
|
198 | 0 | if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) ) |
199 | 0 | Select(); |
200 | 0 | } |
201 | | |
202 | | IMPL_LINK( ListBox, ImplFocusHdl, sal_Int32, nPos, void ) |
203 | 0 | { |
204 | 0 | CallEventListeners( VclEventId::ListboxFocus, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nPos)) ); |
205 | 0 | } |
206 | | |
207 | | IMPL_LINK_NOARG( ListBox, ImplListItemSelectHdl, LinkParamNone*, void ) |
208 | 0 | { |
209 | 0 | CallEventListeners( VclEventId::DropdownSelect ); |
210 | 0 | } |
211 | | |
212 | | IMPL_LINK_NOARG(ListBox, ImplScrollHdl, ImplListBox*, void) |
213 | 0 | { |
214 | 0 | CallEventListeners( VclEventId::ListboxScrolled ); |
215 | 0 | } |
216 | | |
217 | | IMPL_LINK_NOARG(ListBox, ImplCancelHdl, LinkParamNone*, void) |
218 | 0 | { |
219 | 0 | if( IsInDropDown() ) |
220 | 0 | mpFloatWin->EndPopupMode(); |
221 | 0 | } |
222 | | |
223 | | IMPL_LINK( ListBox, ImplSelectionChangedHdl, sal_Int32, nChanged, void ) |
224 | 0 | { |
225 | 0 | if ( mpImplLB->IsTrackingSelect() ) |
226 | 0 | return; |
227 | | |
228 | 0 | const ImplEntryList& rEntryList = mpImplLB->GetEntryList(); |
229 | 0 | if ( rEntryList.IsEntryPosSelected( nChanged ) ) |
230 | 0 | { |
231 | | // FIXME? This should've been turned into an ImplPaintEntry some time ago... |
232 | 0 | if ( nChanged < rEntryList.GetMRUCount() ) |
233 | 0 | nChanged = rEntryList.FindEntry( rEntryList.GetEntryText( nChanged ) ); |
234 | 0 | mpImplWin->SetItemPos( nChanged ); |
235 | 0 | mpImplWin->SetString( rEntryList.GetEntryText( nChanged ) ); |
236 | 0 | if( rEntryList.HasImages() ) |
237 | 0 | { |
238 | 0 | Image aImage = rEntryList.GetEntryImage( nChanged ); |
239 | 0 | mpImplWin->SetImage( aImage ); |
240 | 0 | } |
241 | 0 | } |
242 | 0 | else |
243 | 0 | { |
244 | 0 | mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND ); |
245 | 0 | mpImplWin->SetString( OUString() ); |
246 | 0 | Image aImage; |
247 | 0 | mpImplWin->SetImage( aImage ); |
248 | 0 | } |
249 | 0 | mpImplWin->Invalidate(); |
250 | 0 | } |
251 | | |
252 | | IMPL_LINK_NOARG(ListBox, ImplDoubleClickHdl, ImplListBoxWindow*, void) |
253 | 0 | { |
254 | 0 | DoubleClick(); |
255 | 0 | } |
256 | | |
257 | | IMPL_LINK_NOARG(ListBox, ImplClickBtnHdl, void*, void) |
258 | 0 | { |
259 | 0 | if( mpFloatWin->IsInPopupMode() ) |
260 | 0 | return; |
261 | | |
262 | 0 | CallEventListeners( VclEventId::DropdownPreOpen ); |
263 | 0 | mpImplWin->GrabFocus(); |
264 | 0 | mpBtn->SetPressed( true ); |
265 | 0 | mpFloatWin->StartFloat( true ); |
266 | 0 | CallEventListeners( VclEventId::DropdownOpen ); |
267 | |
|
268 | 0 | ImplClearLayoutData(); |
269 | 0 | if( mpImplLB ) |
270 | 0 | mpImplLB->GetMainWindow()->ImplClearLayoutData(); |
271 | 0 | if( mpImplWin ) |
272 | 0 | mpImplWin->ImplClearLayoutData(); |
273 | 0 | } |
274 | | |
275 | | IMPL_LINK_NOARG(ListBox, ImplPopupModeEndHdl, FloatingWindow*, void) |
276 | 0 | { |
277 | 0 | if( mpFloatWin->IsPopupModeCanceled() ) |
278 | 0 | { |
279 | 0 | if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND ) |
280 | 0 | && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) ) |
281 | 0 | { |
282 | 0 | mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), true ); |
283 | 0 | bool bTravelSelect = mpImplLB->IsTravelSelect(); |
284 | 0 | mpImplLB->SetTravelSelect( true ); |
285 | |
|
286 | 0 | VclPtr<vcl::Window> xWindow = this; |
287 | 0 | Select(); |
288 | 0 | if ( xWindow->isDisposed() ) |
289 | 0 | return; |
290 | | |
291 | 0 | mpImplLB->SetTravelSelect( bTravelSelect ); |
292 | 0 | } |
293 | 0 | } |
294 | | |
295 | 0 | ImplClearLayoutData(); |
296 | 0 | if( mpImplLB ) |
297 | 0 | mpImplLB->GetMainWindow()->ImplClearLayoutData(); |
298 | 0 | if( mpImplWin ) |
299 | 0 | mpImplWin->ImplClearLayoutData(); |
300 | |
|
301 | 0 | mpBtn->SetPressed( false ); |
302 | 0 | CallEventListeners( VclEventId::DropdownClose ); |
303 | 0 | } |
304 | | |
305 | | void ListBox::ToggleDropDown() |
306 | 0 | { |
307 | 0 | if( !IsDropDownBox() ) |
308 | 0 | return; |
309 | | |
310 | 0 | if( mpFloatWin->IsInPopupMode() ) |
311 | 0 | mpFloatWin->EndPopupMode(); |
312 | 0 | else |
313 | 0 | { |
314 | 0 | CallEventListeners( VclEventId::DropdownPreOpen ); |
315 | 0 | mpImplWin->GrabFocus(); |
316 | 0 | mpBtn->SetPressed( true ); |
317 | 0 | mpFloatWin->StartFloat( true ); |
318 | 0 | CallEventListeners( VclEventId::DropdownOpen ); |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | | rtl::Reference<comphelper::OAccessible> ListBox::CreateAccessible() |
323 | 0 | { |
324 | 0 | const bool bIsDropDownBox = (GetStyle() & WB_DROPDOWN) == WB_DROPDOWN; |
325 | 0 | if (bIsDropDownBox) |
326 | 0 | return new VCLXAccessibleDropDownListBox(this); |
327 | 0 | else |
328 | 0 | return new VCLXAccessibleListBox(this); |
329 | 0 | } |
330 | | |
331 | | void ListBox::ApplySettings(vcl::RenderContext& rRenderContext) |
332 | 0 | { |
333 | 0 | rRenderContext.SetBackground(); |
334 | 0 | } |
335 | | |
336 | | void ListBox::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) |
337 | 0 | { |
338 | 0 | mpImplLB->GetMainWindow()->ApplySettings(*pDev); |
339 | |
|
340 | 0 | Point aPos = pDev->LogicToPixel( rPos ); |
341 | 0 | Size aSize = GetSizePixel(); |
342 | 0 | vcl::Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev ); |
343 | |
|
344 | 0 | auto popIt = pDev->ScopedPush(); |
345 | 0 | pDev->SetMapMode(); |
346 | 0 | pDev->SetFont( aFont ); |
347 | 0 | pDev->SetTextFillColor(); |
348 | | |
349 | | // Border/Background |
350 | 0 | pDev->SetLineColor(); |
351 | 0 | pDev->SetFillColor(); |
352 | 0 | bool bBorder = (GetStyle() & WB_BORDER); |
353 | 0 | bool bBackground = IsControlBackground(); |
354 | 0 | if ( bBorder || bBackground ) |
355 | 0 | { |
356 | 0 | tools::Rectangle aRect( aPos, aSize ); |
357 | 0 | if ( bBorder ) |
358 | 0 | { |
359 | 0 | ImplDrawFrame( pDev, aRect ); |
360 | 0 | } |
361 | 0 | if ( bBackground ) |
362 | 0 | { |
363 | 0 | pDev->SetFillColor( GetControlBackground() ); |
364 | 0 | pDev->DrawRect( aRect ); |
365 | 0 | } |
366 | 0 | } |
367 | | |
368 | | // Content |
369 | 0 | if ( nFlags & SystemTextColorFlags::Mono ) |
370 | 0 | { |
371 | 0 | pDev->SetTextColor( COL_BLACK ); |
372 | 0 | } |
373 | 0 | else |
374 | 0 | { |
375 | 0 | if ( !IsEnabled() ) |
376 | 0 | { |
377 | 0 | const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
378 | 0 | pDev->SetTextColor( rStyleSettings.GetDisableColor() ); |
379 | 0 | } |
380 | 0 | else |
381 | 0 | { |
382 | 0 | pDev->SetTextColor( GetTextColor() ); |
383 | 0 | } |
384 | 0 | } |
385 | |
|
386 | 0 | const tools::Long nOnePixel = GetDrawPixel( pDev, 1 ); |
387 | 0 | const tools::Long nOffX = 3*nOnePixel; |
388 | 0 | DrawTextFlags nTextStyle = DrawTextFlags::VCenter; |
389 | 0 | tools::Rectangle aTextRect( aPos, aSize ); |
390 | |
|
391 | 0 | if ( GetStyle() & WB_CENTER ) |
392 | 0 | nTextStyle |= DrawTextFlags::Center; |
393 | 0 | else if ( GetStyle() & WB_RIGHT ) |
394 | 0 | nTextStyle |= DrawTextFlags::Right; |
395 | 0 | else |
396 | 0 | nTextStyle |= DrawTextFlags::Left; |
397 | |
|
398 | 0 | aTextRect.AdjustLeft(nOffX ); |
399 | 0 | aTextRect.AdjustRight( -nOffX ); |
400 | |
|
401 | 0 | if ( IsDropDownBox() ) |
402 | 0 | { |
403 | 0 | OUString aText = GetSelectedEntry(); |
404 | 0 | tools::Long nTextHeight = pDev->GetTextHeight(); |
405 | 0 | tools::Long nTextWidth = pDev->GetTextWidth( aText ); |
406 | 0 | tools::Long nOffY = (aSize.Height()-nTextHeight) / 2; |
407 | | |
408 | | // Clipping? |
409 | 0 | if ( (nOffY < 0) || |
410 | 0 | ((nOffY+nTextHeight) > aSize.Height()) || |
411 | 0 | ((nOffX+nTextWidth) > aSize.Width()) ) |
412 | 0 | { |
413 | 0 | tools::Rectangle aClip( aPos, aSize ); |
414 | 0 | if ( nTextHeight > aSize.Height() ) |
415 | 0 | aClip.AdjustBottom(nTextHeight-aSize.Height()+1 ); // So that HP Printers don't optimize this away |
416 | 0 | pDev->IntersectClipRegion( aClip ); |
417 | 0 | } |
418 | |
|
419 | 0 | pDev->DrawText( aTextRect, aText, nTextStyle ); |
420 | 0 | } |
421 | 0 | else |
422 | 0 | { |
423 | 0 | tools::Long nTextHeight = pDev->GetTextHeight(); |
424 | 0 | sal_uInt16 nLines = ( nTextHeight > 0 ) ? static_cast<sal_uInt16>(aSize.Height() / nTextHeight) : 1; |
425 | 0 | tools::Rectangle aClip( aPos, aSize ); |
426 | |
|
427 | 0 | pDev->IntersectClipRegion( aClip ); |
428 | |
|
429 | 0 | if ( !nLines ) |
430 | 0 | nLines = 1; |
431 | |
|
432 | 0 | for ( sal_uInt16 n = 0; n < nLines; n++ ) |
433 | 0 | { |
434 | 0 | sal_Int32 nEntry = n+mpImplLB->GetTopEntry(); |
435 | 0 | bool bSelected = mpImplLB->GetEntryList().IsEntryPosSelected( nEntry ); |
436 | 0 | if ( bSelected ) |
437 | 0 | { |
438 | 0 | pDev->SetFillColor( COL_BLACK ); |
439 | 0 | pDev->DrawRect( tools::Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ), |
440 | 0 | Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) ); |
441 | 0 | pDev->SetFillColor(); |
442 | 0 | pDev->SetTextColor( COL_WHITE ); |
443 | 0 | } |
444 | |
|
445 | 0 | aTextRect.SetTop( aPos.Y() + n*nTextHeight ); |
446 | 0 | aTextRect.SetBottom( aTextRect.Top() + nTextHeight ); |
447 | |
|
448 | 0 | pDev->DrawText( aTextRect, mpImplLB->GetEntryList().GetEntryText( nEntry ), nTextStyle ); |
449 | |
|
450 | 0 | if ( bSelected ) |
451 | 0 | pDev->SetTextColor( COL_BLACK ); |
452 | 0 | } |
453 | 0 | } |
454 | 0 | } |
455 | | |
456 | | void ListBox::GetFocus() |
457 | 0 | { |
458 | 0 | if ( mpImplLB ) |
459 | 0 | { |
460 | 0 | if( IsDropDownBox() ) |
461 | 0 | mpImplWin->GrabFocus(); |
462 | 0 | else |
463 | 0 | mpImplLB->GrabFocus(); |
464 | 0 | } |
465 | |
|
466 | 0 | Control::GetFocus(); |
467 | 0 | } |
468 | | |
469 | | void ListBox::LoseFocus() |
470 | 0 | { |
471 | 0 | if( IsDropDownBox() ) |
472 | 0 | { |
473 | 0 | if (mpImplWin) |
474 | 0 | mpImplWin->HideFocus(); |
475 | 0 | } |
476 | 0 | else |
477 | 0 | { |
478 | 0 | if (mpImplLB) |
479 | 0 | mpImplLB->HideFocus(); |
480 | 0 | } |
481 | |
|
482 | 0 | Control::LoseFocus(); |
483 | 0 | } |
484 | | |
485 | | void ListBox::DataChanged( const DataChangedEvent& rDCEvt ) |
486 | 0 | { |
487 | 0 | Control::DataChanged( rDCEvt ); |
488 | |
|
489 | 0 | if ( !((rDCEvt.GetType() == DataChangedEventType::FONTS) || |
490 | 0 | (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) || |
491 | 0 | ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) && |
492 | 0 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))) ) |
493 | 0 | return; |
494 | | |
495 | 0 | SetBackground(); // Due to a hack in Window::UpdateSettings the background must be reset |
496 | | // otherwise it will overpaint NWF drawn listboxes |
497 | 0 | Resize(); |
498 | 0 | mpImplLB->Resize(); // Is not called by ListBox::Resize() if the ImplLB does not change |
499 | |
|
500 | 0 | if ( mpImplWin ) |
501 | 0 | { |
502 | 0 | mpImplWin->GetOutDev()->SetSettings( GetSettings() ); // If not yet set... |
503 | 0 | mpImplWin->ApplySettings(*mpImplWin->GetOutDev()); |
504 | |
|
505 | 0 | mpBtn->GetOutDev()->SetSettings( GetSettings() ); |
506 | 0 | ImplInitDropDownButton( mpBtn ); |
507 | 0 | } |
508 | |
|
509 | 0 | if ( IsDropDownBox() ) |
510 | 0 | Invalidate(); |
511 | 0 | } |
512 | | |
513 | | void ListBox::EnableAutoSize( bool bAuto ) |
514 | 0 | { |
515 | 0 | mbDDAutoSize = bAuto; |
516 | 0 | if ( mpFloatWin ) |
517 | 0 | { |
518 | 0 | if ( bAuto && !mpFloatWin->GetDropDownLineCount() ) |
519 | 0 | { |
520 | | // use GetListBoxMaximumLineCount here; before, was on fixed number of five |
521 | 0 | AdaptDropDownLineCountToMaximum(); |
522 | 0 | } |
523 | 0 | else if ( !bAuto ) |
524 | 0 | { |
525 | 0 | mpFloatWin->SetDropDownLineCount( 0 ); |
526 | 0 | } |
527 | 0 | } |
528 | 0 | } |
529 | | |
530 | | void ListBox::SetDropDownLineCount( sal_uInt16 nLines ) |
531 | 0 | { |
532 | 0 | mnLineCount = nLines; |
533 | 0 | if ( mpFloatWin ) |
534 | 0 | mpFloatWin->SetDropDownLineCount( mnLineCount ); |
535 | 0 | } |
536 | | |
537 | | void ListBox::AdaptDropDownLineCountToMaximum() |
538 | 0 | { |
539 | | // Adapt to maximum allowed number. |
540 | | // Limit for LOK as we can't render outside of the dialog canvas. |
541 | 0 | if (comphelper::LibreOfficeKit::isActive()) |
542 | 0 | SetDropDownLineCount(11); |
543 | 0 | else |
544 | 0 | SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount()); |
545 | 0 | } |
546 | | |
547 | | sal_uInt16 ListBox::GetDropDownLineCount() const |
548 | 0 | { |
549 | 0 | if ( mpFloatWin ) |
550 | 0 | return mpFloatWin->GetDropDownLineCount(); |
551 | 0 | return mnLineCount; |
552 | 0 | } |
553 | | |
554 | | void ListBox::setPosSizePixel( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags ) |
555 | 0 | { |
556 | 0 | if( IsDropDownBox() && ( nFlags & PosSizeFlags::Size ) ) |
557 | 0 | { |
558 | 0 | Size aPrefSz = mpFloatWin->GetPrefSize(); |
559 | 0 | if ( ( nFlags & PosSizeFlags::Height ) && ( nHeight >= 2*mnDDHeight ) ) |
560 | 0 | aPrefSz.setHeight( nHeight-mnDDHeight ); |
561 | 0 | if ( nFlags & PosSizeFlags::Width ) |
562 | 0 | aPrefSz.setWidth( nWidth ); |
563 | 0 | mpFloatWin->SetPrefSize( aPrefSz ); |
564 | |
|
565 | 0 | if (IsAutoSizeEnabled()) |
566 | 0 | nHeight = mnDDHeight; |
567 | 0 | } |
568 | |
|
569 | 0 | Control::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); |
570 | 0 | } |
571 | | |
572 | | void ListBox::Resize() |
573 | 0 | { |
574 | 0 | if (isDisposed()) |
575 | 0 | return; |
576 | 0 | Size aOutSz = GetOutputSizePixel(); |
577 | 0 | if( IsDropDownBox() ) |
578 | 0 | { |
579 | | // Initialize the dropdown button size with the standard scrollbar width |
580 | 0 | tools::Long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); |
581 | 0 | tools::Long nBottom = aOutSz.Height(); |
582 | | |
583 | | // Note: in case of no border, pBorder will actually be this |
584 | 0 | vcl::Window *pBorder = GetWindow( GetWindowType::Border ); |
585 | 0 | ImplControlValue aControlValue; |
586 | 0 | Point aPoint; |
587 | 0 | tools::Rectangle aContent, aBound; |
588 | | |
589 | | // Use the full extent of the control |
590 | 0 | tools::Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); |
591 | |
|
592 | 0 | if ( GetNativeControlRegion( ControlType::Listbox, ControlPart::ButtonDown, |
593 | 0 | aArea, ControlState::NONE, aControlValue, aBound, aContent) ) |
594 | 0 | { |
595 | | // Convert back from border space to local coordinates |
596 | 0 | aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) ); |
597 | 0 | aContent.Move( -aPoint.X(), -aPoint.Y() ); |
598 | | |
599 | | // Use the themes drop down size for the button |
600 | 0 | aOutSz.setWidth( aContent.Left() ); |
601 | 0 | mpBtn->setPosSizePixel( aContent.Left(), 0, aContent.GetWidth(), nBottom ); |
602 | | |
603 | | // Adjust the size of the edit field |
604 | 0 | if ( GetNativeControlRegion( ControlType::Listbox, ControlPart::SubEdit, |
605 | 0 | aArea, ControlState::NONE, aControlValue, aBound, aContent) ) |
606 | 0 | { |
607 | | // Convert back from border space to local coordinates |
608 | 0 | aContent.Move( -aPoint.X(), -aPoint.Y() ); |
609 | | |
610 | | // Use the themes drop down size |
611 | 0 | if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects ) |
612 | 0 | { |
613 | | // No border but focus ring behavior -> we have a problem; the |
614 | | // native rect relies on the border to draw the focus |
615 | | // let's do the best we can and center vertically, so it doesn't look |
616 | | // completely wrong. |
617 | 0 | Size aSz( GetOutputSizePixel() ); |
618 | 0 | tools::Long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2; |
619 | 0 | aContent.AdjustTop( -nDiff ); |
620 | 0 | aContent.AdjustBottom( -nDiff ); |
621 | 0 | } |
622 | 0 | mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() ); |
623 | 0 | } |
624 | 0 | else |
625 | 0 | mpImplWin->SetSizePixel( aOutSz ); |
626 | 0 | } |
627 | 0 | else |
628 | 0 | { |
629 | 0 | nSBWidth = CalcZoom( nSBWidth ); |
630 | 0 | mpImplWin->setPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() ); |
631 | 0 | mpBtn->setPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() ); |
632 | 0 | } |
633 | 0 | } |
634 | 0 | else |
635 | 0 | { |
636 | 0 | mpImplLB->SetSizePixel( aOutSz ); |
637 | 0 | } |
638 | | |
639 | | // Retain FloatingWindow size even when it's invisible, as we still process KEY_PGUP/DOWN ... |
640 | 0 | if ( mpFloatWin ) |
641 | 0 | mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize(mpFloatWin->GetParentRect()) ); |
642 | |
|
643 | 0 | Control::Resize(); |
644 | 0 | } |
645 | | |
646 | | void ListBox::FillLayoutData() const |
647 | 0 | { |
648 | 0 | mxLayoutData.emplace(); |
649 | 0 | const ImplListBoxWindow* rMainWin = mpImplLB->GetMainWindow(); |
650 | 0 | if( mpFloatWin ) |
651 | 0 | { |
652 | | // Dropdown mode |
653 | 0 | AppendLayoutData( *mpImplWin ); |
654 | 0 | mpImplWin->SetLayoutDataParent( this ); |
655 | 0 | if( mpFloatWin->IsReallyVisible() ) |
656 | 0 | { |
657 | 0 | AppendLayoutData( *rMainWin ); |
658 | 0 | rMainWin->SetLayoutDataParent( this ); |
659 | 0 | } |
660 | 0 | } |
661 | 0 | else |
662 | 0 | { |
663 | 0 | AppendLayoutData( *rMainWin ); |
664 | 0 | rMainWin->SetLayoutDataParent( this ); |
665 | 0 | } |
666 | 0 | } |
667 | | |
668 | | tools::Long ListBox::GetIndexForPoint( const Point& rPoint, sal_Int32& rPos ) const |
669 | 0 | { |
670 | 0 | if( !HasLayoutData() ) |
671 | 0 | FillLayoutData(); |
672 | | |
673 | | // Check whether rPoint fits at all |
674 | 0 | tools::Long nIndex = Control::GetIndexForPoint( rPoint ); |
675 | 0 | if( nIndex != -1 ) |
676 | 0 | { |
677 | | // Point must be either in main list window |
678 | | // or in impl window (dropdown case) |
679 | 0 | ImplListBoxWindow* rMain = mpImplLB->GetMainWindow(); |
680 | | |
681 | | // Convert coordinates to ImplListBoxWindow pixel coordinate space |
682 | 0 | Point aConvPoint = LogicToPixel( rPoint ); |
683 | 0 | AbsoluteScreenPixelPoint aConvPointAbs = OutputToAbsoluteScreenPixel( aConvPoint ); |
684 | 0 | aConvPoint = rMain->AbsoluteScreenToOutputPixel( aConvPointAbs ); |
685 | 0 | aConvPoint = rMain->PixelToLogic( aConvPoint ); |
686 | | |
687 | | // Try to find entry |
688 | 0 | sal_Int32 nEntry = rMain->GetEntryPosForPoint( aConvPoint ); |
689 | 0 | if( nEntry == LISTBOX_ENTRY_NOTFOUND ) |
690 | 0 | { |
691 | | // Not found, maybe dropdown case |
692 | 0 | if( mpImplWin && mpImplWin->IsReallyVisible() ) |
693 | 0 | { |
694 | | // Convert to impl window pixel coordinates |
695 | 0 | aConvPoint = LogicToPixel( rPoint ); |
696 | 0 | aConvPointAbs = OutputToAbsoluteScreenPixel( aConvPoint ); |
697 | 0 | aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPointAbs ); |
698 | | |
699 | | // Check whether converted point is inside impl window |
700 | 0 | Size aImplWinSize = mpImplWin->GetOutputSizePixel(); |
701 | 0 | if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() ) |
702 | 0 | { |
703 | | // Inside the impl window, the position is the current item pos |
704 | 0 | rPos = mpImplWin->GetItemPos(); |
705 | 0 | } |
706 | 0 | else |
707 | 0 | nIndex = -1; |
708 | 0 | } |
709 | 0 | else |
710 | 0 | nIndex = -1; |
711 | 0 | } |
712 | 0 | else |
713 | 0 | rPos = nEntry; |
714 | |
|
715 | 0 | SAL_WARN_IF( nIndex == -1, "vcl", "found index for point, but relative index failed" ); |
716 | 0 | } |
717 | | |
718 | | // Get line relative index |
719 | 0 | if( nIndex != -1 ) |
720 | 0 | nIndex = ToRelativeLineIndex( nIndex ); |
721 | |
|
722 | 0 | return nIndex; |
723 | 0 | } |
724 | | |
725 | | void ListBox::StateChanged( StateChangedType nType ) |
726 | 0 | { |
727 | 0 | if( nType == StateChangedType::ReadOnly ) |
728 | 0 | { |
729 | 0 | if( mpImplWin ) |
730 | 0 | mpImplWin->Enable( !IsReadOnly() ); |
731 | 0 | if( mpBtn ) |
732 | 0 | mpBtn->Enable( !IsReadOnly() ); |
733 | 0 | } |
734 | 0 | else if( nType == StateChangedType::Enable ) |
735 | 0 | { |
736 | 0 | mpImplLB->Enable( IsEnabled() ); |
737 | 0 | if( mpImplWin ) |
738 | 0 | { |
739 | 0 | mpImplWin->Enable( IsEnabled() ); |
740 | 0 | if ( IsNativeControlSupported(ControlType::Listbox, ControlPart::Entire) |
741 | 0 | && ! IsNativeControlSupported(ControlType::Listbox, ControlPart::ButtonDown) ) |
742 | 0 | { |
743 | 0 | GetWindow(GetWindowType::Border)->Invalidate(); |
744 | 0 | } |
745 | 0 | else |
746 | 0 | mpImplWin->Invalidate(); |
747 | 0 | } |
748 | 0 | if( mpBtn ) |
749 | 0 | mpBtn->Enable( IsEnabled() ); |
750 | 0 | } |
751 | 0 | else if( nType == StateChangedType::UpdateMode ) |
752 | 0 | { |
753 | 0 | mpImplLB->SetUpdateMode( IsUpdateMode() ); |
754 | 0 | } |
755 | 0 | else if ( nType == StateChangedType::Zoom ) |
756 | 0 | { |
757 | 0 | mpImplLB->SetZoom( GetZoom() ); |
758 | 0 | if ( mpImplWin ) |
759 | 0 | { |
760 | 0 | mpImplWin->SetZoom( GetZoom() ); |
761 | 0 | mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); |
762 | 0 | mpImplWin->Invalidate(); |
763 | 0 | } |
764 | 0 | Resize(); |
765 | 0 | } |
766 | 0 | else if ( nType == StateChangedType::ControlFont ) |
767 | 0 | { |
768 | 0 | mpImplLB->SetControlFont( GetControlFont() ); |
769 | 0 | if ( mpImplWin ) |
770 | 0 | { |
771 | 0 | mpImplWin->SetControlFont( GetControlFont() ); |
772 | 0 | mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); |
773 | 0 | mpImplWin->Invalidate(); |
774 | 0 | } |
775 | 0 | Resize(); |
776 | 0 | } |
777 | 0 | else if ( nType == StateChangedType::ControlForeground ) |
778 | 0 | { |
779 | 0 | mpImplLB->SetControlForeground( GetControlForeground() ); |
780 | 0 | if ( mpImplWin ) |
781 | 0 | { |
782 | 0 | mpImplWin->SetControlForeground( GetControlForeground() ); |
783 | 0 | mpImplWin->SetTextColor( GetControlForeground() ); |
784 | 0 | mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); |
785 | 0 | mpImplWin->Invalidate(); |
786 | 0 | } |
787 | 0 | } |
788 | 0 | else if ( nType == StateChangedType::ControlBackground ) |
789 | 0 | { |
790 | 0 | mpImplLB->SetControlBackground( GetControlBackground() ); |
791 | 0 | if ( mpImplWin ) |
792 | 0 | { |
793 | |
|
794 | 0 | mpImplWin->SetBackground( GetControlBackground() ); |
795 | 0 | mpImplWin->SetControlBackground( GetControlBackground() ); |
796 | 0 | mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); |
797 | 0 | mpImplWin->Invalidate(); |
798 | 0 | } |
799 | 0 | } |
800 | 0 | else if ( nType == StateChangedType::Style ) |
801 | 0 | { |
802 | 0 | SetStyle( ImplInitStyle( GetStyle() ) ); |
803 | 0 | mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) != 0 ); |
804 | 0 | bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) != 0; |
805 | 0 | mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode ); |
806 | 0 | } |
807 | 0 | else if( nType == StateChangedType::Mirroring ) |
808 | 0 | { |
809 | 0 | if( mpBtn ) |
810 | 0 | { |
811 | 0 | mpBtn->EnableRTL( IsRTLEnabled() ); |
812 | 0 | ImplInitDropDownButton( mpBtn ); |
813 | 0 | } |
814 | 0 | mpImplLB->EnableRTL( IsRTLEnabled() ); |
815 | 0 | if( mpImplWin ) |
816 | 0 | mpImplWin->EnableRTL( IsRTLEnabled() ); |
817 | 0 | Resize(); |
818 | 0 | } |
819 | |
|
820 | 0 | Control::StateChanged( nType ); |
821 | 0 | } |
822 | | |
823 | | bool ListBox::PreNotify( NotifyEvent& rNEvt ) |
824 | 0 | { |
825 | 0 | bool bDone = false; |
826 | 0 | if ( mpImplLB ) |
827 | 0 | { |
828 | 0 | if( ( rNEvt.GetType() == NotifyEventType::KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) ) |
829 | 0 | { |
830 | 0 | KeyEvent aKeyEvt = *rNEvt.GetKeyEvent(); |
831 | 0 | switch( aKeyEvt.GetKeyCode().GetCode() ) |
832 | 0 | { |
833 | 0 | case KEY_DOWN: |
834 | 0 | { |
835 | 0 | if( mpFloatWin && !mpFloatWin->IsInPopupMode() && |
836 | 0 | aKeyEvt.GetKeyCode().IsMod2() ) |
837 | 0 | { |
838 | 0 | CallEventListeners( VclEventId::DropdownPreOpen ); |
839 | 0 | mpBtn->SetPressed( true ); |
840 | 0 | mpFloatWin->StartFloat( false ); |
841 | 0 | CallEventListeners( VclEventId::DropdownOpen ); |
842 | 0 | bDone = true; |
843 | 0 | } |
844 | 0 | else |
845 | 0 | { |
846 | 0 | bDone = mpImplLB->ProcessKeyInput( aKeyEvt ); |
847 | 0 | } |
848 | 0 | } |
849 | 0 | break; |
850 | 0 | case KEY_UP: |
851 | 0 | { |
852 | 0 | if( mpFloatWin && mpFloatWin->IsInPopupMode() && |
853 | 0 | aKeyEvt.GetKeyCode().IsMod2() ) |
854 | 0 | { |
855 | 0 | mpFloatWin->EndPopupMode(); |
856 | 0 | bDone = true; |
857 | 0 | } |
858 | 0 | else |
859 | 0 | { |
860 | 0 | bDone = mpImplLB->ProcessKeyInput( aKeyEvt ); |
861 | 0 | } |
862 | 0 | } |
863 | 0 | break; |
864 | 0 | case KEY_RETURN: |
865 | 0 | { |
866 | 0 | if( IsInDropDown() ) |
867 | 0 | { |
868 | 0 | mpImplLB->ProcessKeyInput( aKeyEvt ); |
869 | 0 | bDone = true; |
870 | 0 | } |
871 | 0 | } |
872 | 0 | break; |
873 | | |
874 | 0 | default: |
875 | 0 | { |
876 | 0 | bDone = mpImplLB->ProcessKeyInput( aKeyEvt ); |
877 | 0 | } |
878 | 0 | } |
879 | 0 | } |
880 | 0 | else if ( rNEvt.GetType() == NotifyEventType::LOSEFOCUS ) |
881 | 0 | { |
882 | 0 | if ( IsInDropDown() && !HasChildPathFocus( true ) ) |
883 | 0 | mpFloatWin->EndPopupMode(); |
884 | 0 | } |
885 | 0 | else if ( (rNEvt.GetType() == NotifyEventType::COMMAND) && |
886 | 0 | (rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel) && |
887 | 0 | (rNEvt.GetWindow() == mpImplWin) ) |
888 | 0 | { |
889 | 0 | const Point& rMousePos = rNEvt.GetCommandEvent()->GetMousePosPixel(); |
890 | 0 | const tools::Rectangle aWinRect(mpImplWin->GetPosPixel(), mpImplWin->GetSizePixel()); |
891 | 0 | const bool bMousePositionedOverWin = aWinRect.Contains(rMousePos); |
892 | |
|
893 | 0 | MouseWheelBehaviour nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() ); |
894 | 0 | if (bMousePositionedOverWin |
895 | 0 | && ((nWheelBehavior == MouseWheelBehaviour::ALWAYS) |
896 | 0 | || ((nWheelBehavior == MouseWheelBehaviour::FocusOnly) && HasChildPathFocus()))) |
897 | 0 | { |
898 | 0 | bDone = mpImplLB->HandleWheelAsCursorTravel(*rNEvt.GetCommandEvent(), *this); |
899 | 0 | } |
900 | 0 | else |
901 | 0 | { |
902 | 0 | bDone = false; // Don't consume this event, let the default handling take it (i.e. scroll the context) |
903 | 0 | } |
904 | 0 | } |
905 | 0 | } |
906 | | |
907 | 0 | if (rNEvt.GetType() == NotifyEventType::MOUSEMOVE) |
908 | 0 | { |
909 | 0 | const MouseEvent* pMouseEvt = rNEvt.GetMouseEvent(); |
910 | 0 | if (pMouseEvt && (pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow())) |
911 | 0 | { |
912 | | // trigger redraw as mouse over state has changed |
913 | 0 | if (IsNativeControlSupported(ControlType::Listbox, ControlPart::Entire) |
914 | 0 | && !IsNativeControlSupported(ControlType::Listbox, ControlPart::ButtonDown)) |
915 | 0 | { |
916 | 0 | GetWindow(GetWindowType::Border)->Invalidate(); |
917 | 0 | } |
918 | 0 | } |
919 | 0 | } |
920 | |
|
921 | 0 | return bDone || Control::PreNotify( rNEvt ); |
922 | 0 | } |
923 | | |
924 | | void ListBox::Select() |
925 | 0 | { |
926 | 0 | ImplCallEventListenersAndHandler( VclEventId::ListboxSelect, [this] () { maSelectHdl.Call(*this); } ); |
927 | 0 | } |
928 | | |
929 | | void ListBox::DoubleClick() |
930 | 0 | { |
931 | 0 | ImplCallEventListenersAndHandler( VclEventId::ListboxDoubleClick, {} ); |
932 | 0 | } |
933 | | |
934 | | void ListBox::Clear() |
935 | 0 | { |
936 | 0 | if (!mpImplLB) |
937 | 0 | return; |
938 | 0 | mpImplLB->Clear(); |
939 | 0 | if( IsDropDownBox() ) |
940 | 0 | { |
941 | 0 | mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND ); |
942 | 0 | mpImplWin->SetString( OUString() ); |
943 | 0 | Image aImage; |
944 | 0 | mpImplWin->SetImage( aImage ); |
945 | 0 | mpImplWin->Invalidate(); |
946 | 0 | } |
947 | 0 | CallEventListeners( VclEventId::ListboxItemRemoved, reinterpret_cast<void*>(-1) ); |
948 | 0 | } |
949 | | |
950 | | void ListBox::SetNoSelection() |
951 | 0 | { |
952 | 0 | mpImplLB->SetNoSelection(); |
953 | 0 | if( IsDropDownBox() ) |
954 | 0 | { |
955 | 0 | mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND ); |
956 | 0 | mpImplWin->SetString( OUString() ); |
957 | 0 | Image aImage; |
958 | 0 | mpImplWin->SetImage( aImage ); |
959 | 0 | mpImplWin->Invalidate(); |
960 | 0 | } |
961 | 0 | } |
962 | | |
963 | | sal_Int32 ListBox::InsertEntry( const OUString& rStr, sal_Int32 nPos ) |
964 | 0 | { |
965 | 0 | sal_Int32 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList().GetMRUCount(), rStr ); |
966 | 0 | nRealPos = sal::static_int_cast<sal_Int32>(nRealPos - mpImplLB->GetEntryList().GetMRUCount()); |
967 | 0 | CallEventListeners( VclEventId::ListboxItemAdded, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nRealPos)) ); |
968 | 0 | return nRealPos; |
969 | 0 | } |
970 | | |
971 | | sal_Int32 ListBox::InsertEntry( const OUString& rStr, const Image& rImage, sal_Int32 nPos ) |
972 | 0 | { |
973 | 0 | sal_Int32 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList().GetMRUCount(), rStr, rImage ); |
974 | 0 | nRealPos = sal::static_int_cast<sal_Int32>(nRealPos - mpImplLB->GetEntryList().GetMRUCount()); |
975 | 0 | CallEventListeners( VclEventId::ListboxItemAdded, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nRealPos)) ); |
976 | 0 | return nRealPos; |
977 | 0 | } |
978 | | |
979 | | void ListBox::RemoveEntry( sal_Int32 nPos ) |
980 | 0 | { |
981 | 0 | mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList().GetMRUCount() ); |
982 | 0 | CallEventListeners( VclEventId::ListboxItemRemoved, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nPos)) ); |
983 | 0 | } |
984 | | |
985 | | Image ListBox::GetEntryImage( sal_Int32 nPos ) const |
986 | 0 | { |
987 | 0 | if ( mpImplLB && mpImplLB->GetEntryList().HasEntryImage( nPos ) ) |
988 | 0 | return mpImplLB->GetEntryList().GetEntryImage( nPos ); |
989 | 0 | return Image(); |
990 | 0 | } |
991 | | |
992 | | sal_Int32 ListBox::GetEntryPos( std::u16string_view rStr ) const |
993 | 0 | { |
994 | 0 | if (!mpImplLB) |
995 | 0 | return LISTBOX_ENTRY_NOTFOUND; |
996 | 0 | sal_Int32 nPos = mpImplLB->GetEntryList().FindEntry( rStr ); |
997 | 0 | if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
998 | 0 | nPos = nPos - mpImplLB->GetEntryList().GetMRUCount(); |
999 | 0 | return nPos; |
1000 | 0 | } |
1001 | | |
1002 | | OUString ListBox::GetEntry( sal_Int32 nPos ) const |
1003 | 0 | { |
1004 | 0 | if (!mpImplLB) |
1005 | 0 | return OUString(); |
1006 | 0 | return mpImplLB->GetEntryList().GetEntryText( nPos + mpImplLB->GetEntryList().GetMRUCount() ); |
1007 | 0 | } |
1008 | | |
1009 | | sal_Int32 ListBox::GetEntryCount() const |
1010 | 0 | { |
1011 | 0 | if (!mpImplLB) |
1012 | 0 | return 0; |
1013 | 0 | return mpImplLB->GetEntryList().GetEntryCount() - mpImplLB->GetEntryList().GetMRUCount(); |
1014 | 0 | } |
1015 | | |
1016 | | OUString ListBox::GetSelectedEntry(sal_Int32 nIndex) const |
1017 | 0 | { |
1018 | 0 | return GetEntry( GetSelectedEntryPos( nIndex ) ); |
1019 | 0 | } |
1020 | | |
1021 | | sal_Int32 ListBox::GetSelectedEntryCount() const |
1022 | 0 | { |
1023 | 0 | if (!mpImplLB) |
1024 | 0 | return 0; |
1025 | 0 | return mpImplLB->GetEntryList().GetSelectedEntryCount(); |
1026 | 0 | } |
1027 | | |
1028 | | sal_Int32 ListBox::GetSelectedEntryPos( sal_Int32 nIndex ) const |
1029 | 0 | { |
1030 | 0 | if (!mpImplLB) |
1031 | 0 | return LISTBOX_ENTRY_NOTFOUND; |
1032 | | |
1033 | 0 | sal_Int32 nPos = mpImplLB->GetEntryList().GetSelectedEntryPos( nIndex ); |
1034 | 0 | if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
1035 | 0 | { |
1036 | 0 | if ( nPos < mpImplLB->GetEntryList().GetMRUCount() ) |
1037 | 0 | nPos = mpImplLB->GetEntryList().FindEntry( mpImplLB->GetEntryList().GetEntryText( nPos ) ); |
1038 | 0 | nPos = nPos - mpImplLB->GetEntryList().GetMRUCount(); |
1039 | 0 | } |
1040 | 0 | return nPos; |
1041 | 0 | } |
1042 | | |
1043 | | bool ListBox::IsEntryPosSelected( sal_Int32 nPos ) const |
1044 | 0 | { |
1045 | 0 | return mpImplLB->GetEntryList().IsEntryPosSelected( nPos + mpImplLB->GetEntryList().GetMRUCount() ); |
1046 | 0 | } |
1047 | | |
1048 | | void ListBox::SelectEntry( std::u16string_view rStr, bool bSelect ) |
1049 | 0 | { |
1050 | 0 | SelectEntryPos( GetEntryPos( rStr ), bSelect ); |
1051 | 0 | } |
1052 | | |
1053 | | void ListBox::SelectEntryPos( sal_Int32 nPos, bool bSelect ) |
1054 | 0 | { |
1055 | 0 | if (!mpImplLB) |
1056 | 0 | return; |
1057 | | |
1058 | 0 | if ( 0 <= nPos && nPos < mpImplLB->GetEntryList().GetEntryCount() ) |
1059 | 0 | { |
1060 | 0 | sal_Int32 nCurrentPos = mpImplLB->GetCurrentPos(); |
1061 | 0 | mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList().GetMRUCount(), bSelect ); |
1062 | | //Only when bSelect == true, send both Selection & Focus events |
1063 | 0 | if (nCurrentPos != nPos && bSelect) |
1064 | 0 | { |
1065 | 0 | CallEventListeners( VclEventId::ListboxSelect, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nPos))); |
1066 | 0 | if (HasFocus()) |
1067 | 0 | CallEventListeners( VclEventId::ListboxFocus, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nPos))); |
1068 | 0 | } |
1069 | 0 | } |
1070 | 0 | } |
1071 | | |
1072 | | void ListBox::SelectEntriesPos( const std::vector<sal_Int32>& rPositions, bool bSelect ) |
1073 | 0 | { |
1074 | 0 | if (!mpImplLB) |
1075 | 0 | return; |
1076 | | |
1077 | 0 | bool bCallListeners = false; |
1078 | |
|
1079 | 0 | const sal_Int32 nCurrentPos = mpImplLB->GetCurrentPos(); |
1080 | 0 | const auto nEntryCount = mpImplLB->GetEntryList().GetEntryCount(); |
1081 | 0 | const auto nMRUCount = mpImplLB->GetEntryList().GetMRUCount(); |
1082 | |
|
1083 | 0 | for (auto nPos : rPositions) |
1084 | 0 | { |
1085 | 0 | if (0 <= nPos && nPos < nEntryCount) |
1086 | 0 | { |
1087 | 0 | mpImplLB->SelectEntry(nPos + nMRUCount, bSelect); |
1088 | 0 | if (nCurrentPos != nPos && bSelect) |
1089 | 0 | bCallListeners = true; |
1090 | 0 | } |
1091 | 0 | } |
1092 | | |
1093 | | //Only when bSelect == true, send both Selection & Focus events |
1094 | 0 | if (bCallListeners) |
1095 | 0 | { |
1096 | 0 | CallEventListeners(VclEventId::ListboxSelect); |
1097 | 0 | if (HasFocus()) |
1098 | 0 | CallEventListeners(VclEventId::ListboxFocus); |
1099 | 0 | } |
1100 | 0 | } |
1101 | | |
1102 | | void ListBox::SetEntryData( sal_Int32 nPos, void* pNewData ) |
1103 | 0 | { |
1104 | 0 | mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList().GetMRUCount(), pNewData ); |
1105 | 0 | } |
1106 | | |
1107 | | void* ListBox::GetEntryData( sal_Int32 nPos ) const |
1108 | 0 | { |
1109 | 0 | return mpImplLB->GetEntryList().GetEntryData( nPos + mpImplLB->GetEntryList().GetMRUCount() ); |
1110 | 0 | } |
1111 | | |
1112 | | void ListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags ) |
1113 | 0 | { |
1114 | 0 | mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList().GetMRUCount(), nFlags ); |
1115 | 0 | } |
1116 | | |
1117 | | void ListBox::SetTopEntry( sal_Int32 nPos ) |
1118 | 0 | { |
1119 | 0 | mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList().GetMRUCount() ); |
1120 | 0 | } |
1121 | | |
1122 | | sal_Int32 ListBox::GetTopEntry() const |
1123 | 0 | { |
1124 | 0 | sal_Int32 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND; |
1125 | 0 | if ( nPos < mpImplLB->GetEntryList().GetMRUCount() ) |
1126 | 0 | nPos = 0; |
1127 | 0 | return nPos; |
1128 | 0 | } |
1129 | | |
1130 | | bool ListBox::IsTravelSelect() const |
1131 | 0 | { |
1132 | 0 | return mpImplLB->IsTravelSelect(); |
1133 | 0 | } |
1134 | | |
1135 | | bool ListBox::IsInDropDown() const |
1136 | 0 | { |
1137 | | // when the dropdown is dismissed, first mbInPopupMode is set to false, and on the next event iteration then |
1138 | | // mbPopupMode is set to false |
1139 | 0 | return mpFloatWin && mpFloatWin->IsInPopupMode() && mpFloatWin->ImplIsInPrivatePopupMode(); |
1140 | 0 | } |
1141 | | |
1142 | | tools::Rectangle ListBox::GetBoundingRectangle( sal_Int32 nItem ) const |
1143 | 0 | { |
1144 | 0 | tools::Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem ); |
1145 | 0 | tools::Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( *static_cast<vcl::Window*>(const_cast<ListBox *>(this)) ); |
1146 | 0 | aRect.Move( aOffset.Left(), aOffset.Top() ); |
1147 | 0 | return aRect; |
1148 | 0 | } |
1149 | | |
1150 | | void ListBox::EnableMultiSelection( bool bMulti ) |
1151 | 0 | { |
1152 | 0 | mpImplLB->EnableMultiSelection( bMulti ); |
1153 | | |
1154 | | // WB_SIMPLEMODE: |
1155 | | // The MultiListBox behaves just like a normal ListBox |
1156 | | // MultiSelection is possible via corresponding additional keys |
1157 | 0 | bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) != 0; |
1158 | 0 | mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode ); |
1159 | | |
1160 | | // In a MultiSelection, we can't see us travelling without focus |
1161 | 0 | if ( mpFloatWin ) |
1162 | 0 | mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti ); |
1163 | 0 | } |
1164 | | |
1165 | | bool ListBox::IsMultiSelectionEnabled() const |
1166 | 0 | { |
1167 | 0 | return mpImplLB->IsMultiSelectionEnabled(); |
1168 | 0 | } |
1169 | | |
1170 | | void ListBox::SetHighlightColor(const Color& rColor) |
1171 | 0 | { |
1172 | 0 | AllSettings aSettings(GetSettings()); |
1173 | 0 | StyleSettings aStyle(aSettings.GetStyleSettings()); |
1174 | 0 | aStyle.SetHighlightColor(rColor); |
1175 | 0 | aSettings.SetStyleSettings(aStyle); |
1176 | 0 | SetSettings(aSettings); |
1177 | |
|
1178 | 0 | mpImplLB->SetHighlightColor(rColor); |
1179 | 0 | } |
1180 | | |
1181 | | void ListBox::SetHighlightTextColor(const Color& rColor) |
1182 | 0 | { |
1183 | 0 | AllSettings aSettings(GetSettings()); |
1184 | 0 | StyleSettings aStyle(aSettings.GetStyleSettings()); |
1185 | 0 | aStyle.SetHighlightTextColor(rColor); |
1186 | 0 | aSettings.SetStyleSettings(aStyle); |
1187 | 0 | SetSettings(aSettings); |
1188 | |
|
1189 | 0 | mpImplLB->SetHighlightTextColor(rColor); |
1190 | 0 | } |
1191 | | |
1192 | | Size ListBox::CalcMinimumSize() const |
1193 | 0 | { |
1194 | 0 | Size aSz; |
1195 | |
|
1196 | 0 | if (!mpImplLB) |
1197 | 0 | return aSz; |
1198 | | |
1199 | 0 | aSz = CalcSubEditSize(); |
1200 | |
|
1201 | 0 | bool bAddScrollWidth = false; |
1202 | |
|
1203 | 0 | if (IsDropDownBox()) |
1204 | 0 | { |
1205 | 0 | aSz.AdjustHeight(4 ); // add a space between entry and border |
1206 | 0 | aSz.AdjustWidth(4 ); // add a little breathing space |
1207 | 0 | bAddScrollWidth = true; |
1208 | 0 | } |
1209 | 0 | else |
1210 | 0 | bAddScrollWidth = (GetStyle() & WB_VSCROLL) == WB_VSCROLL; |
1211 | |
|
1212 | 0 | if (bAddScrollWidth) |
1213 | 0 | { |
1214 | | // Try native borders; scrollbar size may not be a good indicator |
1215 | | // See how large the edit area inside is to estimate what is needed for the dropdown |
1216 | 0 | ImplControlValue aControlValue; |
1217 | 0 | tools::Rectangle aContent, aBound; |
1218 | 0 | Size aTestSize( 100, 20 ); |
1219 | 0 | tools::Rectangle aArea( Point(), aTestSize ); |
1220 | 0 | if( GetNativeControlRegion( ControlType::Listbox, ControlPart::SubEdit, aArea, ControlState::NONE, |
1221 | 0 | aControlValue, aBound, aContent) ) |
1222 | 0 | { |
1223 | | // use the themes drop down size |
1224 | 0 | aSz.AdjustWidth(aTestSize.Width() - aContent.GetWidth() ); |
1225 | 0 | } |
1226 | 0 | else |
1227 | 0 | aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() ); |
1228 | 0 | } |
1229 | |
|
1230 | 0 | aSz = CalcWindowSize( aSz ); |
1231 | |
|
1232 | 0 | if (IsDropDownBox()) // Check minimum height of dropdown box |
1233 | 0 | { |
1234 | 0 | ImplControlValue aControlValue; |
1235 | 0 | tools::Rectangle aRect( Point( 0, 0 ), aSz ); |
1236 | 0 | tools::Rectangle aContent, aBound; |
1237 | 0 | if( GetNativeControlRegion( ControlType::Listbox, ControlPart::Entire, aRect, ControlState::NONE, |
1238 | 0 | aControlValue, aBound, aContent) ) |
1239 | 0 | { |
1240 | 0 | if( aBound.GetHeight() > aSz.Height() ) |
1241 | 0 | aSz.setHeight( aBound.GetHeight() ); |
1242 | 0 | } |
1243 | 0 | } |
1244 | |
|
1245 | 0 | return aSz; |
1246 | 0 | } |
1247 | | |
1248 | | Size ListBox::CalcSubEditSize() const |
1249 | 0 | { |
1250 | 0 | Size aSz; |
1251 | |
|
1252 | 0 | if (!mpImplLB) |
1253 | 0 | return aSz; |
1254 | | |
1255 | 0 | if ( !IsDropDownBox() ) |
1256 | 0 | aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList().GetEntryCount()); |
1257 | 0 | else |
1258 | 0 | { |
1259 | 0 | aSz.setHeight( mpImplLB->GetEntryHeight() ); |
1260 | | // Size to maximum entry width |
1261 | 0 | aSz.setWidth( mpImplLB->GetMaxEntryWidth() ); |
1262 | |
|
1263 | 0 | if (m_nMaxWidthChars != -1) |
1264 | 0 | { |
1265 | 0 | tools::Long nMaxWidth = m_nMaxWidthChars * approximate_char_width(); |
1266 | 0 | aSz.setWidth( std::min(aSz.Width(), nMaxWidth) ); |
1267 | 0 | } |
1268 | | |
1269 | | // Do not create ultrathin ListBoxes, it doesn't look good |
1270 | 0 | if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() ) |
1271 | 0 | aSz.setWidth( GetSettings().GetStyleSettings().GetScrollBarSize() ); |
1272 | 0 | } |
1273 | |
|
1274 | 0 | return aSz; |
1275 | 0 | } |
1276 | | |
1277 | | Size ListBox::GetOptimalSize() const |
1278 | 0 | { |
1279 | 0 | return CalcMinimumSize(); |
1280 | 0 | } |
1281 | | |
1282 | | Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const |
1283 | 0 | { |
1284 | 0 | Size aSz = rPrefSize; |
1285 | 0 | sal_Int32 nLeft, nTop, nRight, nBottom; |
1286 | 0 | static_cast<vcl::Window*>(const_cast<ListBox *>(this))->GetBorder( nLeft, nTop, nRight, nBottom ); |
1287 | 0 | aSz.AdjustHeight( -(nTop+nBottom) ); |
1288 | 0 | if ( !IsDropDownBox() ) |
1289 | 0 | { |
1290 | 0 | tools::Long nEntryHeight = CalcBlockSize( 1, 1 ).Height(); |
1291 | 0 | tools::Long nLines = aSz.Height() / nEntryHeight; |
1292 | 0 | if ( nLines < 1 ) |
1293 | 0 | nLines = 1; |
1294 | 0 | aSz.setHeight( nLines * nEntryHeight ); |
1295 | 0 | } |
1296 | 0 | else |
1297 | 0 | { |
1298 | 0 | aSz.setHeight( mnDDHeight ); |
1299 | 0 | } |
1300 | 0 | aSz.AdjustHeight(nTop+nBottom ); |
1301 | |
|
1302 | 0 | aSz = CalcWindowSize( aSz ); |
1303 | 0 | return aSz; |
1304 | 0 | } |
1305 | | |
1306 | | Size ListBox::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const |
1307 | 0 | { |
1308 | | // ScrollBars are shown if needed |
1309 | 0 | Size aMinSz = CalcMinimumSize(); |
1310 | | // aMinSz = ImplCalcOutSz( aMinSz ); |
1311 | |
|
1312 | 0 | Size aSz; |
1313 | | |
1314 | | // Height |
1315 | 0 | if ( nLines ) |
1316 | 0 | { |
1317 | 0 | if ( !IsDropDownBox() ) |
1318 | 0 | aSz.setHeight( mpImplLB->CalcSize( nLines ).Height() ); |
1319 | 0 | else |
1320 | 0 | aSz.setHeight( mnDDHeight ); |
1321 | 0 | } |
1322 | 0 | else |
1323 | 0 | aSz.setHeight( aMinSz.Height() ); |
1324 | | |
1325 | | // Width |
1326 | 0 | if ( nColumns ) |
1327 | 0 | aSz.setWidth( nColumns * GetTextWidth( OUString('X') ) ); |
1328 | 0 | else |
1329 | 0 | aSz.setWidth( aMinSz.Width() ); |
1330 | |
|
1331 | 0 | if ( IsDropDownBox() ) |
1332 | 0 | aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() ); |
1333 | |
|
1334 | 0 | if ( !IsDropDownBox() ) |
1335 | 0 | { |
1336 | 0 | if ( aSz.Width() < aMinSz.Width() ) |
1337 | 0 | aSz.AdjustHeight(GetSettings().GetStyleSettings().GetScrollBarSize() ); |
1338 | 0 | if ( aSz.Height() < aMinSz.Height() ) |
1339 | 0 | aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() ); |
1340 | 0 | } |
1341 | |
|
1342 | 0 | aSz = CalcWindowSize( aSz ); |
1343 | 0 | return aSz; |
1344 | 0 | } |
1345 | | |
1346 | | void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const |
1347 | 0 | { |
1348 | 0 | float nCharWidth = approximate_char_width(); |
1349 | 0 | if ( !IsDropDownBox() ) |
1350 | 0 | { |
1351 | 0 | Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel(); |
1352 | 0 | rnCols = static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth); |
1353 | 0 | rnLines = static_cast<sal_uInt16>(aOutSz.Height()/mpImplLB->GetEntryHeightWithMargin()); |
1354 | 0 | } |
1355 | 0 | else |
1356 | 0 | { |
1357 | 0 | Size aOutSz = mpImplWin->GetOutputSizePixel(); |
1358 | 0 | rnCols = static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth); |
1359 | 0 | rnLines = 1; |
1360 | 0 | } |
1361 | 0 | } |
1362 | | |
1363 | | void ListBox::SetReadOnly( bool bReadOnly ) |
1364 | 0 | { |
1365 | 0 | if ( mpImplLB->IsReadOnly() != bReadOnly ) |
1366 | 0 | { |
1367 | 0 | mpImplLB->SetReadOnly( bReadOnly ); |
1368 | 0 | CompatStateChanged( StateChangedType::ReadOnly ); |
1369 | 0 | } |
1370 | 0 | } |
1371 | | |
1372 | | bool ListBox::IsReadOnly() const |
1373 | 0 | { |
1374 | 0 | return mpImplLB->IsReadOnly(); |
1375 | 0 | } |
1376 | | |
1377 | | void ListBox::SetSeparatorPos( sal_Int32 n ) |
1378 | 0 | { |
1379 | 0 | mpImplLB->SetSeparatorPos( n ); |
1380 | 0 | } |
1381 | | |
1382 | | sal_Int32 ListBox::GetSeparatorPos() const |
1383 | 0 | { |
1384 | 0 | return mpImplLB->GetSeparatorPos(); |
1385 | 0 | } |
1386 | | |
1387 | | void ListBox::AddSeparator( sal_Int32 n ) |
1388 | 0 | { |
1389 | 0 | mpImplLB->AddSeparator( n ); |
1390 | 0 | } |
1391 | | |
1392 | | sal_uInt16 ListBox::GetDisplayLineCount() const |
1393 | 0 | { |
1394 | 0 | return mpImplLB->GetDisplayLineCount(); |
1395 | 0 | } |
1396 | | |
1397 | | tools::Rectangle ListBox::GetDropDownPosSizePixel() const |
1398 | 0 | { |
1399 | 0 | return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative(*this) : tools::Rectangle(); |
1400 | 0 | } |
1401 | | |
1402 | | const Wallpaper& ListBox::GetDisplayBackground() const |
1403 | 0 | { |
1404 | | // !!! Recursion does not occur because the ImplListBox is initialized by default |
1405 | | // to a non-transparent color in Window::ImplInitData |
1406 | 0 | return mpImplLB->GetDisplayBackground(); |
1407 | 0 | } |
1408 | | |
1409 | | void ListBox::setMaxWidthChars(sal_Int32 nWidth) |
1410 | 0 | { |
1411 | 0 | if (nWidth != m_nMaxWidthChars) |
1412 | 0 | { |
1413 | 0 | m_nMaxWidthChars = nWidth; |
1414 | 0 | queue_resize(); |
1415 | 0 | } |
1416 | 0 | } |
1417 | | |
1418 | | bool ListBox::set_property(const OUString &rKey, const OUString &rValue) |
1419 | 0 | { |
1420 | 0 | if (rKey == "active") |
1421 | 0 | SelectEntryPos(rValue.toInt32()); |
1422 | 0 | else if (rKey == "max-width-chars") |
1423 | 0 | setMaxWidthChars(rValue.toInt32()); |
1424 | 0 | else if (rKey == "can-focus") |
1425 | 0 | { |
1426 | | // as far as I can see in Gtk, setting a ComboBox as can.focus means |
1427 | | // the focus gets stuck in it, so try here to behave like gtk does |
1428 | | // with the settings that work, i.e. can.focus of false doesn't |
1429 | | // set the hard WB_NOTABSTOP |
1430 | 0 | WinBits nBits = GetStyle(); |
1431 | 0 | nBits &= ~(WB_TABSTOP|WB_NOTABSTOP); |
1432 | 0 | if (toBool(rValue)) |
1433 | 0 | nBits |= WB_TABSTOP; |
1434 | 0 | SetStyle(nBits); |
1435 | 0 | } |
1436 | 0 | else |
1437 | 0 | return Control::set_property(rKey, rValue); |
1438 | 0 | return true; |
1439 | 0 | } |
1440 | | |
1441 | | FactoryFunction ListBox::GetUITestFactory() const |
1442 | 0 | { |
1443 | 0 | return ListBoxUIObject::create; |
1444 | 0 | } |
1445 | | |
1446 | | void ListBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) |
1447 | 0 | { |
1448 | 0 | Control::DumpAsPropertyTree(rJsonWriter); |
1449 | |
|
1450 | 0 | { |
1451 | 0 | auto entriesNode = rJsonWriter.startArray("entries"); |
1452 | 0 | for (int i = 0; i < GetEntryCount(); ++i) |
1453 | 0 | { |
1454 | 0 | rJsonWriter.putSimpleValue(GetEntry(i)); |
1455 | 0 | } |
1456 | 0 | } |
1457 | |
|
1458 | 0 | rJsonWriter.put("selectedCount", GetSelectedEntryCount()); |
1459 | |
|
1460 | 0 | { |
1461 | 0 | auto entriesNode = rJsonWriter.startArray("selectedEntries"); |
1462 | 0 | for (int i = 0; i < GetSelectedEntryCount(); ++i) |
1463 | 0 | { |
1464 | 0 | rJsonWriter.putSimpleValue(OUString::number(GetSelectedEntryPos(i))); |
1465 | 0 | } |
1466 | 0 | } |
1467 | 0 | } |
1468 | | |
1469 | | MultiListBox::MultiListBox( vcl::Window* pParent, WinBits nStyle ) : |
1470 | 0 | ListBox( WindowType::MULTILISTBOX ) |
1471 | 0 | { |
1472 | 0 | ImplInit( pParent, nStyle ); |
1473 | 0 | EnableMultiSelection( true ); |
1474 | 0 | } Unexecuted instantiation: MultiListBox::MultiListBox(vcl::Window*, long) Unexecuted instantiation: MultiListBox::MultiListBox(vcl::Window*, long) |
1475 | | |
1476 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |