LibreOffice Module vcl (master)  1
imp_listbox.cxx
Go to the documentation of this file.
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 <memory>
21 
22 #include <vcl/svapp.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/scrbar.hxx>
26 #include <vcl/toolkit/lstbox.hxx>
27 #include <vcl/i18nhelp.hxx>
28 #include <vcl/naturalsort.hxx>
29 
30 #include <listbox.hxx>
31 #include <svdata.hxx>
32 #include <window.h>
33 
34 #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 
36 #include <sal/log.hxx>
37 #include <o3tl/safeint.hxx>
38 #include <o3tl/string_view.hxx>
39 #include <osl/diagnose.h>
40 #include <comphelper/string.hxx>
42 
43 #include <limits>
44 
45 #define MULTILINE_ENTRY_DRAW_FLAGS ( DrawTextFlags::WordBreak | DrawTextFlags::MultiLine | DrawTextFlags::VCenter )
46 
47 using namespace ::com::sun::star;
48 
49 constexpr tools::Long gnBorder = 1;
50 
52 {
53  pButton->SetSymbol( SymbolType::SPIN_DOWN );
54 
57  pButton->SetBackground();
58 }
59 
61 {
62  mpWindow = pWindow;
65  mnImages = 0;
67 
68  mnMRUCount = 0;
69  mnMaxMRUCount = 0;
70 }
71 
73 {
74  Clear();
75 }
76 
78 {
79  mnImages = 0;
80  maEntries.clear();
81 }
82 
84 {
85  Clear();
86  mpWindow.clear();
87 }
88 
89 void ImplEntryList::SelectEntry( sal_Int32 nPos, bool bSelect )
90 {
91  if (0 <= nPos && o3tl::make_unsigned(nPos) < maEntries.size())
92  {
93  std::vector<std::unique_ptr<ImplEntryType> >::iterator iter = maEntries.begin()+nPos;
94 
95  if ( ( (*iter)->mbIsSelected != bSelect ) &&
97  {
98  (*iter)->mbIsSelected = bSelect;
100  maSelectionChangedHdl.Call( nPos );
101  }
102  }
103 }
104 
105 namespace
106 {
108  {
111  Application::GetSettings().GetLanguageTag().getLocale());
112  return gSorter;
113  };
114 }
115 
116 namespace vcl
117 {
118  sal_Int32 NaturalSortCompare(const OUString &rA, const OUString &rB)
119  {
120  const comphelper::string::NaturalStringSorter &rSorter = GetSorter();
121  return rSorter.compare(rA, rB);
122  }
123 }
124 
125 sal_Int32 ImplEntryList::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort )
126 {
127  assert(nPos >= 0);
128  assert(maEntries.size() < LISTBOX_MAX_ENTRIES);
129 
130  if ( !!pNewEntry->maImage )
131  mnImages++;
132 
133  sal_Int32 insPos = 0;
134  const sal_Int32 nEntriesSize = static_cast<sal_Int32>(maEntries.size());
135 
136  if ( !bSort || maEntries.empty())
137  {
138  if (0 <= nPos && nPos < nEntriesSize)
139  {
140  insPos = nPos;
141  maEntries.insert( maEntries.begin() + nPos, std::unique_ptr<ImplEntryType>(pNewEntry) );
142  }
143  else
144  {
145  insPos = nEntriesSize;
146  maEntries.push_back(std::unique_ptr<ImplEntryType>(pNewEntry));
147  }
148  }
149  else
150  {
151  const comphelper::string::NaturalStringSorter &rSorter = GetSorter();
152 
153  const OUString& rStr = pNewEntry->maStr;
154 
155  ImplEntryType* pTemp = GetEntry( nEntriesSize-1 );
156 
157  try
158  {
159  sal_Int32 nComp = rSorter.compare(rStr, pTemp->maStr);
160 
161  // fast insert for sorted data
162  if ( nComp >= 0 )
163  {
164  insPos = nEntriesSize;
165  maEntries.push_back(std::unique_ptr<ImplEntryType>(pNewEntry));
166  }
167  else
168  {
169  pTemp = GetEntry( mnMRUCount );
170 
171  nComp = rSorter.compare(rStr, pTemp->maStr);
172  if ( nComp <= 0 )
173  {
174  insPos = 0;
175  maEntries.insert(maEntries.begin(), std::unique_ptr<ImplEntryType>(pNewEntry));
176  }
177  else
178  {
179  sal_uLong nLow = mnMRUCount;
180  sal_uLong nHigh = maEntries.size()-1;
181  sal_Int32 nMid;
182 
183  // binary search
184  do
185  {
186  nMid = static_cast<sal_Int32>((nLow + nHigh) / 2);
187  pTemp = GetEntry( nMid );
188 
189  nComp = rSorter.compare(rStr, pTemp->maStr);
190 
191  if ( nComp < 0 )
192  nHigh = nMid-1;
193  else
194  {
195  if ( nComp > 0 )
196  nLow = nMid + 1;
197  else
198  break;
199  }
200  }
201  while ( nLow <= nHigh );
202 
203  if ( nComp >= 0 )
204  nMid++;
205 
206  insPos = nMid;
207  maEntries.insert(maEntries.begin()+nMid, std::unique_ptr<ImplEntryType>(pNewEntry));
208  }
209  }
210  }
211  catch (uno::RuntimeException& )
212  {
213  // XXX this is arguable, if the exception occurred because pNewEntry is
214  // garbage you wouldn't insert it. If the exception occurred because the
215  // Collator implementation is garbage then give the user a chance to see
216  // his stuff
217  insPos = 0;
218  maEntries.insert(maEntries.begin(), std::unique_ptr<ImplEntryType>(pNewEntry));
219  }
220 
221  }
222 
223  return insPos;
224 }
225 
226 void ImplEntryList::RemoveEntry( sal_Int32 nPos )
227 {
228  if (0 <= nPos && o3tl::make_unsigned(nPos) < maEntries.size())
229  {
230  std::vector<std::unique_ptr<ImplEntryType> >::iterator iter = maEntries.begin()+ nPos;
231 
232  if ( !!(*iter)->maImage )
233  mnImages--;
234 
235  maEntries.erase(iter);
236  }
237 }
238 
239 sal_Int32 ImplEntryList::FindEntry( std::u16string_view rString, bool bSearchMRUArea ) const
240 {
241  const sal_Int32 nEntries = static_cast<sal_Int32>(maEntries.size());
242  for ( sal_Int32 n = bSearchMRUArea ? 0 : GetMRUCount(); n < nEntries; n++ )
243  {
244  OUString aComp( vcl::I18nHelper::filterFormattingChars( maEntries[n]->maStr ) );
245  if ( aComp == rString )
246  return n;
247  }
248  return LISTBOX_ENTRY_NOTFOUND;
249 }
250 
251 sal_Int32 ImplEntryList::FindMatchingEntry( const OUString& rStr, sal_Int32 nStart, bool bLazy ) const
252 {
253  sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
254  sal_Int32 nEntryCount = GetEntryCount();
255 
256  const vcl::I18nHelper& rI18nHelper = mpWindow->GetSettings().GetLocaleI18nHelper();
257  for ( sal_Int32 n = nStart; n < nEntryCount; )
258  {
259  ImplEntryType* pImplEntry = GetEntry( n );
260  bool bMatch;
261  if ( bLazy )
262  {
263  bMatch = rI18nHelper.MatchString( rStr, pImplEntry->maStr );
264  }
265  else
266  {
267  bMatch = pImplEntry->maStr.startsWith(rStr);
268  }
269  if ( bMatch )
270  {
271  nPos = n;
272  break;
273  }
274 
275  n++;
276  }
277 
278  return nPos;
279 }
280 
281 tools::Long ImplEntryList::GetAddedHeight( sal_Int32 i_nEndIndex, sal_Int32 i_nBeginIndex ) const
282 {
283  tools::Long nHeight = 0;
284  sal_Int32 nStart = std::min(i_nEndIndex, i_nBeginIndex);
285  sal_Int32 nStop = std::max(i_nEndIndex, i_nBeginIndex);
286  sal_Int32 nEntryCount = GetEntryCount();
287  if( 0 <= nStop && nStop != LISTBOX_ENTRY_NOTFOUND && nEntryCount != 0 )
288  {
289  // sanity check
290  if( nStop > nEntryCount-1 )
291  nStop = nEntryCount-1;
292  if (nStart < 0)
293  nStart = 0;
294  else if( nStart > nEntryCount-1 )
295  nStart = nEntryCount-1;
296 
297  sal_Int32 nIndex = nStart;
298  while( nIndex != LISTBOX_ENTRY_NOTFOUND && nIndex < nStop )
299  {
300  tools::Long nPosHeight = GetEntryPtr( nIndex )->getHeightWithMargin();
301  if (nHeight > ::std::numeric_limits<tools::Long>::max() - nPosHeight)
302  {
303  SAL_WARN( "vcl", "ImplEntryList::GetAddedHeight: truncated");
304  break;
305  }
306  nHeight += nPosHeight;
307  nIndex++;
308  }
309  }
310  else
311  nHeight = 0;
312  return i_nEndIndex > i_nBeginIndex ? nHeight : -nHeight;
313 }
314 
316 {
317  ImplEntryType* pImplEntry = GetEntry( nPos );
318  return pImplEntry ? pImplEntry->getHeightWithMargin() : 0;
319 }
320 
321 OUString ImplEntryList::GetEntryText( sal_Int32 nPos ) const
322 {
323  OUString aEntryText;
324  ImplEntryType* pImplEntry = GetEntry( nPos );
325  if ( pImplEntry )
326  aEntryText = pImplEntry->maStr;
327  return aEntryText;
328 }
329 
330 bool ImplEntryList::HasEntryImage( sal_Int32 nPos ) const
331 {
332  bool bImage = false;
333  ImplEntryType* pImplEntry = GetEntry( nPos );
334  if ( pImplEntry )
335  bImage = !!pImplEntry->maImage;
336  return bImage;
337 }
338 
339 Image ImplEntryList::GetEntryImage( sal_Int32 nPos ) const
340 {
341  Image aImage;
342  ImplEntryType* pImplEntry = GetEntry( nPos );
343  if ( pImplEntry )
344  aImage = pImplEntry->maImage;
345  return aImage;
346 }
347 
348 void ImplEntryList::SetEntryData( sal_Int32 nPos, void* pNewData )
349 {
350  ImplEntryType* pImplEntry = GetEntry( nPos );
351  if ( pImplEntry )
352  pImplEntry->mpUserData = pNewData;
353 }
354 
355 void* ImplEntryList::GetEntryData( sal_Int32 nPos ) const
356 {
357  ImplEntryType* pImplEntry = GetEntry( nPos );
358  return pImplEntry ? pImplEntry->mpUserData : nullptr;
359 }
360 
361 void ImplEntryList::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
362 {
363  ImplEntryType* pImplEntry = GetEntry( nPos );
364  if ( pImplEntry )
365  pImplEntry->mnFlags = nFlags;
366 }
367 
369 {
370  sal_Int32 nSelCount = 0;
371  for ( sal_Int32 n = GetEntryCount(); n; )
372  {
373  ImplEntryType* pImplEntry = GetEntry( --n );
374  if ( pImplEntry->mbIsSelected )
375  nSelCount++;
376  }
377  return nSelCount;
378 }
379 
380 OUString ImplEntryList::GetSelectedEntry( sal_Int32 nIndex ) const
381 {
382  return GetEntryText( GetSelectedEntryPos( nIndex ) );
383 }
384 
385 sal_Int32 ImplEntryList::GetSelectedEntryPos( sal_Int32 nIndex ) const
386 {
387  sal_Int32 nSelEntryPos = LISTBOX_ENTRY_NOTFOUND;
388  sal_Int32 nSel = 0;
389  sal_Int32 nEntryCount = GetEntryCount();
390 
391  for ( sal_Int32 n = 0; n < nEntryCount; n++ )
392  {
393  ImplEntryType* pImplEntry = GetEntry( n );
394  if ( pImplEntry->mbIsSelected )
395  {
396  if ( nSel == nIndex )
397  {
398  nSelEntryPos = n;
399  break;
400  }
401  nSel++;
402  }
403  }
404 
405  return nSelEntryPos;
406 }
407 
408 bool ImplEntryList::IsEntryPosSelected( sal_Int32 nIndex ) const
409 {
410  ImplEntryType* pImplEntry = GetEntry( nIndex );
411  return pImplEntry && pImplEntry->mbIsSelected;
412 }
413 
414 bool ImplEntryList::IsEntrySelectable( sal_Int32 nPos ) const
415 {
416  ImplEntryType* pImplEntry = GetEntry( nPos );
417  return pImplEntry == nullptr || ((pImplEntry->mnFlags & ListBoxEntryFlags::DisableSelection) == ListBoxEntryFlags::NONE);
418 }
419 
420 sal_Int32 ImplEntryList::FindFirstSelectable( sal_Int32 nPos, bool bForward /* = true */ ) const
421 {
422  if( IsEntrySelectable( nPos ) )
423  return nPos;
424 
425  if( bForward )
426  {
427  for( nPos = nPos + 1; nPos < GetEntryCount(); nPos++ )
428  {
429  if( IsEntrySelectable( nPos ) )
430  return nPos;
431  }
432  }
433  else
434  {
435  while( nPos )
436  {
437  nPos--;
438  if( IsEntrySelectable( nPos ) )
439  return nPos;
440  }
441  }
442 
443  return LISTBOX_ENTRY_NOTFOUND;
444 }
445 
447  Control( pParent, 0 ),
448  maEntryList( this ),
449  maQuickSelectionEngine( *this )
450 {
451 
452  mnTop = 0;
453  mnLeft = 0;
454  mnSelectModifier = 0;
456  mbTrack = false;
457  mbTravelSelect = false;
458  mbTrackingSelect = false;
459  mbSelectionChanged = false;
460  mbMouseMoveSelect = false;
461  mbMulti = false;
462  mbGrabFocus = false;
463  mbUserDrawEnabled = false;
464  mbInUserDraw = false;
465  mbReadOnly = false;
466  mbHasFocusRect = false;
467  mbRight = ( nWinStyle & WB_RIGHT );
468  mbCenter = ( nWinStyle & WB_CENTER );
469  mbSimpleMode = ( nWinStyle & WB_SIMPLEMODE );
470  mbSort = ( nWinStyle & WB_SORT );
471  mbIsDropdown = ( nWinStyle & WB_DROPDOWN );
472  mbEdgeBlending = false;
473 
476 
477  GetOutDev()->SetLineColor();
479  SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
480 
482  ImplCalcMetrics();
483 }
484 
486 {
487  disposeOnce();
488 }
489 
491 {
494 }
495 
497 {
498  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
499 
500  ApplyControlFont(rRenderContext, rStyleSettings.GetFieldFont());
501  ApplyControlForeground(rRenderContext, rStyleSettings.GetFieldTextColor());
502 
503  if (IsControlBackground())
504  rRenderContext.SetBackground(GetControlBackground());
505  else
506  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
507 }
508 
510 {
511  mnMaxWidth = 0;
512  mnMaxTxtWidth = 0;
513  mnMaxImgWidth = 0;
514  mnMaxImgTxtWidth= 0;
515  mnMaxImgHeight = 0;
516 
517  mnTextHeight = static_cast<sal_uInt16>(GetTextHeight());
520 
522  mnMaxHeight = static_cast<sal_uInt16>(maUserItemSize.Height());
523  if ( maUserItemSize.Width() > mnMaxWidth )
524  mnMaxWidth= static_cast<sal_uInt16>(maUserItemSize.Width());
525 
526  for ( sal_Int32 n = maEntryList.GetEntryCount(); n; )
527  {
529  ImplUpdateEntryMetrics( *pEntry );
530  }
531 
533  {
535  maFocusRect.SetSize( aSz );
536  }
537 }
538 
540 {
541  maEntryList.Clear();
542 
544  mnMaxWidth = 0;
545  mnMaxTxtWidth = 0;
546  mnMaxImgTxtWidth= 0;
547  mnMaxImgWidth = 0;
548  mnMaxImgHeight = 0;
549  mnTop = 0;
550  mnLeft = 0;
552 
555 
556  Invalidate();
557 }
558 
560 {
562  maUserItemSize = rSz;
563  ImplCalcMetrics();
564 }
565 
566 namespace {
567 
568 struct ImplEntryMetrics
569 {
570  bool bText;
571  bool bImage;
572  tools::Long nEntryWidth;
573  tools::Long nEntryHeight;
574  tools::Long nTextWidth;
575  tools::Long nImgWidth;
576  tools::Long nImgHeight;
577 };
578 
579 }
580 
582 {
584 }
585 
587 {
588  if (maStrGlyphs.IsValid())
589  // Use pre-calculated result.
590  return &maStrGlyphs;
591 
592  std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout(
593  maStr, 0, maStr.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
594  if (!pLayout)
595  return nullptr;
596 
597  // Remember the calculation result.
598  maStrGlyphs = pLayout->GetGlyphs();
599 
600  return &maStrGlyphs;
601 }
602 
604 {
605  ImplEntryMetrics aMetrics;
606  aMetrics.bText = !rEntry.maStr.isEmpty();
607  aMetrics.bImage = !!rEntry.maImage;
608  aMetrics.nEntryWidth = 0;
609  aMetrics.nEntryHeight = 0;
610  aMetrics.nTextWidth = 0;
611  aMetrics.nImgWidth = 0;
612  aMetrics.nImgHeight = 0;
613 
614  if ( aMetrics.bText )
615  {
617  {
618  // multiline case
619  Size aCurSize( PixelToLogic( GetSizePixel() ) );
620  // set the current size to a large number
621  // GetTextRect should shrink it to the actual size
622  aCurSize.setHeight( 0x7fffff );
623  tools::Rectangle aTextRect( Point( 0, 0 ), aCurSize );
624  aTextRect = GetTextRect( aTextRect, rEntry.maStr, DrawTextFlags::WordBreak | DrawTextFlags::MultiLine );
625  aMetrics.nTextWidth = aTextRect.GetWidth();
626  if( aMetrics.nTextWidth > mnMaxTxtWidth )
627  mnMaxTxtWidth = aMetrics.nTextWidth;
628  aMetrics.nEntryWidth = mnMaxTxtWidth;
629  aMetrics.nEntryHeight = aTextRect.GetHeight() + gnBorder;
630  }
631  else
632  {
633  // normal single line case
634  const SalLayoutGlyphs* pGlyphs = rEntry.GetTextGlyphs(GetOutDev());
635  aMetrics.nTextWidth
636  = static_cast<sal_uInt16>(GetTextWidth(rEntry.maStr, 0, -1, nullptr, pGlyphs));
637  if( aMetrics.nTextWidth > mnMaxTxtWidth )
638  mnMaxTxtWidth = aMetrics.nTextWidth;
639  aMetrics.nEntryWidth = mnMaxTxtWidth;
640  aMetrics.nEntryHeight = mnTextHeight + gnBorder;
641  }
642  }
643  if ( aMetrics.bImage )
644  {
645  Size aImgSz = rEntry.maImage.GetSizePixel();
646  aMetrics.nImgWidth = static_cast<sal_uInt16>(CalcZoom( aImgSz.Width() ));
647  aMetrics.nImgHeight = static_cast<sal_uInt16>(CalcZoom( aImgSz.Height() ));
648 
649  if( aMetrics.nImgWidth > mnMaxImgWidth )
650  mnMaxImgWidth = aMetrics.nImgWidth;
651  if( aMetrics.nImgHeight > mnMaxImgHeight )
652  mnMaxImgHeight = aMetrics.nImgHeight;
653 
654  mnMaxImgTxtWidth = std::max( mnMaxImgTxtWidth, aMetrics.nTextWidth );
655  aMetrics.nEntryHeight = std::max( aMetrics.nImgHeight, aMetrics.nEntryHeight );
656 
657  }
658 
659  bool bIsUserDrawEnabled = IsUserDrawEnabled();
660  if (bIsUserDrawEnabled || aMetrics.bImage)
661  {
662  aMetrics.nEntryWidth = std::max( aMetrics.nImgWidth, maUserItemSize.Width() );
663  if (!bIsUserDrawEnabled && aMetrics.bText)
664  aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE;
665  aMetrics.nEntryHeight = std::max( std::max( mnMaxImgHeight, maUserItemSize.Height() ) + 2,
666  aMetrics.nEntryHeight );
667  }
668 
669  if (!aMetrics.bText && !aMetrics.bImage && !bIsUserDrawEnabled)
670  {
671  // entries which have no (aka an empty) text, and no image,
672  // and are not user-drawn, should be shown nonetheless
673  aMetrics.nEntryHeight = mnTextHeight + gnBorder;
674  }
675 
676  if ( aMetrics.nEntryWidth > mnMaxWidth )
677  mnMaxWidth = aMetrics.nEntryWidth;
678  if ( aMetrics.nEntryHeight > mnMaxHeight )
679  mnMaxHeight = aMetrics.nEntryHeight;
680 
681  rEntry.mnHeight = aMetrics.nEntryHeight;
682 }
683 
685 {
686  if ( !IsTravelSelect() && GetEntryList().GetMaxMRUCount() )
687  {
688  // Insert the selected entry as MRU, if not already first MRU
689  sal_Int32 nSelected = GetEntryList().GetSelectedEntryPos( 0 );
690  sal_Int32 nMRUCount = GetEntryList().GetMRUCount();
691  OUString aSelected = GetEntryList().GetEntryText( nSelected );
692  sal_Int32 nFirstMatchingEntryPos = GetEntryList().FindEntry( aSelected, true );
693  if ( nFirstMatchingEntryPos || !nMRUCount )
694  {
695  bool bSelectNewEntry = false;
696  if ( nFirstMatchingEntryPos < nMRUCount )
697  {
698  RemoveEntry( nFirstMatchingEntryPos );
699  nMRUCount--;
700  if ( nFirstMatchingEntryPos == nSelected )
701  bSelectNewEntry = true;
702  }
703  else if ( nMRUCount == GetEntryList().GetMaxMRUCount() )
704  {
705  RemoveEntry( nMRUCount - 1 );
706  nMRUCount--;
707  }
708 
710 
711  ImplEntryType* pNewEntry = new ImplEntryType( aSelected );
712  pNewEntry->mbIsSelected = bSelectNewEntry;
713  GetEntryList().InsertEntry( 0, pNewEntry, false );
714  ImplUpdateEntryMetrics( *pNewEntry );
715  GetEntryList().SetMRUCount( ++nMRUCount );
716  SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
717  maMRUChangedHdl.Call( nullptr );
718  }
719  }
720 
721  maSelectHdl.Call( nullptr );
722  mbSelectionChanged = false;
723 }
724 
725 sal_Int32 ImplListBoxWindow::InsertEntry(sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort)
726 {
727  assert(nPos >= 0);
729 
731  sal_Int32 nNewPos = maEntryList.InsertEntry( nPos, pNewEntry, bSort );
732 
733  if( GetStyle() & WB_WORDBREAK )
735 
736  ImplUpdateEntryMetrics( *pNewEntry );
737  return nNewPos;
738 }
739 
740 sal_Int32 ImplListBoxWindow::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry )
741 {
742  return InsertEntry(nPos, pNewEntry, mbSort);
743 }
744 
745 void ImplListBoxWindow::RemoveEntry( sal_Int32 nPos )
746 {
748  maEntryList.RemoveEntry( nPos );
751  ImplCalcMetrics();
752 }
753 
755 {
756  maEntryList.SetEntryFlags( nPos, nFlags );
757  ImplEntryType* pEntry = maEntryList.GetMutableEntryPtr( nPos );
758  if( pEntry )
759  ImplUpdateEntryMetrics( *pEntry );
760 }
761 
763 {
764  if ( mbHasFocusRect )
765  HideFocus();
767  mbHasFocusRect = true;
768 }
769 
771 {
772  if ( mbHasFocusRect )
773  {
774  HideFocus();
775  mbHasFocusRect = false;
776  }
777 }
778 
779 sal_Int32 ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const
780 {
781  tools::Long nY = gnBorder;
782 
783  sal_Int32 nSelect = mnTop;
784  const ImplEntryType* pEntry = maEntryList.GetEntryPtr( nSelect );
785  while (pEntry)
786  {
787  tools::Long nEntryHeight = pEntry->getHeightWithMargin();
788  if (rPoint.Y() <= nEntryHeight + nY)
789  break;
790  nY += nEntryHeight;
791  pEntry = maEntryList.GetEntryPtr( ++nSelect );
792  }
793  if( pEntry == nullptr )
794  nSelect = LISTBOX_ENTRY_NOTFOUND;
795 
796  return nSelect;
797 }
798 
799 bool ImplListBoxWindow::IsVisible( sal_Int32 i_nEntry ) const
800 {
801  bool bRet = false;
802 
803  if( i_nEntry >= mnTop )
804  {
805  if( maEntryList.GetAddedHeight( i_nEntry, mnTop ) <
806  PixelToLogic( GetSizePixel() ).Height() )
807  {
808  bRet = true;
809  }
810  }
811 
812  return bRet;
813 }
814 
816 {
818  return mnMaxHeight + nMargin;
819 }
820 
822 {
823  sal_Int32 nPos = mnTop;
824  tools::Long nWindowHeight = GetSizePixel().Height();
825  sal_Int32 nCount = maEntryList.GetEntryCount();
826  tools::Long nDiff;
827  for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = maEntryList.GetAddedHeight( nPos, mnTop ) )
828  nPos++;
829 
830  if( nDiff > nWindowHeight && nPos > mnTop )
831  nPos--;
832 
833  if( nPos >= nCount )
834  nPos = nCount-1;
835 
836  return nPos;
837 }
838 
840 {
841  mbMouseMoveSelect = false; // only till the first MouseButtonDown
843 
844  if ( !IsReadOnly() )
845  {
846  if( rMEvt.GetClicks() == 1 )
847  {
848  sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
849  if( nSelect != LISTBOX_ENTRY_NOTFOUND )
850  {
853  else
855 
856  mnCurrentPos = nSelect;
857  mbTrackingSelect = true;
858  bool bCurPosChange = (mnCurrentPos != nSelect);
859  (void)SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ,bCurPosChange);
860  mbTrackingSelect = false;
861  if ( mbGrabFocus )
862  GrabFocus();
863 
865  }
866  }
867  if( rMEvt.GetClicks() == 2 )
868  {
869  maDoubleClickHdl.Call( this );
870  }
871  }
872  else // if ( mbGrabFocus )
873  {
874  GrabFocus();
875  }
876 }
877 
879 {
881  return;
882 
884  if( !aRect.Contains( rMEvt.GetPosPixel() ) )
885  return;
886 
887  if ( IsMouseMoveSelect() )
888  {
889  sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
890  if( nSelect == LISTBOX_ENTRY_NOTFOUND )
891  nSelect = maEntryList.GetEntryCount() - 1;
892  nSelect = std::min( nSelect, GetLastVisibleEntry() );
893  nSelect = std::min( nSelect, static_cast<sal_Int32>( maEntryList.GetEntryCount() - 1 ) );
894  // Select only visible Entries with MouseMove, otherwise Tracking...
895  if ( IsVisible( nSelect ) &&
896  maEntryList.IsEntrySelectable( nSelect ) &&
897  ( ( nSelect != mnCurrentPos ) || !GetEntryList().GetSelectedEntryCount() || ( nSelect != GetEntryList().GetSelectedEntryPos( 0 ) ) ) )
898  {
899  mbTrackingSelect = true;
900  if ( SelectEntries( nSelect, LET_TRACKING ) )
901  {
902  // When list box selection change by mouse move, notify
903  // VclEventId::ListboxSelect vcl event.
904  maListItemSelectHdl.Call(nullptr);
905  }
906  mbTrackingSelect = false;
907  }
908  }
909 
910  // if the DD button was pressed and someone moved into the ListBox
911  // with the mouse button pressed...
912  if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() )
913  {
916  else
918 
920  }
921 }
922 
924 {
925  while ( GetEntryList().GetSelectedEntryCount() )
926  {
927  sal_Int32 nS = GetEntryList().GetSelectedEntryPos( 0 );
928  SelectEntry( nS, false );
929  }
930 }
931 
932 void ImplListBoxWindow::SelectEntry( sal_Int32 nPos, bool bSelect )
933 {
934  if( (maEntryList.IsEntryPosSelected( nPos ) == bSelect) || !maEntryList.IsEntrySelectable( nPos ) )
935  return;
936 
938  if( bSelect )
939  {
940  if( !mbMulti )
941  {
942  // deselect the selected entry
943  sal_Int32 nDeselect = GetEntryList().GetSelectedEntryPos( 0 );
944  if( nDeselect != LISTBOX_ENTRY_NOTFOUND )
945  {
946  //SelectEntryPos( nDeselect, false );
947  GetEntryList().SelectEntry( nDeselect, false );
948  if (IsUpdateMode() && IsReallyVisible())
949  Invalidate();
950  }
951  }
952  maEntryList.SelectEntry( nPos, true );
953  mnCurrentPos = nPos;
954  if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() )
955  {
956  Invalidate();
957  if ( !IsVisible( nPos ) )
958  {
960  sal_Int32 nVisibleEntries = GetLastVisibleEntry()-mnTop;
961  if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) )
962  {
963  Resize();
964  ShowProminentEntry( nPos );
965  }
966  else
967  {
968  ShowProminentEntry( nPos );
969  }
970  }
971  }
972  }
973  else
974  {
975  maEntryList.SelectEntry( nPos, false );
976  Invalidate();
977  }
978  mbSelectionChanged = true;
979 }
980 
981 bool ImplListBoxWindow::SelectEntries( sal_Int32 nSelect, LB_EVENT_TYPE eLET, bool bShift, bool bCtrl, bool bSelectPosChange /*=FALSE*/ )
982 {
983  bool bSelectionChanged = false;
984 
985  if( IsEnabled() && maEntryList.IsEntrySelectable( nSelect ) )
986  {
987  bool bFocusChanged = false;
988 
989  // here (Single-ListBox) only one entry can be deselected
990  if( !mbMulti )
991  {
992  sal_Int32 nDeselect = maEntryList.GetSelectedEntryPos( 0 );
993  if( nSelect != nDeselect )
994  {
995  SelectEntry( nSelect, true );
996  maEntryList.SetLastSelected( nSelect );
997  bFocusChanged = true;
998  bSelectionChanged = true;
999  }
1000  }
1001  // MultiListBox without Modifier
1002  else if( mbSimpleMode && !bCtrl && !bShift )
1003  {
1004  sal_Int32 nEntryCount = maEntryList.GetEntryCount();
1005  for ( sal_Int32 nPos = 0; nPos < nEntryCount; nPos++ )
1006  {
1007  bool bSelect = nPos == nSelect;
1008  if ( maEntryList.IsEntryPosSelected( nPos ) != bSelect )
1009  {
1010  SelectEntry( nPos, bSelect );
1011  bFocusChanged = true;
1012  bSelectionChanged = true;
1013  }
1014  }
1015  maEntryList.SetLastSelected( nSelect );
1016  maEntryList.SetSelectionAnchor( nSelect );
1017  }
1018  // MultiListBox only with CTRL/SHIFT or not in SimpleMode
1019  else if( ( !mbSimpleMode /* && !bShift */ ) || ( mbSimpleMode && ( bCtrl || bShift ) ) )
1020  {
1021  // Space for selection change
1022  if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) )
1023  {
1024  bool bSelect = !maEntryList.IsEntryPosSelected( nSelect );
1025  SelectEntry( nSelect, bSelect );
1026  maEntryList.SetLastSelected( nSelect );
1027  maEntryList.SetSelectionAnchor( nSelect );
1028  if ( !maEntryList.IsEntryPosSelected( nSelect ) )
1030  bFocusChanged = true;
1031  bSelectionChanged = true;
1032  }
1033  else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) ||
1034  ( bShift && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) )
1035  {
1036  mnCurrentPos = nSelect;
1037  bFocusChanged = true;
1038 
1039  sal_Int32 nAnchor = maEntryList.GetSelectionAnchor();
1040  if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && maEntryList.GetSelectedEntryCount() )
1041  {
1043  }
1044  if( nAnchor != LISTBOX_ENTRY_NOTFOUND )
1045  {
1046  // All entries from Anchor to nSelect have to be selected
1047  sal_Int32 nStart = std::min( nSelect, nAnchor );
1048  sal_Int32 nEnd = std::max( nSelect, nAnchor );
1049  for ( sal_Int32 n = nStart; n <= nEnd; n++ )
1050  {
1051  if ( !maEntryList.IsEntryPosSelected( n ) )
1052  {
1053  SelectEntry( n, true );
1054  bSelectionChanged = true;
1055  }
1056  }
1057 
1058  // if appropriate some more has to be deselected...
1059  sal_Int32 nLast = maEntryList.GetLastSelected();
1060  if ( nLast != LISTBOX_ENTRY_NOTFOUND )
1061  {
1062  if ( ( nLast > nSelect ) && ( nLast > nAnchor ) )
1063  {
1064  for ( sal_Int32 n = nSelect+1; n <= nLast; n++ )
1065  {
1066  if ( maEntryList.IsEntryPosSelected( n ) )
1067  {
1068  SelectEntry( n, false );
1069  bSelectionChanged = true;
1070  }
1071  }
1072  }
1073  else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) )
1074  {
1075  for ( sal_Int32 n = nLast; n < nSelect; n++ )
1076  {
1077  if ( maEntryList.IsEntryPosSelected( n ) )
1078  {
1079  SelectEntry( n, false );
1080  bSelectionChanged = true;
1081  }
1082  }
1083  }
1084  }
1085  maEntryList.SetLastSelected( nSelect );
1086  }
1087  }
1088  else if( eLET != LET_TRACKING )
1089  {
1091  Invalidate();
1092  bFocusChanged = true;
1093  }
1094  }
1095  else if( bShift )
1096  {
1097  bFocusChanged = true;
1098  }
1099 
1100  if( bSelectionChanged )
1101  mbSelectionChanged = true;
1102 
1103  if( bFocusChanged )
1104  {
1105  tools::Long nHeightDiff = maEntryList.GetAddedHeight( nSelect, mnTop );
1106  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1107  Size aSz( maFocusRect.GetWidth(),
1108  maEntryList.GetEntryHeight( nSelect ) );
1109  maFocusRect.SetSize( aSz );
1110  if( HasFocus() )
1112  if (bSelectPosChange)
1113  {
1114  maFocusHdl.Call(nSelect);
1115  }
1116  }
1118  }
1119  return bSelectionChanged;
1120 }
1121 
1123 {
1125  bool bInside = aRect.Contains( rTEvt.GetMouseEvent().GetPosPixel() );
1126 
1127  if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp
1128  {
1129  if ( bInside && !rTEvt.IsTrackingCanceled() )
1130  {
1132  ImplCallSelect();
1133  }
1134  else
1135  {
1136  maCancelHdl.Call( nullptr );
1137  if ( !mbMulti )
1138  {
1139  mbTrackingSelect = true;
1141  mbTrackingSelect = false;
1143  {
1145  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1146  Size aSz( maFocusRect.GetWidth(),
1148  maFocusRect.SetSize( aSz );
1150  }
1151  }
1152  }
1153 
1154  mbTrack = false;
1155  }
1156  else
1157  {
1158  bool bTrackOrQuickClick = mbTrack;
1159  if( !mbTrack )
1160  {
1161  if ( bInside )
1162  {
1163  mbTrack = true;
1164  }
1165 
1166  // this case only happens, if the mouse button is pressed very briefly
1167  if( rTEvt.IsTrackingEnded() && mbTrack )
1168  {
1169  bTrackOrQuickClick = true;
1170  mbTrack = false;
1171  }
1172  }
1173 
1174  if( bTrackOrQuickClick )
1175  {
1176  MouseEvent aMEvt = rTEvt.GetMouseEvent();
1177  Point aPt( aMEvt.GetPosPixel() );
1178  bool bShift = aMEvt.IsShift();
1179  bool bCtrl = aMEvt.IsMod1();
1180 
1181  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
1182  if( aPt.Y() < 0 )
1183  {
1185  {
1186  nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0;
1187  if( nSelect < mnTop )
1188  SetTopEntry( mnTop-1 );
1189  }
1190  }
1191  else if( aPt.Y() > GetOutputSizePixel().Height() )
1192  {
1194  {
1195  nSelect = std::min( static_cast<sal_Int32>(mnCurrentPos+1), static_cast<sal_Int32>(maEntryList.GetEntryCount()-1) );
1196  if( nSelect >= GetLastVisibleEntry() )
1197  SetTopEntry( mnTop+1 );
1198  }
1199  }
1200  else
1201  {
1202  nSelect = static_cast<sal_Int32>( ( aPt.Y() + gnBorder ) / mnMaxHeight ) + mnTop;
1203  nSelect = std::min( nSelect, GetLastVisibleEntry() );
1204  nSelect = std::min( nSelect, static_cast<sal_Int32>( maEntryList.GetEntryCount() - 1 ) );
1205  }
1206 
1207  if ( bInside )
1208  {
1209  if ( ( nSelect != mnCurrentPos ) || !GetEntryList().GetSelectedEntryCount() )
1210  {
1211  mbTrackingSelect = true;
1212  SelectEntries(nSelect, LET_TRACKING, bShift, bCtrl);
1213  mbTrackingSelect = false;
1214  }
1215  }
1216  else
1217  {
1218  if ( !mbMulti && GetEntryList().GetSelectedEntryCount() )
1219  {
1220  mbTrackingSelect = true;
1221  SelectEntry( GetEntryList().GetSelectedEntryPos( 0 ), false );
1222  mbTrackingSelect = false;
1223  }
1224  }
1225  mnCurrentPos = nSelect;
1227  {
1229  }
1230  else
1231  {
1233  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1235  maFocusRect.SetSize( aSz );
1237  }
1238  }
1239  }
1240 }
1241 
1243 {
1244  if( !ProcessKeyInput( rKEvt ) )
1245  Control::KeyInput( rKEvt );
1246 }
1247 
1249 {
1250  // entry to be selected
1251  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
1252  LB_EVENT_TYPE eLET = LET_KEYMOVE;
1253 
1254  vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
1255 
1256  bool bShift = aKeyCode.IsShift();
1257  bool bCtrl = aKeyCode.IsMod1() || aKeyCode.IsMod3();
1258  bool bMod2 = aKeyCode.IsMod2();
1259  bool bDone = false;
1260  bool bHandleKey = false;
1261 
1262  switch( aKeyCode.GetCode() )
1263  {
1264  case KEY_UP:
1265  {
1266  if ( IsReadOnly() )
1267  {
1268  if ( GetTopEntry() )
1269  SetTopEntry( GetTopEntry()-1 );
1270  }
1271  else if ( !bMod2 )
1272  {
1274  {
1275  nSelect = maEntryList.FindFirstSelectable( 0 );
1276  }
1277  else if ( mnCurrentPos )
1278  {
1279  // search first selectable above the current position
1280  nSelect = maEntryList.FindFirstSelectable( mnCurrentPos - 1, false );
1281  }
1282 
1283  if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) )
1284  SetTopEntry( mnTop-1 );
1285 
1286  bDone = true;
1287  }
1289  }
1290  break;
1291 
1292  case KEY_DOWN:
1293  {
1294  if ( IsReadOnly() )
1295  {
1296  SetTopEntry( GetTopEntry()+1 );
1297  }
1298  else if ( !bMod2 )
1299  {
1301  {
1302  nSelect = maEntryList.FindFirstSelectable( 0 );
1303  }
1304  else if ( (mnCurrentPos+1) < maEntryList.GetEntryCount() )
1305  {
1306  // search first selectable below the current position
1307  nSelect = maEntryList.FindFirstSelectable( mnCurrentPos + 1 );
1308  }
1309 
1310  if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) )
1311  SetTopEntry( mnTop+1 );
1312 
1313  bDone = true;
1314  }
1316  }
1317  break;
1318 
1319  case KEY_PAGEUP:
1320  {
1321  if ( IsReadOnly() )
1322  {
1323  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
1324  SetTopEntry( ( mnTop > nCurVis ) ?
1325  (mnTop-nCurVis) : 0 );
1326  }
1327  else if ( !bCtrl && !bMod2 )
1328  {
1330  {
1331  nSelect = maEntryList.FindFirstSelectable( 0 );
1332  }
1333  else if ( mnCurrentPos )
1334  {
1335  if( mnCurrentPos == mnTop )
1336  {
1337  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
1338  SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 );
1339  }
1340 
1341  // find first selectable starting from mnTop looking forward
1342  nSelect = maEntryList.FindFirstSelectable( mnTop );
1343  }
1344  bDone = true;
1345  }
1347  }
1348  break;
1349 
1350  case KEY_PAGEDOWN:
1351  {
1352  if ( IsReadOnly() )
1353  {
1355  }
1356  else if ( !bCtrl && !bMod2 )
1357  {
1359  {
1360  nSelect = maEntryList.FindFirstSelectable( 0 );
1361  }
1362  else if ( (mnCurrentPos+1) < maEntryList.GetEntryCount() )
1363  {
1364  sal_Int32 nCount = maEntryList.GetEntryCount();
1365  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop;
1366  sal_Int32 nTmp = std::min( nCurVis, nCount );
1367  nTmp += mnTop - 1;
1368  if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 )
1369  {
1370  tools::Long nTmp2 = std::min( static_cast<tools::Long>(nCount-nCurVis), static_cast<tools::Long>(static_cast<tools::Long>(mnTop)+static_cast<tools::Long>(nCurVis)-1) );
1371  nTmp2 = std::max( tools::Long(0) , nTmp2 );
1372  nTmp = static_cast<sal_Int32>(nTmp2+(nCurVis-1) );
1373  SetTopEntry( static_cast<sal_Int32>(nTmp2) );
1374  }
1375  // find first selectable starting from nTmp looking backwards
1376  nSelect = maEntryList.FindFirstSelectable( nTmp, false );
1377  }
1378  bDone = true;
1379  }
1381  }
1382  break;
1383 
1384  case KEY_HOME:
1385  {
1386  if ( IsReadOnly() )
1387  {
1388  SetTopEntry( 0 );
1389  }
1390  else if ( !bCtrl && !bMod2 && mnCurrentPos )
1391  {
1393  if( mnTop != 0 )
1394  SetTopEntry( 0 );
1395 
1396  bDone = true;
1397  }
1399  }
1400  break;
1401 
1402  case KEY_END:
1403  {
1404  if ( IsReadOnly() )
1405  {
1406  SetTopEntry( 0xFFFF );
1407  }
1408  else if ( !bCtrl && !bMod2 )
1409  {
1411  {
1412  nSelect = maEntryList.FindFirstSelectable( 0 );
1413  }
1414  else if ( (mnCurrentPos+1) < maEntryList.GetEntryCount() )
1415  {
1416  sal_Int32 nCount = maEntryList.GetEntryCount();
1417  nSelect = maEntryList.FindFirstSelectable( nCount - 1, false );
1418  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop + 1;
1419  if( nCount > nCurVis )
1420  SetTopEntry( nCount - nCurVis );
1421  }
1422  bDone = true;
1423  }
1425  }
1426  break;
1427 
1428  case KEY_LEFT:
1429  {
1430  if ( !bCtrl && !bMod2 )
1431  {
1432  ScrollHorz( -HORZ_SCROLL );
1433  bDone = true;
1434  }
1436  }
1437  break;
1438 
1439  case KEY_RIGHT:
1440  {
1441  if ( !bCtrl && !bMod2 )
1442  {
1444  bDone = true;
1445  }
1447  }
1448  break;
1449 
1450  case KEY_RETURN:
1451  {
1452  if ( !bMod2 && !IsReadOnly() )
1453  {
1455  ImplCallSelect();
1456  bDone = false; // do not catch RETURN
1457  }
1459  }
1460  break;
1461 
1462  case KEY_SPACE:
1463  {
1464  if ( !bMod2 && !IsReadOnly() )
1465  {
1466  if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) ) )
1467  {
1468  nSelect = mnCurrentPos;
1469  eLET = LET_KEYSPACE;
1470  }
1471  bDone = true;
1472  }
1473  bHandleKey = true;
1474  }
1475  break;
1476 
1477  case KEY_A:
1478  {
1479  if( bCtrl && mbMulti )
1480  {
1481  // paint only once
1482  bool bUpdates = IsUpdateMode();
1483  SetUpdateMode( false );
1484 
1485  sal_Int32 nEntryCount = maEntryList.GetEntryCount();
1486  for( sal_Int32 i = 0; i < nEntryCount; i++ )
1487  SelectEntry( i, true );
1488 
1489  // tdf#97066 - Update selected items
1490  ImplCallSelect();
1491 
1492  // restore update mode
1493  SetUpdateMode( bUpdates );
1494  Invalidate();
1495 
1497 
1498  bDone = true;
1499  }
1500  else
1501  {
1502  bHandleKey = true;
1503  }
1504  }
1505  break;
1506 
1507  default:
1508  bHandleKey = true;
1509  break;
1510  }
1511  if (bHandleKey && !IsReadOnly())
1512  {
1513  bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt );
1514  }
1515 
1516  if ( ( nSelect != LISTBOX_ENTRY_NOTFOUND )
1517  && ( ( !maEntryList.IsEntryPosSelected( nSelect ) )
1518  || ( eLET == LET_KEYSPACE )
1519  )
1520  )
1521  {
1522  SAL_WARN_IF( maEntryList.IsEntryPosSelected( nSelect ) && !mbMulti, "vcl", "ImplListBox: Selecting same Entry" );
1523  sal_Int32 nCount = maEntryList.GetEntryCount();
1524  if (nSelect >= nCount)
1525  nSelect = nCount ? nCount-1 : LISTBOX_ENTRY_NOTFOUND;
1526  bool bCurPosChange = (mnCurrentPos != nSelect);
1527  mnCurrentPos = nSelect;
1528  if(SelectEntries( nSelect, eLET, bShift, bCtrl, bCurPosChange))
1529  {
1530  // tdf#129043 Correctly deliver events when changing values with arrow keys in combobox
1531  if (mbIsDropdown && IsReallyVisible())
1532  mbTravelSelect = true;
1534  ImplCallSelect();
1535  mbTravelSelect = false;
1536  }
1537  }
1538 
1539  return bDone;
1540 }
1541 
1542 namespace
1543 {
1544  vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_Int32 _nPos, OUString& _out_entryText )
1545  {
1546  OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" );
1547  sal_Int32 nEntryCount( _rList.GetEntryCount() );
1548  if ( _nPos >= nEntryCount )
1549  _nPos = 0;
1550  _out_entryText = _rList.GetEntryText( _nPos );
1551 
1552  // vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based
1553  // => normalize
1554  return reinterpret_cast< vcl::StringEntryIdentifier >( _nPos + 1 );
1555  }
1556 
1557  sal_Int32 lcl_getEntryPos( vcl::StringEntryIdentifier _entry )
1558  {
1559  // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL
1560  return static_cast< sal_Int32 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1;
1561  }
1562 }
1563 
1565 {
1566  return lcl_getEntry( GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos, _out_entryText );
1567 }
1568 
1570 {
1571  sal_Int32 nNextPos = lcl_getEntryPos( _currentEntry ) + 1;
1572  return lcl_getEntry( GetEntryList(), nNextPos, _out_entryText );
1573 }
1574 
1576 {
1577  sal_Int32 nSelect = lcl_getEntryPos( _entry );
1578  if ( maEntryList.IsEntryPosSelected( nSelect ) )
1579  {
1580  // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted
1581  // to select the given entry by typing its starting letters. No need to act.
1582  return;
1583  }
1584 
1585  // normalize
1586  OSL_ENSURE( nSelect < maEntryList.GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" );
1587  sal_Int32 nCount = maEntryList.GetEntryCount();
1588  if (nSelect >= nCount)
1589  nSelect = nCount ? nCount-1 : LISTBOX_ENTRY_NOTFOUND;
1590 
1591  // make visible
1592  ShowProminentEntry( nSelect );
1593 
1594  // actually select
1595  mnCurrentPos = nSelect;
1596  if ( SelectEntries( nSelect, LET_KEYMOVE ) )
1597  {
1598  mbTravelSelect = true;
1599  mnSelectModifier = 0;
1600  ImplCallSelect();
1601  mbTravelSelect = false;
1602  }
1603 }
1604 
1605 void ImplListBoxWindow::ImplPaint(vcl::RenderContext& rRenderContext, sal_Int32 nPos)
1606 {
1607  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1608 
1609  const ImplEntryType* pEntry = maEntryList.GetEntryPtr( nPos );
1610  if (!pEntry)
1611  return;
1612 
1613  tools::Long nWidth = GetOutputSizePixel().Width();
1615  tools::Rectangle aRect(Point(0, nY), Size(nWidth, pEntry->getHeightWithMargin()));
1616 
1617  bool bSelected = maEntryList.IsEntryPosSelected(nPos);
1618  if (bSelected)
1619  {
1620  rRenderContext.SetTextColor(!IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor());
1621  rRenderContext.SetFillColor(rStyleSettings.GetHighlightColor());
1622  rRenderContext.SetLineColor();
1623  rRenderContext.DrawRect(aRect);
1624  }
1625  else
1626  {
1627  ApplySettings(rRenderContext);
1628  if (!IsEnabled())
1629  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
1630  }
1631  rRenderContext.SetTextFillColor();
1632 
1633  if (IsUserDrawEnabled())
1634  {
1635  mbInUserDraw = true;
1636  mnUserDrawEntry = nPos;
1637  aRect.AdjustLeft( -mnLeft );
1638  if (nPos < GetEntryList().GetMRUCount())
1639  nPos = GetEntryList().FindEntry(GetEntryList().GetEntryText(nPos));
1640  nPos = nPos - GetEntryList().GetMRUCount();
1641 
1642  UserDrawEvent aUDEvt(&rRenderContext, aRect, nPos, bSelected);
1643  maUserDrawHdl.Call( &aUDEvt );
1644  mbInUserDraw = false;
1645  }
1646  else
1647  {
1648  DrawEntry(rRenderContext, nPos, true, true);
1649  }
1650 }
1651 
1652 void ImplListBoxWindow::DrawEntry(vcl::RenderContext& rRenderContext, sal_Int32 nPos, bool bDrawImage, bool bDrawText)
1653 {
1654  const ImplEntryType* pEntry = maEntryList.GetEntryPtr(nPos);
1655  if (!pEntry)
1656  return;
1657 
1658  tools::Long nEntryHeight = pEntry->getHeightWithMargin();
1659 
1660  // when changing this function don't forget to adjust ImplWin::DrawEntry()
1661 
1662  if (mbInUserDraw)
1663  nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU
1664 
1666 
1667  if (bDrawImage && maEntryList.HasImages())
1668  {
1669  Image aImage = maEntryList.GetEntryImage(nPos);
1670  if (!!aImage)
1671  {
1672  Size aImgSz = aImage.GetSizePixel();
1673  Point aPtImg(gnBorder - mnLeft, nY + ((nEntryHeight - aImgSz.Height()) / 2));
1674 
1675  if (!IsZoom())
1676  {
1677  rRenderContext.DrawImage(aPtImg, aImage);
1678  }
1679  else
1680  {
1681  aImgSz.setWidth( CalcZoom(aImgSz.Width()) );
1682  aImgSz.setHeight( CalcZoom(aImgSz.Height()) );
1683  rRenderContext.DrawImage(aPtImg, aImgSz, aImage);
1684  }
1685 
1686  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1687  const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
1688 
1689  if (nEdgeBlendingPercent && aImgSz.Width() && aImgSz.Height())
1690  {
1691  const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
1692  const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
1693  const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
1694  const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
1695 
1696  if (!aBlendFrame.IsEmpty())
1697  {
1698  rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
1699  }
1700  }
1701  }
1702  }
1703 
1704  if (bDrawText)
1705  {
1706  OUString aStr(maEntryList.GetEntryText(nPos));
1707  if (!aStr.isEmpty())
1708  {
1709  tools::Long nMaxWidth = std::max(mnMaxWidth, GetOutputSizePixel().Width() - 2 * gnBorder);
1710  // a multiline entry should only be as wide as the window
1711  if (pEntry->mnFlags & ListBoxEntryFlags::MultiLine)
1712  nMaxWidth = GetOutputSizePixel().Width() - 2 * gnBorder;
1713 
1714  tools::Rectangle aTextRect(Point(gnBorder - mnLeft, nY),
1715  Size(nMaxWidth, nEntryHeight));
1716 
1718  {
1719  tools::Long nImageWidth = std::max(mnMaxImgWidth, maUserItemSize.Width());
1720  aTextRect.AdjustLeft(nImageWidth + IMG_TXT_DISTANCE );
1721  }
1722 
1723  DrawTextFlags nDrawStyle = ImplGetTextStyle();
1724  if (pEntry->mnFlags & ListBoxEntryFlags::MultiLine)
1725  nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS;
1727  nDrawStyle |= DrawTextFlags::Disable;
1728 
1729  rRenderContext.DrawText(aTextRect, aStr, nDrawStyle);
1730  }
1731  }
1732 
1733  if ( !maSeparators.empty() && ( isSeparator(nPos) || isSeparator(nPos-1) ) )
1734  {
1735  Color aOldLineColor(rRenderContext.GetLineColor());
1736  rRenderContext.SetLineColor((GetBackground() != COL_LIGHTGRAY) ? COL_LIGHTGRAY : COL_GRAY);
1737  Point aStartPos(0, nY);
1738  if (isSeparator(nPos))
1739  aStartPos.AdjustY(pEntry->getHeightWithMargin() - 1 );
1740  Point aEndPos(aStartPos);
1741  aEndPos.setX( GetOutputSizePixel().Width() );
1742  rRenderContext.DrawLine(aStartPos, aEndPos);
1743  rRenderContext.SetLineColor(aOldLineColor);
1744  }
1745 }
1746 
1748 {
1749  mxLayoutData.emplace();
1750  const_cast<ImplListBoxWindow*>(this)->Invalidate(tools::Rectangle(Point(0, 0), GetOutDev()->GetOutputSize()));
1751 }
1752 
1754 {
1755  sal_Int32 nCount = maEntryList.GetEntryCount();
1756 
1757  bool bShowFocusRect = mbHasFocusRect;
1758  if (mbHasFocusRect)
1760 
1761  tools::Long nY = 0; // + gnBorder;
1762  tools::Long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + gnBorder;
1763 
1764  for (sal_Int32 i = mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++)
1765  {
1766  const ImplEntryType* pEntry = maEntryList.GetEntryPtr(i);
1767  tools::Long nEntryHeight = pEntry->getHeightWithMargin();
1768  if (nY + nEntryHeight >= rRect.Top() &&
1769  nY <= rRect.Bottom() + mnMaxHeight)
1770  {
1771  ImplPaint(rRenderContext, i);
1772  }
1773  nY += nEntryHeight;
1774  }
1775 
1777  maFocusRect.SetPos(Point(0, nHeightDiff));
1779  maFocusRect.SetSize(aSz);
1780  if (HasFocus() && bShowFocusRect)
1782 }
1783 
1785 {
1787  {
1788  // This widget is explicitly double-buffered, so avoid partial paints.
1789  tools::Rectangle aRect(Point(0, 0), GetOutputSizePixel());
1790  ImplDoPaint(rRenderContext, aRect);
1791  }
1792  else
1793  ImplDoPaint(rRenderContext, rRect);
1794 }
1795 
1797 {
1798  // FIXME: ListBoxEntryFlags::MultiLine
1799 
1800  const sal_Int32 nCount = maEntryList.GetEntryCount()-mnTop;
1801  tools::Long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + gnBorder;
1802  sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight );
1803  if( nEntries > nCount )
1804  nEntries = static_cast<sal_uInt16>(nCount);
1805 
1806  return nEntries;
1807 }
1808 
1810 {
1811  Control::Resize();
1812 
1813  bool bShowFocusRect = mbHasFocusRect;
1814  if ( bShowFocusRect )
1816 
1818  {
1820  maFocusRect.SetSize( aSz );
1821  }
1822 
1823  if ( bShowFocusRect )
1825 
1827 }
1828 
1830 {
1831  sal_Int32 nPos = mnCurrentPos;
1832  if ( nPos == LISTBOX_ENTRY_NOTFOUND )
1833  nPos = 0;
1834  tools::Long nHeightDiff = maEntryList.GetAddedHeight( nPos, mnTop );
1835  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1837  maFocusRect.SetSize( aSz );
1840 }
1841 
1843 {
1846 }
1847 
1848 void ImplListBoxWindow::SetTopEntry( sal_Int32 nTop )
1849 {
1850  if( maEntryList.GetEntryCount() == 0 )
1851  return;
1852 
1853  tools::Long nWHeight = PixelToLogic( GetSizePixel() ).Height();
1854 
1855  sal_Int32 nLastEntry = maEntryList.GetEntryCount()-1;
1856  if( nTop > nLastEntry )
1857  nTop = nLastEntry;
1858  const ImplEntryType* pLast = maEntryList.GetEntryPtr( nLastEntry );
1859  while( nTop > 0 && maEntryList.GetAddedHeight( nLastEntry, nTop-1 ) + pLast->getHeightWithMargin() <= nWHeight )
1860  nTop--;
1861 
1862  if ( nTop == mnTop )
1863  return;
1864 
1866  tools::Long nDiff = maEntryList.GetAddedHeight( mnTop, nTop );
1867  PaintImmediately();
1869  mnTop = nTop;
1870  Scroll( 0, nDiff );
1871  PaintImmediately();
1872  if( HasFocus() )
1874  maScrollHdl.Call( this );
1875 }
1876 
1877 void ImplListBoxWindow::ShowProminentEntry( sal_Int32 nEntryPos )
1878 {
1879  sal_Int32 nPos = nEntryPos;
1880  auto nWHeight = PixelToLogic( GetSizePixel() ).Height();
1881  while( nEntryPos > 0 && maEntryList.GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 )
1882  nEntryPos--;
1883 
1884  SetTopEntry( nEntryPos );
1885 }
1886 
1888 {
1889  ScrollHorz( n - mnLeft );
1890 }
1891 
1893 {
1894  tools::Long nDiff = 0;
1895  if ( n > 0 )
1896  {
1897  tools::Long nWidth = GetOutputSizePixel().Width();
1898  if( ( mnMaxWidth - mnLeft + n ) > nWidth )
1899  nDiff = n;
1900  }
1901  else if ( n < 0 )
1902  {
1903  if( mnLeft )
1904  {
1905  tools::Long nAbs = -n;
1906  nDiff = - std::min( mnLeft, nAbs );
1907  }
1908  }
1909 
1910  if ( nDiff )
1911  {
1913  mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff);
1914  PaintImmediately();
1916  Scroll( -nDiff, 0 );
1917  PaintImmediately();
1918  if( HasFocus() )
1920  maScrollHdl.Call( this );
1921  }
1922 }
1923 
1925 {
1926  maSeparators.clear();
1927 
1928  if ( n != LISTBOX_ENTRY_NOTFOUND )
1929  {
1930  maSeparators.insert( n );
1931  }
1932 }
1933 
1935 {
1936  if (!maSeparators.empty())
1937  return *(maSeparators.begin());
1938  else
1939  return LISTBOX_ENTRY_NOTFOUND;
1940 }
1941 
1942 bool ImplListBoxWindow::isSeparator( const sal_Int32 &n) const
1943 {
1944  return maSeparators.find(n) != maSeparators.end();
1945 }
1946 
1947 Size ImplListBoxWindow::CalcSize(sal_Int32 nMaxLines) const
1948 {
1949  // FIXME: ListBoxEntryFlags::MultiLine
1950 
1951  Size aSz;
1952  aSz.setHeight(nMaxLines * GetEntryHeightWithMargin());
1953  aSz.setWidth( mnMaxWidth + 2*gnBorder );
1954  return aSz;
1955 }
1956 
1958 {
1959  const ImplEntryType* pEntry = maEntryList.GetEntryPtr( nItem );
1960  Size aSz( GetSizePixel().Width(), pEntry ? pEntry->getHeightWithMargin() : GetEntryHeightWithMargin() );
1962  tools::Rectangle aRect( Point( 0, nY ), aSz );
1963  return aRect;
1964 }
1965 
1967 {
1968  Control::StateChanged( nType );
1969 
1970  if ( nType == StateChangedType::Zoom )
1971  {
1973  ImplCalcMetrics();
1974  Invalidate();
1975  }
1976  else if ( nType == StateChangedType::UpdateMode )
1977  {
1978  if ( IsUpdateMode() && IsReallyVisible() )
1979  Invalidate();
1980  }
1981  else if ( nType == StateChangedType::ControlFont )
1982  {
1984  ImplCalcMetrics();
1985  Invalidate();
1986  }
1987  else if ( nType == StateChangedType::ControlForeground )
1988  {
1990  Invalidate();
1991  }
1992  else if ( nType == StateChangedType::ControlBackground )
1993  {
1995  Invalidate();
1996  }
1997  else if( nType == StateChangedType::Enable )
1998  {
1999  Invalidate();
2000  }
2001 
2003 }
2004 
2006 {
2007  Control::DataChanged( rDCEvt );
2008 
2009  if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
2011  ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2012  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
2013  {
2016  ImplCalcMetrics();
2017  Invalidate();
2018  }
2019 }
2020 
2022 {
2024 
2025  if (maEntryList.HasImages())
2026  nTextStyle |= DrawTextFlags::Left;
2027  else if (mbCenter)
2028  nTextStyle |= DrawTextFlags::Center;
2029  else if (mbRight)
2030  nTextStyle |= DrawTextFlags::Right;
2031  else
2032  nTextStyle |= DrawTextFlags::Left;
2033 
2034  return nTextStyle;
2035 }
2036 
2038  Control( pParent, nWinStyle ),
2039  maLBWindow(VclPtr<ImplListBoxWindow>::Create( this, nWinStyle&(~WB_BORDER) ))
2040 {
2041  // for native widget rendering we must be able to detect this window type
2042  SetType( WindowType::LISTBOXWINDOW );
2043 
2047 
2048  Link<ScrollBar*,void> aLink( LINK( this, ImplListBox, ScrollBarHdl ) );
2049  mpVScrollBar->SetScrollHdl( aLink );
2050  mpHScrollBar->SetScrollHdl( aLink );
2051 
2052  mbVScroll = false;
2053  mbHScroll = false;
2054  mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL );
2055  mbEdgeBlending = false;
2056 
2057  maLBWindow->SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) );
2058  maLBWindow->SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) );
2060  maLBWindow->Show();
2061 }
2062 
2064 {
2065  disposeOnce();
2066 }
2067 
2069 {
2074  Control::dispose();
2075 }
2076 
2078 {
2079  maLBWindow->Clear();
2080  if ( GetEntryList().GetMRUCount() )
2081  {
2084  }
2085  mpVScrollBar->SetThumbPos( 0 );
2086  mpHScrollBar->SetThumbPos( 0 );
2088 }
2089 
2090 sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr )
2091 {
2092  ImplEntryType* pNewEntry = new ImplEntryType( rStr );
2093  sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
2095  return nNewPos;
2096 }
2097 
2098 sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr, const Image& rImage )
2099 {
2100  ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage );
2101  sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
2103  return nNewPos;
2104 }
2105 
2106 void ImplListBox::RemoveEntry( sal_Int32 nPos )
2107 {
2108  maLBWindow->RemoveEntry( nPos );
2110 }
2111 
2112 void ImplListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
2113 {
2114  maLBWindow->SetEntryFlags( nPos, nFlags );
2115 }
2116 
2117 void ImplListBox::SelectEntry( sal_Int32 nPos, bool bSelect )
2118 {
2119  maLBWindow->SelectEntry( nPos, bSelect );
2120 }
2121 
2123 {
2125 }
2126 
2128 {
2129  if (maLBWindow)
2130  maLBWindow->GrabFocus();
2131  else
2133 }
2134 
2136 {
2137  Control::Resize();
2140 }
2141 
2143 {
2144  CompatStateChanged( StateChangedType::Data );
2145 }
2146 
2148 {
2149  tools::Long nSet = GetTopEntry();
2150  if( nSet > mpVScrollBar->GetRangeMax() )
2151  mpVScrollBar->SetRangeMax( GetEntryList().GetEntryCount() );
2152  mpVScrollBar->SetThumbPos( GetTopEntry() );
2153 
2154  mpHScrollBar->SetThumbPos( GetLeftIndent() );
2155 
2156  maScrollHdl.Call( this );
2157 }
2158 
2159 IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB, void )
2160 {
2161  sal_uInt16 nPos = static_cast<sal_uInt16>(pSB->GetThumbPos());
2162  if( pSB == mpVScrollBar )
2163  SetTopEntry( nPos );
2164  else if( pSB == mpHScrollBar )
2165  SetLeftIndent( nPos );
2166  if( GetParent() )
2167  GetParent()->Invalidate( InvalidateFlags::Update );
2168 }
2169 
2171 {
2172  bool bArrange = false;
2173 
2174  Size aOutSz = GetOutputSizePixel();
2175  sal_Int32 nEntries = GetEntryList().GetEntryCount();
2176  sal_uInt16 nMaxVisEntries = static_cast<sal_uInt16>(aOutSz.Height() / GetEntryHeightWithMargin());
2177 
2178  // vertical ScrollBar
2179  if( nEntries > nMaxVisEntries )
2180  {
2181  if( !mbVScroll )
2182  bArrange = true;
2183  mbVScroll = true;
2184 
2185  // check of the scrolled-out region
2186  if( GetEntryList().GetSelectedEntryCount() == 1 &&
2189  else
2190  SetTopEntry( GetTopEntry() ); // MaxTop is being checked...
2191  }
2192  else
2193  {
2194  if( mbVScroll )
2195  bArrange = true;
2196  mbVScroll = false;
2197  SetTopEntry( 0 );
2198  }
2199 
2200  // horizontal ScrollBar
2201  if( mbAutoHScroll )
2202  {
2203  tools::Long nWidth = static_cast<sal_uInt16>(aOutSz.Width());
2204  if ( mbVScroll )
2205  nWidth -= mpVScrollBar->GetSizePixel().Width();
2206 
2207  tools::Long nMaxWidth = GetMaxEntryWidth();
2208  if( nWidth < nMaxWidth )
2209  {
2210  if( !mbHScroll )
2211  bArrange = true;
2212  mbHScroll = true;
2213 
2214  if ( !mbVScroll ) // maybe we do need one now
2215  {
2216  nMaxVisEntries = static_cast<sal_uInt16>( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeightWithMargin() );
2217  if( nEntries > nMaxVisEntries )
2218  {
2219  bArrange = true;
2220  mbVScroll = true;
2221 
2222  // check of the scrolled-out region
2223  if( GetEntryList().GetSelectedEntryCount() == 1 &&
2226  else
2227  SetTopEntry( GetTopEntry() ); // MaxTop is being checked...
2228  }
2229  }
2230 
2231  // check of the scrolled-out region
2232  sal_uInt16 nMaxLI = static_cast<sal_uInt16>(nMaxWidth - nWidth);
2233  if ( nMaxLI < GetLeftIndent() )
2234  SetLeftIndent( nMaxLI );
2235  }
2236  else
2237  {
2238  if( mbHScroll )
2239  bArrange = true;
2240  mbHScroll = false;
2241  SetLeftIndent( 0 );
2242  }
2243  }
2244 
2245  if( bArrange )
2247 
2249 }
2250 
2252 {
2253  Size aOutSz = maLBWindow->GetOutputSizePixel();
2254 
2255  if ( mbVScroll )
2256  {
2257  sal_Int32 nEntries = GetEntryList().GetEntryCount();
2258  sal_uInt16 nVisEntries = static_cast<sal_uInt16>(aOutSz.Height() / GetEntryHeightWithMargin());
2259  mpVScrollBar->SetRangeMax( nEntries );
2260  mpVScrollBar->SetVisibleSize( nVisEntries );
2261  mpVScrollBar->SetPageSize( nVisEntries - 1 );
2262  }
2263 
2264  if ( mbHScroll )
2265  {
2267  mpHScrollBar->SetVisibleSize( static_cast<sal_uInt16>(aOutSz.Width()) );
2269  mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL );
2270  }
2271 }
2272 
2274 {
2275  // Here we only position the Controls; if the Scrollbars are to be
2276  // visible is already determined in ImplCheckScrollBars
2277 
2278  Size aOutSz = GetOutputSizePixel();
2280  nSBWidth = CalcZoom( nSBWidth );
2281 
2282  Size aInnerSz( aOutSz );
2283  if ( mbVScroll )
2284  aInnerSz.AdjustWidth( -nSBWidth );
2285  if ( mbHScroll )
2286  aInnerSz.AdjustHeight( -nSBWidth );
2287 
2288  Point aWinPos( 0, 0 );
2289  maLBWindow->SetPosSizePixel( aWinPos, aInnerSz );
2290 
2291  // ScrollBarBox
2292  if( mbVScroll && mbHScroll )
2293  {
2294  Point aBoxPos( aInnerSz.Width(), aInnerSz.Height() );
2295  mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) );
2296  mpScrollBarBox->Show();
2297  }
2298  else
2299  {
2300  mpScrollBarBox->Hide();
2301  }
2302 
2303  // vertical ScrollBar
2304  if( mbVScroll )
2305  {
2306  // Scrollbar on left or right side?
2307  Point aVPos( aOutSz.Width() - nSBWidth, 0 );
2308  mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) );
2309  mpVScrollBar->Show();
2310  }
2311  else
2312  {
2313  mpVScrollBar->Hide();
2314  // #107254# Don't reset top entry after resize, but check for max top entry
2315  SetTopEntry( GetTopEntry() );
2316  }
2317 
2318  // horizontal ScrollBar
2319  if( mbHScroll )
2320  {
2321  Point aHPos( 0, aOutSz.Height() - nSBWidth );
2322  mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) );
2323  mpHScrollBar->Show();
2324  }
2325  else
2326  {
2327  mpHScrollBar->Hide();
2328  SetLeftIndent( 0 );
2329  }
2330 }
2331 
2333 {
2334  if ( nType == StateChangedType::InitShow )
2335  {
2337  }
2338  else if ( ( nType == StateChangedType::UpdateMode ) || ( nType == StateChangedType::Data ) )
2339  {
2340  bool bUpdate = IsUpdateMode();
2341  maLBWindow->SetUpdateMode( bUpdate );
2342  if ( bUpdate && IsReallyVisible() )
2344  }
2345  else if( nType == StateChangedType::Enable )
2346  {
2350  maLBWindow->Enable( IsEnabled() );
2351 
2352  Invalidate();
2353  }
2354  else if ( nType == StateChangedType::Zoom )
2355  {
2356  maLBWindow->SetZoom( GetZoom() );
2357  Resize();
2358  }
2359  else if ( nType == StateChangedType::ControlFont )
2360  {
2362  }
2363  else if ( nType == StateChangedType::ControlForeground )
2364  {
2366  }
2367  else if ( nType == StateChangedType::ControlBackground )
2368  {
2370  }
2371  else if( nType == StateChangedType::Mirroring )
2372  {
2377  }
2378 
2379  Control::StateChanged( nType );
2380 }
2381 
2383 {
2384  bool bDone = false;
2385  if ( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
2386  {
2387  const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
2388  if ( rCEvt.GetCommand() == CommandEventId::Wheel )
2389  {
2390  const CommandWheelData* pData = rCEvt.GetWheelData();
2391  if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
2392  {
2393  bDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
2394  }
2395  }
2396  else if (rCEvt.GetCommand() == CommandEventId::Gesture)
2397  {
2399  }
2400  }
2401 
2402  return bDone || Window::EventNotify( rNEvt );
2403 }
2404 
2406 {
2407  return maLBWindow->GetDisplayBackground();
2408 }
2409 
2411 {
2412  bool bDone = false;
2413  if ( rCEvt.GetCommand() == CommandEventId::Wheel )
2414  {
2415  const CommandWheelData* pData = rCEvt.GetWheelData();
2416  if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
2417  {
2418  if (!rControl.HasChildPathFocus())
2419  rControl.GrabFocus();
2420  sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP;
2421  KeyEvent aKeyEvent( 0, vcl::KeyCode( nKey ) );
2422  bDone = ProcessKeyInput( aKeyEvent );
2423  }
2424  }
2425  return bDone;
2426 }
2427 
2428 void ImplListBox::SetMRUEntries( std::u16string_view rEntries, sal_Unicode cSep )
2429 {
2430  bool bChanges = GetEntryList().GetMRUCount() != 0;
2431 
2432  // Remove old MRU entries
2433  for ( sal_Int32 n = GetEntryList().GetMRUCount();n; )
2434  maLBWindow->RemoveEntry( --n );
2435 
2436  sal_Int32 nMRUCount = 0;
2437  sal_Int32 nIndex = 0;
2438  do
2439  {
2440  OUString aEntry( o3tl::getToken(rEntries, 0, cSep, nIndex ) );
2441  // Accept only existing entries
2442  if ( GetEntryList().FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND )
2443  {
2444  ImplEntryType* pNewEntry = new ImplEntryType( aEntry );
2445  maLBWindow->InsertEntry(nMRUCount++, pNewEntry, false);
2446  bChanges = true;
2447  }
2448  }
2449  while ( nIndex >= 0 );
2450 
2451  if ( bChanges )
2452  {
2453  maLBWindow->GetEntryList().SetMRUCount( nMRUCount );
2454  SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
2456  }
2457 }
2458 
2460 {
2461  OUStringBuffer aEntries;
2462  for ( sal_Int32 n = 0; n < GetEntryList().GetMRUCount(); n++ )
2463  {
2464  aEntries.append(GetEntryList().GetEntryText( n ));
2465  if( n < ( GetEntryList().GetMRUCount() - 1 ) )
2466  aEntries.append(cSep);
2467  }
2468  return aEntries.makeStringAndClear();
2469 }
2470 
2472 {
2473  if(mbEdgeBlending != bNew)
2474  {
2475  mbEdgeBlending = bNew;
2477  }
2478 }
2479 
2480 ImplWin::ImplWin( vcl::Window* pParent, WinBits nWinStyle ) :
2481  Control ( pParent, nWinStyle )
2482 {
2485  SetBackground();
2486  else
2487  SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
2488 
2490 
2491  mbEdgeBlending = false;
2493 }
2494 
2496 {
2497  if( IsEnabled() )
2498  {
2499  maMBDownHdl.Call(this);
2500  }
2501 }
2502 
2504 {
2505  mxLayoutData.emplace();
2506  ImplWin* pThis = const_cast<ImplWin*>(this);
2507  pThis->ImplDraw(*pThis->GetOutDev(), true);
2508 }
2509 
2511 {
2512  if( rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE )
2513  {
2514  const MouseEvent* pMouseEvt = rNEvt.GetMouseEvent();
2515  if( pMouseEvt && (pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow()) )
2516  {
2517  // trigger redraw as mouse over state has changed
2520  {
2522  }
2523  }
2524  }
2525 
2526  return Control::PreNotify(rNEvt);
2527 }
2528 
2529 void ImplWin::ImplDraw(vcl::RenderContext& rRenderContext, bool bLayout)
2530 {
2531  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
2532 
2533  if (!bLayout)
2534  {
2535  bool bNativeOK = false;
2536  bool bHasFocus = HasFocus();
2537  bool bIsEnabled = IsEnabled();
2538 
2542  {
2543  // Repaint the (focused) area similarly to
2544  // ImplSmallBorderWindowView::DrawWindow() in
2545  // vcl/source/window/brdwin.cxx
2546  vcl::Window *pWin = GetParent();
2547 
2548  ImplControlValue aControlValue;
2549  bIsEnabled &= pWin->IsEnabled();
2550  if ( !bIsEnabled )
2551  nState &= ~ControlState::ENABLED;
2552  bHasFocus |= pWin->HasFocus();
2553  if ( bHasFocus )
2554  nState |= ControlState::FOCUSED;
2555 
2556  // The listbox is painted over the entire control including the
2557  // border, but ImplWin does not contain the border => correction
2558  // needed.
2559  sal_Int32 nLeft, nTop, nRight, nBottom;
2560  pWin->GetBorder( nLeft, nTop, nRight, nBottom );
2561  Point aPoint( -nLeft, -nTop );
2562  tools::Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() );
2563 
2564  bool bMouseOver = false;
2565  vcl::Window *pChild = pWin->GetWindow( GetWindowType::FirstChild );
2566  while( pChild )
2567  {
2568  bMouseOver = pChild->IsMouseOver();
2569  if (bMouseOver)
2570  break;
2571  pChild = pChild->GetWindow( GetWindowType::Next );
2572  }
2573  if( bMouseOver )
2574  nState |= ControlState::ROLLOVER;
2575 
2576  // if parent has no border, then nobody has drawn the background
2577  // since no border window exists. so draw it here.
2578  WinBits nParentStyle = pWin->GetStyle();
2579  if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) )
2580  {
2581  tools::Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() );
2583  nState, aControlValue, OUString() );
2584  }
2585 
2586  bNativeOK = rRenderContext.DrawNativeControl(ControlType::Listbox, ControlPart::Entire, aCtrlRegion,
2587  nState, aControlValue, OUString());
2588  }
2589 
2590  if (bIsEnabled)
2591  {
2592  if (bHasFocus && !ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
2593  {
2594  if ( !ImplGetSVData()->maNWFData.mbNoFocusRects )
2595  {
2596  rRenderContext.SetFillColor( rStyleSettings.GetHighlightColor() );
2597  rRenderContext.SetTextColor( rStyleSettings.GetHighlightTextColor() );
2598  }
2599  else
2600  {
2601  rRenderContext.SetLineColor();
2602  rRenderContext.SetFillColor();
2603  rRenderContext.SetTextColor( rStyleSettings.GetFieldTextColor() );
2604  }
2605  rRenderContext.DrawRect( maFocusRect );
2606  }
2607  else
2608  {
2609  Color aColor;
2610  if (IsControlForeground())
2611  aColor = GetControlForeground();
2612  else if (ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
2613  {
2614  if( bNativeOK && (nState & ControlState::ROLLOVER) )
2615  aColor = rStyleSettings.GetButtonRolloverTextColor();
2616  else
2617  aColor = rStyleSettings.GetButtonTextColor();
2618  }
2619  else
2620  {
2621  if( bNativeOK && (nState & ControlState::ROLLOVER) )
2622  aColor = rStyleSettings.GetFieldRolloverTextColor();
2623  else
2624  aColor = rStyleSettings.GetFieldTextColor();
2625  }
2626  rRenderContext.SetTextColor(aColor);
2627  if (!bNativeOK)
2628  rRenderContext.Erase(maFocusRect);
2629  }
2630  }
2631  else // Disabled
2632  {
2633  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
2634  if (!bNativeOK)
2635  rRenderContext.Erase(maFocusRect);
2636  }
2637  }
2638 
2639  DrawEntry(rRenderContext, bLayout);
2640 }
2641 
2643 {
2644  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
2645 
2646  ApplyControlFont(rRenderContext, rStyleSettings.GetFieldFont());
2647  ApplyControlForeground(rRenderContext, rStyleSettings.GetFieldTextColor());
2648 
2649  if (IsControlBackground())
2650  rRenderContext.SetBackground(GetControlBackground());
2651  else
2652  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
2653 }
2654 
2655 void ImplWin::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
2656 {
2657  ImplDraw(rRenderContext);
2658 }
2659 
2660 void ImplWin::DrawEntry(vcl::RenderContext& rRenderContext, bool bLayout)
2661 {
2662  tools::Long nBorder = 1;
2663  Size aOutSz(GetOutputSizePixel());
2664 
2665  bool bImage = !!maImage;
2666  if (bImage && !bLayout)
2667  {
2669  Size aImgSz = maImage.GetSizePixel();
2670  Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) );
2671  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2672 
2673  // check for HC mode
2674  Image *pImage = &maImage;
2675 
2676  if ( !IsZoom() )
2677  {
2678  rRenderContext.DrawImage( aPtImg, *pImage, nStyle );
2679  }
2680  else
2681  {
2682  aImgSz.setWidth( CalcZoom( aImgSz.Width() ) );
2683  aImgSz.setHeight( CalcZoom( aImgSz.Height() ) );
2684  rRenderContext.DrawImage( aPtImg, aImgSz, *pImage, nStyle );
2685  }
2686 
2687  const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
2688 
2689  if(nEdgeBlendingPercent)
2690  {
2691  const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
2692  const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
2693  const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
2694  const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
2695 
2696  if(!aBlendFrame.IsEmpty())
2697  {
2698  rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
2699  }
2700  }
2701  }
2702 
2703  if( !maString.isEmpty() )
2704  {
2706 
2707  if ( bImage && !bLayout )
2708  nTextStyle |= DrawTextFlags::Left;
2709  else if ( GetStyle() & WB_CENTER )
2710  nTextStyle |= DrawTextFlags::Center;
2711  else if ( GetStyle() & WB_RIGHT )
2712  nTextStyle |= DrawTextFlags::Right;
2713  else
2714  nTextStyle |= DrawTextFlags::Left;
2715 
2716  tools::Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) );
2717 
2718  if ( bImage )
2719  {
2721  }
2722 
2723  std::vector< tools::Rectangle >* pVector = bLayout ? &mxLayoutData->m_aUnicodeBoundRects : nullptr;
2724  OUString* pDisplayText = bLayout ? &mxLayoutData->m_aDisplayText : nullptr;
2725  rRenderContext.DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText );
2726  }
2727 
2728  if( HasFocus() && !bLayout )
2730 }
2731 
2733 {
2734  Control::Resize();
2736  Invalidate();
2737 }
2738 
2740 {
2742  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2745  {
2747  if( ! pWin )
2748  pWin = GetParent();
2749  pWin->Invalidate();
2750  }
2751  else
2752  Invalidate();
2754 }
2755 
2757 {
2758  HideFocus();
2759  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2762  {
2764  if( ! pWin )
2765  pWin = GetParent();
2766  pWin->Invalidate();
2767  }
2768  else
2769  Invalidate();
2771 }
2772 
2774 {
2776  {
2777  ImplControlValue aControlValue;
2778 
2779  vcl::Window *pWin = GetParent();
2780  tools::Rectangle aParentRect(Point(0, 0), pWin->GetSizePixel());
2782  ControlState::FOCUSED, aControlValue, OUString());
2783  }
2784  Control::ShowFocus(rRect);
2785 }
2786 
2787 ImplBtn::ImplBtn( vcl::Window* pParent, WinBits nWinStyle ) :
2788  PushButton( pParent, nWinStyle )
2789 {
2790 }
2791 
2793 {
2794  if( IsEnabled() )
2795  maMBDownHdl.Call(this);
2796 }
2797 
2799  FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes
2800 {
2801  // for native widget rendering we must be able to detect this window type
2802  SetType( WindowType::LISTBOXWINDOW );
2803 
2804  mpImplLB = nullptr;
2805  mnDDLineCount = 0;
2806  mbAutoWidth = false;
2807 
2809 
2810  vcl::Window * pBorderWindow = ImplGetBorderWindow();
2811  if( pBorderWindow )
2812  {
2813  SetAccessibleRole(accessibility::AccessibleRole::PANEL);
2814  pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
2815  }
2816  else
2817  {
2818  SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
2819  }
2820 
2821 }
2822 
2824 {
2825  disposeOnce();
2826 }
2827 
2829 {
2830  mpImplLB.clear();
2832 }
2833 
2834 
2836 {
2837  if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2838  {
2839  if( !GetParent()->HasChildPathFocus( true ) )
2840  EndPopupMode();
2841  }
2842 
2843  return FloatingWindow::PreNotify( rNEvt );
2844 }
2845 
2847 {
2848  FloatingWindow::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
2849 
2850  // Fix #60890# ( MBA ): to be able to resize the Listbox even in its open state
2851  // after a call to Resize(), we adjust its position if necessary
2852  if ( IsReallyVisible() && ( nFlags & PosSizeFlags::Height ) )
2853  {
2854  Point aPos = GetParent()->GetPosPixel();
2855  aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
2856 
2857  if ( nFlags & PosSizeFlags::X )
2858  aPos.setX( nX );
2859 
2860  if ( nFlags & PosSizeFlags::Y )
2861  aPos.setY( nY );
2862 
2863  sal_uInt16 nIndex;
2865  }
2866 
2867 // if( !IsReallyVisible() )
2868  {
2869  // The ImplListBox does not get a Resize() as not visible.
2870  // But the windows must get a Resize(), so that the number of
2871  // visible entries is correct for PgUp/PgDown.
2872  // The number also cannot be calculated by List/Combobox, as for
2873  // this the presence of the vertical Scrollbar has to be known.
2875  static_cast<vcl::Window*>(mpImplLB)->Resize();
2876  static_cast<vcl::Window*>(mpImplLB->GetMainWindow())->Resize();
2877  }
2878 }
2879 
2881 {
2884 }
2885 
2887 {
2888  Size aFloatSz( maPrefSz );
2889 
2890  sal_Int32 nLeft, nTop, nRight, nBottom;
2891  GetBorder( nLeft, nTop, nRight, nBottom );
2892 
2893  sal_Int32 nLines = mpImplLB->GetEntryList().GetEntryCount();
2894  if ( mnDDLineCount && ( nLines > mnDDLineCount ) )
2895  nLines = mnDDLineCount;
2896 
2897  Size aSz = mpImplLB->CalcSize( nLines );
2898  tools::Long nMaxHeight = aSz.Height() + nTop + nBottom;
2899 
2900  if ( mnDDLineCount )
2901  aFloatSz.setHeight( nMaxHeight );
2902 
2903  if( mbAutoWidth )
2904  {
2905  // AutoSize first only for width...
2906 
2907  aFloatSz.setWidth( aSz.Width() + nLeft + nRight );
2908  aFloatSz.AdjustWidth(nRight ); // adding some space looks better...
2909 
2910  if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList().GetEntryCount() ) ) )
2911  {
2912  // then we also need the vertical Scrollbar
2914  aFloatSz.AdjustWidth(nSBWidth );
2915  }
2916 
2917  tools::Long nDesktopWidth = GetDesktopRectPixel().getWidth();
2918  if (aFloatSz.Width() > nDesktopWidth)
2919  // Don't exceed the desktop width.
2920  aFloatSz.setWidth( nDesktopWidth );
2921  }
2922 
2923  if ( aFloatSz.Height() > nMaxHeight )
2924  aFloatSz.setHeight( nMaxHeight );
2925 
2926  // Minimal height, in case height is not set to Float height.
2927  // The parent of FloatWin must be DropDown-Combo/Listbox.
2928  Size aParentSz = GetParent()->GetSizePixel();
2929  if( (!mnDDLineCount || !nLines) && ( aFloatSz.Height() < aParentSz.Height() ) )
2930  aFloatSz.setHeight( aParentSz.Height() );
2931 
2932  // do not get narrower than the parent...
2933  if( aFloatSz.Width() < aParentSz.Width() )
2934  aFloatSz.setWidth( aParentSz.Width() );
2935 
2936  // align height to entries...
2937  tools::Long nInnerHeight = aFloatSz.Height() - nTop - nBottom;
2938  tools::Long nEntryHeight = mpImplLB->GetEntryHeightWithMargin();
2939  if ( nInnerHeight % nEntryHeight )
2940  {
2941  nInnerHeight /= nEntryHeight;
2942  nInnerHeight++;
2943  nInnerHeight *= nEntryHeight;
2944  aFloatSz.setHeight( nInnerHeight + nTop + nBottom );
2945  }
2946 
2947  if (aFloatSz.Width() < aSz.Width())
2948  {
2949  // The max width of list box entries exceeds the window width.
2950  // Account for the scroll bar height.
2952  aFloatSz.AdjustHeight(nSBWidth );
2953  }
2954 
2955  return aFloatSz;
2956 }
2957 
2958 void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
2959 {
2960  if( IsInPopupMode() )
2961  return;
2962 
2963  Size aFloatSz = CalcFloatSize();
2964 
2965  SetSizePixel( aFloatSz );
2967 
2968  sal_Int32 nPos = mpImplLB->GetEntryList().GetSelectedEntryPos( 0 );
2970 
2971  Size aSz = GetParent()->GetSizePixel();
2972  Point aPos = GetParent()->GetPosPixel();
2973  aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
2974  // FIXME: this ugly hack is for Mac/Aqua
2975  // should be replaced by a real mechanism to place the float rectangle
2976  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2978  {
2979  const sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4;
2980  aPos.AdjustX(nLeft );
2981  aPos.AdjustY(nTop );
2982  aSz.AdjustWidth( -(nLeft + nRight) );
2983  aSz.AdjustHeight( -(nTop + nBottom) );
2984  }
2985  tools::Rectangle aRect( aPos, aSz );
2986 
2987  // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI
2988  // where the document is unmirrored
2989  // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror
2990  vcl::Window *pGrandparent = GetParent()->GetParent();
2991  const OutputDevice *pGrandparentOutDev = pGrandparent->GetOutDev();
2992 
2993  if( pGrandparent->GetOutDev()->ImplIsAntiparallel() )
2994  pGrandparentOutDev->ReMirror( aRect );
2995 
2996  // mouse-button right: close the List-Box-Float-win and don't stop the handling fdo#84795
2998 
2999  if( nPos != LISTBOX_ENTRY_NOTFOUND )
3000  mpImplLB->ShowProminentEntry( nPos );
3001 
3002  if( bStartTracking )
3004 
3007 
3009 
3010 }
3011 
3012 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
Definition: window.cxx:2796
tools::Rectangle maFocusRect
Definition: listbox.hxx:542
tools::Long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
Definition: window3.cxx:65
void SelectEntry(sal_Int32 nPos, bool bSelect)
Size GetSizePixel() const
Definition: Image.cxx:86
void SetPos(const Point &rPoint)
bool IsControlBackground() const
Definition: window2.cxx:1110
bool GetEdgeBlending() const
Definition: listbox.hxx:494
virtual void EnableRTL(bool bEnable=true) override
Definition: ctrl.cxx:65
virtual void ShowFocus(const tools::Rectangle &rRect) override
bool IsInPopupMode() const
Definition: floatwin.hxx:130
virtual const Wallpaper & GetDisplayBackground() const
Definition: window.cxx:3072
bool mbAutoHScroll
Definition: listbox.hxx:388
WinBits const WB_NOSHADOW
virtual void LoseFocus() override
void SetBackground()
Definition: window3.cxx:100
Link< sal_Int32, void > maFocusHdl
Definition: listbox.hxx:232
bool mbEdgeBlending
Definition: listbox.hxx:546
sal_Int32 NaturalSortCompare(const OUString &rA, const OUString &rB)
void StartPopupMode(const tools::Rectangle &rRect, FloatWinPopupFlags nFlags)
Definition: floatwin.cxx:776
void HideFocus()
Definition: window2.cxx:94
sal_Int32 nIndex
SalLayoutGlyphs maStrGlyphs
Definition: listbox.hxx:54
bool mbTrack
Tracking.
Definition: listbox.hxx:209
virtual void Resize() override
#define HORZ_SCROLL
Definition: listbox.hxx:40
virtual void LoseFocus() override
bool HandleKeyEvent(const KeyEvent &_rKEvt)
WinBits const WB_SYSTEMWINDOW
bool HasEntryImage(sal_Int32 nPos) const
virtual void StateChanged(StateChangedType nType) override
void SetNoSelection()
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
This is an overloaded member function, provided for convenience. It differs from the above function o...
OUString maString
Definition: listbox.hxx:539
void SetSelectionAnchor(sal_Int32 nPos)
Definition: listbox.hxx:152
static OUString filterFormattingChars(const OUString &)
Definition: i18nhelp.cxx:93
virtual void FillLayoutData() const override
void setWidth(tools::Long nWidth)
const ImplEntryList & GetEntryList() const
Definition: listbox.hxx:266
virtual void setPosSizePixel(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags=PosSizeFlags::All) override
sal_Int32 GetSelectedEntryPos(sal_Int32 nIndex) const
void SetUserItemSize(const Size &rSz)
const CommandEvent * GetCommandEvent() const
Definition: event.hxx:332
const Color & GetHighlightTextColor() const
BitmapEx createBlendFrame(const Size &rSize, sal_uInt8 nAlpha, Color aColorTopLeft, Color aColorBottomRight)
Create a blend frame as BitmapEx.
Definition: BitmapEx.cxx:1000
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
virtual ~ImplListBoxWindow() override
tools::Long getWidth() const
std::optional< vcl::ControlLayoutData > mxLayoutData
Definition: ctrl.hxx:84
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: button.hxx:34
void ScrollHorz(tools::Long nDiff)
Image maImage
Definition: listbox.hxx:55
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
Definition: bitmapex.cxx:33
bool mbVScroll
Definition: listbox.hxx:386
bool Contains(const Point &rPOINT) const
std::unique_ptr< sal_Int32[]> pData
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
SAL_DLLPRIVATE void ImplClearLayoutData() const
Definition: ctrl.cxx:326
tools::Rectangle maFocusRect
Definition: listbox.hxx:180
sal_uIntPtr sal_uLong
long Long
void disposeAndClear()
Definition: vclptr.hxx:200
tools::Long mnHeight
Definition: listbox.hxx:59
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:760
constexpr sal_uInt16 KEY_A
Definition: keycodes.hxx:56
tools::Long mnMaxImgWidth
Maximum width of an image item.
Definition: listbox.hxx:189
bool mbSelectionChanged
Do not call Select() too often ...
Definition: listbox.hxx:214
void ImplResizeControls()
bool mbEdgeBlending
Definition: listbox.hxx:389
virtual void StateChanged(StateChangedType nStateChange) override
Definition: ctrl.cxx:256
ImplSVNWFData maNWFData
Definition: svdata.hxx:404
sal_Int64 n
SAL_DLLPRIVATE vcl::Window * ImplGetBorderWindow() const
Definition: window2.cxx:893
Link< ImplListBoxWindow *, void > maScrollHdl
Definition: listbox.hxx:226
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
void EnableMouseMoveSelect(bool bMouseMoveSelect)
Definition: listbox.hxx:336
sal_Int32 GetTopEntry() const
Definition: listbox.hxx:450
virtual Size GetSizePixel() const
Definition: window.cxx:2404
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1285
WinBits const WB_RIGHT
constexpr tools::Long gnBorder
Definition: imp_listbox.cxx:49
#define IMG_TXT_DISTANCE
Definition: listbox.hxx:41
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:527
sal_Int32 GetEntryPosForPoint(const Point &rPoint) const
sal_Int32 GetLastSelected() const
Definition: listbox.hxx:150
SAL_DLLPRIVATE void CompatStateChanged(StateChangedType nStateChange)
Definition: window.cxx:3897
bool IsShift() const
Definition: event.hxx:158
bool MatchString(const OUString &rStr1, const OUString &rStr2) const
Definition: i18nhelp.cxx:124
void SetMRUCount(sal_Int32 n)
Definition: listbox.hxx:158
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
void SetTextFillColor()
Definition: text.cxx:732
const Color & GetFieldRolloverTextColor() const
sal_uInt16 GetCode() const
Definition: keycod.hxx:49
void SelectEntry(sal_Int32 nPos, bool bSelect)
Definition: imp_listbox.cxx:89
sal_Int32 FindEntry(std::u16string_view rStr, bool bSearchMRUArea=false) const
sal_Int32 GetSelectedEntryCount() const
PosSizeFlags
Definition: window.hxx:125
DataChangedEventType GetType() const
Definition: event.hxx:362
The invalidated area is updated immediately.
tools::Rectangle GetDesktopRectPixel() const
Definition: window.cxx:2801
sal_Int32 mnMRUCount
Definition: listbox.hxx:94
bool mbMouseMoveSelect
Select at MouseMove.
Definition: listbox.hxx:215
WinBits const WB_VSCROLL
sal_Int32 mnTop
output from line on
Definition: listbox.hxx:201
constexpr::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
sal_uInt16 GetDisplayLineCount() const
const Color & GetControlBackground() const
Definition: window2.cxx:1105
const CommandWheelData * GetWheelData() const
constexpr sal_uInt16 KEY_SPACE
Definition: keycodes.hxx:123
void SetRangeMax(tools::Long nNewRange)
Definition: scrbar.cxx:1332
void SetSeparatorPos(sal_Int32 n)
Removes existing separators, and sets the position of the one and only separator. ...
void SetType(WindowType nType)
Definition: window2.cxx:991
bool mbCenter
center Text output
Definition: listbox.hxx:220
sal_Int32 GetSelectionAnchor() const
Definition: listbox.hxx:153
void PaintImmediately()
Definition: paint.cxx:1268
bool HandleScrollCommand(const CommandEvent &rCmd, ScrollBar *pHScrl, ScrollBar *pVScrl)
Definition: window2.cxx:627
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
virtual void Tracking(const TrackingEvent &rTEvt) override
bool IsRTLEnabled() const
Definition: window3.cxx:127
static Point ImplCalcPos(vcl::Window *pWindow, const tools::Rectangle &rRect, FloatWinPopupFlags nFlags, sal_uInt16 &rArrangeIndex, Point *pLOKTwipsPos=nullptr)
Definition: floatwin.cxx:231
void StartTracking(StartTrackingFlags nFlags=StartTrackingFlags::NONE)
Definition: window2.cxx:251
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:3009
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
const vcl::Font & GetFieldFont() const
tools::Long GetLeftIndent() const
Definition: listbox.hxx:455
DrawTextFlags
const Color & GetFieldTextColor() const
int mnListBoxEntryMargin
Definition: svdata.hxx:347
void ImplUpdateEntryMetrics(ImplEntryType &rEntry)
constexpr sal_uInt16 KEY_UP
Definition: keycodes.hxx:111
#define LISTBOX_ENTRY_NOTFOUND
Definition: lstbox.hxx:37
const Color & GetHighlightColor() const
VclPtr< ImplListBoxWindow > maLBWindow
Definition: listbox.hxx:381
bool mbReadOnly
ReadOnly.
Definition: listbox.hxx:219
ImplEntryList(vcl::Window *pWindow)
Definition: imp_listbox.cxx:60
The invalidated area is painted with the background color/pattern.
void ImplInitScrollBars()
Link< void *, void > maMBDownHdl
Definition: listbox.hxx:585
sal_Int32 GetTopEntry() const
Definition: listbox.hxx:288
constexpr sal_uInt16 KEY_END
Definition: keycodes.hxx:115
void RemoveEntry(sal_Int32 nPos)
const Fraction & GetZoom() const
Definition: window2.cxx:1233
void * GetEntryData(sal_Int32 nPos) const
StateChangedType
Definition: window.hxx:289
constexpr tools::Long Width() const
tools::Long mnMaxWidth
Maximum width of an entry.
Definition: listbox.hxx:191
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
tools::Long mnTextHeight
text height
Definition: listbox.hxx:203
tools::Long GetMaxEntryWidth() const
Definition: listbox.hxx:473
sal_uInt16 GetEdgeBlending() const
sal_uInt16 GetClicks() const
Definition: event.hxx:126
VclPtr< vcl::Window > mpWindow
For getting the current locale when matching strings.
Definition: listbox.hxx:89
sal_Int64 WinBits
IMPL_LINK_NOARG(ImplListBox, MRUChanged, LinkParamNone *, void)
sal_uInt16 sal_Unicode
bool IsTravelSelect() const
Definition: listbox.hxx:323
std::set< sal_Int32 > maSeparators
Separator positions.
Definition: listbox.hxx:197
virtual bool PreNotify(NotifyEvent &rNEvt) override
void RemoveEntry(sal_Int32 nPos)
void SetBackground()
Definition: background.cxx:27
void SetControlFont()
Definition: window2.cxx:432
tools::Long mnMaxImgTxtWidth
Maximum width of a text item.
Definition: listbox.hxx:187
void Enable(bool bEnable=true, bool bChild=true)
Definition: window.cxx:2435
void SetPageSize(tools::Long nNewSize)
Definition: scrbar.hxx:125
SAL_DLLPRIVATE void ReMirror(Point &rPoint) const
Definition: outdev.cxx:687
this flags lets the item be drawn disabled (e.g.
VclPtr< ImplListBox > mpImplLB
Definition: listbox.hxx:501
void SetSymbol(SymbolType eSymbol)
Definition: button.cxx:1611
virtual void StateChanged(StateChangedType nType) override
LB_EVENT_TYPE
Definition: listbox.hxx:43
virtual ~ImplListBoxFloatingWindow() override
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
bool IsControlForeground() const
Definition: window2.cxx:1100
DrawImageFlags
bool IsEnterWindow() const
Definition: event.hxx:138
bool mbHScroll
Definition: listbox.hxx:387
WinBits const WB_HSCROLL
int nCount
void SetMRUChangedHdl(const Link< LinkParamNone *, void > &rLink)
Definition: listbox.hxx:351
void Hide()
Definition: window.hxx:884
AllSettingsFlags GetFlags() const
Definition: event.hxx:363
constexpr sal_uInt16 KEY_PAGEUP
Definition: keycodes.hxx:116
virtual const Wallpaper & GetDisplayBackground() const override
bool mbIsDropdown
Listbox is actually a dropdown (either combobox, or popup window treated as dropdown) ...
Definition: listbox.hxx:224
constexpr tools::Long GetWidth() const
tools::Long mnMaxTxtWidth
Maximum width of a text item.
Definition: listbox.hxx:185
tools::Long getHeightWithMargin() const
virtual void Resize() override
sal_uInt16 GetModifier() const
Definition: keycod.hxx:52
void SetMRUEntries(std::u16string_view rEntries, sal_Unicode cSep)
const void * StringEntryIdentifier
Link< LinkParamNone *, void > maListItemSelectHdl
Definition: listbox.hxx:233
bool IsValid() const
ImplWin(vcl::Window *pParent, WinBits nWinStyle)
sal_Int32 mnMaxMRUCount
Definition: listbox.hxx:95
bool mbSimpleMode
SimpleMode for MultiListBox.
Definition: listbox.hxx:211
void DrawLine(const Point &rStartPt, const Point &rEndPt)
Definition: line.cxx:160
void SetThumbPos(tools::Long nThumbPos)
Definition: scrbar.cxx:1361
const Color & GetEdgeBlendingBottomRightColor() const
Image GetEntryImage(sal_Int32 nPos) const
void SetTextFillColor()
Definition: window3.cxx:97
void SetLineSize(tools::Long nNewSize)
Definition: scrbar.hxx:123
ImplListBoxWindow * GetMainWindow()
Definition: listbox.hxx:412
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:51
sal_Int32 mnTrackingSaveSelection
Selection before Tracking();.
Definition: listbox.hxx:195
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
const Color & GetControlForeground() const
Definition: window2.cxx:1095
this flag disables a selection of an entry completely.
void SetTopEntry(sal_Int32 nTop)
Definition: listbox.hxx:449
constexpr sal_uInt16 KEY_DOWN
Definition: keycodes.hxx:110
void RemoveEntry(sal_Int32 nPos)
void SetScrollHdl(const Link< ImplListBoxWindow *, void > &rLink)
Definition: listbox.hxx:346
Link< void *, void > maMBDownHdl
Definition: listbox.hxx:544
ImplListBoxFloatingWindow(vcl::Window *pParent)
sal_Int32 GetSeparatorPos() const
Gets the position of the separator which was added first.
sal_Int32 GetMRUCount() const
Definition: listbox.hxx:159
bool IsEmpty() const
Definition: BitmapEx.cxx:177
void ShowProminentEntry(sal_Int32 nPos)
Definition: listbox.hxx:451
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
bool ProcessKeyInput(const KeyEvent &rKEvt)
this flag can be used to make an entry multiline capable A normal entry is single line and will there...
void SetLineColor()
Definition: line.cxx:36
sal_Int32 GetScrollBarSize() const
virtual void KeyInput(const KeyEvent &rKEvt) override
void clear()
Definition: vclptr.hxx:190
const Color & GetDisableColor() const
ImplEntryType * GetMutableEntryPtr(sal_Int32 nPos) const
Definition: listbox.hxx:115
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: syswin.cxx:198
std::vector< std::unique_ptr< ImplEntryType > > maEntries
Definition: listbox.hxx:99
virtual bool PreNotify(NotifyEvent &rNEvt)
Definition: event.cxx:52
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
bool IsLeaveWindow() const
Definition: event.hxx:140
int i
virtual void Resize() override
bool IsEntryPosSelected(sal_Int32 nIndex) const
bool IsNativeWidgetEnabled() const
Definition: window.cxx:3709
ImplBtn(vcl::Window *pParent, WinBits nWinStyle)
virtual void Resize() override
constexpr sal_uInt16 KEY_HOME
Definition: keycodes.hxx:114
virtual ~ImplListBox() override
void SetControlBackground()
Definition: window2.cxx:520
virtual bool PreNotify(NotifyEvent &rNEvt) override
WinBits const WB_SIMPLEMODE
IMPL_LINK(ImplListBox, ScrollBarHdl, ScrollBar *, pSB, void)
bool mbMulti
MultiListBox.
Definition: listbox.hxx:210
void SetVisibleSize(tools::Long nNewSize)
Definition: scrbar.cxx:1375
tools::Long mnLeft
output from column on
Definition: listbox.hxx:202
void ImplCheckScrollBars()
Link< ImplListBoxWindow *, void > maDoubleClickHdl
Definition: listbox.hxx:229
void SetSize(const Size &rSize)
void SetControlForeground()
Definition: window2.cxx:480
CommandWheelMode GetMode() const
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1143
SAL_DLLPRIVATE bool ImplIsAntiparallel() const
Definition: outdev.cxx:671
void SetUpdateMode(bool bUpdate)
Definition: window.cxx:2972
sal_Int32 mnSelectionAnchor
Definition: listbox.hxx:91
ImplListBox(vcl::Window *pParent, WinBits nWinStyle)
bool IsUpdateMode() const
Definition: window2.cxx:1196
void SetFillColor()
Definition: fill.cxx:29
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_GRAY
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:175
const AllSettings & GetSettings() const
Definition: window3.cxx:129
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
const Color & GetFieldColor() const
tools::Long GetEntryHeightWithMargin() const
CommandEventId GetCommand() const
const Color & GetLineColor() const
Definition: outdev.hxx:521
VclPtr< ScrollBarBox > mpScrollBarBox
Definition: listbox.hxx:384
void SetZoom(const Fraction &rZoom)
Definition: window2.cxx:393
sal_uInt16 GetModifier() const
Size CalcSize(sal_Int32 nMaxLines) const
void SetTextColor(const Color &rColor)
Definition: text.cxx:714
void SetLastSelected(sal_Int32 nPos)
Definition: listbox.hxx:149
constexpr sal_uInt16 KEY_PAGEDOWN
Definition: keycodes.hxx:117
DrawTextFlags ImplGetTextStyle() const
bool IsZoom() const
Definition: window2.cxx:1238
constexpr tools::Long Top() const
void SetEdgeBlending(bool bNew)
Definition: listbox.hxx:366
void ImplDoPaint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
MouseNotifyEvent GetType() const
Definition: event.hxx:308
void SetLeftIndent(tools::Long n)
bool DrawNativeControl(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, const OUString &aCaption, const Color &rBackgroundColor=COL_AUTO)
Request rendering of a particular control and/or part.
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: ctrl.cxx:58
WinBits const WB_DROPDOWN
const AllSettings & GetSettings() const
Definition: outdev.hxx:295
vcl::QuickSelectionEngine maQuickSelectionEngine
Definition: listbox.hxx:235
bool GetEdgeBlending() const
Definition: listbox.hxx:572
Point PixelToLogic(const Point &rDevicePt) const
Definition: window3.cxx:161
VclPtr< ScrollBar > mpHScrollBar
Definition: listbox.hxx:382
bool HandleWheelAsCursorTravel(const CommandEvent &rCEvt, Control &rControl)
void ApplyControlForeground(vcl::RenderContext &rRenderContext, const Color &rDefaultColor)
Definition: window2.cxx:512
Link< LinkParamNone *, void > maCancelHdl
Definition: listbox.hxx:228
WinBits const WB_SORT
sal_uInt16 GetModifier() const
Definition: event.hxx:156
bool mbSort
ListBox sorted.
Definition: listbox.hxx:208
virtual void LoseFocus()
Definition: window.cxx:1857
bool GetEdgeBlending() const
Definition: listbox.hxx:365
void DrawEntry(vcl::RenderContext &rRenderContext, sal_Int32 nPos, bool bDrawImage, bool bDrawText)
OUString maStr
Definition: listbox.hxx:53
void GrabFocus()
Definition: window.cxx:2981
Link< UserDrawEvent *, void > maUserDrawHdl
Definition: listbox.hxx:230
virtual void ShowFocus(const tools::Rectangle &rRect)
Definition: window2.cxx:52
bool mbTravelSelect
TravelSelect.
Definition: listbox.hxx:212
vcl::Window * GetParent() const
Definition: window2.cxx:1120
ListBoxEntryFlags mnFlags
Definition: listbox.hxx:58
sal_Int32 FindMatchingEntry(const OUString &rStr, sal_Int32 nStart, bool bLazy) const
void SetLeftIndent(sal_uInt16 n)
Definition: listbox.hxx:456
void ImplPaint(vcl::RenderContext &rRenderContext, sal_Int32 nPos)
bool IsTrackingEnded() const
Definition: event.hxx:261
Link< LinkParamNone *, void > maMRUChangedHdl
Definition: listbox.hxx:231
virtual void MouseMove(const MouseEvent &rMEvt) override
void DrawEntry(vcl::RenderContext &rRenderContext, bool bLayout)
Size CalcSize(sal_Int32 nMaxLines) const
Definition: listbox.hxx:470
constexpr sal_uInt16 KEY_RETURN
Definition: keycodes.hxx:119
WinBits const WB_NOBORDER
const Color & GetButtonRolloverTextColor() const
virtual void SetPosSizePixel(const Point &rNewPos, const Size &rNewSize)
Definition: window2.cxx:1291
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1035
constexpr sal_uInt16 KEY_RIGHT
Definition: keycodes.hxx:113
#define MULTILINE_ENTRY_DRAW_FLAGS
Definition: imp_listbox.cxx:45
bool mbIsSelected
Definition: listbox.hxx:57
sal_Int32 mnCurrentPos
Position (Focus)
Definition: listbox.hxx:194
constexpr tools::Long Bottom() const
bool mbUserDrawEnabled
UserDraw possible.
Definition: listbox.hxx:217
VclPtr< ScrollBar > mpVScrollBar
Definition: listbox.hxx:383
tools::Long const nBorder
bool IsMouseMoveSelect() const
Definition: listbox.hxx:337
virtual void setPosSizePixel(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags=PosSizeFlags::All)
Definition: window.cxx:2668
virtual void KeyInput(const KeyEvent &rKEvt)
Definition: window.cxx:1807
const LanguageTag & getLocale()
const vcl::I18nHelper & GetLocaleI18nHelper() const
bool mbUseNativeFocus
Definition: window.h:317
tools::Long mnMaxTxtHeight
Maximum height of a text item.
Definition: listbox.hxx:184
void GetBorder(sal_Int32 &rLeftBorder, sal_Int32 &rTopBorder, sal_Int32 &rRightBorder, sal_Int32 &rBottomBorder) const
Definition: window.cxx:2426
void * mpUserData
Definition: listbox.hxx:56
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:57
void Erase()
Definition: wallpaper.cxx:96
bool IsShift() const
Definition: keycod.hxx:54
tools::Long GetAddedHeight(sal_Int32 nEndIndex, sal_Int32 nBeginIndex) const
helper: add up heights up to index nEndIndex.
bool IsUserDrawEnabled() const
Definition: listbox.hxx:329
bool IsMouseOver() const
Definition: mouse.cxx:620
virtual void Resize() override
Definition: ctrl.cxx:74
ImplEntryType * GetEntry(sal_Int32 nPos) const
Definition: listbox.hxx:101
bool ProcessKeyInput(const KeyEvent &rKEvt)
Definition: listbox.hxx:430
virtual void Scroll(tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags=ScrollFlags::NONE)
Definition: window.cxx:2949
const ImplEntryType * GetEntryPtr(sal_Int32 nPos) const
Definition: listbox.hxx:114
Definition: ctrl.hxx:81
bool IsEntrySelectable(sal_Int32 nPos) const
An Entry is selectable if its mnFlags does not have the ListBoxEntryFlags::DisableSelection flag set...
#define LISTBOX_MAX_ENTRIES
Definition: lstbox.hxx:38
ListBoxEntryFlags
Definition: lstbox.hxx:47
bool IsSynthetic() const
Definition: event.hxx:142
virtual void GetFocus()
Definition: window.cxx:1843
const Color & GetButtonTextColor() const
bool mbNoFocusRects
Definition: svdata.hxx:328
sal_Int32 mnItemPos
because of UserDraw I have to know which item I draw
Definition: listbox.hxx:538
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
WinBits const WB_BORDER
unsigned char sal_uInt8
bool bIsEnabled
const MouseEvent * GetMouseEvent() const
Definition: event.hxx:324
virtual void GetFocus() override
sal_Int32 mnLastSelected
Definition: listbox.hxx:90
tools::Long GetEntryHeightWithMargin() const
Definition: listbox.hxx:472
bool IsVisible() const
Definition: window2.cxx:1125
virtual vcl::StringEntryIdentifier CurrentEntry(OUString &_out_entryText) const override
returns the current entry in the list of searchable strings.
sal_Int32 mnPopupModeStartSaveSelection
Definition: listbox.hxx:504
void SetSeparatorPos(sal_Int32 n)
Removes existing separators, and sets the position of the one and only separator. ...
Definition: listbox.hxx:437
bool SelectEntries(sal_Int32 nSelect, LB_EVENT_TYPE eLET, bool bShift=false, bool bCtrl=false, bool bSelectPosChange=false)
sal_Int32 FindFirstSelectable(sal_Int32 nPos, bool bForward=true) const
sal_uInt16 mnSelectModifier
Modifiers.
Definition: listbox.hxx:205
::OutputDevice const * GetOutDev() const
Definition: window.cxx:567
bool IsLeft() const
Definition: event.hxx:149
tools::Long AdjustWidth(tools::Long n)
void SetScrollHdl(const Link< ScrollBar *, void > &rLink)
Definition: scrbar.hxx:133
Definition: image.hxx:39
bool IsMod1() const
Definition: keycod.hxx:56
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
tools::Long mnMaxImgHeight
Maximum height of an image item.
Definition: listbox.hxx:190
tools::Rectangle GetTextRect(const tools::Rectangle &rRect, const OUString &rStr, DrawTextFlags nStyle=DrawTextFlags::WordBreak, TextRectInfo *pInfo=nullptr, const vcl::ITextLayout *_pTextLayout=nullptr) const
Definition: window3.cxx:201
Reference< XComponentContext > getProcessComponentContext()
tools::Long CalcZoom(tools::Long n) const
Definition: window2.cxx:420
ImplListBoxWindow(vcl::Window *pParent, WinBits nWinStyle)
bool IsGrabFocusAllowed() const
Definition: listbox.hxx:300
const Point & GetPosPixel() const
Definition: event.hxx:123
sal_Int32 mnImages
Definition: listbox.hxx:92
WinBits const WB_AUTOHSCROLL
tools::Long AdjustHeight(tools::Long n)
virtual void GetFocus() override
tools::Long GetEntryHeight(sal_Int32 nPos) const
sal_Int32 InsertEntry(sal_Int32 nPos, ImplEntryType *pNewEntry)
Size GetOutputSizePixel() const
Definition: window3.cxx:89
void setHeight(tools::Long nHeight)
virtual bool EventNotify(NotifyEvent &rNEvt) override
Event to pass information for UserDraw() handling eg. in comboboxes.
Definition: event.hxx:221
tools::Long GetDelta() const
WinBits const WB_CENTER
sal_Int32 InsertEntry(sal_Int32 nPos, const OUString &rStr)
bool isSeparator(const sal_Int32 &n) const
Checks if the given number n is an element of the separator positions set.
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Width of the text.
Definition: window3.cxx:66
ScXMLEditAttributeMap::Entry const aEntries[]
bool IsEnabled() const
Definition: window2.cxx:1145
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
#define SAL_WARN(area, stream)
Image maImage
Definition: listbox.hxx:540
OUString GetSelectedEntry(sal_Int32 nIndex) const
void SetTopEntry(sal_Int32 nTop)
bool IsTrackingCanceled() const
Definition: event.hxx:263
OUString GetMRUEntries(sal_Unicode cSep) const
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), tools::Long nLogicWidth=0, o3tl::span< const sal_Int32 > pLogicDXArray={}, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::text::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1308
WinBits GetStyle() const
Definition: window2.cxx:976
void SelectEntry(sal_Int32 nPos, bool bSelect)
Link< sal_Int32, void > maSelectionChangedHdl
Definition: listbox.hxx:97
sal_Int32 mnUserDrawEntry
Definition: listbox.hxx:199
virtual void FillLayoutData() const override
bool IsReadOnly() const
Definition: listbox.hxx:361
void ApplyControlFont(vcl::RenderContext &rRenderContext, const vcl::Font &rDefaultFont)
Definition: window2.cxx:472
OUString GetEntryText(sal_Int32 nPos) const
constexpr sal_uInt16 KEY_LEFT
Definition: keycodes.hxx:112
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2808
void StartFloat(bool bStartTracking)
sal_Int32 GetLastVisibleEntry() const
void SetEntryData(sal_Int32 nPos, void *pNewData)
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
Definition: window3.cxx:74
void ImplInitDropDownButton(PushButton *pButton)
Definition: imp_listbox.cxx:51
sal_Int32 compare(const OUString &rLHS, const OUString &rRHS) const
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
void SetAccessibleRole(sal_uInt16 nRole)
bool HasImages() const
Definition: listbox.hxx:130
bool mbInUserDraw
In UserDraw.
Definition: listbox.hxx:218
const MouseEvent & GetMouseEvent() const
Definition: event.hxx:257
bool IsReallyVisible() const
Definition: window2.cxx:1130
vcl::Font GetControlFont() const
Definition: window2.cxx:461
bool mbGrabFocus
Grab focus at MBDown.
Definition: listbox.hxx:216
virtual vcl::StringEntryIdentifier NextEntry(vcl::StringEntryIdentifier _currentEntry, OUString &_out_entryText) const override
returns the next entry in the list.
SalLayoutGlyphs * GetTextGlyphs(const OutputDevice *pOutputDevice)
Computes maStr's text layout (glyphs), cached in maStrGlyphs.
const Wallpaper & GetBackground() const
Definition: window3.cxx:63
bool HasFocus() const
Definition: window.cxx:2986
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: floatwin.cxx:204
const Color & GetEdgeBlendingTopLeftColor() const
void SetEdgeBlending(bool bNew)
WinBits const WB_WORDBREAK
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
bool SupportsDoubleBuffering() const
Can the widget derived from this Window do the double-buffering via RenderContext properly...
Definition: window.cxx:3859
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
Definition: text.cxx:795
tools::Long mnMaxHeight
Maximum height of an entry.
Definition: listbox.hxx:192
void ShowProminentEntry(sal_Int32 nEntryPos)
ShowProminentEntry will set the entry corresponding to nEntryPos either at top or in the middle depen...
void EndPopupMode(FloatWinPopupEndFlags nFlags=FloatWinPopupEndFlags::NONE)
Definition: floatwin.cxx:949
sal_Int32 InsertEntry(sal_Int32 nPos, ImplEntryType *pNewEntry, bool bSort)
sal_Int32 nState
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1280
aStr
virtual void Resize() override
Definition: syswin.cxx:1005
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
virtual void GetFocus() override
bool mbCallSelectionChangedHdl
Definition: listbox.hxx:98
sal_Int32 GetEntryCount() const
Definition: listbox.hxx:129
bool IsMod3() const
Definition: keycod.hxx:60
sal_uInt16 nPos
tools::Rectangle GetBoundingRectangle(sal_Int32 nItem) const
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
virtual void DataChanged(const DataChangedEvent &rDCEvt)
Definition: event.cxx:36
Link< LinkParamNone *, void > maSelectHdl
Definition: listbox.hxx:227
bool IsMod1() const
Definition: event.hxx:160
void ImplDraw(vcl::RenderContext &rRenderContext, bool bLayout=false)
constexpr tools::Long GetHeight() const
WinBits const WB_DRAG
bool IsMod2() const
Definition: keycod.hxx:58
bool mbTrackingSelect
Selected at a MouseMove.
Definition: listbox.hxx:213
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2189
ImplEntryList maEntryList
EntryList.
Definition: listbox.hxx:179
const ImplEntryList & GetEntryList() const
Definition: listbox.hxx:411
bool mbRight
right align Text output
Definition: listbox.hxx:221
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo